Install on a server
Quick install
Section titled “Quick install”On a Linux server with systemd:
curl -fsSL https://hotline.dev/install | sh -s -- --serverIt downloads the server build for your architecture, checks it against the
release’s checksums, installs hotline to /usr/local/bin, creates the
hotline account and the unit below, and starts the desk. It asks for the
listen address and public URL, or takes them as
--listen and --public-url. Once the desk is up it shows a pairing QR, so
keep your phone handy.
The installer detects an existing install and reports its version and the
available version. It asks before updating when a terminal is attached;
--yes skips that question, as does running without a terminal. An install
already at the requested version is left alone unless you pass --force.
Pass --listen and --public-url again to change them (add --force when
keeping the same version); if the desk won’t start with the new values,
the previous unit goes back.
Update a server
Section titled “Update a server”For a server installed at /usr/local/bin/hotline with the hotline systemd
unit:
hotline update --check # report the installed and available versionssudo /usr/local/bin/hotline update # install the latest server releaseTo choose a particular release, including an intentional downgrade:
sudo /usr/local/bin/hotline update --version X.Y.ZThe updater downloads the server archive for your architecture, verifies its
SHA-256 checksum, and replaces only the binary with an atomic rename. The
room, pairings and systemd unit stay untouched. If the unit is running, it
restarts and the updater checks that the desk comes back; a failed start
restores the previous binary and tries to restart it. A stopped unit stays
stopped. Without root, the command prints the exact sudo command to run;
--check never needs root and never changes the install.
Rollback restores the executable, not room-data changes a newer release may
have made. Keep an encrypted backup of the room, taken with the service stopped,
before upgrading or downgrading. If recovery also fails, the updater preserves
the old binary and prints its backup path; inspect journalctl -u hotline
before recovering manually.
This command is only for the Linux server binary. Desktop installs use the
app’s updater or their package manager; hotline update does not overwrite
.deb, .rpm, AppImage, macOS app or Windows setup installations.
Older releases, including 0.26.0, do not have hotline update. For that first
upgrade, rerun the installer once:
curl -fsSL https://hotline.dev/install | sh -s -- --serverIt keeps the existing room, pairings and unit. Use hotline update after that.
An older binary without --version may be reported as unknown when its
running desk’s version is not readable; the installer still offers the upgrade.
Manual install
Section titled “Manual install”The rest of this page is the same install done by hand.
Get the binary
Section titled “Get the binary”Each release from
0.26.0 carries hotline-server_<version>_linux_x86_64.tar.gz and
hotline-server_<version>_linux_aarch64.tar.gz, each with the hotline
binary and a systemd unit. To build it yourself instead:
cargo build --release -p hotline-cli # target/release/hotlineInstall it as a service
Section titled “Install it as a service”tar xzf hotline-server_*_linux_x86_64.tar.gzsudo install -m 0755 hotline-server_*/hotline /usr/local/bin/hotlinesudo useradd --system --create-home --home-dir /var/lib/hotline --shell /usr/sbin/nologin hotlinesudo install -m 0644 hotline-server_*/hotline.service /etc/systemd/system/hotline.servicesudo systemctl edit --full hotline # set --listen and --public-url, belowsudo systemctl daemon-reloadsudo systemctl enable --now hotlineThe unit runs as the hotline account with the room at
/var/lib/hotline/room. It sets HOME, PATH and HOTLINE_DATA_DIR
itself and reads no login shell, so add to its PATH what your teammates
need: a Node install for harnesses run through npx, for example.
Listen address and TLS
Section titled “Listen address and TLS”--listen and --public-url are both required.
hotline serve --store file --listen 192.0.2.10:9443 --public-url https://desk.example:9443--listenis exactly one local IP and a fixed port. Wildcards (0.0.0.0), port zero and falling back to another address are refused. IPv6 goes in brackets:--listen '[2001:db8::10]:9443'. If the address isn’t up yet at boot, the desk waits for it.--public-urlis where the phone connects: anhttps://address with a DNS name or IP, or a TLS proxy in front of the desk. It goes into the pairing QR. Don’t put credentials or a query in it.- TLS is self-signed unless you pass
--tls-cert fullchain.pem --tls-key key.pem, which the service account must be able to read.--tls selfsays the default out loud. The phone trusts the server’s key, not its certificate, so rotating certificates never breaks a pairing. --store filekeeps secrets as owner-only files under the room. Encrypt the disk, and its snapshots and backups.nativeuses the OS credential store, which a server usually doesn’t have.
Open the port in your firewall for the phones that will connect, and nothing else. Only a phone holding a pairing gets past the handshake; to anything else the port offers nothing but TLS and a closed door.
Check it’s running
Section titled “Check it’s running”sudo -u hotline HOTLINE_DATA_DIR=/var/lib/hotline/room hotline statusA fresh room says No teammate can run yet: connect a model provider. That is expected: pair your phone, then connect a model.