This article will teach you how to run one or more Redis instances on a Linux server using systemd to spawn copies of a service. I’ll be using Redis as an example but you can also use PostgreSQL or any other service as long as you can configure the port.

Installing Redis

The easiest way to install Redis in Linux is with your distributions package manager. Here is how you would do it on openSUSE:

sudo zypper install redis

In case your distribution doesn’t provide a Redis package, you can always follow these instructions to compile it from scratch.

Configuring a Redis instance

Once installed you will need to create a configuration file for each instance of the service you want to run.

  1. Add a configuration file

    Make a copy of the example/default file that is provided by the package

     cd /etc/redis/
     cp default.conf.example my_app.conf
    

    Use a name that will help you recognize the purpose of the instance. For example if each instance will be mapped to a different application give it the name of the application. If each instance will be mapped to the same application use the port in which it will be running.

  2. Change the ownership of the configuration file

    The configuration file needs to be owned by “root” and belong to the “redis” group.

     chown root.redis my_app.conf
    
  3. Edit “my_app.conf”

    Add a “pidfile”, a “logfile” and a “dir”

     pidfile /var/run/redis/my_app.pid
     logfile /var/log/redis/my_app.log
     dir /var/lib/redis/my_app/
    

    Each of these attributes has to match with the name of the configuration file without the extension.

    Make sure the “daemonize” option is set to “no” (this is the default value)

     daemonize no
    

    If you set this option to yes Redis and systemd will interfere with each other when spawning the processes.

    Define a “port” number.

     port 6379
    

    Remember that each instance should be running on a different port.

  4. Save the configuration file

  5. Create the database directory at the location given in the configuration file

     install -d -o redis -g redis -m 0750 /var/lib/redis/my_app
    

    The database directory has to be owned by user “redis” and belong to the group “redis” and with permissions 750.

Repeat the steps in Configure a Redis instance for every instance you want to set up. In my case I set up a second instance called “my_other_app”

.
├── default.conf.example
├── my_app.conf
└── my_other_app.conf

Adding Units to systemd for the Redis service

In order for systemd to know how to enable and start each instance individually you will need to add a service unit inside the system configuration directory located at /etc/systemd/system. For convenience you might also want to start/stop all instances at once. For that you will need to add a target unit.

In case you installed Redis on openSUSE these two files will be already provided for you under the sytem unit directory /usr/lib/systemd/system.

  1. Create the service unit file redis@.service with the following contents:

     [Unit]
     Description=Redis
     After=network.target
     PartOf=redis.target[Service]
     Type=simple
     User=redis
     Group=redis
     PrivateTmp=true
     PIDFile=/var/run/redis/%i.pid
     ExecStart=/usr/sbin/redis-server /etc/redis/%i.conf
     Restart=on-failure[Install]
     WantedBy=multi-user.target redis.target
    

    The unit file is separated in sections. Each section consists of variables and the value assigned to them. In this example:

    • After: when the Redis instance is enabled it will get started only after the network has been started.
    • PartOf: this instance belongs to the redis.target and will get started/stopped as part of that group.
    • Type: simple means the service process doesn’t fork.
    • %i: a specifier that is expanded by systemd to the “my_app” instance.
  2. Create the target unit file redis.target with the following contents:

[Unit]
Description=Redis target allowing to start/stop all redis@.service instances at once

Interacting with Redis

If everything went as expected you should be able to interact with the individual instances:

systemctl start redis@my_app
systemctl enable redis@my_other_app

And also with all the instances at the same time:

systemctl restart redis.target
systemctl stop redis.target

Troubleshooting

If things didn’t go as expected and you cannot start the instance make sure to check the instance’s status:

systemctl status redis@my_app

If the issue doesn’t show up there then check systemd’s journal:

journalctl -u redis@my_app

For example if you forgot to give the right permissions to the configuration file you’d see something like this inside the journal:

Apr 23 10:02:53 mxps redis-server[26966]: 26966:C 23 Apr 10:02:53.917 # Fatal error, can’t open config file ‘/etc/redis/my_app.conf’

Acknowledgments

Thanks to the openSUSE Redis package maintainers for creating such a nice package that you can learn from it.

The book How Linux Works provided the details on how systemd instances work.