feat(deploy): host hardening on the frontend server (FH-D.3)
server-setup.sh configured ufw and stopped there, which leaves SSH open
to unlimited password guessing and the kernel on defaults that are wrong
for an internet-facing host.
Adds three drop-in files, so a re-run replaces its own config and never
edits a distro file in place:
/etc/ssh/sshd_config.d/10-marketplaces-hardening.conf
password and keyboard-interactive auth off, root key-only,
no agent/X11 forwarding, MaxAuthTries 3, 30s login grace
/etc/fail2ban/jail.d/marketplaces.local
sshd, nginx-http-auth, nginx-bad-request; 5 in 10m, 1h ban
/etc/sysctl.d/99-marketplaces-hardening.conf
no redirects or source routing, rp_filter, SYN cookies,
forwarding off, restricted kernel pointers and dmesg
Both accounts on the host are key-only by construction - the deploy user
is created with no password at all - so disabling password auth cannot
lock anyone out. It only closes guessing against a credential nobody
intended to exist.
The sshd block runs `sshd -t` first and removes its own drop-in if the
test fails. A bad sshd config that takes effect on a remote box is how
people lock themselves out permanently.
DEPLOYMENT.md §3.2 documents all three plus the post-provision checks.
Not copied from the reference implementation: its hardcoded server IP.
Kept as-is because ours is already better: add-domain.sh pre-checks the
DNS A record and runs nginx -t before and after.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -64,6 +64,28 @@ password, writes the catch-all nginx config, opens 80/443/OpenSSH in ufw, and
|
||||
installs a root-owned, argument-validating API-domain helper. The deploy user may
|
||||
run that helper and reload nginx, but cannot replace the helper.
|
||||
|
||||
It also applies host hardening (added 2026-08-21, FH-D.3) — three drop-in files,
|
||||
so a re-run replaces its own config and never edits a distro file in place:
|
||||
|
||||
| File | Effect |
|
||||
|---|---|
|
||||
| `/etc/ssh/sshd_config.d/10-marketplaces-hardening.conf` | Password and keyboard-interactive auth off, root key-only, no agent/X11 forwarding, `MaxAuthTries 3`, 30 s login grace |
|
||||
| `/etc/fail2ban/jail.d/marketplaces.local` | `sshd`, `nginx-http-auth`, `nginx-bad-request` jails — 5 failures in 10 min, 1 h ban |
|
||||
| `/etc/sysctl.d/99-marketplaces-hardening.conf` | No redirects or source routing, reverse-path filtering, SYN cookies, forwarding off, restricted kernel pointers and dmesg |
|
||||
|
||||
Both accounts on this host are key-only by construction, so disabling password
|
||||
auth cannot lock anyone out — it only closes unlimited guessing against a
|
||||
credential nobody intended to exist. The script runs `sshd -t` before reloading
|
||||
and removes its own drop-in if the test fails, because a bad sshd config taking
|
||||
effect on a remote box is how people lock themselves out permanently.
|
||||
|
||||
Confirm after provisioning:
|
||||
|
||||
```bash
|
||||
sudo fail2ban-client status sshd
|
||||
sudo sshd -T | grep -E 'passwordauthentication|permitrootlogin|maxauthtries'
|
||||
```
|
||||
|
||||
Verify before continuing:
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user