Adds title, description, type, domain, and tags frontmatter to every doc for improved KB semantic search. The description field is prepended to every search chunk, and domain/type/tags enable filtered queries. Type values: context, guide, runbook, reference, troubleshooting Domain values match directory structure (networking, docker, etc.) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
7.9 KiB
| title | description | type | domain | tags | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Harbor Registry Setup Guide | Step-by-step guide to deploying Harbor as a self-hosted Docker registry on a Proxmox LXC. Covers installation, NPM reverse proxy config, Gitea Actions integration, vulnerability scanning, backup strategy, and troubleshooting. | guide | server-configs |
|
Harbor Docker Registry Setup Guide
Complete guide to setting up Harbor on a Proxmox LXC for self-hosted Docker registry.
Prerequisites
- Proxmox LXC with Ubuntu 22.04
- 2 CPU cores, 4GB RAM, 50GB disk
- Docker and docker-compose installed
- Domain name (e.g., registry.manticorum.com)
Quick Setup
1. Create LXC Container
# On Proxmox host
pct create 227 local:vztmpl/ubuntu-22.04-standard_22.04-1_amd64.tar.zst \
--hostname harbor \
--cores 2 \
--memory 4096 \
--swap 512 \
--net0 name=eth0,bridge=vmbr0,ip=10.10.0.227/24,gw=10.10.0.1 \
--rootfs local-lvm:50 \
--unprivileged 1 \
--features nesting=1 \
--onboot 1 \
--start 1
2. Install Docker
ssh root@10.10.0.227
apt update && apt install -y curl
curl -fsSL https://get.docker.com | sh
systemctl enable docker
3. Download Harbor
cd /opt
wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz
tar xzvf harbor-offline-installer-v2.10.0.tgz
cd harbor
4. Configure Harbor
cp harbor.yml.tmpl harbor.yml
# Edit harbor.yml
nano harbor.yml
Key settings to change:
hostname: registry.manticorum.com # Your domain
# HTTPS (configure after NPM setup, start with HTTP for now)
# https:
# port: 443
# certificate: /path/to/cert
# private_key: /path/to/key
# Or disable HTTPS initially
# Comment out entire https section
harbor_admin_password: YourSecurePassword123
database:
password: YourDBPassword123
data_volume: /mnt/harbor-data
5. Install Harbor
./install.sh
6. Access Harbor
Open: http://10.10.0.227 (or http://registry.manticorum.com if DNS configured)
Default login:
- Username:
admin - Password:
YourSecurePassword123(what you set)
7. Configure NPM Reverse Proxy
In Nginx Proxy Manager (10.10.0.16):
Proxy Host:
- Domain:
registry.manticorum.com - Scheme:
http - Forward Hostname:
10.10.0.227 - Forward Port:
80 - Websockets: ✅ Enabled
- Block Common Exploits: ✅ Enabled
- SSL: Let's Encrypt
Custom Nginx Configuration:
# Increase timeouts for large image uploads
proxy_read_timeout 900;
proxy_send_timeout 900;
client_max_body_size 0; # No upload limit
# Required for Docker registry
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;
Using Your Registry
1. Login from Dev Machine
docker login registry.manticorum.com
# Username: admin
# Password: YourSecurePassword123
2. Tag and Push Image
# Tag existing image
docker tag manticorum67/paper-dynasty:latest registry.manticorum.com/paper-dynasty/bot:latest
# Push to your registry
docker push registry.manticorum.com/paper-dynasty/bot:latest
3. Pull from Production
# On sba-bots
docker login registry.manticorum.com
docker pull registry.manticorum.com/paper-dynasty/bot:latest
4. Update docker-compose
services:
paper-dynasty:
# Old: image: manticorum67/paper-dynasty:latest
# New:
image: registry.manticorum.com/paper-dynasty/bot:latest
Integrating with Gitea Actions
Update your workflow to push to both registries:
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to Harbor
uses: docker/login-action@v3
with:
registry: registry.manticorum.com
username: ${{ secrets.HARBOR_USERNAME }}
password: ${{ secrets.HARBOR_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.ref == 'refs/heads/main' }}
tags: |
manticorum67/paper-dynasty:latest
manticorum67/paper-dynasty:v${{ steps.meta.outputs.version }}
registry.manticorum.com/paper-dynasty/bot:latest
registry.manticorum.com/paper-dynasty/bot:v${{ steps.meta.outputs.version }}
Harbor Features
Create Projects
- Login to Harbor UI
- Click New Project
- Name:
paper-dynasty - Access Level: Private or Public
Enable Vulnerability Scanning
- Go to Administration → Interrogation Services
- Enable Trivy scanner
- Set scan on push: ✅ Enabled
Now images are auto-scanned for CVEs!
Set Up Replication
Replicate between Harbor and Docker Hub:
- Administration → Replications
- New Replication Rule
- Name:
sync-to-dockerhub - Source: Local
- Destination: Docker Hub (add endpoint first)
- Trigger: Event Based
- Name:
Garbage Collection
Free up disk space from deleted images:
- Administration → Garbage Collection
- Schedule: Daily at 2 AM
- Dry run first to see what would be deleted
Backup Strategy
What to Backup
- Harbor database (PostgreSQL)
- Image storage (
/mnt/harbor-data) - Configuration (
/opt/harbor/harbor.yml)
Backup Script
#!/bin/bash
BACKUP_DIR="/mnt/backups/harbor"
DATE=$(date +%Y%m%d)
# Stop Harbor
cd /opt/harbor
docker-compose down
# Backup database
docker exec harbor-db pg_dumpall -U postgres > $BACKUP_DIR/harbor-db-$DATE.sql
# Backup data (incremental)
rsync -av /mnt/harbor-data/ $BACKUP_DIR/harbor-data/
# Backup config
cp /opt/harbor/harbor.yml $BACKUP_DIR/harbor-config-$DATE.yml
# Start Harbor
docker-compose up -d
# Keep last 7 days
find $BACKUP_DIR -name "harbor-db-*.sql" -mtime +7 -delete
Monitoring
Check Harbor Status
cd /opt/harbor
docker-compose ps
# View logs
docker-compose logs -f
Disk Usage
du -sh /mnt/harbor-data
# By project
du -sh /mnt/harbor-data/docker/registry/v2/repositories/*
API Health Check
curl -k https://registry.manticorum.com/api/v2.0/health
Troubleshooting
"401 Unauthorized" on push
Problem: Docker login not working
Solution:
# Clear old credentials
rm ~/.docker/config.json
# Login again
docker login registry.manticorum.com
"413 Request Entity Too Large"
Problem: Nginx upload limit
Solution: Add to NPM custom config:
client_max_body_size 0;
Disk space full
Problem: Old images filling disk
Solution:
# Run garbage collection
cd /opt/harbor
docker-compose exec core /harbor/garbage-collection.sh
# Or via UI: Administration → Garbage Collection → Run Now
Can't pull from registry
Problem: Firewall or network issue
Solution:
# Test connection
telnet 10.10.0.227 80
# Check Harbor logs
docker-compose logs registry
Advanced: High Availability
For production-critical registries, set up HA:
- Multiple Harbor instances
- Shared storage (NFS, S3, Minio)
- Load balancer in front
- Database replication
Cost Analysis
LXC Resources:
- CPU: 2 cores = $0 (spare capacity)
- RAM: 4GB = $0 (spare capacity)
- Disk: 50GB = $0 (local storage)
- Bandwidth: Internal = $0
Total ongoing cost: $0/month
Docker Hub Pro alternative: $5/month
Time investment:
- Setup: 2-3 hours
- Maintenance: 30 min/month
- Break-even: 3 months of learning value
Next Steps
- ✅ Set up Harbor on LXC 227
- ✅ Configure NPM reverse proxy
- ✅ Test push/pull from dev machine
- ✅ Update one project to use Harbor
- ✅ Set up Gitea Actions to push to both registries
- ✅ Configure vulnerability scanning
- ✅ Set up automated backups
Created: 2026-02-04 For: Manticorum Home Lab Reference: Paper Dynasty as first use case