Skip to content

Security Posture

Defence in depth

Layer 0 — Network

  • UFW deny-by-default with 4 ports open: 22, 80, 443, 2222
  • No public Docker socket exposure
  • nginx is the only process bound to public 80/443

Layer 1 — Identity & secrets

  • Vaultwarden at vault.joaoluisbrazao.cloud is the authoritative password store
  • Signups are closed — new accounts require admin action
  • No secret committed to git — .env files are read at container start and never persisted to images
  • SSH key auth only — root password disabled

Layer 2 — Runtime monitoring

  • Falco runs continuously, detecting anomalous syscall patterns at the kernel level
  • ClamAV scans uploads and email attachments via the clamav container
  • Uptime Kuma with 36 monitors watches every public surface
  • Alert pipe: Falco/Kuma → Telegram @DownRabbitbot (CHAT_ID 1827458013)

Layer 3 — Application

  • All inputs validated at FastAPI level via Pydantic v2
  • SQL queries always parameterised — never string-concatenated
  • JWT tokens: 15 min access, 7 days refresh, httpOnly cookies
  • CORS: explicit allowlist, never wildcard
  • Security headers enforced by nginx: X-Frame-Options, X-Content-Type-Options, CSP

What we reject

Data classification

Class Examples Where it lives
Public TCN site, gamine.org marketing static files served by nginx
Internal Vikunja tasks, brain knowledge Postgres on VPS, behind auth
Sensitive Vaultwarden vault, credentials Vaultwarden only, never copied
RGPD Art. 9 (health) MedVault (when deployed) Local only — no external LLM, no external cloud

SSL/TLS

  • All public domains served via HTTPS only — HTTP redirects to HTTPS
  • TLS 1.3 enforced; TLS 1.2 left enabled only for legacy compat where needed
  • Certs renew automatically via infra-certbot; expiry alerts via Telegram

Known gaps

Gap Tracking Severity
No off-site backup copies Vikunja #59 High
Volume backups empty for some volumes Vikunja #59 High
Quarterly restore drill never performed (this doc) Medium
Backstage SSO for docs not yet implemented (this doc) Low
Hostinger-level firewall not configured Acceptable (UFW handles it) None
Malware scanner via hPanel not installed Acceptable (ClamAV container handles it) None