Introduction
1. The Management Layer: Nginx Proxy Manager (NPM) 🌐
A. Deploy Nginx Proxy Manager
2. The Monitoring Stack 📊
A. Create the Prometheus Configuration
Create the project directory
Create the prometheus.yml file
B. Deploy the Stack with Docker Compose
C. Configure Grafana
3. The Homer Launchpad Dashboard 🚀
Conclusion Welcome to Part 2 of my homelab series! In Part 1, we built a solid foundation by turning an old laptop into a hardened Debian server with Docker. Now that our server is running, we need to deploy services to manage, monitor, and easily access our projects. In this guide, we'll deploy three essential stacks. First, Nginx Proxy Manager (NPM) will act as our server's front door and create a shared network for our containers. Second, we'll set up a professional-grade monitoring stack with Prometheus and Grafana. Finally, we'll deploy a Homer dashboard to create a beautiful and convenient launchpad for all our services. Before we can deploy our other services, we need a way to manage connections between them. NPM will act as our reverse proxy and, crucially, will create the shared Docker network that all our other services will connect to. First, let's create a directory and the docker-compose.yml file for NPM. Paste in the following configuration. This file defines the NPM service and creates a network named npm_default. services: app: image: 'jc21/nginx-proxy-manager:latest' container_name: npm-app-1 restart: unless-stopped ports: - '80:80' - '443:443' - '81:81' volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt
networks: default: name: npm_defaultplaintext docker compose up -dyamlYou can now log in to the admin UI at http://<your-server-ip>:81. With our shared network in place, we can now deploy our monitoring stack. Prometheus: Collects all the metrics. Node Exporter: Exposes the server's hardware metrics. cAdvisor: Exposes Docker container metrics. Grafana: Visualizes all the data in beautiful dashboards. Prometheus needs a config file to know what to monitor. mkdir -p ~/docker/monitoringcd ~/docker/monitoring nano prometheus.yml`plaintext Paste in the following configuration: `global: scrape_interval: 15s Next, create the docker-compose.yml file in the same ~/docker/monitoring directory. nano docker-compose.ymlplaintext This file defines all four monitoring services and tells them to connect to the npm_default network we created earlier. `services: prometheus: image: prom/prometheus:latest container_name: prometheus restart: unless-stopped ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus networks: - default grafana: image: grafana/grafana:latest container_name: grafana restart: unless-stopped ports: - "3001:3000" volumes: - grafana_data:/var/lib/grafana networks: - default node-exporter: image: prom/node-exporter:latest container_name: node-exporter restart: unless-stopped volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--path.rootfs=/rootfs' - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)' networks: - default cadvisor: image: gcr.io/cadvisor/cadvisor:latest container_name: cadvisor restart: unless-stopped ports: - "8081:8080" volumes: - /:/rootfs:ro - /var/run:/var/run:rw - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro networks: - default volumes: prometheus_data: grafana_data: networks: default: name: npm_default external: true`shell Now, launch the stack: Log in to Grafana at http://<your-server-ip>:3001 (default: admin/admin). Import Dashboards: Go to Dashboards > New > Import and add these dashboards by ID: Finally, let's deploy Homer as our beautiful start page with custom icons. Create Directories & Download Icons: First, create a directory for Homer and an assets subdirectory. Then, cd into the assets folder and download the icons. mkdir -p ~/docker/homer/assetscd ~/docker/homer/assetswget -O grafana.png [https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/grafana.png](https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/grafana.png)wget -O prometheus.png [https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/prometheus.png](https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/prometheus.png)wget -O cadvisor.png [https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/cadvisor.png](https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/cadvisor.png)wget -O npm.png [https://nginxproxymanager.com/icon.png](https://nginxproxymanager.com/icon.png) Create Configuration: Go back to the main homer directory and create the config.yml file. cd ~/docker/homernano config.yml Paste in the following configuration. The logo: lines point to the icons we just downloaded. title: "Homelab Dashboard"subtitle: "Server Management"theme: "dark" Create Docker Compose File: Finally, create the docker-compose.yml file. nano docker-compose.yml This configuration connects Homer to our shared network. `services: homer: image: b4bz/homer container_name: homer volumes: - ./config.yml:/www/assets/config.yml - ./assets:/www/assets/tools ports: - "8090:8080" restart: unless-stopped networks: - npm_default networks: npm_default: external: true
` Launch: Run docker compose up -d. You can now access your new dashboard with custom icons at http://<your-server-ip>:8090. Our homelab now has a powerful management and monitoring foundation. Nginx Proxy Manager is ready to direct traffic, Grafana is visualizing our server's health, and Homer provides a central launchpad. In the next part of the series, we'll deploy our core network service, AdGuard Home, and use NPM to create clean, memorable local domains for all the applications we set up today. Stay tuned! Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to ? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse
$ -weight: 500;">docker-compose.yml
# Create the directory
mkdir -p ~/-weight: 500;">docker/-weight: 500;">npm
cd ~/-weight: 500;">docker/-weight: 500;">npm # Create the -weight: 500;">docker-compose.yml
nano -weight: 500;">docker-compose.yml
# Create the directory
mkdir -p ~/-weight: 500;">docker/-weight: 500;">npm
cd ~/-weight: 500;">docker/-weight: 500;">npm # Create the -weight: 500;">docker-compose.yml
nano -weight: 500;">docker-compose.yml
# Create the directory
mkdir -p ~/-weight: 500;">docker/-weight: 500;">npm
cd ~/-weight: 500;">docker/-weight: 500;">npm # Create the -weight: 500;">docker-compose.yml
nano -weight: 500;">docker-compose.yml
npm_default
services: app: image: 'jc21/nginx-proxy-manager:latest' container_name: -weight: 500;">npm-app-1 -weight: 500;">restart: unless-stopped ports: - '80:80' - '443:443' - '81:81' volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt
networks: default: name: npm_default
-weight: 500;">docker compose up -d
http://<your-server-ip>:81
-weight: 500;">docker-compose.yml
~/-weight: 500;">docker/monitoring
nano -weight: 500;">docker-compose.yml
npm_default
-weight: 500;">docker compose up -d
http://<your-server-ip>:3001
http://prometheus:9090
- **Node Exporter Full (ID: `1860`)** - **Docker Host/Container Metrics (ID: `193`)**
- **Node Exporter Full (ID: `1860`)** - **Docker Host/Container Metrics (ID: `193`)**
- **Node Exporter Full (ID: `1860`)** - **Docker Host/Container Metrics (ID: `193`)**
mkdir -p ~/-weight: 500;">docker/homer/assets
cd ~/-weight: 500;">docker/homer/assets
-weight: 500;">wget -O grafana.png [https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/grafana.png](https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/grafana.png)
-weight: 500;">wget -O prometheus.png [https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/prometheus.png](https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/prometheus.png)
-weight: 500;">wget -O cadvisor.png [https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/cadvisor.png](https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/cadvisor.png)
-weight: 500;">wget -O -weight: 500;">npm.png [https://nginxproxymanager.com/icon.png](https://nginxproxymanager.com/icon.png)
cd ~/-weight: 500;">docker/homer
nano config.yml
- name: "Monitoring" icon: "fas fa-chart-bar" items: - name: "Grafana" logo: "assets/tools/grafana.png" subtitle: "Metrics Dashboard" url: "http://<your-server-ip>:3001" - name: "Prometheus" logo: "assets/tools/prometheus.png" subtitle: "Metrics Database" url: "http://<your-server-ip>:9090" - name: "cAdvisor" logo: "assets/tools/cadvisor.png" subtitle: "Container Metrics" url: "http://<your-server-ip>:8081"
```
- name: "Monitoring" icon: "fas fa-chart-bar" items: - name: "Grafana" logo: "assets/tools/grafana.png" subtitle: "Metrics Dashboard" url: "http://<your-server-ip>:3001" - name: "Prometheus" logo: "assets/tools/prometheus.png" subtitle: "Metrics Database" url: "http://<your-server-ip>:9090" - name: "cAdvisor" logo: "assets/tools/cadvisor.png" subtitle: "Container Metrics" url: "http://<your-server-ip>:8081"
```
- name: "Monitoring" icon: "fas fa-chart-bar" items: - name: "Grafana" logo: "assets/tools/grafana.png" subtitle: "Metrics Dashboard" url: "http://<your-server-ip>:3001" - name: "Prometheus" logo: "assets/tools/prometheus.png" subtitle: "Metrics Database" url: "http://<your-server-ip>:9090" - name: "cAdvisor" logo: "assets/tools/cadvisor.png" subtitle: "Container Metrics" url: "http://<your-server-ip>:8081"
```
-weight: 500;">docker-compose.yml
nano -weight: 500;">docker-compose.yml
-weight: 500;">docker compose up -d
http://<your-server-ip>:8090 - Prometheus: Collects all the metrics.
- Node Exporter: Exposes the server's hardware metrics.
- cAdvisor: Exposes Docker container metrics.
- Grafana: Visualizes all the data in beautiful dashboards. - job_name: 'prometheus'
static_configs: targets: ['localhost:9090']
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs: targets: ['node-exporter:9100']
- targets: ['node-exporter:9100']
- job_name: 'cadvisor'
static_configs: targets: ['cadvisor:8080']
`yaml
- targets: ['cadvisor:8080']
`yaml - targets: ['localhost:9090'] - targets: ['node-exporter:9100'] - targets: ['cadvisor:8080']
`yaml - Add Data Source: Go to Connections > Data Sources, add a Prometheus source, and set the URL to http://prometheus:9090.
- Import Dashboards: Go to Dashboards > New > Import and add these dashboards by ID: - Create Directories & Download Icons: First, create a directory for Homer and an assets subdirectory. Then, cd into the assets folder and download the icons. mkdir -p ~/-weight: 500;">docker/homer/assets
cd ~/-weight: 500;">docker/homer/assets
-weight: 500;">wget -O grafana.png [https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/grafana.png](https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/grafana.png)
-weight: 500;">wget -O prometheus.png [https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/prometheus.png](https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/prometheus.png)
-weight: 500;">wget -O cadvisor.png [https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/cadvisor.png](https://raw.githubusercontent.com/walkxcode/dashboard-icons/main/png/cadvisor.png)
-weight: 500;">wget -O -weight: 500;">npm.png [https://nginxproxymanager.com/icon.png](https://nginxproxymanager.com/icon.png)
- Create Configuration: Go back to the main homer directory and create the config.yml file. cd ~/-weight: 500;">docker/homer
nano config.yml Paste in the following configuration. The logo: lines point to the icons we just downloaded. ` title: "Homelab Dashboard"
subtitle: "Server Management"
theme: "dark" services: name: "Management"
icon: "fas fa-server"
items: name: "Nginx Proxy Manager"
logo: "assets/tools/-weight: 500;">npm.png"
subtitle: "Reverse Proxy Admin"
url: "http://:81"
- name: "Management"
icon: "fas fa-server"
items: name: "Nginx Proxy Manager"
logo: "assets/tools/-weight: 500;">npm.png"
subtitle: "Reverse Proxy Admin"
url: "http://:81"
- name: "Nginx Proxy Manager"
logo: "assets/tools/-weight: 500;">npm.png"
subtitle: "Reverse Proxy Admin"
url: "http://:81" - name: "Management"
icon: "fas fa-server"
items: name: "Nginx Proxy Manager"
logo: "assets/tools/-weight: 500;">npm.png"
subtitle: "Reverse Proxy Admin"
url: "http://:81"
- name: "Nginx Proxy Manager"
logo: "assets/tools/-weight: 500;">npm.png"
subtitle: "Reverse Proxy Admin"
url: "http://:81" - name: "Nginx Proxy Manager"
logo: "assets/tools/-weight: 500;">npm.png"
subtitle: "Reverse Proxy Admin"
url: "http://:81" - Create Docker Compose File: Finally, create the -weight: 500;">docker-compose.yml file. nano -weight: 500;">docker-compose.yml This configuration connects Homer to our shared network. `
services: homer: image: b4bz/homer container_name: homer volumes: - ./config.yml:/www/assets/config.yml - ./assets:/www/assets/tools ports: - "8090:8080" -weight: 500;">restart: unless-stopped networks: - npm_default networks: npm_default: external: true
`
- Launch: Run -weight: 500;">docker compose up -d. You can now access your new dashboard with custom icons at http://<your-server-ip>:8090.