Skip to content

Flox and systemd

Flox environments have a built-in concept of services. Flox environment services are managed by invoking the flox services category of sub-commands such as flox services status.

This tutorial shows how to create and use systemd services with Flox by creating unit files manually. You will learn how to run a Flox environment service as both a systemd user unit and a systemd system unit.

Prerequisites

  • A Linux system with systemd support. This tutorial was tested on Ubuntu 24.04.
  • Flox installed in multi-user mode. This tutorial was tested on Flox 1.10.0.

Constraints

  • The systemd service that invokes Flox cannot run as root.
  • The service cannot listen on a port with a value less than 1024.
  • The UID for the user running the systemd service should be >= 1000 for logs to function properly. See flox#2e789b5 for details.
  • Logs may not function properly if the process forks. See flox#9b1e750 for details.

Run a Flox environment service as a systemd user unit

In this section you will set up a Redis service from a FloxHub environment and run it as a systemd user unit.

Create the Redis environment locally

Create a directory for the environment and pull the flox/redis environment from FloxHub:

mkdir -p redis
cd redis
flox pull flox/redis

Test the environment with Flox services

Before creating the systemd unit, verify that the environment works with Flox services commands:

flox activate
flox services status
flox services start
redis-cli ping
# should respond PONG

Once verified, stop the services and exit the environment:

flox services stop
exit

Create the systemd user service

Create the systemd user unit file:

mkdir -p ~/.config/systemd/user/
cat > ~/.config/systemd/user/redis.service << 'EOF'
[Unit]
Description=Redis Server (Flox)

[Service]
ExecStart=flox activate -d /home/ubuntu/redis -c 'redis-server "$REDISCONFIG" --daemonize no --dir "$REDISDATA"'

[Install]
WantedBy=default.target
EOF

Note

Update the path /home/ubuntu/redis in the ExecStart line to match the location where you created the environment.

By default, systemd user units only run while the user is logged in. Enabling lingering allows the service to start at boot without a login session. If you only need the service to run while you are logged in, you can skip this step.

sudo loginctl enable-linger ubuntu

Load, enable, and start the service:

systemctl --user daemon-reload
systemctl --user enable redis.service
systemctl --user start redis.service

Verify the service is running:

systemctl --user status redis.service

Verify Redis is responding:

flox activate -d /home/ubuntu/redis -c 'redis-cli -p "$REDISPORT" ping'
# should respond PONG

User unit cleanup

To stop and fully remove the systemd user unit:

systemctl --user stop redis.service
systemctl --user disable redis.service
rm ~/.config/systemd/user/redis.service
systemctl --user daemon-reload

Run a Flox environment service as a systemd system unit

For services that should run under a dedicated system user rather than your personal account, you can create a system-level systemd unit instead.

Create a dedicated Redis user

sudo useradd --system --no-create-home --shell /usr/sbin/nologin redis

Create the environment and set ownership

sudo mkdir -p /home/redis
sudo chown -R redis:redis /home/redis
sudo -u redis flox pull flox/redis -d /home/redis/redis

Create the system unit file

Since the redis user has no login session, user units will not work. Create a system unit instead:

sudo tee /etc/systemd/system/redis.service << 'EOF'
[Unit]
Description=Redis Server (Flox)

[Service]
User=redis
ExecStart=flox activate -d /home/redis/redis -c 'redis-server "$REDISCONFIG" --daemonize no --dir "$REDISDATA"'

[Install]
WantedBy=multi-user.target
EOF

Note

Enable lingering is not needed for system units. System units start at boot automatically.

Load, enable, and start

sudo systemctl daemon-reload
sudo systemctl enable redis.service
sudo systemctl start redis.service

Verify

sudo systemctl status redis.service
flox activate -d /home/ubuntu/redis -c 'redis-cli -p "$REDISPORT" ping'
# should respond PONG

Note

Key differences from the user unit approach: the system unit goes in /etc/systemd/system/, uses multi-user.target, requires sudo, and no lingering is needed.

System unit cleanup

To stop and fully remove the systemd system unit:

sudo systemctl stop redis.service
sudo systemctl disable redis.service
sudo rm /etc/systemd/system/redis.service
sudo systemctl daemon-reload

Where to next?