Nginx Proxy Manager
Access your home services via a secure URL from anywhere in the world. This guide covers setting up AdGuard Home for custom DNS, Nginx Proxy Manager for wildcard SSL certificates via Cloudflare and Tailscale for a zero-config VPN mesh.
References
Section titled “References”-
Tailscale
Section titled “Tailscale”Setup TailscaleInstall and configure the Tailscale client to establish a secure mesh network and manage node connectivity. -
Docker
Section titled “Docker”Deploy AdGuard Home and Nginx Proxy Manager as containerized services for network filtering and reverse proxying.
-
Make directory
Section titled “Make directory”Terminal window mkdir -p {{DOCKER_PATH_VAR}}/dns-proxy && cd {{DOCKER_PATH_VAR}}/dns-proxy -
compose.yml
Section titled “compose.yml”Terminal window nano compose.ymlcompose.yml services:adguard:image: adguard/adguardhomecontainer_name: adguardrestart: unless-stoppedvolumes:- ./adguard/work:/opt/adguardhome/work- ./adguard/conf:/opt/adguardhome/confnetwork_mode: hostnpm:image: "jc21/nginx-proxy-manager:latest"container_name: npmrestart: unless-stoppednetwork_mode: hostvolumes:- ./npm/data:/data- ./npm/letsencrypt:/etc/letsencryptenvironment:- DB_SQLITE_FILE=/data/database.sqlitecompose.yml services:adguard:image: adguard/adguardhomecontainer_name: adguardrestart: unless-stoppedvolumes:- ./adguard/work:/opt/adguardhome/work- ./adguard/conf:/opt/adguardhome/confnetwork_mode: hostadguardhome-sync:image: ghcr.io/bakito/adguardhome-sync:latestcontainer_name: adguardhome-synccommand: runenvironment:ORIGIN_URL: ${ORIGIN_URL}ORIGIN_USERNAME: ${ORIGIN_USERNAME}ORIGIN_PASSWORD: ${ORIGIN_PASSWORD}REPLICA_URL: ${REPLICA_URL}REPLICA_USERNAME: ${REPLICA_USERNAME}REPLICA_PASSWORD: ${REPLICA_PASSWORD}CRON: "*/10 * * * *"RUN_ON_START: "true"npm:image: "jc21/nginx-proxy-manager:latest"container_name: npmrestart: unless-stoppednetwork_mode: hostvolumes:- ./npm/data:/data- ./npm/letsencrypt:/etc/letsencryptenvironment:- DB_SQLITE_FILE=/data/database.sqlitekeepalived:image: osixia/keepalived:latestcontainer_name: keepalivedrestart: unless-stoppednetwork_mode: hostcap_add:- NET_ADMIN- NET_BROADCAST- NET_RAWvolumes:# optional- ./keepalived/keepalived.conf:/etc/keepalived/keepalived.conf:roenvironment:- KEEPALIVED_STATE=MASTER # MASTER | BACKUP- KEEPALIVED_INTERFACE=enp3s0 # eth0 | enp3s0 | wlan0- KEEPALIVED_VIRTUAL_ROUTER_ID=51- KEEPALIVED_PRIORITY=101- KEEPALIVED_UNICAST_PEERS={{CLIENT_IP_VAR}} # Peers/other devices- KEEPALIVED_VIRTUAL_IPS={{VIRTUAL_IP_VAR}}/24- KEEPALIVED_PASSWORD=${KEEPALIVED_PASSWORD}Terminal window nano .env.env ORIGIN_URL=http://{{SERVER_IP_VAR}}:8080ORIGIN_USERNAME=adminORIGIN_PASSWORD=passwordREPLICA_URL=http://{{CLIENT_IP_VAR}}:8080REPLICA_USERNAME=adminREPLICA_PASSWORD=passwordKEEPALIVED_PASSWORD=passwordkeepalived.conf (Optional)
Terminal window mkdir -p ./keepalived && nano ./keepalived/keepalived.conf./keepalived/keepalived.conf global_defs {enable_script_securityscript_user root}vrrp_script check_adguard {script "/usr/bin/curl -fsS http://{{SERVER_IP_VAR}}:8080/control/status"interval 2weight 2}vrrp_instance VI_1 {state MASTER # MASTER | BACKUPinterface enp3s0 # eth0 | enp3s0 | wlan0virtual_router_id 51priority 101 # MASTER: 101 | BACKUP: 100advert_int 1unicast_peer {# Add peers as necessary# 192.168.100.212 # peer 1# 192.168.100.213 # peer 2}authentication {auth_type PASSauth_pass password # Change max 8 characters}virtual_ipaddress {{{VIRTUAL_IP_VAR}}/24}track_script {check_adguard}}
-
Fix port conflict (53)
Section titled “Fix port conflict (53)”Disable the stub listener
Section titled “Disable the stub listener”Terminal window sudo nano /etc/systemd/resolved.confSet
DNSStubListener=noRestart systemd-resolved
Section titled “Restart systemd-resolved”Terminal window sudo systemctl restart systemd-resolved -
Start container
Section titled “Start container”Terminal window docker compose up -d
-
-
Cloudflare
Section titled “Cloudflare”Generate a scoped API token to automate DNS record management and SSL certificate validation.
- Go to Dashboard > My Profile > API Tokens.
- Create Token: Use the
Edit zone DNS template. - Permissions: Select
Zone|DNS|Edit. - Zone Resources: Select
Include|Specific zone|your-domain.tld.
-
AdGuard Home
Section titled “AdGuard Home”Complete the initial web setup to manage network-wide DNS filtering and security rules.
-
Initial setup
Section titled “Initial setup”- Go to http://localhost:3000 or http://{{SERVER_IP_VAR}}:3000
- Admin Web Interface.
- Listen interface: Select
All interfaces. - Port: Change to
8080.
-
DNS rewrites
Section titled “DNS rewrites”- Go to http://localhost:8080 or http://{{SERVER_IP_VAR}}:8080
- Go to Filters > DNS Rewrites.
- Click Add DNS rewrite.
- Domain name:
*.lan.your-domain.tld. - IP address: Enter your device IP
{{SERVER_IP_VAR}}or virtual IP{{VIRTUAL_IP_VAR}}.
-
Blocklists (optional)
Section titled “Blocklists (optional)”- Preconfigured list
- Go to Filters > DNS Blocklists > Add Blocklist:
Choose from the list.- AdGuard DNS filter
- AdAway Default Blocklist
- HaGeZi’s Pro++ Blocklist
- OISD Blocklist Small
- OISD Blocklist Big
- HaGeZi’s Samsung Tracker Blocklist
- Go to Filters > DNS Blocklists > Add Blocklist:
- Custom list
- Go to Filters > DNS Blocklists > Add Blocklist:
Add a custom list. - Name: Enter a name.
-
URL https://raw.githubusercontent.com/huffmanks/code-share/refs/heads/main/src/files/config/adguard/blocklist.txt
- Go to Filters > DNS Blocklists > Add Blocklist:
- Preconfigured list
-
General settings (optional)
Section titled “General settings (optional)”- Go to Settings > General Settings.
- Use AdGuard
browsing securityweb service. - Use AdGuard
parental controlweb service. - Use
Safe Search.
- Use AdGuard
- Go to Settings > General Settings.
-
DNS settings (optional)
Section titled “DNS settings (optional)”-
Go to Settings > DNS settings.
-
Upstream DNS servers.
https://dns.quad9.net/dns-queryhttps://dns.cloudflare.com/dns-queryhttps://dns.adguard-dns.com/dns-query- Enter the DNS providers above.
- Click
apply.
-
DNS server configuration.
- Enable DNSSEC.
- Click
save.
-
Access Settings > Allowed clients.
100.64.0.0/10{{SUBNET_VAR}}- Add Tailscale and device IP ranges above.
- Leave blank to allow all.
- Click
Save configuration.
-
-
-
Filters (optional)
Section titled “Filters (optional)”-
Go to Filters > Custom filtering rules.
@@||tailscale.com^@@||tailscale.io^@@||log.tailscale.io^||*.church^$denyallow=host.church|life.church|online.church,badfilter- Add domains to allow.
- Click
Apply.
-
-
-
Nginx Proxy Manager
Section titled “Nginx Proxy Manager”Access the administrative dashboard to route incoming traffic and manage SSL certificates for your services.
-
Certificate
Section titled “Certificate”- Go to http://localhost:81 or http://{{SERVER_IP_VAR}}:81
- Go to Certificates > Add Certificate > Let’s Encrypt via DNS.
- Domain Names: Enter
*.lan.your-domain.tld. - DNS Provider: Select
Cloudflare. - Credentials File Content: Replace
dns_cloudflare_api_token=YOUR_CLOUDFLARE_API_KEY. - Agree to terms and click
Save.
-
Proxy host
Section titled “Proxy host”- In NPM, go to Hosts > Proxy Hosts > Add Proxy Host.
- Domain Names:
adguard.lan.your-domain.tld. - Scheme:
http. - Forward IP:
{{SERVER_IP_VAR}}. - Forward Port:
8080. - Block common exploits and Websockets support: toggle to
ON. - SSL Tab: Select the certificate you created.
- Force SSL and HTTP/2 Support: toggle to
ON. - Click
Save.
-
-
Router config
Section titled “Router config”Update the Primary DNS, often located under LAN, DHCP or DNS Settings.
- Primary DNS:
{{SERVER_IP_VAR}}or{{VIRTUAL_IP_VAR}}(Your device’s Local LAN IP or virtual IP, not the Tailscale one). - Secondary DNS:
1.1.1.1(Fail-safe so your internet still works if your device is turned off).
- Primary DNS: