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>
418 lines
13 KiB
Markdown
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
|