Hub service installation
The initial production target is a supported Linux host with systemd,
PostgreSQL, Node.js 20 or newer, pg_isready, runuser, setpriv, bubblewrap,
socat and cph. The Hub runs as the dedicated non-login cph-hub user; do not
create or run the unit as root.
Build or deploy the Hub under /srv/curriculum-project-hub, then run:
sudo BASE=/srv/curriculum-project-hub \
HUB_DIR=/srv/curriculum-project-hub/hub \
bash /srv/curriculum-project-hub/hub/deploy/install_service.sh
On a clean host the first invocation creates
/srv/curriculum-project-hub/.secrets/platform.env with every supported
production key and exits with status 78. Fill every required blank, set
CPH_BIN to an executable compatible cph, keep the file mode at 0600, and
run the same command again. No systemd unit is installed until configuration,
paths, Node, bubblewrap, socat, cph --version, PostgreSQL connectivity and directory
ownership all pass preflight.
An existing service account is accepted only when its primary group, home and
non-login shell match the requested configuration and it has no supplementary
groups. After provisioning, the installer executes path-access, built Hub,
Prisma, an authenticated database query, cph, socat and bubblewrap namespace probes
as that account with no_new_privs set. Inaccessible parents, UID-specific
database/network policy, or a host that forbids unprivileged user namespaces
therefore fail before unit installation.
The default persistent layout is deliberately outside every source/release tree:
/var/lib/cph-hub/home
/var/lib/cph-hub/state
/var/lib/cph-hub/workspaces
/var/cache/cph-hub
Custom paths are supported with SERVICE_HOME, STATE_DIR, CACHE_DIR and
WORKSPACE_ROOT, but all must be absolute. The installer rejects any persistent
path that is equal to, above, or below BASE; this keeps rsync, release
switching, rollback and pruning unable to traverse customer workspaces. Set the
same custom workspace in HUB_PROJECT_WORKSPACE_ROOT inside platform.env.
After a successful installation:
sudo systemctl start cph-hub.service
sudo systemctl status cph-hub.service
HOST and PORT in platform.env are passed to the real HTTP listener. The
default 127.0.0.1:8788 expects a local TLS reverse proxy; the public OAuth URL
must be an HTTPS HUB_PUBLIC_BASE_URL.