- In use
Own Linux server – web, DNS, mail and databases
Running my own Debian server with several websites and services, own name servers (BIND, DNSSEC), a mail server (Exim4, Dovecot) with SPF, DKIM, DMARC, MTA-STS and DANE, databases and Docker.
Overview
I run my own Debian VPS – this website runs on it too. From the web server to DNS, e-mail, databases and containers, I set up, secure and maintain everything myself.
Web
- Apache with virtual hosts for several websites and services, HTTPS with Let’s Encrypt (one certificate per site, automatic renewal)
- HSTS and security headers, separated permissions (files owned by the user, the web server only reads)
- PHP-FPM and Apache as a reverse proxy for applications – including the ASP.NET app SupplyTracker as a systemd service
- Deployment with Git and my own scripts, password-protected staging environment
DNS
- Own authoritative name servers with BIND for several domains
- DNSSEC-signed zone for juscinski.net
- Mail server with Exim4 (SMTP) and Dovecot (IMAP/POP3 over TLS)
- Deliverability and anti-spoofing: SPF, DKIM, DMARC (strict)
- Enforced encryption between mail servers: MTA-STS (enforce), DANE/TLSA, TLS reporting
Databases and containers
- MariaDB, plus PostgreSQL and Microsoft SQL Server in Docker containers
- Databases reachable only locally – no access from the internet
Security and maintenance
- Firewall (UFW) with default deny – only services that need to be public are reachable
- SSH login only with a key and two-factor authentication (TOTP)
- fail2ban with custom rules for SSH, SMTP (Exim) and IMAP (Dovecot)
- Automatic security updates (unattended-upgrades), log rotation, script-based monitoring
- Regular security audits with my own read-only script – findings are documented and fixed
- The server status on the home page is live – a script refreshes it every five minutes
What I learned
How the building blocks of an internet service fit together – DNS, TLS, web, mail and databases – and that a change in one place often affects three others. Above all: test every change first, then activate it, then verify it from the outside – and document everything so it can be traced and rolled back.