Install rootless
Rootless runs Quasar under an ordinary account, quasar, reducing its host privileges.
Both engines are
experimental rootless: see Container engines.
For a rootful install, use the quick start instead.
What you need
Section titled “What you need”- Linux with systemd, and root once, for the steps below.
- Podman, or Docker with its rootless extras (
dockerd-rootless-setuptool.sh). setfacl(theaclpackage) for the device rules.- On SELinux (Fedora and its relatives):
semanageandrestorecon, frompolicycoreutils-python-utils. On an image-based system:sudo rpm-ostree install policycoreutils-python-utils, then reboot. - On NVIDIA: complete NVIDIA setup for rootless engines.
The examples keep homes in /var/lib/quasar/homes and templates beside them. Use a
directory of its own, never /home or another system tree.
Prepare the host, once, as root
Section titled “Prepare the host, once, as root”Run each step from an account with sudo. Every step is safe to repeat.
-
Create the
quasaraccount and turn on lingering, so its engine runs with nobody logged in and starts at boot:Terminal window sudo useradd --create-home --user-group --comment Quasar quasarsudo loginctl enable-linger quasar -
Check its subordinate ID ranges. The containers’ own users map into them.
Terminal window grep '^quasar:' /etc/subuid /etc/subgidMost distributions add both with
useradd. If either line is missing, add a 65536-wide range that no other line in that file uses, for example:Terminal window sudo usermod --add-subuids 524288-589823 --add-subgids 524288-589823 quasar -
Install the device rules from Device rules. They give the
quasargroup/dev/uinput, Quasar’s own virtual input devices and the GPU render nodes, and nothing else. -
Create the agent’s runtime directory, made again at every boot:
Terminal window echo 'd /run/quasar-agent 0750 quasar quasar -' | sudo tee /etc/tmpfiles.d/quasar.confsudo systemd-tmpfiles --create /etc/tmpfiles.d/quasar.conf -
Create the homes and templates roots, owned by
quasar:Terminal window sudo install -d -m 0750 -o quasar -g quasar /var/lib/quasar/homes /var/lib/quasar/templates -
SELinux only (Podman, or Docker with SELinux on): label those directories for containers. This changes labels only; SELinux stays enforcing.
Terminal window for d in /run/quasar-agent /var/lib/quasar/homes /var/lib/quasar/templates; dosudo semanage fcontext -a -t container_file_t "$d(/.*)?"sudo restorecon -R "$d"done -
Start the engine for
quasar.Podman, its API socket and the restart of Quasar’s containers at boot:
Terminal window sudo machinectl shell quasar@ /bin/sh -c \'systemctl --user enable --now podman.socket podman-restart.service'Docker, installed and started for
quasar:Terminal window sudo machinectl shell quasar@ /bin/sh -c \'dockerd-rootless-setuptool.sh install && systemctl --user enable --now docker' -
NVIDIA only: complete rootless NVIDIA setup, including CDI and any required SELinux policy.
-
Only for a port below 1024 (the defaults are 8080 and 8443): let unprivileged services bind from that port, here 443:
Terminal window echo 'net.ipv4.ip_unprivileged_port_start=443' | sudo tee /etc/sysctl.d/99-quasar-ports.confsudo sysctl -w net.ipv4.ip_unprivileged_port_start=443
For smoother streams, set the UDP send buffer.
Check it worked
Section titled “Check it worked”| Check | Expect |
|---|---|
grep '^quasar:' /etc/subuid /etc/subgid |
A line in each. |
ls /var/lib/systemd/linger/ |
quasar listed. |
ls -ld /run/quasar-agent /var/lib/quasar/homes /var/lib/quasar/templates |
All three owned by quasar. |
ls /etc/udev/rules.d/70-quasar.rules |
The file exists. |
ls -Zd /var/lib/quasar/homes (SELinux) |
container_file_t in the label. |
sudo machinectl shell quasar@ /bin/sh -c 'systemctl --user is-enabled podman.socket podman-restart.service' (Podman) |
enabled twice. |
The add-host command checks the same things, and names anything still missing.
Optional shortcut
Section titled “Optional shortcut”deploy/prepare-host.sh
does the steps above in one go (step 9 only with --unprivileged-port-start). It
also sets the UDP send buffer and loads uinput at boot. Read it before you run
it. --dry-run prints what it would change and changes nothing:
sudo sh prepare-host.sh --mode rootless --engine podman \ --homes /var/lib/quasar/homes --templates /var/lib/quasar/templates --dry-runConsole mode on a rootless host
Section titled “Console mode on a rootless host”A machine that shows a desktop on its own screen needs more access, because a rootless
engine passes no device rules: the quasar account must be able to open every device
the console desktop is given.
-
Install the console rules from Device rules: the display cards, sound devices, i2c buses, this machine’s input devices and
tty8, each by ACL. Or runprepare-host.shwith--console. On SELinux it also loads thequasar-console-devicesmodule, which lets the console session open those input, sound andhidrawnodes and read the udev database; without it the desktop starts with no keyboard, mouse or sound. SELinux stays enforcing. -
Keep login prompts off
tty8:Terminal window sudo systemctl mask getty@tty8.service autovt@tty8.service -
Free the display: no desktop or login screen may run on the output the console uses.
It worked when every console check on the host’s page passes once console mode is on (see Console mode). A device plugged in later works through the rules alone.
Install, as quasar
Section titled “Install, as quasar”Open a full session as the account (sudo -u quasar is not enough):
sudo machinectl shell quasar@-
Start the seed. Fill in
QUASAR_PUBLIC_HOST, the name or LAN address you type into the browser.Podman: write
~/.config/containers/systemd/quasar-seed.container:[Unit]Description=Quasar seedWants=network-online.targetRequires=podman.socketAfter=network-online.target podman.socket[Container]ContainerName=quasar-seedImage=ghcr.io/accreleus/quasar/quasar-recovery:latestPull=alwaysExec=seedSecurityLabelDisable=trueVolume=%t/podman/podman.sock:/var/run/docker.sockVolume=quasar-machine:/var/lib/quasar-machine:roEnvironment=QUASAR_ROLE="combined"Environment=QUASAR_PUBLIC_HOST="192.168.1.50"Environment=QUASAR_HOME_ROOT="/var/lib/quasar/homes"Environment=QUASAR_TEMPLATE_ROOT="/var/lib/quasar/templates"Environment=QUASAR_CONTROL_PLANE_IMAGE="ghcr.io/accreleus/quasar/quasar-control-plane:latest"Environment=QUASAR_AGENT_IMAGE="ghcr.io/accreleus/quasar/quasar-node-agent:latest"[Service]Restart=always[Install]WantedBy=default.targetTerminal window systemctl --user daemon-reloadsystemctl --user start quasar-seedDocker:
Terminal window docker run -d --name quasar-seed --restart unless-stopped --pull always \--security-opt label=disable \-v "${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/docker.sock:/var/run/docker.sock" \-v quasar-machine:/var/lib/quasar-machine:ro \-e QUASAR_ROLE=combined \-e QUASAR_PUBLIC_HOST=192.168.1.50 \-e QUASAR_HOME_ROOT=/var/lib/quasar/homes \-e QUASAR_TEMPLATE_ROOT=/var/lib/quasar/templates \-e QUASAR_CONTROL_PLANE_IMAGE=ghcr.io/accreleus/quasar/quasar-control-plane:latest \-e QUASAR_AGENT_IMAGE=ghcr.io/accreleus/quasar/quasar-node-agent:latest \ghcr.io/accreleus/quasar/quasar-recovery:latest seedOther inputs (control-only, your own Postgres, ports) are the same as on Docker.
-
Check it came up, then claim it with the one-time setup token (
dockerfor Docker):Terminal window podman exec quasar-recovery quasar-recovery statuscurl http://localhost:8080/healthpodman exec quasar-control-plane cat /run/quasar/setup-token/healthanswers{"status":"ok","db":"ok"}. Openhttps://<QUASAR_PUBLIC_HOST>:8443and continue with First run and checks.
Add a rootless GPU host
Section titled “Add a rootless GPU host”Prepare it as above, then run the Add host command
from a sudo machinectl shell quasar@ session. It never uses sudo.