Installation guide for setting up Home Assistant, AdGuard Home, Pi-hole, Nginx Proxy Manager, and Portainer as Docker containers in an Ubuntu LXC container on a Proxmox VE server. The setup includes a reverse proxy using Nginx Proxy Manager and a Cloudflare Tunnel for secure external access. Portainer will be added to manage all Docker containers. This guide assumes you’re starting from scratch and includes specific commands and configurations.
Step 1: Prepare the Ubuntu LXC Container
- Access Proxmox VE:
- Log in to your Proxmox web interface (e.g.,
https://proxmox-ip:8006
). - Ensure an Ubuntu LXC container (or VM) is set up. If not, create one:
- Select “Create CT” in Proxmox.
- Choose Ubuntu (e.g., 22.04 LTS or 24.04 LTS) template.
- Allocate resources (e.g., 2 CPU cores, 4GB RAM, 20GB storage).
- Enable Docker-compatible features: Enable “Nesting” and “FUSE” in the container options.
- Access the Ubuntu Container:
- SSH into the container:
ssh user@container-ip
(replaceuser
andcontainer-ip
with your credentials/IP). - Alternatively, use the Proxmox console.
- Update and Install Docker:
- Update the package list:
sudo apt update && sudo apt upgrade -y
. - Install Docker and Docker Compose:
bash sudo apt install docker.io docker-compose -y sudo systemctl enable docker sudo systemctl start docker
- Add your user to the Docker group:
sudo usermod -aG docker $USER
, then log out and back in.
- Create a Project Directory:
- Create a directory for all Docker configurations:
bash mkdir ~/homelab && cd ~/homelab
Step 2: Set Up Docker Compose with All Services
- Create the Docker Compose File:
- Create a
docker-compose.yml
file:nano docker-compose.yml
. - Add the following configuration, which includes Home Assistant, AdGuard Home, Pi-hole, Nginx Proxy Manager, and Portainer. Replace
Your/Timezone
(e.g.,America/New_York
) andyour_pihole_password
with your desired values.
version: ‘3.8’
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: homeassistant
restart: unless-stopped
ports:
– “8123:8123” # Internal port for Home Assistant
volumes:
– ./homeassistant:/config
environment:
– TZ=Your/Timezone
adguard:
image: adguard/adguardhome:latest
container_name: adguard
restart: unless-stopped
ports:
– “1053:53/tcp” # Avoid port 53 conflict with Pi-hole
– “1053:53/udp”
– “3000:3000” # Web UI (internal)
volumes:
– ./adguard/workdir:/opt/adguardhome/work
– ./adguard/confdir:/opt/adguardhome/conf
pihole:
image: pihole/pihole:latest
container_name: pihole
restart: unless-stopped
ports:
– “53:53/tcp” # DNS port
– “53:53/udp”
– “8080:80/tcp” # Web UI (avoid conflict with NPM)
environment:
– TZ=Your/Timezone
– WEBPASSWORD=your_pihole_password
volumes:
– ./pihole/etc-pihole:/etc/pihole
– ./pihole/etc-dnsmasq.d:/etc/dnsmasq.d
npm:
image: jc21/nginx-proxy-manager:latest
container_name: npm
restart: unless-stopped
ports:
– “80:80” # HTTP
– “443:443” # HTTPS
– “81:81” # NPM admin UI
volumes:
– ./npm/data:/data
– ./npm/letsencrypt:/etc/letsencrypt
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
restart: unless-stopped
ports:
– “9000:9000” # Portainer Web UI (internal)
volumes:
– /var/run/docker.sock:/var/run/docker.sock
– ./portainer/data:/data
environment:
– TZ=Your/Timezone
- Notes on Configuration:
- Port Conflicts: Pi-hole uses port 53 for DNS, so AdGuard uses port 1053 to avoid conflicts. Pi-hole’s web UI is moved to 8080 to avoid clashing with Nginx Proxy Manager’s port 80.
- Volumes: Persistent data is stored in
~/homelab/<service>
directories (e.g.,./homeassistant
). - Portainer: Maps to port 9000 for its web UI and connects to Docker via
/var/run/docker.sock
.
- Start the Containers:
- Run:
docker compose up -d
. - Verify containers are running:
docker ps
. You should see five containers:homeassistant
,adguard
,pihole
,npm
, andportainer
.
- Test Local Access:
- Home Assistant:
http://container-ip:8123
- AdGuard Home:
http://container-ip:3000
- Pi-hole:
http://container-ip:8080/admin
- Nginx Proxy Manager:
http://container-ip:81
(default login:admin@example.com
, password:changeme
) - Portainer:
http://container-ip:9000
(set up admin user on first login)
Step 3: Configure Nginx Proxy Manager (Reverse Proxy)
- Access Nginx Proxy Manager:
- Open
http://container-ip:81
in a browser. - Log in with default credentials (update the password immediately).
- Add Proxy Hosts:
- In NPM, go to “Hosts” → “Proxy Hosts” → “Add Proxy Host”.
- Configure each service:
- Home Assistant:
- Domain:
ha.yourdomain.com
- Scheme:
http
- Forward Host:
homeassistant
- Forward Port:
8123
- Enable “Block Common Exploits” and “Websockets Support”.
- AdGuard Home:
- Domain:
adguard.yourdomain.com
- Scheme:
http
- Forward Host:
adguard
- Forward Port:
3000
- Pi-hole:
- Domain:
pi.yourdomain.com
- Scheme:
http
- Forward Host:
pihole
- Forward Port:
80
- Portainer:
- Domain:
portainer.yourdomain.com
- Scheme:
http
- Forward Host:
portainer
- Forward Port:
9000
- For each, request an SSL certificate via NPM’s “SSL” tab (select “Request a new certificate” with Let’s Encrypt, enable “Force SSL”).
- Update Docker Compose for External Access:
- Edit
docker-compose.yml
to remove conflicting ports (only NPM needs 80/443 exposed externally). Update the ports section:yaml services: homeassistant: ports: [] # Remove 8123 adguard: ports: - "1053:53/tcp" - "1053:53/udp" # Remove 3000 pihole: ports: - "53:53/tcp" - "53:53/udp" # Remove 8080 npm: ports: - "80:80" - "443:443" - "81:81" portainer: ports: [] # Remove 9000
- Apply changes:
docker compose down && docker compose up -d
.
Step 4: Set Up Cloudflare Tunnel
- Install cloudflared:
- In the Ubuntu container, install the Cloudflare daemon:
bash wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb sudo dpkg -i cloudflared-linux-amd64.deb
- Authenticate with Cloudflare:
- Run:
cloudflared tunnel login
. - A browser window opens; log in to Cloudflare and authorize the tunnel.
- Create a Tunnel:
- Create a tunnel:
cloudflared tunnel create homelab-tunnel
. - Note the tunnel UUID and credentials file path (e.g.,
/root/.cloudflared/<tunnel-uuid>.json
).
- Configure the Tunnel:
- Create a configuration file:
nano ~/.cloudflared/config.yml
. - Add:
tunnel: homelab-tunnel
credentials-file: /root/.cloudflared/.json
ingress: - hostname: ha.yourdomain.com
service: http://npm:80 - hostname: adguard.yourdomain.com
service: http://npm:80 - hostname: pi.yourdomain.com
service: http://npm:80 - hostname: portainer.yourdomain.com
service: http://npm:80 - service: http_status:404
- Replace
<tunnel-uuid>
with your actual tunnel UUID.
- Route DNS in Cloudflare:
- For each subdomain, create a CNAME record in the Cloudflare dashboard pointing to
<tunnel-uuid>.cfargotunnel.com
. Example:ha.yourdomain.com
→<tunnel-uuid>.cfargotunnel.com
- Repeat for
adguard
,pi
, andportainer
.
- Alternatively, use:
cloudflared tunnel route dns homelab-tunnel ha.yourdomain.com
(repeat for each subdomain).
- Run the Tunnel:
- Start the tunnel:
cloudflared tunnel run homelab-tunnel
. - For persistence, set up as a systemd service:
bash sudo cloudflared service install sudo systemctl enable cloudflared sudo systemctl start cloudflared
Step 5: Configure Portainer for Docker Management
- Access Portainer:
- Initially, access Portainer at
http://container-ip:9000
. - After reverse proxy setup, use
https://portainer.yourdomain.com
. - On first login, create an admin user and password.
- Manage Containers:
- In Portainer, go to “Environments” and ensure the local Docker environment is connected (it uses
/var/run/docker.sock
). - Navigate to “Containers” to view and manage all Docker containers (Home Assistant, AdGuard, Pi-hole, NPM).
- Use Portainer to start/stop containers, view logs, or update images (e.g.,
docker pull
equivalent).
- Optional: Stack Management:
- In Portainer, go to “Stacks” → “Add Stack”.
- Copy the
docker-compose.yml
content into the web editor to manage the entire setup as a stack. - This allows you to update all services via Portainer’s UI instead of the command line.
Step 6: Post-Setup Configuration
- DNS Configuration:
- Pi-hole: Access
https://pi.yourdomain.com/admin
. Set as your router’s primary DNS for network-wide ad blocking. - AdGuard Home: Access
https://adguard.yourdomain.com
. Use as a secondary DNS (port 1053) or configure Pi-hole to forward to AdGuard. - To avoid conflicts, consider running only one DNS service or configuring them in tandem (e.g., Pi-hole as primary, AdGuard as upstream).
- Security:
- Update all service passwords (Home Assistant, Pi-hole, AdGuard, Portainer, NPM).
- In Proxmox, restrict firewall rules to allow only ports 80, 443, and 81 inbound.
- Enable 2FA in Cloudflare for added security.
- Backups:
- Back up Docker volumes (
~/homelab/<service>
) to Proxmox storage or an external location. - Use Portainer’s “Volumes” section to inspect and manage data.
- Testing:
- Verify external access:
- Home Assistant:
https://ha.yourdomain.com
- AdGuard:
https://adguard.yourdomain.com
- Pi-hole:
https://pi.yourdomain.com/admin
- Portainer:
https://portainer.yourdomain.com
- Home Assistant:
- Check logs if issues arise:
docker compose logs -f <service-name>
or use Portainer’s log viewer.
Step 7: Troubleshooting Tips
- Port Conflicts: Ensure no services bind to the same ports (e.g., only NPM uses 80/443 externally).
- Cloudflare Tunnel Issues: Verify CNAME records and tunnel status (
cloudflared tunnel info homelab-tunnel
). - Docker Issues: Use Portainer’s “Containers” view or
docker ps -a
to check container status. - Logs: Access detailed logs via Portainer or
docker logs <container-name>
.
Total Containers
This setup includes five Docker containers:
- Home Assistant
- AdGuard Home
- Pi-hole
- Nginx Proxy Manager
- Portainer
Additional Notes
- Refer to official documentation for specific service configurations:
- Home Assistant: https://www.home-assistant.io
- Pi-hole: https://pi-hole.net
- AdGuard Home: https://adguard.com/adguard-home
- Portainer: https://docs.portainer.io
- Nginx Proxy Manager: https://nginxproxymanager.com
- Ensure your domain is correctly set up in Cloudflare before configuring the tunnel.
- Test each service locally before enabling the reverse proxy and Cloudflare Tunnel.
- Regularly update containers via Portainer or
docker compose pull && docker compose up -d
.
This guide provides a complete setup with Portainer for easy management, accessible securely via Cloudflare Tunnel. Let me know if you need specific tweaks or further clarification!
https://grok.com/share/c2hhcmQtMw%3D%3D_d07e38a3-c7ad-42d8-8479-c49583c6b66a