~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
80 lines · 7.1 KB Raw History
# The Linux host contract

A Linux host that runs `socialweb-computer install gateway` or `socialweb-computer install bidder`
must satisfy every check in the table below. `socialweb-computer check-host` probes the host as the
installed account and prints each check with its fix. `install` runs the same probe as the account
after it creates the account, and install fails when a check fails.

## Run the check

Run `check-host` as the account that runs the host's components (gateway: `socialweb`, bidder:
`swc-bidder`). Do not run it as root: the `account` check fails when the effective user is root.

```
socialweb-computer check-host -role gateway -state-dir <state>
socialweb-computer check-host -role bidder -state-dir <state>
```

`<state>` is the account's state dir. `install` writes it into the account's config; `check-host`
reads `-state-dir`, or the `SOCIALWEB_STATE_DIR` environment variable when `-state-dir` is not
passed.

| Option | Required | Default | Meaning |
| --- | --- | --- | --- |
| `-role` | yes | none | `gateway` or `bidder`; selects the check set |
| `-state-dir` | yes | `SOCIALWEB_STATE_DIR` | the account's state dir, for the probe output and the POSIX ACL check |
| `-asset-cache` | no | `<state-dir>/runtime` | the asset extraction root |
| `-pasta` | no | none | the pasta executable for a dev build; a release build extracts the embedded one |
| `-json` | no | off | print the results as JSON |

The command prints one line per check, in table order. The status is `OK`, `FAIL` or `INFO`. A `FAIL`
line is followed by a `fix:` line.

```
OK    account                      socialweb (uid 1000)
FAIL  dev-kvm                      /dev/kvm does not exist
                                   fix: enable hardware virtualization and load kvm_intel or kvm_amd (root); never chmod /dev/kvm
```

The command succeeds when no check has status `FAIL`: every line is `OK` or `INFO` and the exit code
is 0. On a failure it names the failed checks on stderr as
`check-host: the <role> host contract is not met: <names>`.

| Exit code | Meaning |
| --- | --- |
| 0 | The contract holds. No check failed. |
| 1 | One or more checks failed. The names go to stderr. |
| 2 | Usage error: a missing or unknown `-role`, a missing `-state-dir`, or an unknown flag. |

Pass `-json` to print the results as a JSON array. Each element is an object with `name`, `status`
(`ok`, `fail` or `info`), `detail`, and `fix` (present only on a failed check).

## Checks

`Applies to` is `both` for the gateway and the bidder. The rows are in the order the report prints.

| Check | Applies to | Passes when | If it fails |
| --- | --- | --- | --- |
| account | both | The command runs as the host account, not as root | Run `check-host` as the account; `install` runs it as the account after it creates the account |
| systemd-version | both | The account's user manager answers on its private socket and reports systemd 253 or newer (GetUnitByPIDFD) | Upgrade the host to a distribution that ships systemd 253 or newer, and enable linger so the user manager runs |
| probe-unit-properties | both | A transient `socialweb-probe-<rand>.service` starts with every property the runtime sets (MemoryMax, MemorySwapMax=0, OOMPolicy, TasksMax, CPUQuota, CPUWeight, CollectMode, After, Wants, Slice, KillSignal, TimeoutStopSec, StandardOutput=append:, plus FileDescriptorStoreMax for the gateway) and the user manager reads every one back | Use a host whose systemd (253 or newer) keeps every property the runtime sets |
| cgroup-v2 | both | `/sys/fs/cgroup` is the cgroup v2 unified hierarchy | Boot the kernel with `systemd.unified_cgroup_hierarchy=1` (the default on current distributions) |
| user-manager-delegation | both | `user@<uid>.service` `cgroup.controllers` include `cpu`, `memory` and `pids` | Run `install`, which writes the `Delegate=cpu memory pids` drop-in; then restart `user@<uid>` or reboot the host |
| linger | both | `/var/lib/systemd/linger/<account>` exists | Run `install`, which enables linger once the account, its groups and the delegation drop-in are in place |
| runtime-dir-socket-length | both | `XDG_RUNTIME_DIR` plus the longest runtime socket path is under 108 bytes | Use the default `/run/user/<uid>` runtime directory |
| boot-id | both | `/proc/sys/kernel/random/boot_id` is readable | Mount `/proc` normally; reboot detection reads `boot_id` |
| dev-kvm | bidder | `/dev/kvm` opens read-write as the account | Enable hardware virtualization and load `kvm_intel` or `kvm_amd` as root; run `install bidder`, which adds the account to the `kvm` group; never chmod `/dev/kvm` |
| user-manager-kvm-group | bidder | The groups of `user@<uid>`'s process include `kvm` | Restart `user@<uid>` (this stops every VM) or reboot the host; logging in again does not refresh a lingering user manager |
| dev-net-tun | bidder | `/dev/net/tun` opens read-write | Load the tun module as root: `modprobe tun` |
| pasta-userns | bidder | The embedded pasta creates a user and network namespace and execs through `/bin/sh` | On Ubuntu 24.04 and newer run `install bidder`, which loads the AppArmor profile; otherwise allow unprivileged user namespaces through the `kernel.unprivileged_userns_clone` and `user.max_user_namespaces` sysctls |
| apparmor-pasta-profile | bidder | AppArmor does not restrict unprivileged user namespaces, or the `socialweb-pasta` profile is loaded | Run `install bidder`, which writes `/etc/apparmor.d/socialweb-pasta` and loads it with `apparmor_parser -r` |
| subuid-subgid-range | bidder | Exactly one range of 65536 ids or more for the account in both `/etc/subuid` and `/etc/subgid`, overlapping no other entry of either file | Run `install bidder`, which reserves one contiguous range above every existing entry; remove the other tool's overlapping entry |
| newuidmap-newgidmap | bidder | The distribution's `newuidmap` and `newgidmap` are setuid root or carry file capabilities | Install the distribution's uidmap (Debian/Ubuntu) or shadow-utils (Fedora/RHEL) package as root; never ship a setuid helper |
| newuidmap-first-vm-range | bidder | A throwaway user namespace maps 0-65535 onto the account's first VM sub-range through `newuidmap` and `newgidmap` | Fix the `subuid-subgid-range` and `newuidmap-newgidmap` checks first |
| state-dir-posix-acl | bidder | The state dir's filesystem supports POSIX ACLs | Put the state dir on a filesystem mounted with ACL support (ext4, xfs and btrfs support ACLs by default) |
| systemd-oomd | both | Reported only; reports whether systemd-oomd is active and never fails | No action; every unit runs below `socialweb.slice`, outside the `app.slice` systemd-oomd watches |
| user-manager-fd-store | gateway | `FileDescriptorStoreMax` reads back from a transient service | Use a systemd whose user manager keeps an fd store for transient services; the kcp front restarts without a refused-connection window only with it |
| k3s-slot-hostname | gateway | Reported only; never fails, and the check is not probed yet | No action |
| tzdata | gateway | `/usr/share/zoneinfo/UTC` exists (the embedded postgres uses the system tzdata path) | Install the distribution's tzdata package as root |

`socialweb-computer dev check` reports the development host subset; it changes nothing on the host.