E-04 · RUNNING
Self-hosted infrastructure I run myself
My projects and client sites run on a server I set up and maintain. Running it myself means I own every security decision, from the edge to the backups. This page shows how it's built and what I'd still tighten.
Architecture
E-04 · simplifiedCONTABO · APP + DATABASE SERVERS
PUBLIC PATH
ADMIN PATH
Visitors
CloudflareDNS · TLS · WAF · cache
Coolify proxyroutes by domain
Docker appsklientakarte, client sites
PostgreSQLown server
Me
VPNonly way in
Admin panelsnot public
Cloudflare R2off-server backups
HTTPS
private network
automated backup
PUBLIC PATH
Visitors
HTTPS
Cloudflare · DNS, TLS, WAF, cache
CONTABO · APP + DATABASE SERVERS
Coolify proxy · routes by domain
Docker apps · klientakarte, client sites
private network
PostgreSQL · own server
Admin panels · not public
automated backup
Cloudflare R2 · off-server backups
ADMIN PATHMe
VPN
Admin panels
Controls in place
- Edge protectionAll public traffic goes through Cloudflare, which handles DNS, TLS, caching and a web application firewall in front of the server.
- Admin behind a VPNAdmin panels aren't reachable from the public internet. The only way in is through the VPN.
- Isolated appsEach app runs in its own container, deployed through Coolify, with its proxy routing traffic by domain.
- Database on its own serverPostgreSQL runs on a separate server that only listens on a private network, with key-only SSH and password logins off.
- Off-server backupsEncrypted database backups go to Cloudflare R2 in the EU, a different provider from the servers, in full every week and incrementally every day. Losing a server doesn't mean losing the data.
Backups and restore
every night at 03:00 · encrypted · to Cloudflare R2 in the EU
SunFULL
MonDIFF
TueDIFF
WedDIFF
ThuDIFF
FriDIFF
SatDIFF
FULL a complete copy of the databaseDIFF only what changed since the last full
timed restore drill · before real data44.6 s
Restore from R2 into a throwaway container, then database recovery. Next drill runs with real data.What I'd still tighten
- DONERan and timed a restore drill from the encrypted backups, before the database held real data.
- NEXTRepeat the drill with real data and write down how much data I can lose (RPO) and how fast I recover (RTO).
- DONEThe app server only accepts web traffic coming from Cloudflare, so nobody can bypass the firewall by hitting it directly.
- DONEKey-only SSH and automatic security updates on the app server too, matching the database server.
- NEXTUptime monitoring and alerts, so I hear about problems before a client does.
- NEXTCentral secrets management instead of per-app environment files.
Running it myself is the fastest way to learn what can go wrong.
Every incident I prevent here is one I can explain to a team later.