Document pve10 static IPs, monitoring stack, and site LXCs; add portfolio to inventory; Mailcow mailbox automation; vault import/export scripts; security audit guides and UniFi DHCP reference. Co-authored-by: Cursor <cursoragent@cursor.com>
9.3 KiB
Security Audit Report
Date: 2026-05-20
Auditor: Automated read-only scan (scripts/security-audit-*.sh)
Scope: Proxmox nodes pve201 (10.0.10.201) and pve10 (10.0.10.10), all LXCs via pct exec, SSH deep-dive on hypervisors.
Repo baseline (roles/ssh/defaults/main.yml): PermitRootLogin prohibit-password, PasswordAuthentication no, UFW enabled.
Executive summary
| Area | Critical | High | Medium |
|---|---|---|---|
| Hypervisors (201, 10) | 2 | 4 | 2 |
| LXCs on 201 (10 running) | 0 | 10 | 8 |
| LXCs on 10 (3 running) | 0 | 3 | 3 |
Top priorities
- Harden SSH on both Proxmox hosts (root + passwords currently allowed).
- Restrict Proxmox API/UI port 8006 to admin IPs.
- Disable password SSH on all LXCs; deploy keys +
make copy-ssh-keysfor inventory IPs. - Patch hosts with 40–105 pending apt upgrades (hypervisors worst).
- Put HTTP services (8080, 8000, qBit, etc.) behind reverse proxy + TLS or bind to internal IPs.
Proxmox hypervisors
pve201 — 10.0.10.201 (pve)
| Resource | Status |
|---|---|
| OS | Debian 12, PVE 8.4.16, kernel 6.8.12-18-pve |
| RAM free | ~2.5 GB / 126 GB (critical) |
| Pending apt | 105 |
| UFW / fail2ban / unattended-upgrades | None |
SSH audit (dedicated)
| Setting | Current | Target |
|---|---|---|
permitrootlogin |
yes | prohibit-password |
passwordauthentication |
yes | no |
pubkeyauthentication |
yes | yes |
maxauthtries |
6 | 3–4 |
x11forwarding |
yes | no (on servers) |
| Root keys | 3 keys in authorized_keys |
audit/remove unused |
Exposed services
| Port | Service | Risk |
|---|---|---|
| 22 | SSH | Brute-force (no fail2ban) |
| 8006 | Proxmox API/UI | Critical — full cluster control |
| 3128 | spiceproxy | Medium |
| 111 | rpcbind | Low — reduce exposure |
Fixes (pve201)
# 1) SSH — prefer Ansible after limiting to your IP
make copy-ssh-key HOST=pve201 # if needed
# Manual quick fix on host:
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sshd -t && systemctl reload sshd
# 2) Proxmox firewall — Datacenter → Firewall → restrict 8006 to 10.0.10.0/24 or admin IP
# Or iptables on host for port 8006
# 3) fail2ban
apt install fail2ban -y
systemctl enable --now fail2ban
# 4) Auto security updates
apt install unattended-upgrades apt-listchanges -y
dpkg-reconfigure -plow unattended-upgrades
# 5) Patch
apt update && apt upgrade -y
Ansible (when ready): add pve201 / pve10 to a proxmox group play with roles/ssh + roles/monitoring_server (fail2ban). Do not lock yourself out — test with second session first.
pve10 — 10.0.10.10 (PVENAS)
| Resource | Status |
|---|---|
| OS | Debian 13 (trixie), PVE, kernel 6.17.13-3-pve |
| Load | ~30 on 24 CPUs (overloaded) |
| Pending apt | 92 |
| UFW / fail2ban / unattended-upgrades | None |
ZFS NAS.SP00 |
inactive (I/O suspended) |
PBS PVEBUVD00 → 10.0.10.200:8007 |
unreachable |
SSH audit (dedicated)
Same as pve201: permitrootlogin yes, passwordauthentication yes, 3 root authorized_keys.
Exposed services
| Port | Service | Risk |
|---|---|---|
| 22 | SSH | High |
| 8006 | Proxmox API/UI | Critical |
| 2049, mountd, statd | NFS/RPC | High on LAN |
| 3128 | spiceproxy | Medium |
Fixes (pve10)
Same SSH / fail2ban / unattended-upgrades / patch steps as pve201.
Additional:
# Investigate ZFS pool
zpool status NAS.SP00
# Fix PBS connectivity or remove stale datastore from Proxmox UI
LXCs on pve201 (via pct exec)
| VMID | Name | IP | Status | SSH root | Password auth | UFW | fail2ban | Upgrades | Public services |
|---|---|---|---|---|---|---|---|---|---|
| 301 | vikunja-debian | 10.0.10.159 | running | without-password | yes | no | no | 0 | 3456, 22 |
| 302 | qbit-debian | 10.0.10.91 | running | without-password | yes | no | no | 0 | 8080 (qBit), 22 |
| 303 | searchXNG-debian | 10.0.10.70 | running | without-password | yes | no | no | 83 | 8080, 22 |
| 304 | wireguard-debian | 10.0.10.192 | running | without-password | yes | no | no | 0 | 22 |
| 305 | kuma-debian | 10.0.10.197 | stopped | — | — | — | — | — | replaced by LXC 218 |
| 306 | portfolio | — | destroyed | — | — | — | — | — | migrated → pve10 LXC 219 @ 10.0.10.106 (purged 2026-05-22) |
| 307 | jobber-delian | 10.0.10.178 | running | without-password | yes | no | no | 83 | 3005, 22 |
| 308 | stirling-pdf | 10.0.10.43 | running | without-password | yes | no | no | 0 | 8080, 22 |
| 9001 | pote-dev | 10.0.10.114 | stopped | — | — | — | — | — | — |
| 9101 | punimTagFE-dev | 10.0.10.121 | running | without-password | yes | active | no | 89 | 8000, 111, 22 |
| 9401 | mirrormatch-dev | 10.0.10.141 | stopped | — | — | — | — | — | — |
Inventory mapping: vikanjans → 159, qBittorrent → 91, punimTag app → 121.
Common LXC issues (pve201)
| Issue | Severity | Fix |
|---|---|---|
passwordauthentication yes on all LXCs |
High | Set PasswordAuthentication no in /etc/ssh/sshd_config, reload sshd |
| No fail2ban | High | Install fail2ban or rely on Proxmox FW + LAN segmentation |
Apps on 0.0.0.0:8080 / 8000 / 3456 |
High | Bind to localhost + Caddy, or restrict via Proxmox guest firewall (firewall=1 on net0 — enable rules) |
| 79–89 pending upgrades on several CTs | Medium | pct exec <id> -- apt update && apt upgrade -y |
| Stopped dev CTs (9001, 9401) | Low | Start when needed or keep stopped to reduce attack surface |
Per-LXC fixes (pve201)
# Example: harden + patch vikunja (301) from Proxmox host
pct exec 301 -- sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
pct exec 301 -- systemctl reload ssh
# Patch container
pct exec 303 -- bash -c 'apt update && apt upgrade -y'
# Copy your SSH key (from Mac, once password/key works)
make copy-ssh-key HOST=vikanjans # 10.0.10.159
make copy-ssh-key HOST=qBittorrent # 10.0.10.91
punimTagFE-dev (9101): Only LXC with UFW active — extend rules to deny inbound except 22 from admin subnet; still disable password auth.
LXCs on pve10 (via pct exec)
| VMID | Name | IP | Status | SSH root | Password auth | UFW | fail2ban | Upgrades | Public services |
|---|---|---|---|---|---|---|---|---|---|
| 210 | cal | 10.0.10.228 | running | without-password | yes | no | no | 0 | 3000, 22 |
| 215 | caseware | 10.0.10.105 | running | without-password | yes | no | no | 40 | 80 (nginx), 22 |
| 216 | auto | 10.0.10.59 | running | without-password | yes | no | no | 40 | 80 (nginx), 22 |
Inventory mapping: caseware → 105, auto → 59.
Fixes (pve10 LXCs)
# SSH harden caseware (215)
pct exec 215 -- sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
pct exec 215 -- systemctl reload sshd
# Patch
pct exec 215 -- apt update && apt upgrade -y
pct exec 216 -- apt update && apt upgrade -y
# Deploy keys from Mac
make copy-ssh-key HOST=caseware
make copy-ssh-key HOST=auto
HTTP port 80 on caseware/auto: Ensure TLS termination on Caddy (inventory host caddy 10.0.10.50) and no plain HTTP from WAN if exposed.
SSH hardening checklist (all Linux targets)
Use this order to avoid lockout:
- Confirm your key works:
ssh -o BatchMode=yes root@<ip> true - Set
PasswordAuthentication no - Set
PermitRootLogin prohibit-password(LXCs alreadywithout-password— equivalent for keys-only) sshd -t && systemctl reload sshd- Open second terminal and test before closing first
- Optional: change SSH port,
MaxAuthTries 4, disableX11Forwarding
Ansible alignment:
# After keys on host
make dev HOST=<hostname> --tags security
# or role ssh via playbooks that include roles/ssh
Re-run audits
# Hypervisor full audit
ssh root@10.0.10.201 'bash -s' < scripts/security-audit-remote.sh
ssh root@10.0.10.10 'bash -s' < scripts/security-audit-remote.sh
# Hypervisor SSH-only
ssh root@10.0.10.201 'bash -s' < scripts/security-audit-ssh.sh
# All LXCs on a node
ssh root@10.0.10.201 'bash -s' < scripts/security-audit-lxc-via-pve.sh
ssh root@10.0.10.10 'bash -s' < scripts/security-audit-lxc-via-pve.sh
Tracking
| Item | Owner | Status |
|---|---|---|
| SSH harden pve201 | ☐ | |
| SSH harden pve10 | ☐ | |
| Restrict 8006 on both nodes | ☐ | |
| fail2ban on hypervisors | ☐ | |
| Patch pve201 / pve10 | ☐ | |
| Disable password SSH on all LXCs | ☐ | |
copy-ssh-keys for inventory |
☐ | |
| TLS for :80/:8080 services | ☐ | |
| Fix ZFS NAS.SP00 on pve10 | ☐ |
References
- Security remediation plan — phased fixes (critical → low) and login model
- Security hardening guide
- SECURITY_HARDENING_PLAN.md
- Role defaults:
roles/ssh/defaults/main.yml