Three auditable shell scripts that provision and lock down a fresh Debian 13 box. No app. No telemetry. No lock-in. Built with privacy in mind — safe even for filming. Configuration is regenerated from the scripts on every run — nothing drifts between takes, nothing leaks on camera.
bash setup.sh --domain example.com --proxy-port 8000 vps-01
Runs from your machine. Verifies SSH reachability, waits for cloud-init to finish, forces public DNS resolvers, swaps apt sources to a configurable mirror, and uploads the other two scripts. Then runs them in order. Prints no addresses — the target is supplied by the operator and never echoed.
Runs on the VPS. Installs nginx, ufw, fail2ban,
unattended-upgrades, python3, git, curl, wget,
rsync, sqlite3. Generates an nginx security-headers
snippet, a placeholder site (static or reverse-proxy
to a port you specify), and a systemd unit template
you fill in later. Creates /var/www/acme
and carves /.well-known/acme-challenge/
out of the dotfile deny, so certificate issuance
works out of the box.
Runs on the VPS. SSH daemon hardening, ssh-audit cipher/KEX/MAC hardening, MOTD + LastLog suppression, fail2ban with an aggressive sshd jail and a recidive backstop, sysctl kernel hardening, BBR + fq network tuning, unattended-upgrades, and UFW rules.
A fresh Debian box is not a hardened box. These are the layers this tool adds — every one of them a heredoc you can read.
Every /etc/* file this tool writes is a
heredoc in one of the three scripts. Re-read the scripts,
you know exactly what's on the box. Re-run the tool, you
get the same result. Nothing accumulates, nothing drifts,
nothing fights the machine.
This is why re-running setup.sh on an
already-provisioned box is a no-op apart from package
upgrades, and why there's no state file to corrupt or
migrate.
The same discipline applies to what ends up on camera.
Every script carries a redact_ips() helper
and a top-of-file note: the target is supplied, the
address is never echoed. Between takes, nothing leaks —
not in the terminal, not in the logs, not in the frame.