Prerequisites
- Debian 11/12 or Ubuntu 22.04+ VPS with root access
- Docker and Docker Compose installed (see the Docker guide)
- Ports 80, 81 and 443 open
- A domain name pointing to your VPS IP
Step 1: Prepare the environment
Create a folder for NPM:
sudo mkdir -p /opt/nginx-proxy-manager
cd /opt/nginx-proxy-manager
Step 2: docker-compose file
Create the docker-compose.yml file:
sudo nano docker-compose.yml
Paste the following:
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
environment:
DISABLE_IPV6: 'false'
Step 3: Start the container
sudo docker compose up -d
Check the container is running:
sudo docker ps
Step 4: First login
Open your browser at:
http://YOUR_VPS_IP:81
Default credentials:
- Email:
[email protected] - Password:
changeme
Important: change the email and password immediately on first login.
Step 5: Add a Proxy Host
Click Hosts → Proxy Hosts → Add Proxy Host.
Fill in:
- Domain Names:
app.your-domain.com - Scheme:
http - Forward Hostname / IP: the internal IP or hostname of the service (e.g.
172.17.0.1for the host, or another Docker container name) - Forward Port: the service port (e.g.
3000) - Check Block Common Exploits
- Check Websockets Support if the service uses WebSocket
Step 6: Enable Let's Encrypt SSL
In the SSL tab of the same proxy host:
- SSL Certificate:
Request a new SSL Certificate - Check Force SSL
- Check HTTP/2 Support
- Check HSTS Enabled
- Enter your email for Let's Encrypt
- Accept the terms
Click Save. NPM contacts Let's Encrypt, validates the domain and installs the certificate automatically.
Step 7: Secure access to the NPM interface
Port 81 exposes the admin interface. Block public access via UFW:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow from YOUR_FIXED_IP to any port 81
sudo ufw enable
Step 8: Configure a Stream (TCP/UDP)
To proxy a non-HTTP service (Minecraft, remote database, etc.):
Hosts → Streams → Add Stream
- Incoming Port: public port (e.g. 25565 for Minecraft)
- Forward Host: target server IP
- Forward Port: service port
- TCP / UDP depending on the protocol
Troubleshooting
"502 Bad Gateway"
The service behind the proxy is unreachable. Check:
sudo docker exec -it nginx-proxy-manager ping SERVICE_IP
On Docker, use the container name or host.docker.internal rather than a fixed IP.
Let's Encrypt certificate generation fails
Verify port 80 is open and your domain points to the VPS IP:
dig +short your-domain.com
Cloudflare must be in DNS only mode (grey cloud) during certificate generation, not proxy mode.
Container crashes
Inspect the logs:
sudo docker logs nginx-proxy-manager --tail 100
Useful commands
# Real-time logs
sudo docker logs -f nginx-proxy-manager
# Restart NPM
sudo docker compose restart
# Update NPM
sudo docker compose pull && sudo docker compose up -d
# Backup config
sudo tar -czf npm-backup-$(date +%F).tar.gz data letsencrypt
Conclusion
Nginx Proxy Manager dramatically simplifies the management of a multi-domain reverse proxy. Combined with Docker, you can now host as many services as your VPS can handle, each with its own SSL certificate and subdomain.
Resources
- Official site: https://nginxproxymanager.com
- GitHub: https://github.com/NginxProxyManager/nginx-proxy-manager
- VeryCloud guide — Docker: https://verycloud.fr/docs/article/install-docker-linux


















