# 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:

```bash
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`.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733597485517/3203e535-8830-496a-ae40-3be888c2f230.png align="center")

---

## 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`](http://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:

1. **Go to Portainer Dashboard.**
    
2. **Click "Add Stack."**
    
3. ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733597510658/611e6a9d-6cad-4758-a702-8e24cfb66e54.png align="center")
    
    **Add the** `docker-compose.yml` content from [Nginx Proxy Manager’s setup page](https://nginxproxymanager.com/setup/). Here’s the content for reference:
    

```dockerfile
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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733689715814/1c5cf959-6627-4465-9d12-4cab11f6c55e.png align="center")

---

### 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:

1. **Create a New Stack in Portainer**  
    Add a new stack with the following `docker-compose.yml` configuration:
    

```dockerfile
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**.

2. **Visit AdGuard’s Setup Page**  
    After deploying the stack, visit `http://<your-pi-address-or-hostname>:8080` to complete the initial setup.
    
3. **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.
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733597897142/33e6f5a3-7cbd-47a2-9b4a-83376abdf404.png align="center")
    
    ### Fixing DNS Rebinding
    
    To resolve DNS rebinding issues and ensure smooth access to your local services, follow these steps:
    
    1. **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.
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733690200867/c017acc4-0ee2-410f-bd4d-8f7f803ceee5.png align="center")
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733690205727/ddd97925-ec3e-40a1-9639-d82a8338793a.png align="center")
        
    2. **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](https://medium.com/@life-is-short-so-enjoy-it/homelab-nginx-proxy-manager-setup-ssl-certificate-with-domain-name-in-cloudflare-dns-732af64ddc0b) 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:

1. Go to **Portainer → Containers** and find the `nginx_proxy_manager-app-1` container (or your NPM container name).
    
2. Scroll down to the **Connected Networks** section.
    
3. Join the AdGuard network so NPM can communicate with it.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733691667996/9df941d7-4566-43db-b80c-a1e1c00f1d1e.png align="center")

#### **Step 2: Add an SSL Certificate**

1. Open **Nginx Proxy Manager (NPM)**.
    
2. Go to **SSL Certificates** and click **Add SSL Certificate**.
    
3. 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**

1. In NPM, navigate to **Hosts → Proxy Hosts** and click **Add Proxy Host**.
    
2. Fill in the details:
    
    * **Domain Name**: Enter the domain or subdomain (e.g., [adguard.localdomain.com](http://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.
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733691751345/390b07bb-e965-4161-b347-5722f8b05f1d.png align="center")
        
3. Go to the **SSL Tab** and select the SSL certificate you created earlier.
    
4. Enable the following options for better security and performance:
    
    * **Force SSL** (redirects all traffic to HTTPS).
        
    * **HTTP/2 Support** (makes things faster and smoother).
        
5. 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.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733691765345/06947181-e221-496d-9675-80f9b7d9ccea.png align="center")

#### **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:

```dockerfile
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:

1. Go to **Portainer → Containers** and locate the `wallos` container.
    
2. 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`](http://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! 🎉

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733598089569/f0197804-bce3-4435-9ad6-0ad62bd710e2.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1733598099727/c74db07f-ad45-4c02-a73d-108f7ccf2303.png align="center")

## 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. 🚀
