platform-deployments/docker/verdaccio
2026-04-12 00:06:10 -07:00
..
config
app.manifest.yaml deps-upgrade(docker): ⬆️ Update containerized PyPI and Verdaccio dependencies in manifest files 2026-03-17 19:25:21 -07:00
CHANGES.md
DEPLOY.md
docker-compose.yml infra(docker): 🧱 Update Docker Compose configurations for Forgejo, local-registry, and Verdaccio services with service definitions, networking, and resource optimizations 2026-04-12 00:06:10 -07:00
INSTALL.sh
README.md

Verdaccio - Hybrid NPM Cache

Purpose: Cache public npm packages + mirror @lilith/* from Forgejo Location: black server (10.0.0.11) via VPN Access: http://npm.nasty.sh:4873/ (VPN-only) Storage: /bigdisk/verdaccio/storage/


Architecture

Package Resolution Flow

Developer/CI → npm install <package>
    ↓
Verdaccio (npm.nasty.sh:4873)
    ├─ @lilith/* → Proxy to forge.nasty.sh (2h cache)
    └─ Public → Cache from npmjs.org (7d cache)

Publishing Flow

Developer → npm publish @lilith/package
    ↓
publishConfig in package.json → forge.nasty.sh (unchanged)
    ↓
Verdaccio mirrors from forge (auto-update within 2h)

Key principle: Verdaccio is consumption-only. Publishing still targets forge.nasty.sh.


Quick Start

Deploy to Black

# From lilith-platform directory
scp -r deployments/docker/verdaccio black:/bigdisk/
ssh black
cd /bigdisk/verdaccio
docker-compose up -d

Check Status

ssh black "docker ps | grep verdaccio"
# Or
curl http://npm.nasty.sh:4873/-/ping
# Expected: {}

View Logs

ssh black "cd /bigdisk/verdaccio && docker-compose logs -f"

First-Time Setup

1. Create Admin User

ssh black
cd /bigdisk/verdaccio/config

# Create htpasswd file
htpasswd -Bc htpasswd lilith
# Enter password when prompted

# Restart Verdaccio
cd /bigdisk/verdaccio
docker-compose restart

2. Update Forgejo Nginx

Add to /bigdisk/forgejo/nginx.conf:

# Verdaccio upstream
upstream verdaccio {
    server verdaccio:4873;
}

# npm.nasty.sh - Verdaccio NPM Cache
server {
    listen 80;
    server_name npm.nasty.sh;

    # VPN-only access
    allow 10.0.0.0/24;   # LAN
    allow 10.9.0.0/24;   # VPN
    deny all;

    client_max_body_size 100M;

    location / {
        proxy_pass http://verdaccio;
        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;

        # Disable buffering for npm publish
        proxy_buffering off;
        proxy_request_buffering off;

        # Timeouts for large packages
        proxy_connect_timeout 60s;
        proxy_send_timeout 300s;
        proxy_read_timeout 300s;
    }
}

Reload nginx:

ssh black "docker exec forgejo-nginx nginx -t"
ssh black "docker exec forgejo-nginx nginx -s reload"

3. Add DNS Entry

# Via PowerDNS
pdnsutil add-record nasty.sh npm A 10.0.0.11

# Or add to /etc/hosts
echo "10.0.0.11 npm.nasty.sh" | sudo tee -a /etc/hosts

4. Test Access

curl http://npm.nasty.sh:4873/-/ping
# Expected: {}

# Web UI
curl -I http://npm.nasty.sh:4873/
# Expected: 200 OK

Client Configuration

For Developers

Update ~/.npmrc:

# Verdaccio for consumption
@lilith:registry=http://npm.nasty.sh:4873/

# Auth for Verdaccio (reuse Forgejo token)
//npm.nasty.sh:4873/:_authToken=${FORGEJO_NPM_TOKEN}

# Forge auth (still needed for publishing)
//forge.nasty.sh/api/packages/lilith/npm/:_authToken=${FORGEJO_NPM_TOKEN}

Login to Verdaccio

npm adduser --registry=http://npm.nasty.sh:4873/
# Username: lilith (or created via htpasswd)
# Password: <password from htpasswd>
# Email: your@email.com

Test Installation

# Public package (caches from npmjs.org)
npm install react --registry=http://npm.nasty.sh:4873/

# @lilith/* package (proxies to forge)
npm install @lilith/ui-theme --registry=http://npm.nasty.sh:4873/

Publishing (Unchanged)

cd ~/Code/@packages/@ui/ui-theme
npm version patch
npm publish  # Uses publishConfig → forge.nasty.sh

Troubleshooting

Container Won't Start

# Check logs
ssh black "cd /bigdisk/verdaccio && docker-compose logs"

# Check network
ssh black "docker network ls | grep forgejo"

Cannot Access Web UI

  1. Check nginx config:

    ssh black "docker exec forgejo-nginx nginx -t"
    
  2. Check DNS:

    dig npm.nasty.sh +short
    # Expected: 10.0.0.11
    
  3. Check firewall (should allow port 80 from VPN):

    ssh black "sudo ufw status"
    

Package Install Fails

  1. Check Verdaccio health:

    curl http://npm.nasty.sh:4873/-/ping
    
  2. Check auth:

    npm whoami --registry=http://npm.nasty.sh:4873/
    
  3. Check uplink connectivity:

    # From black server
    ssh black "docker exec verdaccio wget -q -O- http://forge.nasty.sh/api/packages/lilith/npm/"
    ssh black "docker exec verdaccio wget -q -O- https://registry.npmjs.org/react"
    

Publishing Fails

Expected behavior: Publishing should target forge.nasty.sh, not Verdaccio.

Verify publishConfig in package.json:

{
  "publishConfig": {
    "registry": "http://forge.nasty.sh/api/packages/lilith/npm/"
  }
}

If accidentally published to Verdaccio, unpublish:

npm unpublish @lilith/package@version --registry=http://npm.nasty.sh:4873/

Maintenance

Update Verdaccio

ssh black
cd /bigdisk/verdaccio
docker-compose pull
docker-compose up -d

Add User

ssh black
cd /bigdisk/verdaccio/config
htpasswd -b htpasswd <username> <password>
cd /bigdisk/verdaccio
docker-compose restart

Check Disk Usage

ssh black "du -sh /bigdisk/verdaccio/storage"
ssh black "du -sh /bigdisk/verdaccio/storage/* | sort -rh | head -20"

Clear Cache (Package-Specific)

ssh black
rm -rf /bigdisk/verdaccio/storage/@lilith/package-name
docker-compose restart verdaccio

Backup Storage

ssh black
tar -czf verdaccio-backup-$(date +%Y%m%d).tar.gz /bigdisk/verdaccio/storage/

Performance Metrics

Expected Improvements

  • First build after cache: No change (downloads from upstream)
  • Subsequent builds: 20-40% faster (LAN vs internet)
  • CI parallel builds: Significant improvement (shared cache)

Storage Estimates

  • @lilith/ packages*: ~35MB (69 packages, metadata only)
  • Public packages: ~2-4GB after 30 days
  • Growth rate: ~1GB/month

Monitoring

# Cache hit rate (approximate)
ssh black "grep 'cache: hit' /var/log/docker/verdaccio.log | wc -l"

# Package count
ssh black "find /bigdisk/verdaccio/storage -name 'package.json' | wc -l"

# Top packages by size
ssh black "du -sh /bigdisk/verdaccio/storage/* | sort -rh | head -20"

Security Notes

  • VPN-only access: npm.nasty.sh resolves to 10.0.0.11 (LAN/VPN only)
  • No internet exposure: Nginx restricts to 10.0.0.0/24 and 10.9.0.0/24
  • Authentication: htpasswd file (bcrypt hashed)
  • Upstream auth: Proxies to forge use forge credentials (configured in uplink)

References


Last Updated: 2026-01-11 Deployed: black (10.0.0.11) Status: Production-ready