7.5 KiB
NPM Configuration for Docker Registry (registry.directlx.dev)
Overview
This guide configures Nginx Proxy Manager to proxy registry.directlx.dev to the backend Docker registry at 192.168.200.200:5000 with HTTPS/SSL termination.
Prerequisites
- ✅ DNS configured: registry.directlx.dev → 192.168.200.71
- ✅ NPM running at 192.168.200.71
- ✅ Docker registry running at 192.168.200.200:5000
- ⚠️ NPM admin access required
Step-by-Step Configuration
1. Access NPM Admin Panel
# Open in browser
http://192.168.200.71:81/
# Default credentials (if first time):
# Email: admin@example.com
# Password: changeme
2. Create Proxy Host
Navigate to: Hosts → Proxy Hosts → Add Proxy Host
Details Tab
Domain Names:
registry.directlx.dev
Scheme: http
Forward Hostname / IP: 192.168.200.200
Forward Port: 5000
Options:
- ☐ Cache Assets
- ☑ Block Common Exploits
- ☑ Websockets Support (for Docker registry v2 API)
- ☐ Access List
SSL Tab
SSL Certificate:
- Select existing Let's Encrypt certificate for
*.directlx.dev, OR - Request New SSL Certificate:
- ☑ Force SSL
- ☑ HTTP/2 Support
- ☑ HSTS Enabled
- ☑ HSTS Subdomains
- Email:
your-email@example.com - ☑ I Agree to the Let's Encrypt Terms of Service
Note: If using wildcard certificate, ensure DNS challenge is configured.
Advanced Tab (IMPORTANT for Docker Registry)
Add the following custom Nginx configuration:
# Docker Registry v2 API requires specific headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Increase timeouts for large image pushes
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;
# Disable buffering for chunked uploads
proxy_request_buffering off;
# Allow large body sizes for Docker images (5GB max)
client_max_body_size 5120M;
# Disable access log for registry (too verbose)
access_log off;
3. Save and Test
Click Save to create the proxy host.
4. Verify Configuration
Test DNS Resolution
nslookup registry.directlx.dev
# Should return: 192.168.200.71
Test HTTPS Access
curl -I https://registry.directlx.dev/v2/
# Expected: HTTP/2 200
Test Docker Registry API
# List repositories
curl -s https://registry.directlx.dev/v2/_catalog | jq '.'
# Expected output:
# {
# "repositories": [
# "atm-incident-backend",
# "hiveops-incident",
# ...
# ]
# }
Test Docker Pull
docker pull registry.directlx.dev/hiveops-incident:latest
Troubleshooting
502 Bad Gateway
Cause: NPM can't reach backend registry
Check backend is running:
ansible docker -m shell -a "docker ps | grep registry"
ansible docker -m shell -a "curl -I http://localhost:5000/v2/"
Check firewall:
ansible docker -m shell -a "ufw status" -b
SSL Certificate Error
Cause: Let's Encrypt can't verify domain
Solution:
- Ensure port 80/443 are open on NPM server
- Verify DNS propagation:
nslookup registry.directlx.dev - Check NPM logs: Tools → Error Logs
413 Request Entity Too Large
Cause: client_max_body_size too small
Solution: Add to Advanced tab:
client_max_body_size 5120M;
Connection Timeout on Large Pushes
Cause: Timeout values too low
Solution: Add to Advanced tab:
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;
Docker Push Hangs
Cause: Request buffering enabled
Solution: Add to Advanced tab:
proxy_request_buffering off;
Docker Client Configuration
No Additional Configuration Required
With HTTPS enabled, Docker will work without insecure registry configuration:
# Just works!
docker pull registry.directlx.dev/my-image:latest
docker push registry.directlx.dev/my-image:latest
Legacy HTTP Configuration (NOT RECOMMENDED)
If you need HTTP-only access (not recommended):
Edit /etc/docker/daemon.json:
{
"insecure-registries": ["registry.directlx.dev"]
}
Restart Docker:
sudo systemctl restart docker
Testing the Complete Setup
1. Tag and Push Test Image
# Pull a small test image
docker pull alpine:latest
# Tag for your registry
docker tag alpine:latest registry.directlx.dev/test-alpine:latest
# Push to registry
docker push registry.directlx.dev/test-alpine:latest
2. Verify Upload
# Check repository exists
curl -s https://registry.directlx.dev/v2/_catalog | jq '.repositories[] | select(. == "test-alpine")'
# Check tags
curl -s https://registry.directlx.dev/v2/test-alpine/tags/list | jq '.'
3. Pull from Another Machine
# Remove local image
docker rmi registry.directlx.dev/test-alpine:latest
# Pull from registry
docker pull registry.directlx.dev/test-alpine:latest
# Verify
docker images | grep test-alpine
4. Cleanup
# Remove test image from local
docker rmi alpine:latest registry.directlx.dev/test-alpine:latest
NPM Configuration Summary
| Setting | Value |
|---|---|
| Domain | registry.directlx.dev |
| Scheme | http |
| Forward Host | 192.168.200.200 |
| Forward Port | 5000 |
| SSL | Enabled (Let's Encrypt) |
| Force SSL | Yes |
| HTTP/2 | Yes |
| HSTS | Yes |
| Max Body Size | 5120M |
| Timeouts | 300s |
Security Considerations
✅ Implemented
- HTTPS/TLS encryption (via Let's Encrypt)
- SSL certificate validation
- Block common exploits enabled
- Large body size limits (prevents DoS)
- Access logging disabled (prevents log spam)
⚠️ Not Implemented (Consider for Production)
- Authentication (Docker registry supports basic auth, tokens, OAuth)
- Access lists (NPM can restrict by IP/network)
- Rate limiting (prevent abuse)
- Image scanning (vulnerability detection)
- Content trust (signed images)
Authentication Setup (Optional)
To add basic authentication to the registry:
- Generate htpasswd file on docker server:
ansible docker -m shell -a "docker run --rm --entrypoint htpasswd httpd:alpine -Bbn username password > /opt/docker-registry/auth/htpasswd"
- Update registry configuration to use auth:
auth:
htpasswd:
realm: Registry Realm
path: /auth/htpasswd
-
Restart registry container
-
Docker login:
docker login registry.directlx.dev
Related Documentation
Maintenance
Update SSL Certificate
Certificates auto-renew via Let's Encrypt. To force renewal:
- NPM Admin → SSL Certificates
- Find
registry.directlx.devcertificate - Click ... → Renew Certificate
Monitor Logs
# NPM access logs (if enabled)
ansible npm -m shell -a "tail -f /data/logs/proxy-host-*.log"
# NPM error logs
ansible npm -m shell -a "tail -f /data/logs/error.log"
# Registry logs
ansible docker -m shell -a "docker logs -f registry" -b
Backup Configuration
# Backup NPM database
ansible npm -m shell -a "sqlite3 /data/database.sqlite .dump > /tmp/npm-backup.sql"
# Download backup
ansible npm -m fetch -a "src=/tmp/npm-backup.sql dest=./backups/"
Created: 2026-02-14 Last Updated: 2026-02-14 Author: DirectLX Infrastructure Team