My Homelab Journey: Step-by-Step Guide with Raspberry Pi - Part 2


Welcome back! After setting up Docker and Docker Compose in the first part, it’s time to move on to the fun stuff: Portainer, Nginx Proxy Manager (NPM), and AdGuard Home. These tools will take my homelab to the next level, helping me manage containers, secure services with SSL, and handle DNS issues like a pro. Let me walk you through what I did.
Portainer: Simplifying Docker Management
I love how Docker makes managing containers easy, but typing commands every time can get tedious. That’s where Portainer comes in! It’s a web-based tool that lets me manage Docker with just a few clicks.
Setting Up Portainer
First, let’s create a volume to store Portainer’s database:
docker volume create portainer_data
Next, download and install the Portainer Server container:
docker run -d \
-p 8000:8000 \
-p 9443:9443 \
-p 9000:9000 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:2.21.4
Once done, open your browser and navigate to:
https://<your-pi-address-or-hostname>:9443
In my case, I used https://pifour.local:9000
.
Setting Up Nginx Proxy Manager for SSL Certificates
After getting Portainer set up, I turned my attention to Nginx Proxy Manager (NPM). Why? Because I wanted to access my services with nice, clean URLs (like app.localdomain.com
) and secure them with SSL certificates.
Why a Domain Name?
I bought a domain name specifically for local use. The domain is mapped to the Raspberry Pi’s local IP address. This setup allows me to generate SSL certificates and bypass potential DNS rebinding issues.
Why NPM?
Here’s why I’m loving NPM:
Custom Domains: No more memorizing IPs and ports.
SSL Made Easy: Let’s Encrypt certificates with a few clicks.
Simple UI: Setting up reverse proxies is super straightforward.
Installing Nginx Proxy Manager
We’ll create a stack from the Portainer dashboard:
Go to Portainer Dashboard.
Click "Add Stack."
Add the
docker-compose.yml
content from Nginx Proxy Manager’s setup page. Here’s the content for reference:
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80' # HTTP
- '443:443' # HTTPS
- '81:81' # Admin UI
environment:
DB_MYSQL_HOST: "db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD: "npm"
DB_MYSQL_NAME: "npm"
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
depends_on:
- db
db:
image: 'yobasystems/alpine-mariadb:latest'
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: 'npm'
MYSQL_DATABASE: 'npm'
MYSQL_USER: 'npm'
MYSQL_PASSWORD: 'npm'
volumes:
- ./mysql:/var/lib/mysql
Note: The yobasystems/alpine-mariadb
image is used here because it supports ARM devices like the Raspberry Pi.
After deploying the stack, visit: http://<your-pi-address-or-hostname>:81
Default Credentials:
Email: admin@example.com
Password: changeme
Update your details and password after logging in.
Configuring SSL and Fixing DNS Rebinding
One challenge I faced was DNS rebinding. This happens when trying to access local domains, and some routers block them for security reasons. To fix this and improve my network’s DNS, I installed AdGuard Home.
Setting Up AdGuard Home
AdGuard Home is fantastic for blocking ads and resolving DNS issues like rebinding protection.
Here’s how I set it up:
- Create a New Stack in Portainer
Add a new stack with the followingdocker-compose.yml
configuration:
services:
adguardhome:
image: adguard/adguardhome
container_name: adguardhome
restart: unless-stopped
ports:
- "8080:80/tcp" # HTTP interface (use alternative ports to avoid conflicts)
- "8443:443/tcp" # HTTPS interface (use alternative ports to avoid conflicts)
volumes:
- /data/adguard-home/work:/opt/adguardhome/work
- /data/adguard-home/confdir:/opt/adguardhome/conf
Since Nginx Proxy Manager is already using ports 80 and 443, I mapped AdGuard Home to 8080 and 8443.
Visit AdGuard’s Setup Page
After deploying the stack, visithttp://<your-pi-address-or-hostname>:8080
to complete the initial setup.Set AdGuard as Your Router’s DNS:
Update your router’s DHCP settings to use AdGuard for DNS. For instance, with Freebox OS, you can easily configure the DNS settings in the router's admin panel. The process will be similar for most routers.Fixing DNS Rebinding
To resolve DNS rebinding issues and ensure smooth access to your local services, follow these steps:
Configure DNS Rewrites in AdGuard
In AdGuard Home, go to Filters → DNS Rewrites, and add your domain along with the Pi’s local IP address. This will ensure local access to your services without DNS rebinding errors.SSL Setup for Local Domains
To securely use your local domains, I used Cloudflare to manage SSL certificates.you can follow this topic that explain well this step sHere’s a summary of the steps:Buy a domain from a registrar (I used Namecheap).
Set up DNS in Cloudflare to point to the Raspberry Pi’s local IP address.
Adding SSL Certificates and Proxy Hosts in NPM
Step 1: Connect AdGuard to NPM
Before setting up SSL for AdGuard (or any other service), ensure it’s connected to NPM:
Go to Portainer → Containers and find the
nginx_proxy_manager-app-1
container (or your NPM container name).Scroll down to the Connected Networks section.
Join the AdGuard network so NPM can communicate with it.
Step 2: Add an SSL Certificate
Open Nginx Proxy Manager (NPM).
Go to SSL Certificates and click Add SSL Certificate.
Use Let's Encrypt with Cloudflare DNS to validate the certificate.
- Make sure your domain & subdomain is already set up in Cloudflare and points to your local IP.
Step 3: Create a Proxy Host
In NPM, navigate to Hosts → Proxy Hosts and click Add Proxy Host.
Fill in the details:
Domain Name: Enter the domain or subdomain (e.g., adguard.localdomain.com).
Forward Hostname/IP: Enter the local IP of the service (e.g., your Raspberry Pi’s IP).
Forward Port: Enter the port where the service is running.
Go to the SSL Tab and select the SSL certificate you created earlier.
Enable the following options for better security and performance:
Force SSL (redirects all traffic to HTTPS).
HTTP/2 Support (makes things faster and smoother).
Save your settings.
Step 4: Test Your Setup
Open your browser and visit the domain or subdomain you just set up. You should see the service running securely over HTTPS.
Step 5: Repeat for Other Services
For each additional service, follow the same process:
Make sure the service is connected to NPM’s network in Portainer.
Add a proxy host in NPM with the correct domain, IP, port, and SSL certificate.
That’s it! Your services are now secured and easily accessible with clean, HTTPS-enabled URLs. 🎉
Trying Out an App: Wallos
With everything set up, it’s time to have some fun and test an app! I decided to try Wallos, a handy tool for managing subscriptions. Here’s how I got it up and running:
Step 1: Add Wallos in Portainer
In Portainer, create a new stack and use the following configuration:
yamlCopier le codeservices:
wallos:
container_name: wallos
image: bellamy/wallos:latest
ports:
- "8282:80"
volumes:
- './db:/var/www/html/db'
- './logos:/var/www/html/images/uploads/logos'
restart: unless-stopped
Step 2: Connect Wallos to NPM
Once the stack is deployed, connect Wallos to the Nginx Proxy Manager network:
Go to Portainer → Containers and locate the
wallos
container.Scroll to the Connected Networks section and join the network used by Nginx Proxy Manager.
Step 3: Create a Proxy Host for Wallos
In NPM, set up a new proxy host:
Enter your domain name (e.g.,
wallos.localdomain.com
).Set the local IP and port (
8282
) for the Wallos container.Select your SSL certificate, enable Force SSL, and save.
Step 4: Test Wallos
Now, open your browser and visit the domain you set up. You should see Wallos ready to manage your subscriptions securely and efficiently! 🎉
Wrapping Up
This journey has been an incredible learning experience. From fixing tricky DNS rebinding issues to configuring SSL for local domains, every step was a mix of challenges and triumphs. Each error pushed me to explore new concepts, and the solutions taught me skills I never thought I’d need.
But this is just the beginning! There’s so much more to discover in the world of homelabs, and I can’t wait to see where this adventure takes me next. 🚀
Subscribe to my newsletter
Read articles from Ayoub Touba directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Ayoub Touba
Ayoub Touba
With over a decade of hands-on experience, I specialize in building robust web applications and scalable software solutions. My expertise spans across cutting-edge frameworks and technologies, including Node.js, React, Angular, Vue.js, and Laravel. I also delve into hardware integration with ESP32 and Arduino, creating IoT solutions.