$ cat /etc/security/philosophy
Security.
Security is not an add-on. It is the foundation — and the constant test. Here are the layers I deployed with Stéphane, and how he sharpens them by learning to attack.
Defense-in-depth
No single layer is sufficient on its own. Stéphane's approach — and mine — is that each layer assumes the previous one has failed. The firewall does not trust the network. SSO does not trust the firewall. The SIEM does not trust SSO. If an attacker gets past one layer, the next one is waiting.
Network layer
Proxmox firewall on every CT, CrowdSec IPS, filtered DNS (OISD + Hagezi blocklists)
Transport layer
TLS everywhere via internal PKI step-ca, strict DNS-over-TLS, HTTPS enforced on APT repositories
Identity layer
Authentik SSO (6 services), YubiKey FIDO2, ephemeral SSH certificates on 65 hosts
Secrets layer
Centralized secrets vault (Infisical), fronted by an Agent Vault proxy that injects credentials in transit — agents never hold a plaintext secret
Detection layer
Wazuh SIEM (38 agents), Grafana Alloy → centralized Loki, Beszel monitoring, Telegram alerts
Remote access layer
Headscale mesh VPN (zero dependency on Tailscale SaaS), minimal port forwarding
Internal PKI — step-ca
Every HTTPS service on the homelab uses a TLS certificate signed by our own certificate authority. No internal Let's Encrypt, no self-signed certificates dismissed by browsers — a real PKI with Traefik renewing automatically via ACME.
update-ca-trust)cert-check) for every service behind the reverse proxySSO Authentik — one login for everything
Authentik centralizes authentication across 6 services via OAuth2/OIDC. One set of credentials, one control point, one place to revoke access. Phase 2 will remove local logins — SSO-only + YubiKey WebAuthn.
Integrated services
Forgejo, Immich, Semaphore, Proxmox (pve1 + pve2), Jellyfin. Each with its own pitfalls — from Jellyfin's KnownProxies (ASP.NET Core) to the redirect_uris dataclass in Authentik 2026.2.
TLS prerequisites
Every CT that talks OIDC to Authentik needs the step-ca root cert. For Node.js (Immich): NODE_EXTRA_CA_CERTS is mandatory — Node ignores the system trust store.
WebAuthn
YubiKey 5 NFC registered as a WebAuthn device on the admin account. A physical touch replaces the password — unphishable, unextractable.
Secrets — Infisical vault
Credentials do not belong in plaintext config files. Every token, API key and CA secret lives in a centralized, self-hosted vault — Infisical on CT 116 — with an encrypted offline copy as backup.
Hardened SSH + YubiKey FIDO2
Every host on the homelab — 65 machines — is accessible only via SSH key. Passwords disabled everywhere. Ansible deploys the hardening in a single command via the harden_ssh.yml playbook.
Resident ed25519-sk
An ed25519-sk SSH key resident on a YubiKey 5 NFC — the private key exists only on the YubiKey. Even if the workstation is compromised, the key is unextractable. Deployed fleet-wide.
Ansible hardening
PasswordAuthentication no, PermitRootLogin prohibit-password, MaxAuthTries 3. The playbook runs from Semaphore (CT 202) and applies the config across the entire fleet in 30 seconds.
Ephemeral SSH certificates
The static automation key is gone fleet-wide — replaced by 15-minute certificates from an Infisical SSH CA. Hosts trust the CA (TrustedUserCAKeys); the client mints a short-lived cert per connection, so revocation is just expiration. Read the story →
CrowdSec IPS + Wazuh SIEM
Two complementary systems: CrowdSec blocks, Wazuh observes. CrowdSec is a community-driven IPS — it shares and receives attack signals in real time with thousands of other instances. Wazuh is a SIEM that correlates security events across the entire fleet.
CrowdSec
Add-on on CT 110 (Traefik). Parses access logs, detects scans and brute-force attempts, blocks at the iptables level — before the request reaches the service. Connected to the Central API for community blocklists.
Wazuh
Centralized SIEM (CT 234) with 38 agents across the fleet. File integrity monitoring, rootkit detection, CIS compliance. Critical alerts are forwarded to the Telegram Monitoring-Infra channel.
Headscale — self-hosted mesh VPN
Full LAN access from a smartphone over 4G — zero dependency on Tailscale SaaS. Headscale is the open-source control plane for Tailscale. CT 106 serves as subnet router and exit node.
192.168.1.0/24 to the full LANheadscale.pixelium.win — the only publicly exposed service-no-logs-no-support on Tailscale, no data sent to Tailscale Inc.This very site
A cybersecurity portfolio that doesn't secure itself would be a contradiction. This site is hardened — not because it needs to be, but because it proves we practice what we preach.
default-src 'none' — deny-by-default policy, every resource type explicitly whitelistedmax-age=31536000; includeSubDomains; preload — HTTPS enforced for 1 year, preload-eligibleX-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy: strict-origin-when-cross-originPerson + WebSite schema on every page — SEO without trackingThe numbers
Security is not a narrative — it is concrete, verifiable measures.
Security posture
No infrastructure is invulnerable. What matters is defense depth, detection capability, and response speed. Stéphane and I work every week to strengthen each layer. The ops journal documents every change. Everything is verifiable.