Self-Hosting Security: 20 Things to Fix 2026
Self-Hosting Security Checklist: 20 Things to Lock Down
Self-hosting gives you control, but you're also responsible for security. Here are the 20 things you need to lock down before exposing any self-hosted service to the internet.
Server Access (Items 1-5)
1. ✅ Disable Root Login
# /etc/ssh/sshd_config
PermitRootLogin no
sudo systemctl restart sshd
Create a regular user and use sudo:
adduser deployer
usermod -aG sudo deployer
2. ✅ SSH Key-Only Authentication
# On your local machine
ssh-keygen -t ed25519 -C "your@email.com"
ssh-copy-id deployer@your-server
# Then disable password auth
# /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
3. ✅ Change SSH Port
# /etc/ssh/sshd_config
Port 2222 # Pick any non-standard port
Reduces automated brute force attempts by 99%.
4. ✅ Set Up Fail2Ban
sudo apt install -y fail2ban
# /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 2222
filter = sshd
maxretry = 3
bantime = 3600
findtime = 600
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
5. ✅ Configure UFW Firewall
sudo ufw default deny incoming
sudo ufw default allow outgoing
# SSH (your custom port)
sudo ufw allow 2222/tcp
# HTTP/HTTPS (for Caddy)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Enable
sudo ufw enable
sudo ufw status
Never expose database ports (5432, 3306, 6379) to the internet.
Docker Security (Items 6-10)
6. ✅ Don't Run Containers as Root
# docker-compose.yml
services:
myapp:
user: "1000:1000" # Non-root user
Or in Dockerfile:
RUN adduser -D appuser
USER appuser
7. ✅ Limit Container Resources
services:
myapp:
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
memory: 512M
Prevents a single container from consuming all server resources.
8. ✅ Use Read-Only File Systems Where Possible
services:
myapp:
read_only: true
tmpfs:
- /tmp
- /var/tmp
volumes:
- app_data:/data # Only mount what's needed
9. ✅ Don't Bind to 0.0.0.0 for Internal Services
# BAD — exposed to internet
ports:
- "5432:5432"
# GOOD — only accessible from localhost (for reverse proxy)
ports:
- "127.0.0.1:5432:5432"
# BEST — no port binding, use Docker networks
# (services communicate via Docker internal DNS)
10. ✅ Use Docker Networks for Service Isolation
services:
app:
networks:
- frontend
- backend
db:
networks:
- backend # Not accessible from frontend network
networks:
frontend:
backend:
internal: true # No external access
Web Security (Items 11-14)
11. ✅ Force HTTPS Everywhere
Caddy does this automatically. For other reverse proxies:
# Nginx
server {
listen 80;
return 301 https://$host$request_uri;
}
12. ✅ Security Headers
Caddy adds basic headers. For stricter security:
# /etc/caddy/Caddyfile
(security_headers) {
header {
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
X-XSS-Protection "1; mode=block"
Referrer-Policy strict-origin-when-cross-origin
Strict-Transport-Security "max-age=31536000; includeSubDomains"
}
}
myapp.yourdomain.com {
import security_headers
reverse_proxy localhost:3000
}
13. ✅ Rate Limiting
# Caddy rate limiting
myapp.yourdomain.com {
rate_limit {
zone dynamic_zone {
key {remote_host}
events 100
window 1m
}
}
reverse_proxy localhost:3000
}
14. ✅ Restrict Admin Panels by IP
# Only allow admin access from specific IPs
admin.yourdomain.com {
@blocked not remote_ip 1.2.3.4 5.6.7.8
respond @blocked "Forbidden" 403
reverse_proxy localhost:3000
}
Application Security (Items 15-17)
15. ✅ Use Strong, Unique Passwords for Every Service
Generate strong passwords:
openssl rand -hex 32 # Database passwords
openssl rand -hex 64 # Secret keys, encryption keys
Never reuse passwords between services. Store them in Vaultwarden.
16. ✅ Enable 2FA on All Admin Accounts
| Tool | 2FA Support |
|---|---|
| Vaultwarden | TOTP, WebAuthn, YubiKey |
| Uptime Kuma | TOTP |
| Gitea | TOTP, WebAuthn |
| Nextcloud | TOTP, WebAuthn |
| Keycloak | TOTP, WebAuthn |
| Outline | Via Keycloak SSO |
17. ✅ Disable Sign-Ups After Setup
Most tools let you disable public registration:
# Vaultwarden
SIGNUPS_ALLOWED=false
# n8n
N8N_USER_MANAGEMENT_DISABLED=true
# Gitea
DISABLE_REGISTRATION=true
# Grafana
GF_USERS_ALLOW_SIGN_UP=false
Invite users through admin panel instead.
Monitoring & Maintenance (Items 18-20)
18. ✅ Automatic Security Updates
# Ubuntu/Debian — enable unattended upgrades
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
# Verify it's enabled
cat /etc/apt/apt.conf.d/20auto-upgrades
19. ✅ Monitor for Intrusions
Check auth logs regularly:
# Failed SSH attempts
journalctl -u sshd --since "24 hours ago" | grep "Failed"
# Fail2ban status
sudo fail2ban-client status sshd
Set up alerts:
- Monitor with Uptime Kuma for service availability
- Set up Fail2Ban email notifications
- Monitor disk usage (prevent denial of service)
20. ✅ Keep Docker Images Updated
# Check for updates
docker compose pull
# Update all services
docker compose up -d
# Clean up old images
docker image prune -f
Schedule monthly updates:
# First Sunday of each month at 4 AM
0 4 1-7 * 0 cd /opt/mystack && docker compose pull && docker compose up -d
Security Audit Script
Run this to check your server's security posture:
#!/bin/bash
# security-check.sh
echo "=== Security Audit ==="
# SSH config
echo -n "Root login disabled: "
grep -q "^PermitRootLogin no" /etc/ssh/sshd_config && echo "✅" || echo "❌"
echo -n "Password auth disabled: "
grep -q "^PasswordAuthentication no" /etc/ssh/sshd_config && echo "✅" || echo "❌"
# Firewall
echo -n "UFW active: "
sudo ufw status | grep -q "active" && echo "✅" || echo "❌"
# Fail2Ban
echo -n "Fail2Ban running: "
systemctl is-active fail2ban > /dev/null && echo "✅" || echo "❌"
# Docker
echo -n "Exposed ports (should be minimal): "
docker ps --format '{{.Ports}}' | grep "0.0.0.0" | wc -l
# Updates
echo -n "Unattended upgrades: "
dpkg -l | grep -q unattended-upgrades && echo "✅" || echo "❌"
# SSL
echo -n "SSL certificates valid: "
echo | openssl s_client -connect yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates 2>/dev/null && echo "✅" || echo "❌"
echo "=== Done ==="
Common Mistakes
| Mistake | Risk | Fix |
|---|---|---|
| Exposing database ports publicly | Direct database access | Use Docker networks, bind to 127.0.0.1 |
| Default passwords | Unauthorized access | Generate unique passwords for everything |
| No firewall | All ports open | Enable UFW with deny-by-default |
| Running as root | Full server compromise if app is exploited | Create non-root users |
| No backups | Total data loss | Implement 3-2-1 backup strategy |
| No monitoring | Attacks go unnoticed | Set up Uptime Kuma + Fail2Ban alerts |
| Outdated software | Known vulnerabilities | Enable automatic updates |
| HTTP without redirect | Data interception | Force HTTPS via reverse proxy |
Find secure, self-hostable tools on OSSAlt — security features, licensing, and deployment guides side by side.
Security Gains Only Count If You Reduce Hidden Trust
Self-hosting can improve security, but only when it reduces trust assumptions instead of moving them around. Bringing a service in-house is not automatically safer if the result is one unpatched VPS, a wide-open admin panel, and no log review. The real gain comes from shrinking who can read the data, who can change configuration, and how many external processors sit between your users and their information. That is why privacy and security articles need to focus on control boundaries. Ask which credentials unlock the system, where audit trails live, and how incident response changes when the software is on infrastructure you administer directly.
Useful adjacent tools reinforce that boundary model. Vaultwarden guide matters because weak shared secrets are still one of the fastest ways to negate every other security measure. CrowdSec guide belongs in the conversation because exposure without ban rules or log-based detection is just optimism. Authelia guide is the missing layer when teams have multiple internal apps but no unified MFA and policy engine. None of those tools replaces process, but together they make a small-team security posture far more coherent.
A Defensible Security Baseline for Small Teams
For most organizations, the defensible baseline is surprisingly attainable. Put admin interfaces behind SSO or at least MFA, remove public exposure where a VPN or access gateway is enough, enforce automatic updates on the host OS, send logs somewhere durable, and test restores regularly. Then document one incident playbook that covers credential compromise, failed upgrades, and suspicious traffic spikes. That playbook does not have to be enterprise-grade to be valuable. It only has to exist before the bad day arrives.
The practical advantage of open source here is inspectability and composability. You can audit default settings, place reverse proxies and WAF rules in front of services, and export metrics into your own monitoring stack. More importantly, you can keep sensitive workloads off third-party dashboards entirely. That combination of transparency and constrained trust is the strongest argument for self-hosted security-minded systems, and it is more persuasive than any simplistic claim that open source is inherently safer.
Decision Framework for Picking the Right Fit
The simplest way to make a durable decision is to score the options against the constraints you cannot change: who will operate the system, how often it will be upgraded, whether the workload is business critical, and what kinds of failures are tolerable. That sounds obvious, but many migrations still start with screenshots and end with painful surprises around permissions, backup windows, or missing audit trails. A short written scorecard forces the trade-offs into the open. It also keeps the project grounded when stakeholders ask for new requirements halfway through rollout.
One more practical rule helps: optimize for reversibility. A good self-hosted choice preserves export paths, avoids proprietary lock-in inside the replacement itself, and can be documented well enough that another engineer could take over without archaeology. The teams that get the most value from self-hosting are not necessarily the teams with the fanciest infrastructure. They are the teams that keep their systems legible, replaceable, and easy to reason about.
Related Reading
Security Gains Only Count If You Reduce Hidden Trust
Self-hosting can improve security, but only when it reduces trust assumptions instead of moving them around. Bringing a service in-house is not automatically safer if the result is one unpatched VPS, a wide-open admin panel, and no log review. The real gain comes from shrinking who can read the data, who can change configuration, and how many external processors sit between your users and their information. That is why privacy and security articles need to focus on control boundaries. Ask which credentials unlock the system, where audit trails live, and how incident response changes when the software is on infrastructure you administer directly.
Useful adjacent tools reinforce that boundary model. Vaultwarden guide matters because weak shared secrets are still one of the fastest ways to negate every other security measure. CrowdSec guide belongs in the conversation because exposure without ban rules or log-based detection is just optimism. Authelia guide is the missing layer when teams have multiple internal apps but no unified MFA and policy engine. None of those tools replaces process, but together they make a small-team security posture far more coherent.
A Defensible Security Baseline for Small Teams
For most organizations, the defensible baseline is surprisingly attainable. Put admin interfaces behind SSO or at least MFA, remove public exposure where a VPN or access gateway is enough, enforce automatic updates on the host OS, send logs somewhere durable, and test restores regularly. Then document one incident playbook that covers credential compromise, failed upgrades, and suspicious traffic spikes. That playbook does not have to be enterprise-grade to be valuable. It only has to exist before the bad day arrives.
The practical advantage of open source here is inspectability and composability. You can audit default settings, place reverse proxies and WAF rules in front of services, and export metrics into your own monitoring stack. More importantly, you can keep sensitive workloads off third-party dashboards entirely. That combination of transparency and constrained trust is the strongest argument for self-hosted security-minded systems, and it is more persuasive than any simplistic claim that open source is inherently safer.
Related Reading
Security Gains Only Count If You Reduce Hidden Trust
Self-hosting can improve security, but only when it reduces trust assumptions instead of moving them around. Bringing a service in-house is not automatically safer if the result is one unpatched VPS, a wide-open admin panel, and no log review. The real gain comes from shrinking who can read the data, who can change configuration, and how many external processors sit between your users and their information. That is why privacy and security articles need to focus on control boundaries. Ask which credentials unlock the system, where audit trails live, and how incident response changes when the software is on infrastructure you administer directly.
Useful adjacent tools reinforce that boundary model. Vaultwarden guide matters because weak shared secrets are still one of the fastest ways to negate every other security measure. CrowdSec guide belongs in the conversation because exposure without ban rules or log-based detection is just optimism. Authelia guide is the missing layer when teams have multiple internal apps but no unified MFA and policy engine. None of those tools replaces process, but together they make a small-team security posture far more coherent.
A Defensible Security Baseline for Small Teams
For most organizations, the defensible baseline is surprisingly attainable. Put admin interfaces behind SSO or at least MFA, remove public exposure where a VPN or access gateway is enough, enforce automatic updates on the host OS, send logs somewhere durable, and test restores regularly. Then document one incident playbook that covers credential compromise, failed upgrades, and suspicious traffic spikes. That playbook does not have to be enterprise-grade to be valuable. It only has to exist before the bad day arrives.
The practical advantage of open source here is inspectability and composability. You can audit default settings, place reverse proxies and WAF rules in front of services, and export metrics into your own monitoring stack. More importantly, you can keep sensitive workloads off third-party dashboards entirely. That combination of transparency and constrained trust is the strongest argument for self-hosted security-minded systems, and it is more persuasive than any simplistic claim that open source is inherently safer.
Related Reading
Incident Readiness Notes
Incident readiness starts with fast credential rotation, immutable backups, and central logging. If those three controls are weak, every other security improvement becomes harder to rely on under pressure.