dlx-ansible/docs/NPM-REGISTRY-SETUP.md

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: HostsProxy HostsAdd 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:

  1. Ensure port 80/443 are open on NPM server
  2. Verify DNS propagation: nslookup registry.directlx.dev
  3. Check NPM logs: ToolsError 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

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:

  1. 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"
  1. Update registry configuration to use auth:
auth:
  htpasswd:
    realm: Registry Realm
    path: /auth/htpasswd
  1. Restart registry container

  2. Docker login:

docker login registry.directlx.dev

Maintenance

Update SSL Certificate

Certificates auto-renew via Let's Encrypt. To force renewal:

  1. NPM Admin → SSL Certificates
  2. Find registry.directlx.dev certificate
  3. 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