Server Modes · Rex Docs

Server Modes

How you run a Rex server decides which account it runs as and who can connect to it. There are three ways to run the Rex server on Linux and FreeBSD:

Mode Who it’s for Runs as Started by
Personal Just you Your account Any rex command, or rex server start
Shared A few people you trust with one account rex rex.service, or rex.socket on demand
Login Several people, each as themselves root, then each person’s account rex-login-server.service, or rex-login-server.socket on demand

If you’re the only person using Rex on the machine, run a personal server. If a few people need it and can share one account, use the shared server. If you or others need to access and login as separate accounts, use the login server.

The shared server and the login server can’t run together. Their services and sockets all use /run/rex, so starting the service or socket of one stops both units of the other. On Alpine and FreeBSD, each refuses to start while the other is running. Personal servers can run alongside either one. With the login server, your personal server is the same server the login server connects you to, so local rex commands and remote connections see the same sessions.

Every mode listens only on Unix sockets on this machine by default. To connect from another computer, see Remote Access.

Personal Server

A personal server runs as your own user account and doesn’t require any special setup or root access. Any rex command automatically starts a personal server if none is running:

rex ls

An automatically started personal server stops on its own around 10 seconds after its last session and its last connection close. To start one that remains running you must explicitly start it:

rex server start

rex server start does nothing if a server is already running, including one that a rex command started, so its safe to call multiple times. Its options, such as --max-sessions, apply only when it starts a new server. To change them, stop the server and start it again.

Command Effect
rex server status Show the running server’s status.
rex server logs --follow Show and follow the log of a server started by rex server start.
rex server stop Stop the server. This ends every session on it.

The socket is in $XDG_RUNTIME_DIR/rex, which is usually /run/user/<uid>/rex. Logs and other state are in ~/.local/state/rex, or $XDG_STATE_HOME/rex if you’ve set it. FreeBSD has no /run/user, so there the socket is in ~/.local/state/rex/run. The same goes for Linux machines without it, such as many containers.

A rex command starts a server on its own only for a socket in that directory, or in REX_RUNTIME_DIR instead if you’ve set it. Given any other socket with -S, such as the shared server’s, it starts nothing and says how to start a server there. To run one of your own at another path, start it yourself. Your account must be able to create files in the socket’s directory:

rex -S PATH server start

To keep rex commands from starting a server at all, set REX_AUTOSTART=0.

Shared Server

A shared server is one server that runs as the rex system account. Members of the rex group can connect to it, and every program they start runs as rex. It’s the simplest way to let more than one person use Rex.

Access to the shared server is access to the rex account. Anyone in the group can see and type into every session on it. Only add people you would trust with that account.

Add each person to the group, then start the service now and at every boot:

sudo usermod --append --groups rex alice
sudo systemctl enable --now rex.service

A group change applies the next time that person logs in. The server keeps its data in /var/lib/rex, or /var/db/rex on FreeBSD. On Alpine, the OpenRC commands do both steps, and on FreeBSD, the FreeBSD commands.

To start the server only when someone first connects, enable rex.socket instead of rex.service. See Starting on Demand.

A package upgrade restarts the service, which automatically ends every session on it. See Upgrading.

Read Shared Server before you set it up for other people. It covers giving them access, configuring the server, and changing the service without losing your changes on upgrade.

Login Server

The login server gives each person a server that runs as their own account, with their own files and permissions. It runs as root. When someone connects, it identifies them, checks /etc/rex/accounts.jsonc for the accounts they may use, and hands the connection to a server running as that account. It starts that server if needed.

The login server is the most similar to SSH: one root service that lets each person in as their own account. Unlike SSH, it has no passwords or keys. It identifies people only by how they connect, such as the local account on the other end of its socket or their Tailscale login. Anyone who can reach it that way can use the accounts listed for them.

Each account’s server keeps running when the login server stops, restarts, or is upgraded, so sessions survive all three. After an upgrade, each one keeps the old version until its sessions end.

The accounts file ships empty, which lets nobody in. Add at least one account, then start the service now and at every boot:

sudo $EDITOR /etc/rex/accounts.jsonc
sudo systemctl enable --now rex-login-server.service

On Alpine, use the OpenRC commands instead. On FreeBSD, use the FreeBSD commands, and edit `/usr/local/etc/rex/accounts.jsonc.

To start the login server only when someone first connects, enable rex-login-server.socket instead of rex-login-server.service. See Starting on Demand.

After you change the accounts file, reload it. This doesn’t drop any connections:

sudo systemctl reload rex-login-server.service

On Alpine, run rc-service rex-login-server reload. On FreeBSD, run service rex-login-server reload.

Read Login Server before you add accounts. It covers the accounts file, how people choose an account when they connect, and the PAM policy the login server checks accounts against.

Switching Between the Services

Starting either server stops the other, but disable the old server’s service and socket too, so that neither comes back at the next boot:

sudo systemctl disable --now rex.service rex.socket
sudo systemctl enable --now rex-login-server.service

To start the new server on demand, enable its socket instead, such as rex-login-server.socket. To switch back, swap the names: disable rex-login-server.service and rex-login-server.socket, then enable rex.service or rex.socket.

On Alpine, starting either service fails while the other is running, so stop the old one first:

rc-service rex stop
rc-update del rex
rc-update add rex-login-server
rc-service rex-login-server start

On FreeBSD, the same applies. Stop and disable the old one first:

service rex stop
sysrc rex_enable=NO
sysrc rex_login_server_enable=YES
service rex-login-server start

Switching from the shared server ends every session on it.

Switching from the login server leaves each account’s server running. On machines without systemd-logind, or with a login server run with --pam=false, those servers keep their sockets in /run/rex/accounts, and rex.service and rex.socket refuse to start while that directory exists. Once nobody needs those sessions, clear the directory and start the shared server:

sudo rm -rf /run/rex
sudo systemctl start rex.service

To start the shared server on demand, start rex.socket instead. A refused start can still stop the login server’s units, so if you back out, start the login server’s service or socket again.

Alpine has no systemd-logind, so the account servers always keep their sockets in /run/rex/accounts there. Clear the directory the same way, then run rc-service rex start.

FreeBSD has no systemd-logind either, and keeps /var/run across reboots, so there the rex service refuses to start only while /var/run/rex/accounts holds a socket. Clear it the same way with rm -rf /var/run/rex, then run service rex start.