Skip to content

Hardening checklist

Before going productive, walk through this list. Everything is optional, but skip few of them. Vesana's baseline stance is outbound-only: the server has no outbound connection to monitored machines — agents and collectors always connect from the inside out. That structurally reduces the attack surface; the points below harden the server itself.

Authentication

  • [ ] Mandatory 2FA for super admin and tenant admin — available methods: TOTP (authenticator app such as Aegis/Authy/Google Authenticator), or WebAuthn (hardware key/passkey). Backup codes are mandatory when enabling.
  • [ ] Password complexity in admin settings to high
  • [ ] JWT lifetime capped at 8–24 h (shorter = more frequent login, safer)
  • [ ] Default admin account renamed or disabled — don't leave admin@example.com
  • [ ] Login rate limit verified — default 10 req/min/IP for login and 2FA verify, 3 req/min for 2FA resend

Tokens

  • [ ] Distribute agent tokens minimally — only one per host
  • [ ] Collector API keys with long prefix so leaks reveal which tenant
  • [ ] Personal access tokens with short lifetime (e.g. 90 days) and targeted scope

Encryption

  • [ ] FIELD_ENCRYPTION_KEY in password manager + printed safe-stored
  • [ ] Backup of key separate from DB backup
  • [ ] Only 1–2 people should know the key

TLS

  • [ ] Real cert (Let's Encrypt or own CA), not self-signed in production
  • [ ] HSTS active (default yes)
  • [ ] TLS 1.2+ only in nginx config
  • [ ] A/A+ at SSL Labs
  • [ ] Auto-renewal (Let's Encrypt) or calendar reminder before expiry

Network

  • [ ] Outbound whitelist on the server: only allowed targets (registry, licence portal, browser push services, SMTP)
  • [ ] Inbound 80/443 only — all other ports closed except possibly SSH and NSCA. If agents report in from foreign networks: enable the agent gateway and expose ONLY the gateway port publicly instead (UI port internal/VPN)
  • [ ] SSH key-only, no password
  • [ ] Fail2ban or similar on SSH brute-force
  • [ ] Firewall rules documented and versioned

API replicas and locking

  • [ ] With multiple API replicas: distributed locks via Redis working (watch system tab)
  • [ ] Redis auth active (REDIS_PASSWORD set — default yes, verify)

Container isolation

  • [ ] Confirm non-root — API, worker, receiver, and AI-service containers run as non-root (USER app, UID 1000). Only deliberate exception: the updater container stays root because it needs to write to the Docker socket to run updates.
  • [ ] Docker socket not additionally mounted into other containers
  • [ ] Frontend image (nginx) runs with the built-in nginx user — no adjustment needed

Logging and monitoring

  • [ ] Audit log active and retention configured
  • [ ] Log tailing external if compliance-relevant (SIEM)
  • [ ] System health email alarm to super admins
  • [ ] Failed-login alerts via an event-log/script check + alert rule

Updates

  • [ ] GUI updater works (test with small update before first live update)
  • [ ] Backup before each update runs (default yes, verify)
  • [ ] Update window communicated (status page / wiki)

Backup

  • [ ] Backup sidecar active
  • [ ] Off-site copy (at least weekly)
  • [ ] Restore drill at least once per quarter
  • [ ] .env backup separate

RBAC

Vesana is deny by default: every API endpoint requires an explicit permission — without a matching permission you get 403, never an implicit "allowed anyway". Four base roles (Super Admin, Admin, Operator, Viewer) cover the standard cases; custom roles allow granular permission composition beyond that. tenant_access separately controls which tenants a user even sees (one tenant, several, or all as super admin) — every database query is additionally auto-filtered by tenant.

  • [ ] Permission inventory — no user with more than necessary
  • [ ] Default admin account not for daily use
  • [ ] Auditor role for external auditors (read-only permissions such as audit_log.view_tenant)
  • [ ] Check tenant_access — cross-tenant read only where genuinely needed (MSP roles)

AI

  • [ ] With cloud provider: be clear what goes to the API
  • [ ] AI permissions sparingly — not every user needs ai.query
  • [ ] AI visibility toggle in user pref explained (privacy wish)

Phone / push

  • [ ] HTTPS is mandatory — without a secure context no browser allows installation or push
  • [ ] Back up the push keys (VAPID) — they belong to the instance and are part of the backup; after a rebuild without backup every device has to re-enable push

Custom code (scripts, profiles)

Script-capable check types (agent_script, custom, ssh_script, ssh_custom) can run arbitrary code on monitored machines — the most sensitive point in the whole system, and hardened accordingly:

  • Apply scope per user: who's allowed to create/change script checks can be restricted granularly — by tenant, by tag, or on individual hosts. Without an explicit setting the role default applies: Admin may apply scripts on all accessible tenants, any other role may not (super admins are never restricted). A stored setting replaces the default — including "None" for an admin.
  • Reach is asked, not assumed: before saving a script body you see how many checks depend on it and choose "for all", "as own script" (copy) or "only this device". Nobody changes a script shared by many hosts by accident.
  • Sandboxed Active Collector: scripts run with restricted capabilities, not full root rights. Server-internal addresses (loopback, Docker networks) are blocked for checks of non-privileged users, and per tenant you can allow whether network checks or custom plugins may run on the server (Admin → Agents & Collectors → Active checker, from v1.9.437).

Checklist:

  • [ ] script.create not for viewer/operator
  • [ ] Apply scope per user meaningfully restricted (not a blanket "all tenants")
  • [ ] Custom scripts tested on test machine before rollout
  • [ ] Profile imports from unknown source carefully
  • [ ] Policies rolling out scripts — super admin only (enforced by the system, not configurable)

Security updates

  • [ ] CVE feeds watched (Postgres, Redis, FastAPI, React)
  • [ ] Docker images pulled regularly (GUI updater does this)

Operations docs

  • [ ] Runbooks in wiki — what to do on XYZ
  • [ ] Contact list for escalations (in wiki)
  • [ ] Status page for external communication
  • [ ] Storage of FIELD_ENCRYPTION_KEY documented (who has access)

Compliance-specific

Standard Special note
ISO 27001 Audit log + 2FA + backup drill suffice for most audits
GDPR Clear: no personal data is monitored (devices). Login data yes → DPA with vendor
HIPAA Disable cloud AI or pick provider with BAA
PCI Vesana is out of scope unless in card-data path — but can help with monitoring

Next