claude-home/server-configs/gitea/harbor-registry-setup.md
Cal Corum 4b7eca8a46
All checks were successful
Reindex Knowledge Base / reindex (push) Successful in 3s
docs: add YAML frontmatter to all 151 markdown files
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>
2026-03-12 09:00:44 -05:00

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
proxmox
lxc
gitea-actions
vulnerability-scanning
docker

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

  1. Login to Harbor UI
  2. Click New Project
  3. Name: paper-dynasty
  4. Access Level: Private or Public

Enable Vulnerability Scanning

  1. Go to AdministrationInterrogation Services
  2. Enable Trivy scanner
  3. Set scan on push: Enabled

Now images are auto-scanned for CVEs!

Set Up Replication

Replicate between Harbor and Docker Hub:

  1. AdministrationReplications
  2. New Replication Rule
    • Name: sync-to-dockerhub
    • Source: Local
    • Destination: Docker Hub (add endpoint first)
    • Trigger: Event Based

Garbage Collection

Free up disk space from deleted images:

  1. AdministrationGarbage Collection
  2. Schedule: Daily at 2 AM
  3. Dry run first to see what would be deleted

Backup Strategy

What to Backup

  1. Harbor database (PostgreSQL)
  2. Image storage (/mnt/harbor-data)
  3. 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:

  1. Multiple Harbor instances
  2. Shared storage (NFS, S3, Minio)
  3. Load balancer in front
  4. 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

  1. Set up Harbor on LXC 227
  2. Configure NPM reverse proxy
  3. Test push/pull from dev machine
  4. Update one project to use Harbor
  5. Set up Gitea Actions to push to both registries
  6. Configure vulnerability scanning
  7. Set up automated backups

Created: 2026-02-04 For: Manticorum Home Lab Reference: Paper Dynasty as first use case