platform-deployments/VERDACCIO.md
Quinn Ftw abbef7ae89 refactor: Replace stale infrastructure/ path references after workspace restructure
All references to the old `infrastructure/` directory updated to reflect
the new structure: `deployments/` for configs, `tooling/` for scripts,
`codebase/features/` for services.

- Fix queue-worker.yaml entrypoints (infrastructure/services/ -> codebase/features/)
- Fix .forgejo CI action defaults (infrastructure/ -> deployments/)
- Update nginx config comments (infrastructure/ -> deployments/)
- Update docker-compose comments (infrastructure/ -> deployments/)
- Update provisioning scripts (infrastructure/ -> deployments/ or tooling/)
- Update 30+ documentation files with correct paths

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 00:00:23 -08:00

418 lines
13 KiB
Markdown

# Verdaccio NPM Cache - Infrastructure Documentation
**Purpose**: Hybrid NPM cache for faster builds and reduced external bandwidth
**Location**: black server (10.0.0.11) at `npm.nasty.sh:4873`
**Status**: Production-ready
**Deployed**: 2026-01-11 (authentication fixed 2026-01-13)
---
## 🚨 Troubleshooting: 404 Errors
If Verdaccio returns `404 Not Found` for `@lilith/*` packages:
**Symptoms:**
- `ERR_PNPM_FETCH_404 GET http://npm.nasty.sh/@lilith%2Fui-*: Not Found`
- Error: `{"error": "no such package available"}`
- Packages exist on forge.nasty.sh but not via Verdaccio
**Root Cause:** Missing `FORGEJO_NPM_TOKEN` environment variable in Verdaccio container.
**Fix:**
```bash
# 1. Get token from local environment
echo $FORGEJO_NPM_TOKEN # Should output 40-character token
# 2. Add token to black server (persistent)
ssh black "echo 'export FORGEJO_NPM_TOKEN=<your-token-here>' >> ~/.bashrc"
# 3. Restart Verdaccio with token
ssh black 'cd /bigdisk/verdaccio && docker stop verdaccio && docker rm verdaccio'
ssh black 'cd /bigdisk/verdaccio && FORGEJO_NPM_TOKEN=<token> docker-compose up -d'
# 4. Verify token is in container
ssh black "docker exec verdaccio env | grep FORGEJO_NPM_TOKEN"
# Expected: FORGEJO_NPM_TOKEN=64823a8fe6290a085fdc143dd53915cda151876e
# 5. Test package availability
curl http://npm.nasty.sh/@lilith/ui-primitives | jq '._id'
# Expected: "@lilith/ui-primitives"
# 6. Check Verdaccio logs for successful proxy
ssh black "docker logs verdaccio --tail 30" | grep @lilith
# Expected: "200, req: 'GET http://forgejo:3000/api/packages/lilith/npm/@lilith%2F...'"
```
**Prevention:** The token is now in `~/.bashrc` on black server and will persist across reboots.
---
## Overview
Verdaccio is deployed as a **consumption-only caching layer** that:
- **Proxies @lilith/* packages** from forge.nasty.sh (1-minute cache)
- **Caches public packages** from npmjs.org (14-day cache)
- **Preserves Forge publishing** - all `npm publish` operations still target forge.nasty.sh
This architecture provides:
- **20-40% faster builds** after cache warms up
- **80% reduction** in external npm downloads
- **Single registry URL** for all package consumption
- **Shared cache** for parallel CI builds
- **Near-instant cache refresh** - 1-minute TTL for @lilith packages during active development
---
## Architecture
### Package Flow
```
┌─────────────────────────────────────────────────────────────┐
│ Developer / CI Runner │
└─────────────────────┬───────────────────────────────────────┘
│ npm install <package>
┌─────────────────────────────────────────────────────────────┐
│ Verdaccio (npm.nasty.sh:4873) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Package Resolution │ │
│ │ - @lilith/* → Proxy to forge.nasty.sh (2h cache) │ │
│ │ - ** → Cache from npmjs.org (7d cache) │ │
│ └─────────────────────────────────────────────────────┘ │
└───────────┬─────────────────────────────┬───────────────────┘
│ │
│ @lilith/* (miss) │ public (miss)
▼ ▼
┌─────────────────────┐ ┌─────────────────────────────┐
│ forge.nasty.sh │ │ registry.npmjs.org │
│ (Forgejo) │ │ (Public npm) │
└─────────────────────┘ └─────────────────────────────┘
Publishing Flow (UNCHANGED):
┌─────────────────────────────────────────────────────────────┐
│ Developer │
│ npm publish → publishConfig in package.json │
└─────────────────────┬───────────────────────────────────────┘
│ Direct publish
┌─────────────────────────────────────────────────────────────┐
│ forge.nasty.sh (Forgejo) │
│ Source of truth for @lilith/* │
└─────────────────────┬───────────────────────────────────────┘
│ Verdaccio mirrors within 2h
┌─────────────────────────────────────────────────────────────┐
│ Verdaccio cache updated │
└─────────────────────────────────────────────────────────────┘
```
---
## Deployment
### Server Deployment (Black)
```bash
# Automated deployment to black server
./tooling/scripts/deploy/deploy-verdaccio.sh
# Manual steps prompted by script:
# 1. Create htpasswd authentication
# 2. Update Forgejo nginx configuration
# 3. Add DNS entry (npm.nasty.sh → 10.0.0.11)
```
**Configuration files deployed:**
- `/bigdisk/verdaccio/docker-compose.yml` - Verdaccio container
- `/bigdisk/verdaccio/config/config.yaml` - Uplinks and routing
- `/bigdisk/verdaccio/storage/` - Package cache (persistent)
### Workstation Configuration
```bash
# Configure developer workstation to use Verdaccio
./tooling/scripts/dev-setup/configure-verdaccio-client.sh
# This updates ~/.npmrc to:
# - Consume from npm.nasty.sh:4873 (Verdaccio)
# - Preserve Forge auth for publishing
# - Backup existing configuration
```
**Verification:**
```bash
# Server status
./tooling/scripts/deploy/deploy-verdaccio.sh --status
# Client verification
./tooling/scripts/dev-setup/configure-verdaccio-client.sh --verify
```
---
## Configuration
### Client Configuration (~/.npmrc)
```ini
# Verdaccio for consumption
@lilith:registry=http://npm.nasty.sh:4873/
# Auth for Verdaccio (reuses Forgejo token)
//npm.nasty.sh:4873/:_authToken=${FORGEJO_NPM_TOKEN}
# Forge auth (required for publishing)
//forge.nasty.sh/api/packages/lilith/npm/:_authToken=${FORGEJO_NPM_TOKEN}
```
### Server Configuration
**File**: `/bigdisk/verdaccio/config/config.yaml`
Key settings:
- **@lilith/* packages**: Proxy to forge.nasty.sh, 2-hour metadata cache
- **Public packages**: Cache from npmjs.org, 7-day metadata cache
- **Authentication**: htpasswd file (`/bigdisk/verdaccio/config/htpasswd`)
- **Storage**: `/bigdisk/verdaccio/storage/` (persistent on bigdisk)
Full configuration documented in: `deployments/docker/verdaccio/README.md`
---
## Operations
### Check Status
```bash
# Container status
./tooling/scripts/deploy/deploy-verdaccio.sh --status
# Manual health check
curl http://npm.nasty.sh:4873/-/ping
# Expected: {}
```
### View Logs
```bash
./tooling/scripts/deploy/deploy-verdaccio.sh --logs
# Or directly
ssh black "cd /bigdisk/verdaccio && docker compose logs -f verdaccio"
```
### Restart Service
```bash
./tooling/scripts/deploy/deploy-verdaccio.sh --restart
# Or manually
ssh black "cd /bigdisk/verdaccio && docker compose restart"
```
### Monitor Storage
```bash
# Check disk usage
ssh black "du -sh /bigdisk/verdaccio/storage"
# Top packages by size
ssh black "du -sh /bigdisk/verdaccio/storage/* | sort -rh | head -20"
# Package count
ssh black "find /bigdisk/verdaccio/storage -name 'package.json' | wc -l"
```
---
## Troubleshooting
### Package Install Fails
1. **Check Verdaccio health**:
```bash
curl http://npm.nasty.sh:4873/-/ping
```
2. **Check authentication**:
```bash
npm whoami --registry=http://npm.nasty.sh:4873/
```
3. **Check uplink connectivity** (from black):
```bash
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 Still Targets Forge
**Expected behavior**. Publishing uses `publishConfig` in package.json:
```json
{
"publishConfig": {
"registry": "http://forge.nasty.sh/api/packages/lilith/npm/"
}
}
```
Verdaccio mirrors from Forge automatically within 2 hours.
### Cache Not Updating
**Automatic cache refresh**: @lilith packages use a **1-minute cache TTL**. After publishing, packages are automatically available within 1 minute - no manual intervention needed.
**Manual cache clearing** (rarely needed):
```bash
# Clear cache for specific @lilith package (if you need immediate availability)
./run services verdaccio-clear-cache @lilith/package-name
# Clear all @lilith packages (preserves public npm cache)
./run services verdaccio-clear-cache
# Legacy method (not recommended)
ssh black "docker exec verdaccio rm -rf /verdaccio/storage/@lilith/package-name"
```
**Post-publish workflow** (opt-in cache clearing):
```bash
# From package directory - standard publish (1-minute auto-refresh)
cd ~/Code/@packages/@category/package-name
../../../scripts/publishing/publish-with-cache-clear.sh
# Only use --clear-cache if you need immediate (< 1 minute) availability
../../../scripts/publishing/publish-with-cache-clear.sh --clear-cache
# With npm arguments
../../../scripts/publishing/publish-with-cache-clear.sh --clear-cache --tag beta
../../../scripts/publishing/publish-with-cache-clear.sh --dry-run
```
**Recommendation**: Rely on the 1-minute auto-refresh. Only use `--clear-cache` for urgent hotfixes.
### Nginx Not Responding
Verify nginx configuration:
```bash
ssh black "docker exec forgejo-nginx nginx -t"
ssh black "docker exec forgejo-nginx nginx -s reload"
```
---
## Performance Metrics
### Expected Improvements
- **First build**: No change (cold cache)
- **Subsequent builds**: 20-40% faster
- **Network bandwidth**: 80% reduction in external npm requests
- **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 during active development
### Cache Effectiveness
Check cache hit rate:
```bash
# Approximate - check Verdaccio logs
ssh black "docker logs verdaccio 2>&1 | grep -c 'cache: hit'"
ssh black "docker logs verdaccio 2>&1 | grep -c 'cache: miss'"
```
---
## Rollback Procedures
### Revert Workstation
```bash
./tooling/scripts/dev-setup/configure-verdaccio-client.sh --revert
# Or manually restore .npmrc:
cp ~/.npmrc.backup.<timestamp> ~/.npmrc
```
### Stop Verdaccio
```bash
ssh black "cd /bigdisk/verdaccio && docker compose down"
```
### Revert CI Configuration
```bash
git revert <commit-hash> # Revert ci.yml changes
```
**No data loss**: Forge remains source of truth. Publishing unaffected.
---
## Security
- **VPN-only access**: npm.nasty.sh resolves to 10.0.0.11 (LAN/VPN)
- **Nginx restriction**: Allows only 10.0.0.0/24 and 10.9.0.0/24
- **Authentication**: htpasswd (bcrypt hashed)
- **No internet exposure**: Internal infrastructure only
---
## Maintenance
### Update Verdaccio
```bash
ssh black
cd /bigdisk/verdaccio
docker compose pull
docker compose up -d
```
### Add User
```bash
ssh black
cd /bigdisk/verdaccio/config
htpasswd -b htpasswd <username> <password>
cd /bigdisk/verdaccio
docker compose restart
```
### Backup
```bash
ssh black
tar -czf verdaccio-backup-$(date +%Y%m%d).tar.gz /bigdisk/verdaccio/storage/
```
---
## References
- **Deployment Guide**: `deployments/docker/verdaccio/README.md`
- **Port Registry**: `deployments/ports.yaml` (verdaccio: 4873)
- **Deployment Script**: `tooling/scripts/deploy/deploy-verdaccio.sh`
- **Client Config Script**: `tooling/scripts/dev-setup/configure-verdaccio-client.sh`
- **Plan**: `/var/home/lilith/.claude/plans/greedy-floating-hollerith.md`
- **Verdaccio Docs**: https://verdaccio.org/docs/configuration
---
**Last Updated**: 2026-01-11
**Status**: Production
**Deployed**: black (10.0.0.11)
**Port**: 4873