Use
Security
What every guest is protected by, what iac verifies before it installs something – and what it trusts.
In every guest
| Login | root with an SSH key only: PasswordAuthentication no, PermitRootLogin prohibit-password. No admin user, no keys in images – the keys come with the deployment |
| Firewall | nftables, incoming policy drop (below) |
| Secrets | generated once per instance in /etc/iac/settings.env (0600) – never in a repository or an image |
| Sandbox | services of the apps run with ProtectSystem=strict, only their data writable, a syscall filter and no needless capabilities; the CI rejects a unit rated worse than 5.0 by systemd-analyze security. Exceptions (e.g. update, backup) are marked in the unit with a reason |
| Kernel | (VM) kernel addresses and dmesg only for root, ptrace only on own children, no BPF for users, no ICMP redirects or source routing; AppArmor active. Containers are unprivileged and take these from the host |
| Traceability | etckeeper commits /etc before and after every update; every run is logged in /var/log/iac/iac.log |
Firewall
- Incoming: established connections, loopback, ICMP, DHCP and SSH (port 22) are allowed; everything else is dropped.
- The app’s
portsand those of active modules are opened per port –publicfor everyone,privateonly from10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,fc00::/7andfe80::/10.172.16.0.0/12also contains Docker’s bridge networks: containers on the guest count as private. - Your own rules:
/etc/nftables.d/90-local.nft. Every file is checked withnft -cfirst; a broken file leaves the old rules active. - Web interfaces get TLS from a reverse proxy such as Traefik. Apps that are opened directly bring a self-signed certificate today – the internal CA WIP will replace it.
What iac verifies
| Source | Check |
|---|---|
| Debian packages | Debian’s signatures (apt) |
| Third-party APT repositories | only where an app needs one (Zammad, Elasticsearch), key pinned in iac-core |
| Downloads of apps (GitHub, Codeberg, …) | checksum of the release before anything is unpacked; no checksum, no download |
| npm packages | integrity hashes of the registry |
| App versions | most apps are pinned to a version the CI built and boot-tested; new releases are raised by pull request, majors wait for a review |
| VM images | built and booted in a test VM, smoke test green, then published with SHA256SUMS; vm.sh checks the checksum before the import |
What iac trusts
Be aware of this chain when you run iac:
- The one-liners (
ct.sh,vm.sh,adopt.sh) run as root on the Proxmox host and load iac-core fromgit.heyer.systems. Read them first if you like – they are short and only loadlib/host.func. updateloads iac-core (tagv2) and the app (branchmain) over HTTPS fromgit.heyer.systemsand runs them as root. Their integrity rests on TLS and on who may write to the organisationiac– there are no signatures yet. With auto-update a change reaches every guest within a day; without it, only when you runupdate.- Image checksums come from the same server as the images: they protect against broken downloads, not against a compromised server.
Work in progress – planned, not available yet
Planned: signatures in addition to the checksums, checked by update and vm.sh.
Modules for more
| Module | Use |
|---|---|
| auto-update | nightly update – Debian security updates and app updates without waiting for you |
| unattended-upgrades | Debian security updates only, daily – for guests without auto-update |
| backup | restic to SFTP, S3, a REST server or a path – the way back after a mistake or an attack |
| fail2ban | blocks addresses after failed SSH logins |
| crowdsec | detects attacks in the logs and blocks them with nftables, with the community blocklist |
For logins of apps behind a reverse proxy, fail2ban in the guest would only see the proxy: those apps (or the nginx in front of them) limit failed logins themselves.