Self-Hosting Best Practices
Best practices for security, reliability, and management from years of homelab experience.
Self-Hosting Best Practices
After years of running a homelab, we've learned what works and what doesn't. Here are our battle-tested best practices for self-hosting.
Security First
Never Expose Directly
Always use a reverse proxy with proper TLS:
# Traefik configuration
http:
routers:
myapp:
rule: "Host(`app.example.com`)"
entryPoints:
- websecure
tls:
certResolver: letsencrypt
middlewares:
- auth
Authentication Everywhere
Implement SSO with Authentik or similar:
- Central identity management
- 2FA enforcement
- Audit logging
- Session management
Network Segmentation
Isolate services by trust level:
Internet -> WAF -> Reverse Proxy -> Services
|
DMZ -----+-----+-----+ Internal
| |
Public Apps Private Apps
Reliability Engineering
High Availability
Design for failure:
- Redundant storage - RAID or distributed systems
- Multiple nodes - Cluster critical services
- Automatic failover - Let systems self-heal
- Load balancing - Distribute traffic
Monitoring Essentials
What to monitor:
| Metric | Tool | Alert Threshold | |--------|------|-----------------| | Uptime | Uptime Kuma | < 99.9% | | Disk Space | Prometheus | > 80% | | Memory | Prometheus | > 90% | | CPU | Prometheus | > 95% (5m avg) | | SSL Expiry | Uptime Kuma | < 14 days |
Backup Strategy
Follow the 3-2-1 rule:
# Automated backup script
#!/bin/bash
DATE=$(date +%Y-%m-%d)
# Local backup
restic backup /data --tag daily
# Sync to offsite
rclone sync /backups remote:backups
# Notify on completion
curl -d "Backup completed: $DATE" ntfy.example.com/backups
Container Best Practices
Use Compose Files
Never run raw docker run commands in production:
version: '3.8'
services:
app:
image: myapp:1.2.3 # Pin versions
restart: unless-stopped
networks:
- internal
volumes:
- app_data:/data
environment:
- TZ=America/New_York
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
volumes:
app_data:
networks:
internal:
Image Management
- Use official images when possible
- Pin to specific versions, not
latest - Scan images for vulnerabilities
- Build custom images from minimal bases
Resource Limits
Always set limits to prevent runaway containers:
deploy:
resources:
limits:
memory: 512M
cpus: '0.5'
reservations:
memory: 256M
cpus: '0.25'
Documentation
What to Document
- Architecture diagrams - Visual overview
- Service inventory - What runs where
- Recovery procedures - Step-by-step guides
- Credentials location - Password manager references
- Change log - What changed and why
Documentation Tools
We use:
- Markdown files in Git
- Diagram as code with Mermaid
- Wiki for procedures
Maintenance Schedule
Daily
- [ ] Check monitoring dashboards
- [ ] Review backup status
- [ ] Scan for security alerts
Weekly
- [ ] Update containers
- [ ] Review resource usage
- [ ] Test a random backup restore
Monthly
- [ ] Security audit
- [ ] Documentation review
- [ ] Capacity planning
Quarterly
- [ ] Disaster recovery drill
- [ ] Infrastructure review
- [ ] Clean up unused resources
Common Mistakes to Avoid
- No backups - Always have tested backups
- Default passwords - Change every default credential
- Exposed management interfaces - Keep admin panels internal
- No monitoring - You can't fix what you can't see
- Skipping updates - Security patches matter
- Over-engineering - Simple solutions work best
- No documentation - Write it down now
Summary
Self-hosting is a journey, not a destination. Start with security, build for reliability, automate what you can, and document everything. Your future self will thank you.
Was this article helpful?