Archived
Stage 1 base config/hardening toolset, applied and verified on pve1
Splits the repo into Stage 1 (base host config/hardening, applies to any node) and Stage 2 (future HA/Ceph cluster, deferred - pve1's mini-PC hardware can't support the assumed split-disk/multi-NIC layout). Adds the Stage 1 toolset: firewall deploy, named admin user creation, unattended security upgrades, subscription-nag removal (with an apt hook so the patch survives package updates), and a read-only audit script. Fixes switch-to-no-subscription-repo.sh, which only handled the legacy .list format and silently no-op'd against PVE 9's deb822 .sources files; it now removes enterprise sources outright rather than commenting them out. Shared logic (root check, idempotent file writes, backups) factored into scripts/lib/common.sh. Ran the full sequence against pve1 via scripts/bootstrap.sh + create-admin-user.sh; scripts/audit.sh confirms all checks pass.
This commit is contained in:
@@ -1,14 +1,33 @@
|
||||
# Security Hardening
|
||||
|
||||
Proxmox has no `sudo` out of the box — everything defaults to root. That's
|
||||
the install default, not the recommended end state. Two layers to harden
|
||||
separately.
|
||||
Stage 1 (see `00-overview.md`) — applies to any Proxmox host, independent
|
||||
of cluster plans. Proxmox has no `sudo` out of the box — everything
|
||||
defaults to root. That's the install default, not the recommended end
|
||||
state. Two layers to harden separately.
|
||||
|
||||
## Checklist / script mapping
|
||||
|
||||
Run `scripts/bootstrap.sh` for everything except the admin user (needs a
|
||||
username decision) and 2FA enrollment (must be done interactively via the
|
||||
web UI — there's no safe way to script TOTP secret generation over SSH).
|
||||
Then run `scripts/audit.sh` to verify. Order matters (matches
|
||||
`bootstrap.sh`):
|
||||
|
||||
| # | Item | Script | Manual step required? |
|
||||
|---|------|--------|------------------------|
|
||||
| 1 | Remove enterprise repos, switch to no-subscription | `switch-to-no-subscription-repo.sh` | no |
|
||||
| 2 | SSH: key-only root login + fail2ban | `harden-ssh.sh` | no (requires an `authorized_keys` already in place — script warns if missing) |
|
||||
| 3 | Unattended security upgrades, no auto-reboot | `setup-unattended-upgrades.sh` | no |
|
||||
| 4 | PVE firewall, default-deny, mgmt-only SSH/8006 | `deploy-firewall.sh` | needs `MGMT_CIDR` set |
|
||||
| 5 | Disable subscription nag (cosmetic) | `disable-subscription-nag.sh` | no |
|
||||
| 6 | Named PVE admin user, Administrator role | `create-admin-user.sh <username>` | yes — pick the username, change the generated password on first login |
|
||||
| 7 | 2FA/TOTP on that user and `root@pam` | — | yes — web UI only: Datacenter → Permissions → Two Factor, or user menu → TFA |
|
||||
| 8 | Verify everything above | `audit.sh` | no |
|
||||
|
||||
## Linux/SSH layer
|
||||
|
||||
- `PermitRootLogin prohibit-password` in `sshd_config` — root can only
|
||||
log in via SSH key, never password. Kills most brute-force attempts.
|
||||
See `scripts/harden-ssh.sh`.
|
||||
- fail2ban jail for SSH on top of that.
|
||||
- Restrict SSH to the management VLAN/trusted IPs via the Proxmox
|
||||
firewall (see `03-networking.md`) rather than exposing broadly.
|
||||
@@ -20,7 +39,8 @@ separately.
|
||||
|
||||
- Keep `root@pam` for emergencies only.
|
||||
- Create a named user (e.g. `wayne@pve`) with the Administrator role for
|
||||
routine cluster management: Datacenter → Permissions → Users.
|
||||
routine cluster management — `create-admin-user.sh` does this, or
|
||||
Datacenter → Permissions → Users manually.
|
||||
- Enable 2FA (TOTP or hardware key) on both that account and `root@pam`:
|
||||
Datacenter → Permissions → Realms/Users.
|
||||
- For API integrations (monitoring, automation, Terraform, etc.), issue
|
||||
@@ -30,15 +50,29 @@ separately.
|
||||
## Firewall
|
||||
|
||||
Default-deny at datacenter/node level, whitelist only what's needed (see
|
||||
`03-networking.md` for the specifics). Config templates in
|
||||
`config/pve-firewall/`.
|
||||
`03-networking.md` for the specifics). Template in
|
||||
`config/pve-firewall/cluster.fw.example`, applied by
|
||||
`scripts/deploy-firewall.sh`.
|
||||
|
||||
## Repos and updates
|
||||
|
||||
Fresh installs point at the enterprise repo, which fails on `apt update`
|
||||
without a subscription. Switch to the no-subscription repo (or pay for
|
||||
enterprise). See `scripts/switch-to-no-subscription-repo.sh`. Keep the
|
||||
host patched — hypervisor CVEs are high-value targets.
|
||||
without a subscription. `scripts/switch-to-no-subscription-repo.sh`
|
||||
removes the enterprise sources entirely (renamed `.disabled`, not just
|
||||
commented out) and switches to the no-subscription repo — handles both
|
||||
the legacy `.list` format and the deb822 `.sources` format current
|
||||
installers write. Keep the host patched — hypervisor CVEs are high-value
|
||||
targets; `scripts/setup-unattended-upgrades.sh` automates security
|
||||
patches (deliberately no auto-reboot on a hypervisor — check
|
||||
`/var/run/reboot-required` and reboot during a planned window).
|
||||
|
||||
The web UI's "No valid subscription" popup and dashboard indicator are
|
||||
cosmetic upsell, not a security control, but with no subscription they'll
|
||||
nag on every login — `scripts/disable-subscription-nag.sh` patches
|
||||
`proxmox-widget-toolkit`'s JS to suppress them, and installs an apt
|
||||
`Post-Invoke` hook that reapplies the patch automatically after every
|
||||
`apt`/`dpkg` run, since a `proxmox-widget-toolkit` package upgrade
|
||||
overwrites the patched file.
|
||||
|
||||
## Misc
|
||||
|
||||
@@ -47,7 +81,7 @@ host patched — hypervisor CVEs are high-value targets.
|
||||
- If the web UI is ever needed outside the LAN, put it behind a VPN —
|
||||
don't port-forward 8006 directly.
|
||||
|
||||
## Further reading
|
||||
## Further reading / not yet automated here
|
||||
|
||||
- CIS Benchmark for Proxmox VE
|
||||
- Community PVE hardening guides (kernel parameters, audit logging,
|
||||
|
||||
Reference in New Issue
Block a user