Building a Zero Trust Home Server with Raspberry Pi, Cloudflare, and Tailscale
In today's digital landscape, running your own private infrastructure is becoming increasingly popular. With a simple Raspberry Pi, you can self-host your own media, files, ad blocker, automation workflows, and more right from home, while maintaining complete control over your data.
This guide will help you understand how to set up a secure and accessible home server using zero trust principles, with no open ports on your home router.
Why Build a Zero Trust Home Server?
- Complete Digital Privacy: Keep your data local and away from big tech companies
- Enhanced Security: Access services without opening ports on your router
- Centralised Control: Host your own media, files, dashboards, and automation tools
- Accessible From Anywhere: Use secure tunnelling to access your services globally
What You Can Self-Host Securely
Here are some powerful services you can run on your Raspberry Pi:
| Use Case | Service | What It Does | Resource Requirements |
|---|---|---|---|
| Ad Blocking | AdGuard Home / Pi-hole | Network-wide ad and tracker blocking | Low: 100MB RAM, minimal CPU |
| Zero Trust Access | Tailscale / Cloudflare Tunnel | Secure remote access without port forwarding | Low: 200MB RAM, minimal CPU |
| Firewall & Protection | UFW / Fail2Ban | Secure your server from unwanted access | Very Low: System level |
| Media Streaming | Jellyfin | Host your own Netflix-like streaming platform | Medium-High: 1-2GB RAM, moderate CPU |
| Personal Cloud Storage | Nextcloud | Self-hosted alternative to Dropbox/Google Drive | Medium: 1-2GB RAM, moderate CPU |
| Smart Home | Home Assistant | Smart home automation hub | Medium: 1GB RAM, moderate CPU |
| Service Monitoring | Uptime Kuma | Monitor your services' health | Low: 200-500MB RAM, low CPU |
| Password Management | Vaultwarden | Self-hosted Bitwarden-compatible password manager | Low: 500MB RAM, minimal CPU |
| Docker Management | Portainer | Graphical interface to manage Docker containers | Low: 500MB RAM, minimal CPU |
| Workflow Automation | n8n | Create powerful automation workflows | Medium: 1GB RAM, moderate CPU |
| RSS Aggregator | FreshRSS | Track news and updates from your favorite sites | Low: 200MB RAM, minimal CPU |
| Document Management | Paperless-ngx | Scan, store, and search your documents | Medium: 1GB RAM, moderate CPU |
Example Homer dashboard showing various self-hosted services
Real-World Performance Expectations on Raspberry Pi 4 (4GB)
- Jellyfin: 1-2 direct play streams OR 1 1080p transcode
- Nextcloud: Comfortable file syncing for 3-5 users
- AdGuard + Tailscale + Uptime Kuma: Can run simultaneously with minimal impact
- Storage needs: Start with 128GB SSD for OS + Docker, external HDD for media/backups
Setting Up Your Raspberry Pi
Hardware Requirements
For a reliable zero trust home server, you'll need:
- Raspberry Pi 4 (4GB or 8GB recommended)
- USB SSD (128GB+ recommended) instead of microSD for reliability
- Official Power Supply (3A for Pi 4)
- Case with cooling (like the Argon ONE M.2 or Flirc case)
- Ethernet connection (strongly recommended for stability)
Raspberry Pi 4 with SSD and cooling case for optimal home server performance
Step 1: Install Raspberry Pi OS
Download and Install Raspberry Pi Imager:
- Visit the Raspberry Pi Software page and download for your OS
Configure with Raspberry Pi Imager:
- Open the Raspberry Pi Imager application
- Click "Choose device" and select your Raspberry Pi model
- Click "Choose OS" and select Raspberry Pi OS Lite (64-bit) for a headless server
- Click "Choose storage" and select your SSD (connected via USB adapter)
Configure Advanced Options:
- Press Ctrl+Shift+X to open advanced options
- Set a hostname (e.g.,
homeserver) - Enable SSH and configure an SSH key for passwordless login
- Configure your WiFi (if not using Ethernet)
- Set locale settings
- Click Save and then Write
Insert the SSD into your Raspberry Pi and power it on
Step 2: Initial Configuration
Connect to your Raspberry Pi via SSH:
ssh username@homeserver.local
Update your system:
"hljs-string">"hljs-built_in">"hljs-built_in">sudo apt update && "hljs-string">"hljs-built_in">"hljs-built_in">sudo apt full-upgrade -y
Set a static IP address (recommended):
"hljs-string">"hljs-built_in">"hljs-built_in">sudo nano /etc/dhcpcd.conf
Add these lines, customizing for your network:
interface eth0
static ip_address=192.168.1.100/24
static routers=192.168.1.1
static domain_name_servers=1.1.1.1 1.0.0.1
Reboot to apply changes:
"hljs-string">"hljs-built_in">"hljs-built_in">sudo reboot
Step 3: Security Hardening
Remove Password Authentication for SSH
If you didn't set up SSH keys during installation:
"hljs-string">"hljs-comment"># On your "hljs-built_in">local machine
ssh-keygen -t ed25519 -C "hljs-string">"hljs-string">"hljs-string">"your_email@example.com"
ssh-copy-id username@your-pi-ip-address
Then disable password authentication:
"hljs-string">"hljs-built_in">"hljs-built_in">sudo nano /etc/ssh/sshd_config
Find and modify these lines:
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
Restart SSH service:
"hljs-string">"hljs-built_in">"hljs-built_in">sudo systemctl restart sshd
Set Up Basic Firewall
Install and configure UFW:
"hljs-string">"hljs-built_in">"hljs-built_in">sudo apt install ufw
"hljs-string">"hljs-built_in">"hljs-built_in">sudo ufw default deny incoming
"hljs-string">"hljs-built_in">"hljs-built_in">sudo ufw default allow outgoing
"hljs-string">"hljs-built_in">"hljs-built_in">sudo ufw allow ssh
"hljs-string">"hljs-built_in">"hljs-built_in">sudo ufw "hljs-string">"hljs-built_in">"hljs-built_in">enable
Install Fail2Ban to Protect from Brute Force Attacks
"hljs-string">"hljs-built_in">"hljs-built_in">sudo apt install fail2ban
"hljs-string">"hljs-built_in">"hljs-built_in">sudo "hljs-string">"hljs-built_in">"hljs-built_in">cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
"hljs-string">"hljs-built_in">"hljs-built_in">sudo systemctl "hljs-string">"hljs-built_in">"hljs-built_in">enable fail2ban
"hljs-string">"hljs-built_in">"hljs-built_in">sudo systemctl start fail2ban
Configure a custom SSH jail:
"hljs-string">"hljs-built_in">"hljs-built_in">sudo nano /etc/fail2ban/jail.local
Add/modify the SSH section:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 86400 # 24 hours
Restart Fail2Ban:
"hljs-string">"hljs-built_in">"hljs-built_in">sudo systemctl restart fail2ban
Setting Up Docker and Portainer
Portainer dashboard showing running containers and resource usage
Docker allows you to run multiple services in isolated containers.
Install Docker and Docker Compose
curl -fsSL https://get.docker.com | sh
"hljs-string">"hljs-built_in">"hljs-built_in">sudo usermod -aG docker "hljs-string">"hljs-variable">"hljs-variable">$USER
"hljs-string">"hljs-built_in">"hljs-built_in">sudo apt install -y docker-compose-plugin
Log out and log back in for group changes to take effect:
"hljs-string">"hljs-built_in">"hljs-built_in">exit
"hljs-string">"hljs-comment"># Reconnect via SSH
Create Directory Structure
"hljs-string">"hljs-built_in">"hljs-built_in">mkdir -p ~/docker/{compose,configs,data}
Install Portainer for Docker Management
Create a docker-compose file for Portainer:
nano ~/docker/compose/portainer.yml
Add the following content:
version: '3'
services:
portainer:
container_name: portainer
image: portainer/portainer-ce:latest
restart: unless-stopped
security_opt:
- no-new-privileges:true
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ~/docker/data/portainer:/data
ports:
- 9000:9000
Start Portainer:
"hljs-string">"hljs-built_in">"hljs-built_in">cd ~/docker/compose
docker compose -f portainer.yml up -d
You can now access Portainer at http://your-pi-ip:9000 to set up your admin account.
Setting Up AdGuard Home In Detail
AdGuard Home dashboard showing blocked requests and filtering statistics
AdGuard Home is a powerful network-wide ad blocker and DNS server. Here's how to set it up and configure it properly.
Initial Setup
First Create and deploy the docker file
version: '3'
services:
# Network-wide ad blocking
adguard:
container_name: adguard
image: adguard/adguardhome:latest
restart: unless-stopped
volumes:
- ~/docker/configs/adguard:/opt/adguardhome/conf
- ~/docker/data/adguard:/opt/adguardhome/work
ports:
- 3000:3000 # Admin Panel
- 53:53/tcp # DNS
- 53:53/udp # DNS
- 784:784/udp # DNS-over-QUIC
- 853:853/tcp # DNS-over-TLS
- 443:443/udp # DNS-over-HTTPS
cap_add:
- NET_ADMIN
networks:
- home_network
Then run the file and access it
http://your-pi-ip:3000
Follow the setup wizard:
- Create an administrator account
- Configure network settings:
- Choose the interfaces to listen on (typically all)
- Keep default ports:
- DNS: 53
- Web interface: 3000
Common DNS Issues and Fixes
Before AdGuard can function correctly, make sure port 53 is available:
"hljs-string">"hljs-comment"># Check "hljs-keyword">if port 53 is "hljs-keyword">in use
"hljs-string">"hljs-built_in">"hljs-built_in">sudo lsof -i :53
If systemd-resolved is using it, reconfigure it:
"hljs-string">"hljs-comment"># Edit resolved configuration
"hljs-string">"hljs-built_in">"hljs-built_in">sudo nano /etc/systemd/resolved.conf
Add or modify these lines:
DNSStubListener=no
Then restart the service:
"hljs-string">"hljs-built_in">"hljs-built_in">sudo systemctl restart systemd-resolved
Configuring AdGuard Home
1. DNS Settings
In the AdGuard Home dashboard, go to Settings > DNS Settings:
Set upstream DNS servers (recommended):
- Cloudflare:
1.1.1.1and1.0.0.1 - Quad9:
9.9.9.9and149.112.112.112
- Cloudflare:
Enable DNS-over-HTTPS/TLS (for security)
Enable blocking of domains from filters
2. Filtering
Go to Filters > DNS blocklists and add these recommended lists:
- AdGuard DNS filter
- AdAway Default Blocklist
- Peter Lowe's Ad and tracking server list
- Malicious URL Blocklist by Curben
- NoCoin Filter List
3. Configuring Local DNS Records
To use .home.internal domain names for local services:
- Go to Settings > DNS rewrite
- Add entries for each service:
- Domain name:
jellyfin.home.internal - Answer:
your-pi-ip - Repeat for other services
- Domain name:
4. Client Configuration
Set your router to use AdGuard as the DNS server:
- Access your router's admin interface
- Find DHCP/DNS settings
- Set primary DNS to your Raspberry Pi's IP address
- Save changes
Alternatively, configure individual devices to use your Pi's IP as their DNS server.
5. Security Features
Enable these additional security features:
- Safe Search: Forces safe search on Google, Bing, etc.
- Parental Control: Optional content filtering
- Safe Browsing: Blocks malicious domains
6. Statistics and Logs
AdGuard Home provides detailed statistics and logs:
- View top blocked domains
- Check query logs for troubleshooting
- Monitor overall network activity
Using AdGuard with Tailscale
To use AdGuard as your DNS server while connected to Tailscale:
In Tailscale admin console, set a DNS nameserver:
- Go to DNS > Nameservers
- Add your Raspberry Pi's Tailscale IP
Configure split DNS (optional):
- In Tailscale admin, set up split DNS for
.home.internaldomains - This allows resolving local domains when away from home
- In Tailscale admin, set up split DNS for
Setting Up Zero Trust Remote Access

Method 1: Tailscale - VPN-Like Mesh Network
Tailscale creates a secure mesh network between your devices without opening ports.
Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
"hljs-string">"hljs-built_in">"hljs-built_in">sudo tailscale up
Follow the authentication link to connect your Raspberry Pi to your Tailscale account.
Configure Tailscale for Subnet Routing (Optional)
To access other devices on your home network through Tailscale:
"hljs-string">"hljs-built_in">"hljs-built_in">sudo tailscale up --advertise-routes=192.168.1.0/24
Go to the Tailscale admin console and approve the subnet routes.
Setting Up ACLs and Policy
For enhanced security, set up access control policies in the Tailscale admin panel.
Example ACL policy:
{
"acls": [
{
"action": "accept",
"users": ["user@example.com"],
"ports": ["*:*"]
}
]
}
Method 2: Cloudflare Tunnel with Docker Compose
Diagram showing how Cloudflare Tunnel provide secure remote access
Cloudflare Tunnel lets you expose services using a custom domain without opening ports. Running it in Docker keeps everything neatly containerized.
Prerequisites
- Registered domain on Cloudflare
- Cloudflare account
Setting Up Cloudflare Tunnel via Web UI Docker Compose
The Cloudflare Tunnel can also be set up directly from the Cloudflare Zero Trust dashboard, which many users find more convenient:
Log in to your Cloudflare account and navigate to Zero Trust > Access > Tunnels
Click Create a tunnel and give it a name (e.g., "Home Server")
You'll be provided with a tunnel token. Create a docker-compose file for Cloudflare:
nano ~/docker/compose/cloudflare.yml
Add the following content:
version: "3.8"
services:
flaresolverr:
image: ghcr.io/flaresolverr/flaresolverr:latest
container_name: flaresolverr
environment:
- LOG_LEVEL=info
- CAPTCHA_SOLVER=none
ports:
- 8191:8191
restart: unless-stopped
- Start the Cloudflare tunnel:
"hljs-string">"hljs-built_in">"hljs-built_in">cd ~/docker/compose
docker compose -f cloudflare.yml up -d
Back in the Cloudflare dashboard, you'll be asked to configure public hostnames:
- Click Add a public hostname
- Enter the subdomain and domain (e.g., jellyfin.yourdomain.com)
- For service, select "HTTP" and enter the local service address and port (e.g., jellyfin:8096)
- Repeat for each service you want to expose
Optional: Add authentication
- In the Cloudflare dashboard, under the "Public Hostname" settings, you can enable "Zero Trust Policy"
- Configure authentication methods (Google, GitHub, email one-time passwords, etc.)
- Set up custom policies for who can access each service
Setting Up Essential Self-Hosted Services
Create a Complete Docker Compose Stack
Create a new docker-compose file:
nano ~/docker/compose/services.yml
Add the following content:
version: '3'
services:
# Network-wide ad blocking
adguard:
container_name: adguard
image: adguard/adguardhome:latest
restart: unless-stopped
volumes:
- ~/docker/configs/adguard:/opt/adguardhome/conf
- ~/docker/data/adguard:/opt/adguardhome/work
ports:
- 3000:3000 # Admin Panel
- 53:53/tcp # DNS
- 53:53/udp # DNS
- 784:784/udp # DNS-over-QUIC
- 853:853/tcp # DNS-over-TLS
- 443:443/udp # DNS-over-HTTPS
cap_add:
- NET_ADMIN
networks:
- home_network
# Service monitoring
uptime-kuma:
container_name: uptime-kuma
image: louislam/uptime-kuma:latest
restart: unless-stopped
volumes:
- ~/docker/data/uptime-kuma:/app/data
ports:
- 3001:3001
networks:
- home_network
# Media server
jellyfin:
container_name: jellyfin
image: jellyfin/jellyfin:latest
restart: unless-stopped
volumes:
- ~/docker/configs/jellyfin:/config
- /mnt/media:/media
ports:
- 8096:8096
networks:
- home_network
environment:
- JELLYFIN_PublishedServerUrl=jellyfin.yourdomain.com
# Personal cloud storage
nextcloud:
container_name: nextcloud
image: nextcloud:latest
restart: unless-stopped
volumes:
- ~/docker/data/nextcloud:/var/www/html
ports:
- 8080:80
depends_on:
- nextcloud-db
networks:
- home_network
environment:
- MYSQL_HOST=nextcloud-db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=secure_password_here
# Database for Nextcloud
nextcloud-db:
container_name: nextcloud-db
image: mariadb:latest
restart: unless-stopped
volumes:
- ~/docker/data/nextcloud-db:/var/lib/mysql
networks:
- home_network
environment:
- MYSQL_ROOT_PASSWORD=very_secure_root_password
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=secure_password_here
# Workflow automation
n8n:
container_name: n8n
image: n8nio/n8n:latest
restart: unless-stopped
ports:
- 5678:5678
volumes:
- ~/docker/data/n8n:/home/node/.n8n
networks:
- home_network
environment:
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=admin
- N8N_BASIC_AUTH_PASSWORD=secure_password_here
# Password manager
vaultwarden:
container_name: vaultwarden
image: vaultwarden/server:latest
restart: unless-stopped
volumes:
- ~/docker/data/vaultwarden:/data
ports:
- 8081:80
networks:
- home_network
networks:
home_network:
driver: bridge
Start all services:
"hljs-string">"hljs-built_in">"hljs-built_in">cd ~/docker/compose
docker compose -f services.yml up -d
Setting Up a Homer Dashboard
Homer provides a clean, customizable dashboard for all your self-hosted services.
Create a docker-compose file for Homer:
nano ~/docker/compose/homer.yml
Add the following content:
version: '3'
services:
homer:
container_name: homer
image: b4bz/homer:latest
restart: unless-stopped
volumes:
- ~/docker/configs/homer:/www/assets
ports:
- 8082:8080
networks:
- home_network
networks:
home_network:
external: true
Start Homer:
"hljs-string">"hljs-built_in">"hljs-built_in">cd ~/docker/compose
docker compose -f homer.yml up -d
Create a basic configuration:
"hljs-string">"hljs-built_in">"hljs-built_in">mkdir -p ~/docker/configs/homer
nano ~/docker/configs/homer/config.yml
Add this sample configuration:
title: "Home Server Dashboard"
subtitle: "Your Self-Hosted Services"
logo: "assets/icons/logo.png"
header: true
footer: 'Created with ❤️ with Homer
'
# Links to services
services:
- name: "Media"
icon: "fas fa-play-circle"
items:
- name: "Jellyfin"
logo: "assets/icons/jellyfin.png"
subtitle: "Media Server"
tag: "media"
url: "http://jellyfin.home.internal"
target: "_blank"
- name: "Storage"
icon: "fas fa-database"
items:
- name: "Nextcloud"
logo: "assets/icons/nextcloud.png"
subtitle: "File Storage"
tag: "storage"
url: "http://nextcloud.home.internal"
target: "_blank"
- name: "System"
icon: "fas fa-cogs"
items:
- name: "Portainer"
logo: "assets/icons/portainer.png"
subtitle: "Docker Management"
tag: "system"
url: "http://portainer.home.internal"
target: "_blank"
- name: "AdGuard Home"
logo: "assets/icons/adguard.png"
subtitle: "Ad Blocking"
tag: "system"
url: "http://adguard.home.internal"
target: "_blank"
- name: "Automation"
icon: "fas fa-robot"
items:
- name: "n8n"
logo: "assets/icons/n8n.png"
subtitle: "Workflow Automation"
tag: "automation"
url: "http://n8n.home.internal"
target: "_blank"
Create a directory for custom icons:
"hljs-string">"hljs-built_in">"hljs-built_in">mkdir -p ~/docker/configs/homer/icons
You can download icons for your services and place them in this directory.
Setting Up Nginx Proxy Manager for Local Domain Names
To access your services with nice local URLs like portainer.home.internal:
nano ~/docker/compose/nginx-proxy.yml
Add the following content:
version: '3'
services:
nginx-proxy-manager:
container_name: nginx-proxy-manager
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80'
- '443:443'
- '81:81'
volumes:
- ~/docker/data/nginx-proxy-manager/data:/data
- ~/docker/data/nginx-proxy-manager/letsencrypt:/etc/letsencrypt
networks:
- home_network
networks:
home_network:
external: true
Start Nginx Proxy Manager:
"hljs-string">"hljs-built_in">"hljs-built_in">cd ~/docker/compose
docker compose -f nginx-proxy.yml up -d
Access the admin interface at http://your-pi-ip:81 and set up proxy hosts for each service.
For each service, add a proxy host with:
- Domain name:
service.home.internal - Forward hostname/IP: The container name or IP
- Forward port: The internal port of the service
To use .home.internal domains on your devices, either:
- Add entries to your hosts file on each device
- Configure AdGuard Home to handle local DNS resolution (recommended)
Accessing Your Services
On Your Local Network
Using nice local domain names:
- Homer Dashboard:
http://homer.home.internal - Portainer:
http://portainer.home.internal - Jellyfin:
http://jellyfin.home.internal - Nextcloud:
http://nextcloud.home.internal - n8n:
http://n8n.home.internal - AdGuard Home:
http://adguard.home.internal
Or using IP address:
- Homer Dashboard:
http://your-pi-ip:8082 - Portainer:
http://your-pi-ip:9000 - Jellyfin:
http://your-pi-ip:8096 - Nextcloud:
http://your-pi-ip:8080 - n8n:
http://your-pi-ip:5678 - AdGuard Home:
http://your-pi-ip:3000
Remote Access with Tailscale
When away from home, connect to Tailscale and access services using the same local domain names or IP addresses.
Remote Access with Cloudflare Tunnel
Access through your custom domains from anywhere:
- Jellyfin:
https://jellyfin.yourdomain.com - Portainer:
https://portainer.yourdomain.com - Nextcloud:
https://nextcloud.yourdomain.com - n8n:
https://n8n.yourdomain.com - Homer Dashboard:
https://homer.yourdomain.com
Advanced Security Enhancements
Set Up Service-Specific Networks
Modify your docker-compose file to use specific networks for different types of services:
networks:
frontend_network:
driver: bridge
backend_network:
driver: bridge
database_network:
driver: bridge
Then assign services to appropriate networks:
jellyfin:
networks:
- frontend_network
nextcloud:
networks:
- frontend_network
- backend_network
nextcloud-db:
networks:
- database_network
- backend_network
Container Hardening
Add security constraints to your containers:
yourservice:
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp
restart: unless-stopped
Implement Traefik as a Reverse Proxy (Optional)
For more advanced configurations, implement Traefik to handle routing and SSL:
traefik:
container_name: traefik
image: traefik:latest
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ~/docker/configs/traefik:/etc/traefik
command:
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --certificatesresolvers.myresolver.acme.tlschallenge=true
- --certificatesresolvers.myresolver.acme.email=your@email.com
- --certificatesresolvers.myresolver.acme.storage=/etc/traefik/acme.json
Troubleshooting Common Issues
Network Connectivity Issues
| Problem | Possible Solutions |
|---|---|
| Can't SSH into server | • Check IP address is correct • Verify hostname resolution works • Ensure SSH service is running • Check firewall settings |
| Can't access web UIs | • Verify correct ports are open in UFW • Check Docker container is running • Ensure service is bound to correct network interface |
| DNS not working with AdGuard | • Check port 53 is not in use by systemd-resolved • Verify network configuration points to AdGuard • Check AdGuard logs for errors • Try sudo systemctl stop systemd-resolved |
Docker Issues
| Problem | Possible Solutions |
|---|---|
| Container won't start | • Check logs: docker logs container_name• Verify port conflicts: netstat -tulpn• Check volume permissions |
| Permission errors | • Check UID/GID mappings • Fix permissions: chown -R user:group /path/to/volume |
| Resource limitations | • Check resource usage: docker stats• Add memory limits to containers • Monitor with htop |
Cloudflare Tunnel Issues
| Problem | Possible Solutions |
|---|---|
| Tunnel not connecting | • Check cloudflared logs: sudo journalctl -u cloudflared• Verify credentials file exists • Ensure tunnel ID matches in config |
| Cannot access services | • Check DNS records in Cloudflare dashboard • Verify service is running on specified port • Ensure your Access policies are configured correctly |
Maintenance Checklist
To keep your home server running smoothly, perform these maintenance tasks regularly:
Weekly Tasks
- Check disk space:
df -h - Update containers:
docker compose pull && docker compose up -d - Review logs for errors:
docker logs --since 24h container_name
Monthly Tasks
- Update host OS:
sudo apt update && sudo apt upgrade -y - Check for unused containers/images:
docker system prune - Review backup integrity
- Check UPS battery status (if applicable)
Quarterly Tasks
- Change passwords for critical services
- Review port forwarding/firewall rules
- Check hardware (dust, connections, etc.)
- Update documentation of your setup
Community Resources
Get help and inspiration from these community resources:
Forums & Communities
- r/selfhosted - Reddit's self-hosting community
- r/homelab - More advanced home server setups
- Home Assistant Community - Smart home focused
- Jellyfin Forums - Media server discussions
- TrueNAS Forum - Storage-focused discussions
Discord Servers
- Homelab - Home lab discussions
YouTube Channels
- TechnoTim - Great server tutorials
- DB Tech - Docker-focused tutorials
- The Digital Life - Self-hosting guides
What's Next?
You now have a solid foundation for running your own secure private cloud using zero trust principles.
Here are some advanced projects to tackle next:
Advanced Projects
- Automated Backups: Set up Restic or Duplicati to automatically backup important data
- Analytics: Monitor your network with InfluxDB + Grafana for beautiful dashboards
- Home Automation: Connect Home Assistant to your lights, sensors, and more
- CI/CD Pipeline: Set up Gitea + Drone CI for your personal development projects
- Extended Storage: Build a proper NAS with TrueNAS or Unraid
Final Thoughts
Your zero trust home server is more than just a tech project—it's a statement about data ownership and privacy. With Cloudflare Tunnel and Tailscale, you can access your services securely from anywhere without compromising your home network security.
Last updated: April 2025