Advanced Setup: Portainer and NPM
This tutorial covers an advanced deployment scenario using Portainer for container management and Nginx Proxy Manager (NPM) as a reverse proxy.
This setup is ideal for users who want: - A GUI to manage Docker containers (Portainer). - Automatic SSL/TLS certificates (NPM + Let's Encrypt). - Optimized Nginx configuration for PiGallery2. - A shared configuration structure.
Prerequisites
- Docker and Docker Compose installed on your server.
- A Domain Name with DNS records pointing to your server's IP address.
- Ports 80 and 443 open on your firewall.
Preparation
It is recommended to keep all configuration files in a centralized location for easy backups.
mkdir -p ~/configs/nginx-proxy-manager/data
mkdir -p ~/configs/nginx-proxy-manager/letsencrypt
mkdir -p ~/configs/pigallery2/config
1. Portainer Setup
Portainer provides a web UI for managing Docker stacks, containers, and networks.
Deploy Portainer
Run the following command to start Portainer:
docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
Access it at https://<your-server-ip>:9443.
2. Shared Network
To allow NPM to communicate with other containers, we use a shared Docker network named frontend.
In Portainer, go to Networks -> Add network:
- Name: frontend
- Driver: bridge
3. Nginx Proxy Manager (NPM) Stack
NPM will handle SSL termination and routing.
In Portainer, create a new Stack (Docker Compose) named nginx-proxy-manager:
version: '3.8'
services:
app:
container_name: nginx-proxy-manager
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- /home/<user>/configs/nginx-proxy-manager/data:/data
- /home/<user>/configs/nginx-proxy-manager/letsencrypt:/etc/letsencrypt
networks:
- frontend
networks:
frontend:
external: true
<user> with your actual username.
4. PiGallery2 Stack
Deploy PiGallery2 and connect it to the frontend network.
Create a new Stack named pigallery2 and copy the content of this compose file (original):
version: '3'
services:
pigallery2:
image: bpatrik/pigallery2:latest
container_name: pigallery2
deploy:
resources:
limits:
memory: 3G # <1GB RAM might also work. It will trigger GC more often. GC is slow. See https://github.com/bpatrik/pigallery2/issues/1080
environment:
- NODE_ENV=production
- # - NODE_OPTIONS=--enable-source-maps # enable source map support on the backend for development
volumes:
- "/home/<user>/configs/pigallery2/config:/app/data/config"
- "db-data:/app/data/db"
- "/mnt/images:/app/data/images:ro" # Path to your photos
- "/mnt/pigallery2-tmp:/app/data/tmp" # Path to a tmp folder
expose:
- "80"
restart: always
networks:
- frontend
volumes:
db-data:
networks:
frontend:
external: true
5. Configuring NPM
Access the NPM admin interface at http://<your-server-ip>:81.
Add PiGallery2 Proxy Host
- Domain Names:
photos.yourdomain.com - Scheme:
http - Forward Hostname / IP:
pigallery2 - Forward Port:
80 - SSL Tab: Select "Request a new SSL Certificate", enable "Force SSL" and "HTTP/2 Support".
Advanced Tab
Paste the following to enable Gzip compression and handle API/UI routing correctly:
gzip on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/css
text/plain
text/javascript
text/markdown
application/javascript
application/json
application/gpx+xml
application/x-javascript
application/xml
application/xml+rss
application/xhtml+xml
application/x-font-ttf
application/x-font-opentype
application/vnd.ms-fontobject
image/svg+xml
image/x-icon
application/rss+xml
application/atom_xml;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
# API handles all methods (GET, POST, PUT, DELETE, etc.)
location /pgapi {
proxy_pass http://pigallery2:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# UI is restricted to GET for security
location / {
limit_except GET {
deny all;
}
proxy_pass http://pigallery2:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
Summary
With this setup, you have: - Portainer to easily manage and update your containers. - Nginx Proxy Manager providing SSL and routing. - PiGallery2 securely accessible via your own subdomain. - A shared Docker network allowing internal communication between the proxy and the app.




