Runs Ghost via podman/oci-containers (nixpkgs has no native services.ghost module), reverse-proxied through nginx with ACME. Uses sqlite3 as the database, with an explicit connection filename and useNullAsDefault - the image defaults to MySQL on 127.0.0.1:3306 in production mode otherwise. Provisions /var/lib/ghost via tmpfiles since podman won't auto-create a missing bind-mount source. Wires the content directory into the existing encrypted backup flow and the pre-upgrade/post-upgrade healthcheck in auto-update.nix, matching the other services. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|---|---|---|
| modules | ||
| scripts | ||
| secrets | ||
| .gitignore | ||
| configuration.nix | ||
| disk-config.nix | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
nix-server
NixOS flake configuration for a single Contabo VPS (meuer.xyz) hosting a
handful of self-hosted services behind an nginx reverse proxy, deployed with
nixos-rebuild --target-host and secrets managed via
agenix.
Structure
.
├── flake.nix # entrypoint: nixosConfigurations.contabo-server
├── configuration.nix # host-wide base config (bootloader, SSH, ACME defaults, agenix identity)
├── disk-config.nix # disko partitioning/LVM layout
├── modules/ # one file per service, imported from flake.nix
├── scripts/ # deploy + operational helper scripts
└── secrets/ # agenix-encrypted secrets (*.age) and secrets.nix key registry
Each service lives in its own modules/*.nix file and is wired into the
system via the modules list in flake.nix. Services that need a public
hostname declare their own services.nginx.virtualHosts.<domain> block
with enableACME = true; forceSSL = true;, so TLS certs are issued
automatically per-domain by the ACME module configured in
configuration.nix.
Modules
nginx.nix— enables the shared nginx instance used as the reverse proxy for every other service, plus the Diffie-Hellman params it uses for TLS.postgres.nix— shared PostgreSQL instance. Services connect over the local Unix socket using peer authentication (the connecting system user must match the Postgres role name), so no DB passwords are needed. Runsservices.postgresqlBackup.vaultwarden.nix— Bitwarden-compatible password manager atvault.meuer.xyz. Signups disabled; SMTP + admin token supplied via thevaultwarden-env.agesecret.hedgedoc.nix— collaborative Markdown editor atpad.meuer.xyz.jitsi.nix— self-hosted video conferencing atjitsi.meuer.xyz.minecraft.nix— declarative Minecraft server on port43000.forgejo.nix— self-hosted git forge (the software Codeberg.org runs on) atgit.meuer.xyz. Uses Postgres via peer auth, LFS enabled, public registration disabled (admin accounts are created viascripts/forgejo-create-admin.sh), git-over-SSH on port2222(its own built-in SSH server, separate from the host's OpenSSH on port 22). Reuses thesmtp-passwordsecret declared inauto-update.nixfor outgoing mail.backup.nix— nightly-triggered oneshot service that GPG-encrypts apg_dumpof the Vaultwarden database (symmetric, passphrase frombackup-passphrase.age) and prunes backups older than 14 days.auto-update.nix—system.autoUpgradeat 03:00 daily, gated on a successful Vaultwarden backup first. After a successful upgrade+switch, a health-check service verifies core services came back up and emailsfelix@meuer.xyz(viasmtp-password.age) if any failed to restart.
Secrets
Secrets are encrypted with agenix and
committed as secrets/*.age. secrets/secrets.nix lists which public keys
(the server's own SSH host key, plus a local personal key for editing) each
secret is encrypted for:
vaultwarden-env.age— VaultwardenSMTP_PASSWORD/ADMIN_TOKENenv file.smtp-password.age— shared SMTP password, referenced byauto-update.nixandforgejo.nix.backup-passphrase.age— GPG passphrase for encrypted Vaultwarden backups.
Edit a secret with agenix -e <name>.age (run from secrets/, requires
your local SSH key to be one of the listed public keys). The server
decrypts secrets at activation time using its own SSH host key
(/etc/ssh/ssh_host_ed25519_key), configured via age.identityPaths in
configuration.nix.
Scripts
deploy.sh— rsyncs the repo to/etc/nixos-server-config/on the server and runsnixos-rebuild switch --target-hostagainst it.backup-vaultwarden.sh— one-off, on-demand GPG-encrypted Vaultwarden backup, downloaded to the local machine.forgejo-create-admin.sh— creates a Forgejo admin user via the Forgejo CLI on the server (registration is disabled, so this is the only way to provision accounts).post-upgrade-alert-email.tmpl— email template used by thepost-upgrade-healthcheckservice inauto-update.nix.
Deploying
./scripts/deploy.sh
This builds and switches the contabo-server flake output on the remote
host over SSH. Requires SSH access to root@meuer.xyz.