docs: add architecture, hardening, and building documentation

Document the design and how to operate it: architecture, building
(including toolchain-free/minimal builds), hardening guide, editions,
observability, and the toolchain. README ties it together.
This commit is contained in:
Blake Ridgway
2026-08-21 13:15:43 -05:00
parent 33652064f9
commit 87fc370541
7 changed files with 474 additions and 0 deletions

83
docs/hardening.md Normal file
View File

@@ -0,0 +1,83 @@
# Hardening guide
Every edition ships the same hardening baseline (the `overlays/base` layer).
This page explains what each piece does and how to tune it. Everything is
documented *in* the config files too — read them, they are the source of truth.
## Kernel
- **Boot cmdline** (`editions/*/kernel.cmdline`) — applied to both the live ISO
and (via `configure-system.sh``/etc/default/grub`) any installed system:
- `init_on_alloc=1 init_on_free=1` — zero freshly allocated and freed memory
- `slab_nomerge` — prevent slab object merging
- `page_poison=1` — fill freed pages to catch use-after-free
- `pti=on` — kernel page-table isolation
- `spectre_v2=on spec_store_bypass=on tsx=off` — mitigations forced on
- `lockdown=integrity` — kernel refuses unsigned in-memory modification
- `oops=panic panic=-1` — halt (and stay down) on kernel oops
- **sysctl** (`overlays/base/etc/sysctl.d/10-arcline-hardening.conf`):
- memory: sane dirty ratios, no overcommit
- network: strict rp_filter, no ICMP redirects, syncookies, TCP hardening
- visibility: `dmesg_restrict=1`, `kptr_restrict=2`, `perf_event_paranoid=3`,
`ptrace_scope=1`, `unprivileged_bpf_disabled=1`
- filesystem: protected hardlinks/symlinks/fifos, `suid_dumpable=0`
- **Module blacklist** (`overlays/base/etc/modprobe.d/arcline-hardening.conf`):
- exotic network protocols (`sctp`, `dccp`, `rds`, `tipc`) and legacy
filesystems (`cramfs`, `hfs`, `hfsplus`, `jffs2`, `udf`, …).
> The **workstation** edition relaxes a few of these for developer ergonomics
> (`perf`, tracing, rootless containers) via
> `overlays/workstation/etc/sysctl.d/90-arcline-desktop.conf`.
## Firewall — nftables, default-deny
`overlays/base/etc/nftables.conf` ships a **drop-by-default** policy:
- allow: loopback, established/related, ICMP (for PMTU discovery)
- allow: `tcp/22` (ssh — key auth only)
- everything else inbound: **dropped**
- forward chain: **dropped** (container bridges manage their own rules)
Open a port by editing the file and `systemctl reload nftables`, e.g.:
```
sudo nft add rule inet filter input tcp dport 443 accept
```
You opt in to exposure; nothing is open unless you say so.
## ssh
`overlays/base/etc/ssh/sshd_config.d/10-arcline-hardening.conf`:
- `PermitRootLogin prohibit-password` — root only via key
- `PasswordAuthentication no` — keys only (this is the secure default; change
deliberately)
- `MaxAuthTries 3`, `LoginGraceTime 30`, `ClientAliveInterval 300`
- no `X11Forwarding`, `UseDNS no`
## Logging
`journald.conf.d/10-arcline.conf` — persistent, bounded (500M), compressed,
14-day retention. Logs live on the `@log` subvolume so they survive rollbacks.
## AppArmor
Arcline uses Debian's AppArmor profiles (loaded at boot) plus the kernel
hardening above. Extra profiles can be dropped into
`/etc/apparmor.d/local/` — the enforcement is on by default.
## systemd hardening
`system.conf.d/10-arcline.conf` — no core dumps on disk, sane default limits
(`NOFILE=65535`, `NPROC=4096`).
## Verifying a build
```
tests/smoke/verify-rootfs.sh build/rootfs/server
```
The smoke test asserts the guarantees above (kptr_restrict, policy drop, ssh
keys-only, no telemetry, no snapd, btrfs tooling present). The build fails if
any are missing.