Installing on Linux · Rex Docs
Installing on Linux
Rex can run as a server on Linux so that clients can access it as a remote host.
IMPORTANT: Rex on Linux is in testing. The install commands show below once you’ve logged in with Discord.
System Requirements
| Requirement | Supported |
|---|---|
| Architecture | x86-64, ARM64 |
| C library | glibc 2.26 or later (Amazon Linux 2, Ubuntu 18.04, Debian 10, RHEL 8, or newer), or musl on Alpine 3.21 or later |
| Init system | systemd, or OpenRC on Alpine, for the shared server and the login server. The rex command runs without either. |
| Packages | .deb (Debian, Ubuntu), .rpm (Fedora, RHEL and its rebuilds, openSUSE), .pkg.tar.zst (Arch Linux and derivatives), .apk (Alpine), Nix |
The Alpine package holds the musl build of Rex. It’s dynamically linked, not static, because Rex loads PAM at run time. On other distributions, including other musl ones, install the binary alone with --tarball, which picks the musl build on a musl system.
Install
Log in with Discord to see the install commands.
The install script (install.sh) is a convenience that adds the Rex repository to apt, dnf, zypper, pacman, or apk and installs the rex package, so updates arrive with your normal system updates. Running it again upgrades Rex, as Upgrading covers. To see what it would do first, add -s -- --dry-run after sh. On NixOS and other distributions without a Rex repository, it explains the options and exits.
| Option | Effect |
|---|---|
--channel NAME |
Install from stable, preview, or snapshot. |
--tarball |
Install only the rex binary, into /usr/local/bin, with no services. Needs glibc 2.26 or later, or musl, where it installs the musl build. Run the script again to update. |
--dry-run |
Print every command without running it. |
Pass options after sh -s --. For example, to install only the binary, with no services:
curl -fsSL https://pkgs.superlogical.com/rex/install.sh | sh -s -- --tarball
Channels
Rex publishes to three channels:
| Channel | What it gets |
|---|---|
stable |
Tagged releases (none right now) |
preview |
Tagged previews of the next release |
snapshot |
A frequent, likely unstable build |
The install script defaults to stable but until the first stable release exists, will fall back to preview and say so in the output.
To switch channels later, change the channel name in the repository file: Suites: in /etc/apt/sources.list.d/rex.sources, or the name and baseurl lines in /etc/yum.repos.d/rex.repo or zypper’s repository, or the Server line in /etc/pacman.d/rex.conf. On Alpine, change it in /etc/apk/repositories.d/rex.list if the install script set up the repository, or in the Rex line in /etc/apk/repositories if you added it yourself, then run apk update.
Moving from snapshot to preview or stable upgrades Rex. Moving back to snapshot is a downgrade, which you have to ask for. See Switching Channels and Downgrading.
Package Contents
The rex package installs:
| Path | What it is |
|---|---|
/usr/bin/rex |
The server and the CLI, in one binary |
rex.service |
One shared server, run as the rex account. Not enabled. |
rex.socket |
Starts rex.service when a client first connects. Not enabled. |
rex-login-server.service |
One server per account, after a login. Not enabled. |
rex-login-server.socket |
Starts rex-login-server.service when a client first connects. Not enabled. |
rex account and group |
A locked system account, with its home at /var/lib/rex |
/etc/rex/accounts.jsonc |
The login server’s accounts. It ships empty, which admits nobody. |
/etc/pam.d/rex-login-server |
The login server’s PAM policy, for your distribution |
xterm-rex terminfo |
Rex’s terminal type |
/etc/ssh/ssh_config.d/50-rex.conf |
Falls back to xterm-256color when you SSH from Rex to a host that doesn’t know xterm-rex |
To run a server, enable one of the four units. Each socket starts its service the first time a client connects, instead of at boot. Server Modes helps you choose.
On Alpine, OpenRC scripts at /etc/init.d/rex and /etc/init.d/rex-login-server take the place of the two services. The package never ships /etc/conf.d/rex or /etc/conf.d/rex-login-server, so your changes to the services go there.
On Arch, the package creates the rex account through /usr/lib/sysusers.d/rex.conf, and its home through /usr/lib/tmpfiles.d/rex.conf.
Upgrades keep your changes to the accounts file and the PAM policy. See Keeping Your Changes.
The SSH Fallback
50-rex.conf sets TERM with ssh’s SetEnv keyword, so what it does depends on your OpenSSH version:
| OpenSSH | What happens |
|---|---|
| 8.7 or later | ssh sends xterm-256color to hosts that don’t know xterm-rex. |
| 7.8 to 8.6 | ssh reads the fallback but still sends xterm-rex. RHEL 8 has 8.0. |
| Older than 7.8 | ssh rejects any configuration that contains the fallback, so every ssh command fails. Amazon Linux 2 has 7.4, Ubuntu 18.04 has 7.6. |
rex terminfo setup, with or without --system, checks the version first. On an ssh older than 7.8, it installs the terminfo entry, skips the fallback, says why, and exits with status 1. The package can’t check, so it installs 50-rex.conf everywhere. That’s safe on Ubuntu 18.04 only because its ssh never reads the file, as Debian and Ubuntu explains.
To check that ssh still parses its configuration, run:
ssh -G example.com >/dev/null && echo ok
Debian and Ubuntu
Debian and Ubuntu ship an unrelated package also named rex: (R)?ex, a Perl automation framework. The install script and the Debian tab pin the Rex repository above it, so apt installs Rex, and replaces (R)?ex if it’s already installed.
If rex -v prints (R)?ex, your machine’s own apt preferences outranked the pin. Run apt-cache policy rex to see which rule won, fix it, then run the install script again.
On Ubuntu 18.04, /etc/ssh/ssh_config has no Include line, so ssh never reads /etc/ssh/ssh_config.d/50-rex.conf. Its OpenSSH 7.6 is too old for the SSH fallback. Don’t add an Include line for /etc/ssh/ssh_config.d on Ubuntu 18.04. It breaks ssh for every account on the machine.
Fedora
Fedora ships (R)?ex, the same unrelated tool, as Rex. Both packages own /usr/bin/rex, so remove it with sudo dnf remove Rex before you install Rex.
Amazon Linux 2
Amazon Linux 2 reached the end of its support on 2026-06-30, and its rpm and systemd are too old for the Rex package. So the install script installs only the rex binary there, into /usr/local/bin, as --tarball does, and prints a notice saying so. The Fedora tab doesn’t work on Amazon Linux 2, so use the install script. Amazon Linux 2023 uses the Rex repository, like Fedora.
There are no services and no login server. To start a personal server for your account, run:
rex server start
To update Rex, run the install script again. A server that’s already running keeps the old version until it stops.
If an earlier run of the script left /etc/yum.repos.d/rex.repo behind, the script removes it. Its OpenSSH 7.4 is too old for the SSH fallback, so rex terminfo setup installs only the terminfo entry.
Arch Linux
On Arch, installing a package also upgrades the system, because pacman doesn’t support partial upgrades. So the Arch Linux tab and the install script both run pacman -Syu. The script also passes --needed, so running it again with Rex up to date doesn’t reinstall Rex or restart its services.
Derivatives that set ID_LIKE=arch in /etc/os-release, such as Manjaro, EndeavourOS, CachyOS, and Garuda, install the same way. SteamOS doesn’t, because its root file system is read-only. Omarchy needs one change, which Omarchy covers.
The repository lists one version of Rex at a time, the newest on its channel. Older packages stay in the channel’s directory, so to go back to one, pass its URL to pacman -U:
sudo pacman -U https://pkgs.superlogical.com/rex/arch/snapshot/x86_64/rex-VERSION-1-x86_64.pkg.tar.zst
If you installed rex-bin from the AUR, remove it first with sudo pacman -R rex-bin. It conflicts with rex, so the install script stops until it’s gone. Unlike rex, removing rex-bin doesn’t stop or disable the Rex units, so stop and disable any you enabled first:
sudo systemctl disable --now rex.service rex.socket \
rex-login-server.service rex-login-server.socket
Omarchy
Omarchy upgrades the system only through omarchy update, and it cancels pacman -Syu with a “Woah partner” message. The install script handles this. On Omarchy, it installs Rex without upgrading anything else, and omarchy update keeps Rex up to date from then on.
To install by hand, run the Arch Linux tab without its last line, sudo pacman -Syu rex, then run:
omarchy update
sudo pacman -S --needed rex
omarchy refresh pacman and omarchy channel set replace /etc/pacman.conf, which removes the Rex repository. Rex stays installed but stops getting updates until you run the install script again.
Alpine
Alpine has no sudo by default, so run the commands on these pages as root. Alpine uses OpenRC instead of systemd. Where a page gives a systemctl command, use the OpenRC form:
| On systemd | On Alpine |
|---|---|
sudo systemctl enable --now rex.service |
rc-update add rex, then rc-service rex start |
sudo systemctl enable --now rex-login-server.service |
rc-update add rex-login-server, then rc-service rex-login-server start |
sudo systemctl reload rex-login-server.service |
rc-service rex-login-server reload |
sudo systemctl disable --now rex.service |
rc-service rex stop, then rc-update del rex |
sudo systemctl edit rex.service |
Set command_args in /etc/conf.d/rex |
journalctl -u rex.service -f |
tail -f /var/log/rex/server.log |
journalctl -u rex-login-server.service |
cat /var/log/rex-login-server.log |
sudo usermod --append --groups rex alice |
addgroup alice rex |
OpenRC has no socket activation, so rex.socket and rex-login-server.socket have no Alpine form. Use the services instead.
/etc/conf.d/rex is a shell script that OpenRC reads before the service’s own script, so a command_args set there replaces the server’s command line. Shared Server and Remote Access show what to put in it.
The services need OpenRC, which a full Alpine install has. Containers often don’t. To install it, run apk add openrc.
On musl, who and last don’t list Rex sessions, because musl keeps no utmp or wtmp. lastlog records logins as usual.
Nix and NixOS
Rex has a flake for each channel, at https://pkgs.superlogical.com/rex/nix/<channel>.tar.gz. It packages the release binary rather than building Rex from source, for x86-64 and ARM64 Linux. The Nix tab installs it into your profile. Older versions of Nix call nix profile add by its old name, nix profile install.
To try Rex without installing it:
nix run https://pkgs.superlogical.com/rex/nix/snapshot.tar.gz -- --help
The channel URL always serves the newest release on its channel, but flake.lock records the exact release, so a lock keeps working after newer releases come out. To move to the newest one, run nix flake update rex.
The NixOS Module
On NixOS, add the flake as an input and import rex.nixosModules.default. The module runs Rex as a systemd service in one of two modes, the same two the packages ship:
services.rex.enableruns one shared server as therexaccount, on/run/rex/server.sock. Members of therexgroup can connect.services.rex.loginServer.enableruns one root process that identifies each caller, maps them to an account, and runs a server per account as that account. It listens on/run/rex/login-server.sock.
They can’t both be on. Either mode also installs rex for every user, puts Rex’s terminal type where the service can find it, and adds the SSH fallback to /etc/ssh/ssh_config.
services.rex.socketActivation and services.rex.loginServer.socketActivation start the server the first time a client connects, through rex.socket or rex-login-server.socket, instead of at boot. Each needs its mode’s enable, and services.rex.socketActivation also needs a Unix socketPath. The module keeps the socket unit and the server’s command line in agreement. With tailscaleServe.enable, the socket unit holds the Serve socket too, so a request through Tailscale Serve also starts the server.
Unlike the packages’ services, the module’s services require their sockets, so stopping rex.socket alone stops the server too. Turning either option on or off restarts a running server at the next nixos-rebuild switch, which ends every session on a shared server.
A shared server that one person can use:
{
inputs.rex.url = "https://pkgs.superlogical.com/rex/nix/snapshot.tar.gz";
outputs = { nixpkgs, rex, ... }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [\
rex.nixosModules.default\\
{\
services.rex.enable = true;\
users.users.alice = {\
isNormalUser = true;\
extraGroups = [ "rex" ];\
};\
}\
];
};
};
}
A login server that lets Alice use her own account over Tailscale Serve. The module writes the accounts to /etc/rex/accounts.jsonc, but doesn’t create them:
{
services.tailscale.enable = true;
users.users.alice.isNormalUser = true;
services.rex.loginServer = {
enable = true;
accounts.alice.principals = [ "tailscale:alice@example.com" ];
tailscaleServe.enable = true;
};
}
The host must be logged in to Tailscale, with HTTPS enabled for the tailnet. Changes to the accounts reload the login server without ending sessions. Connections whose account is no longer allowed are closed.
The home-manager Module
The home-manager module sets up Rex for your own account. It works on any Linux with Nix and systemd, such as Fedora or Amazon Linux 2023, not only on NixOS. Add the flake as an input and import rex.homeManagerModules.default. It’s also exported as rex.homeModules.default, the name some setups expect.
A personal server that keeps running between sessions:
{
inputs.rex.url = "https://pkgs.superlogical.com/rex/nix/snapshot.tar.gz";
outputs = { home-manager, nixpkgs, rex, ... }: {
homeConfigurations.alice = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
modules = [\
rex.homeManagerModules.default\
{\
home.username = "alice";\
home.homeDirectory = "/home/alice";\
home.stateVersion = "26.05";\
\
programs.rex.enable = true;\
services.rex.enable = true;\
\
# home-manager writes ~/.ssh/config only when this is on, and\
# programs.rex adds the SSH fallback to it.\
programs.ssh.enable = true;\
}\
];
};\
};
}
The module has two parts:
| Option | Effect |
|---|---|
programs.rex.enable |
Installs rex, writes the xterm-rex terminfo entry to ~/.terminfo, and adds the SSH fallback to ~/.ssh/config. programs.rex.config writes ~/.config/rex/init.lua. |
services.rex.enable |
Runs a personal server as your account, in a systemd user service named rex. Also turns on programs.rex. |
The SSH fallback needs programs.ssh.enable = true. Without it, the module prints a warning, and you can run rex terminfo setup once instead. Running rex terminfo setup with the module in place is harmless. It sees the guard home-manager already includes and writes nothing to your ssh configuration, and rex terminfo status reports that guard as in effect.
Unlike rex terminfo setup, the module doesn’t check your OpenSSH version. On an ssh older than 7.8, set programs.rex.sshGuard = false, because the SSH fallback breaks every ssh command there.
The service uses the same socket as every rex command, so rex ls, rex server status, and rex server stop all reach it. systemd restarts it if it fails, but not after rex server stop. To start it again, run systemctl --user start rex. It returns once the server is accepting connections, so a rex command you run right after it works. Its log is in journalctl --user -u rex.
The service starts when you log in and stops when you log out, which ends every session. home-manager switch warns about this each time. To start it at boot and keep it running while you’re logged out, run this once:
loginctl enable-linger
For remote access, services.rex.tailscale.enable turns on built-in Tailscale. authKeyFile needs systemd 250 or later (Fedora 36, Amazon Linux 2023). The other options, such as extraListen, blockDirs, and maxSessions, are described in home-manager-module.nix, which comes with the flake.
On macOS, turn on only programs.rex. The Rex app runs the server, so services.rex stops the build with an error there.
The shared server and the login server need root, so home-manager can’t run them. Use the NixOS module, or the packages.