A hardened install, end to end¶
The pages in this section are organised by topic, which is the right shape for looking something up and the wrong shape for doing an install for the first time. This page is the other axis: the order, on a hardened systemd host with no container, and the handful of places where doing the right thing at the wrong moment is the same as not doing it.
It repeats no commands. Each phase says what it is for, what has to be true before it, and which page holds the instructions. Where a phase carries a trap, the trap is here, because it lives in the sequence rather than in any one page.
Decide three things first¶
They change later phases, and discovering them late usually means starting over.
How each surface is reached. The internal surface goes on the consultancy's VPN or restricted network, the portal goes to the client. That decides two hostnames, two certificates, and whether either name resolves publicly. See TLS and reverse proxy.
Whether the data volume is encrypted. If it is, it changes the order of two later phases, and the unlock method decides whether the host can boot unattended. See Host hardening.
New install or migration. A migration carries a master key that already exists, and the moment it is put in place is the one thing that cannot be corrected afterwards. See Moving to another host.
1. The host¶
Platform, packages, and the Python the sidecar needs. Prerequisites and platforms.
2. The identities¶
Four of them: peart, peart-portal, peart-render, and the group peart-work, which owns no user.
The users and groups.
They come before anything is created on disk, because the directory tree is created owned by them and
install -d cannot name a user that does not exist yet.
peart is also a member of peart-portal. Both surfaces open the same database, and the -wal and
-shm files beside it are created by whichever opens first, landing in the directory's group. Without
that membership the install works until the first reboot that happens to start the portal first.
3. The binaries and the sidecar¶
Direct install for peart and peart-portal, then the rendering
sidecar, which is Python in a virtual
environment of its own rather than a third binary.
4. The encrypted volume, if there is one¶
Before the directory tree, not after. A tree created while the mount point is still an empty directory on the root filesystem disappears under the volume the moment it mounts, and the symptom is data that was there a minute ago. Host hardening covers unlocking over the network and what it costs; If the data directory is on a separate volume covers what the units do about it.
5. The directory tree and the configuration¶
Ownership and modes, then the configuration file itself.
/etc/peart is writable by peart on purpose: on a new install PEART creates the master key there on
first boot, and a directory the service can only read makes that first boot fail.
6. On a migration only: the master key¶
After the volume is mounted, and before the first boot. Moving to another host has both halves and the reason each one bites: a key written before the mount lands on the root filesystem and vanishes; a first boot with no key generates a new one, and from then on the evidence and the backups you brought cannot be read at all.
7. The secrets¶
Out of config.yaml and into the environment files, which systemd reads as root. What goes in each
environment file.
8. The units¶
Running as a service. Enable the sidecar's socket, not its service: the sidecar runs with no network of its own and is reachable only because the socket unit opens the port in the host's namespace and hands the descriptor over. Enabling the service instead produces a sidecar that starts, looks healthy, and cannot be reached.
9. First boot, then the database file¶
Start the services, run the migration, and only then set the database file's owner and mode: it is created with the process umask, and the portal needs to write it. The database file itself.
The -wal and -shm files take their mode from the database, so fixing the database is the whole fix
and fixing the companions is not.
10. TLS, one terminator per surface¶
TLS and reverse proxy. tls: true in the configuration is what makes session cookies Secure
and sends HSTS; no forwarded header is read, so a proxy terminating TLS with tls: false behind it is a
silent downgrade.
11. Verify, and know what each check proved¶
What each end-to-end check proves. Run all four: they fail for different reasons, and passing one says nothing about the others. If something fails in a way that smells like the sandbox, When a hardening directive is the cause is indexed by the log line.
12. Export the key, and prove the backup¶
Data directory and backups. The master key is not in the backup, by design, so a backup without a separately stored key restores nothing readable. Do this before the first real engagement, not after.
What you should not have had to do¶
Nothing in this sequence asks you to relax a systemd directive. If you find yourself writing a drop-in to make something work, that is a defect worth reporting rather than a workaround worth keeping, and Host hardening states the posture the product is supported under.