Skip to main content

Set Up a Linux Host

Run Daintree as a host on Linux, including headless servers and cloud VMs: packages, the systemd user service Daintree installs, linger, setting it up by hand, everyday commands, updating, the desktop restart prompt and the limits.

Updated
Reviewed

What You Need

The normal Daintree Linux package is the host. There is no separate server build and no desktop is needed: on a machine with no display, Daintree in Host mode runs headless by itself, with no Xvfb or virtual display. A small cloud VM, a home server and a Linux workstation all work the same way.

  • x64. There is no arm64 Linux build yet.
  • An ssh server (openssh-server) that accepts your key with no prompt.
  • A normal user account, not root. Host mode runs as the person whose projects, agent sign-ins and Git keys it uses, and Chromium won't run as root anyway. On a fresh cloud VM that logs in as root, create a user, copy your key to it and add that user as the host.
  • systemd with working user services (systemctl --user), which setup and start at login rely on. Daintree runs as a systemd user service.
  • Optional: avahi-utils, so the host can advertise itself on your local network and a Linux client can discover hosts there. Without it, Tailscale discovery still works, or enter the SSH target by hand.

The Quick Way

  1. Make sure ssh you@server 'echo ok' works from the machine you work on.
  2. On that machine, open Settings → Hosts → Add host, enter you@server and Check host.
  3. Plan install shows the plan for the AppImage, the default, and Install on host installs it without root. Or install the .deb on the server yourself first (below) and Check again.
  4. Turn on Host mode. Daintree writes and enables its user service, starts it if Daintree isn't already running there, turns Host mode on with start at login, and asks the server to keep the service running when nobody is logged in.
  5. Add host.

From then on the server serves Daintree, and with linger on it does so after a reboot with nobody logged in. Setup usually takes seconds once the package is there, and longer for an AppImage that runs unpacked. If the service keeps exiting as it starts, setup stops waiting after two restarts and quotes the first error it finds in the service's journal.

AppImage or .deb

AppImage.deb
RootNot neededNeeded to install (sudo apt install)
Location~/Applications/Daintree.AppImage/opt/Daintree, with /usr/bin/daintree
Installed from the Add host dialogYes, the defaultNo: install it on the server yourself
Distributionsx64 distributions with glibc and the usual desktop librariesDebian, Ubuntu and derivatives
NotesWithout FUSE (libfuse2) it runs unpacked each time it starts, which is slower to startPreferred by setup when both are present

Both are on the download page and the Daintree release feed. To install the .deb on the server:

curl -LO https://updates.daintree.org/releases/daintree_0.44.0_amd64.deb
sudo apt install ./daintree_0.44.0_amd64.deb

Installing the package starts nothing. Daintree runs as a host only once Host mode is turned on. A server already on the .deb stays on it: the dialog won't switch it to the AppImage, and you update the .deb there yourself. Daintree checks whether the server has FUSE (libfuse2), which Ubuntu 22.04 and later don't install by default; without it, setup configures the AppImage to run unpacked.

Headless Servers

On a server with no display, Host mode runs Chromium headless with the GPU off, and answers native dialogs with their cancel choice, rather than crashing on a dialog it can't show. Chromium picks its display backend before Daintree's own code runs, so a headless launch has to say so on its command line: --ozone-platform=headless. The service Daintree installs always passes it, display or not, because a service that outlives your login shouldn't depend on an X server that goes away with it.

The one thing a headless server usually lacks is a usable keyring, so plugins can't store secrets there: Plugin secrets unavailable on this host: no keyring (headless). Projects, terminals and agents work as usual. Use environment variables or a CLI's own login on the server for anything that needs a secret.

The Service Daintree Installs

Turn on Host mode in the Add host dialog writes a systemd user unit at ~/.config/systemd/user/daintree-host.service, enables it, and starts it if Daintree isn't already running there. Turning on Start at login in Settings on the machine itself writes and enables the same unit. For the .deb it reads:

[Unit]
Description=Daintree host (serves Daintree windows on other machines over SSH)

[Service]
Type=simple
ExecStart="/opt/Daintree/daintree" "--host-mode" "--ozone-platform=headless"
Environment=XDG_RUNTIME_DIR=/run/user/%U
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%U/bus
Restart=on-failure
RestartSec=10
KillMode=mixed
TimeoutStopSec=30

[Install]
WantedBy=default.target
  • For an AppImage, ExecStart names the AppImage instead. Without FUSE it also sets APPIMAGE_EXTRACT_AND_RUN=1 and adds an ExecStop that asks Daintree itself to quit, because the AppImage's runtime is then the service's main process.
  • KillMode=mixed sends the stop signal to the service's main process alone, which for the .deb is Daintree, so it closes its own helper processes cleanly instead of all of them being killed at once. For an AppImage running unpacked, the added ExecStop asks Daintree to quit first.
  • After an update, a host started by its own unit rewrites the unit if this build would write it differently. Settings on the host shows whether the unit on disk matches.

The socket lives at /run/user/<uid>/daintree/host.sock, beside host.json and host-mode.json, readable only by your user.

Linger

Normally systemd starts your personal service manager when you log in and stops it, with everything it runs, when your last session ends. Linger is a setting on your user account that starts that service manager at boot and keeps it running with nobody logged in. It is what lets a Linux host serve after a reboot or after you log out. Linger keeps your services alive; the unit file says that Daintree is one of them.

Setup runs loginctl enable-linger for you, without sudo. Many distributions let a user turn it on for themselves. If the server refuses, the Advise step shows the refusal and the service only runs while you are logged in. Ask someone with sudo to run, once:

sudo loginctl enable-linger you

The host's own Settings shows whether linger is on in its Start at login row: linger is on, so it starts at boot or linger is off, so it starts only once you log in.

Set It Up by Hand

Everything setup does can be done in a terminal on the server, which helps if you manage machines with your own tooling. On a .deb install:

# 1. Install the package (nothing runs yet)
sudo apt install ./daintree_0.44.0_amd64.deb

# 2. Let your services run with nobody logged in
sudo loginctl enable-linger $USER

# 3. Write the unit shown above to ~/.config/systemd/user/daintree-host.service

# 4. Load it, start it now, and start it at every boot
systemctl --user daemon-reload
systemctl --user enable --now daintree-host.service

# 5. Record Host mode as switched on, with start at login
/opt/Daintree/daintree --host-mode --enable-host-mode --host-mode-handoff

# 6. Check: host.sock and host.json appear while it listens
ls /run/user/$(id -u)/daintree/

Step 5 hands the request to the running service, which saves Host mode as on. Use the unit text exactly as shown: Daintree compares the unit on disk with the one it would write, and Settings flags one that differs. To try Host mode without a service, run /opt/Daintree/daintree --host-mode --ozone-platform=headless in a terminal; it serves until you stop it.

Day to Day

Everyday Commands

systemctl --user status daintree-host      # is it running?
journalctl --user -u daintree-host -f      # its log, live
journalctl --user -u daintree-host -e      # the end of its log
systemctl --user restart daintree-host     # restart, e.g. after installing a new .deb
ls /run/user/$(id -u)/daintree/            # host.sock exists while it listens
Note
systemctl --user stop daintree-host stops the host, but a client still trying to connect may start the service again, because the host is set up to serve. To take a server out of service, remove it from the host list on the machines that use it, or disable the service and delete its unit file: systemctl --user disable --now daintree-host, then remove ~/.config/systemd/user/daintree-host.service.

Updating a Linux Host

  • AppImage: use Check for update on the host's page in Settings → Hosts, or Update studio-01 when Daintree offers it. Daintree replaces the AppImage in use and restarts the service, waiting for idle agents if you ask it to.
  • .deb: install the new package on the server, then restart the service:
sudo apt install ./daintree_0.44.1_amd64.deb
systemctl --user restart daintree-host

Restarting ends the host's terminals, as quitting Daintree would. Windows on other machines show the outage and reconnect on their own.

Opening Daintree on the Host's Desktop

On a Linux desktop, the service always runs headless, and with linger on it starts at boot, before the graphical session. Opening Daintree from the desktop's app menu then asks:

Restart Daintree with a window? Daintree is already running on this machine in Host mode, with no window, for other machines to use. Restarting it closes the terminals and agents running in it, including any another machine is using.

Restart with a window stops the service and relaunches Daintree with a window. Host mode stays on and is served by the windowed Daintree, and other machines reconnect to it. Cancel leaves the headless host running untouched. Quitting the windowed Daintree stops serving until the service starts it again, at the next boot or when a client needs it.

Limits

  • x64 only. The probe recognizes arm64, but there is no arm64 package to install.
  • Usually no keyring on a headless server, so no plugin secrets there.
  • Packaged installs only. Setup recognizes /opt/Daintree, AppImages in ~/Applications, and the AppImage the Host mode service or a running Daintree names. A build run from source isn't recognized as a host.
  • One AppImage at a time. With several Daintree AppImages in ~/Applications and nothing naming the one in use, setup asks you to keep only one.
  • One user, one host. Each user account on a server runs its own Daintree, socket and settings. Whoever can ssh in as that user can use it.