A guide for anyone who puts a website or a homelab on the internet. It follows the tactics of MITRE D3FEND®: know what you have, then harden, detect, isolate, evict and restore. The seventh tactic, Deceive, is left out on purpose: decoys and honeypots only pay off once the basics are in place. Every step ends with a self-check question. You can answer the same questions in the D3FEND cube and see where you stand.
Order matters. Short on time? Start with steps 3, 6, 7 and 16: one entry point, a second factor, updates and a rehearsed restore. Those four cover the most common causes of real damage.
Model
D3FEND tactic
01
Keep an inventory
You can only protect what you know. A list of every service, device, image and version is the basis for everything else, from updates to recovery.
The simplest form is a file in your Git repository, one section per service.
Record per service: purpose, version, public yes/no, where its data lives.
Update it when you add or remove a service — not "later".
Self-check: Is there a current list of every service, device and version?
Which subdomains, ports and services does the internet see? Often more than you think: a forgotten test service, a router panel, an open database port.
Check from outside, e.g. over mobile data — not from your own LAN.
Certificate transparency logs show which subdomains are publicly known.
Write down dependencies: what breaks if the database or DNS goes down?
Self-check: Do you know which services are visible from outside and what depends on what?
Network MappingService Dependency Mapping
Harden
D3FEND tactic
03
Exactly one entry point, everything else closed
A reverse proxy accepts every request on port 443 and routes it. No service gets its own port on the router. Databases and admin panels are not reachable from outside at all.
Router: forward only 80/443, and 80 only for the redirect to HTTPS.
Apps without strong sign-in of their own go behind a central login, e.g. via ForwardAuth.
Services only you need belong behind a VPN, not on the public internet.
Self-check: Is there exactly one public entry point and a login in front of every app?
Every connection is encrypted. Certificates renew themselves — an expired certificate is the most common self-inflicted outage.
Let's Encrypt with automatic renewal, ideally a wildcard certificate via DNS challenge.
Enable HSTS so browsers never ask unencrypted again.
Switch off outdated protocols (TLS 1.0/1.1).
Self-check: Is every connection TLS-encrypted, with certificates renewing automatically?
Message EncryptionCertificate Rotation
05
Set security headers
A handful of response headers tell the browser what it may do. The most important is the Content Security Policy: it defines where scripts, styles and fonts may be loaded from. A generic example for a purely static site:
The most dangerous backup is the one that has been failing silently for weeks. Every important job reports its success actively; if the report is missing, an alert fires.
A "dead man’s switch": a push monitor with an expected interval.
Monitoring for reachability, certificate expiry, disk space.
Test the alert path itself: does the message really arrive?
Self-check: Does your monitoring report outages and silent failures on its own?
Free public tools show what a stranger sees of your site: Mozilla Observatory and securityheaders.com check the headers, SSL Labs the TLS configuration. Only test systems you own.