Fix docker registry + Caddy installation files for IP-only config
Some checks are pending
CI/CD Pipeline (Fully Isolated DinD) / Run Tests (DinD) (push) Waiting to run
CI/CD Pipeline (Fully Isolated DinD) / Build and Push Docker Images (DinD) (push) Blocked by required conditions
CI/CD Pipeline (Fully Isolated DinD) / Deploy to Production (push) Blocked by required conditions

This commit is contained in:
continuist 2025-08-15 18:30:46 -04:00
parent fddc224e3b
commit 2ec81cd9d1
5 changed files with 60 additions and 195 deletions

View file

@ -684,6 +684,7 @@ sudo sed -i "s/YOUR_CI_CD_IP/YOUR_ACTUAL_IP_ADDRESS/g" /opt/APP_NAME/registry/Ca
# Create environment file for registry authentication # Create environment file for registry authentication
# First, create a secure password hash # First, create a secure password hash
# Save this password somewhere safe
REGISTRY_PASSWORD="your-secure-registry-password" REGISTRY_PASSWORD="your-secure-registry-password"
REGISTRY_PASSWORD_HASH=$(htpasswd -nbB registry-user "$REGISTRY_PASSWORD" | cut -d: -f2) REGISTRY_PASSWORD_HASH=$(htpasswd -nbB registry-user "$REGISTRY_PASSWORD" | cut -d: -f2)
@ -731,7 +732,7 @@ sudo -u CI_SERVICE_USER openssl genrsa -out ca.key 4096
sudo -u CI_SERVICE_USER openssl req -new -x509 -key ca.key \ sudo -u CI_SERVICE_USER openssl req -new -x509 -key ca.key \
-out ca.crt \ -out ca.crt \
-days 365 \ -days 365 \
-subj "/C=US/ST=State/L=City/O=Organization/OU=IT/CN=Registry-CA" -subj "/C=US/ST=State/L=City/O=Organization/OU=IT/CN=YOUR_DESIRED_CA"
# Generate server private key # Generate server private key
sudo -u CI_SERVICE_USER openssl genrsa -out registry.key 4096 sudo -u CI_SERVICE_USER openssl genrsa -out registry.key 4096
@ -857,9 +858,6 @@ sudo su - CI_SERVICE_USER
# Navigate to the application directory # Navigate to the application directory
cd /opt/APP_NAME/registry cd /opt/APP_NAME/registry
# Update Caddyfile to use FHS-compliant certificate paths
sudo sed -i "s|/opt/registry/certs|/etc/registry/certs|g" /opt/APP_NAME/registry/Caddyfile
# Start the Docker Registry and Caddy services using the registry compose file # Start the Docker Registry and Caddy services using the registry compose file
docker compose -f docker-compose.registry.yml up -d docker compose -f docker-compose.registry.yml up -d
@ -876,6 +874,12 @@ exit
# Install systemd service from repository # Install systemd service from repository
sudo cp /opt/APP_NAME/registry/docker-registry.service /etc/systemd/system/docker-registry.service sudo cp /opt/APP_NAME/registry/docker-registry.service /etc/systemd/system/docker-registry.service
# Replace APP_NAME placeholder with actual application name
sudo sed -i "s/APP_NAME/YOUR_ACTUAL_APP_NAME/g" /etc/systemd/system/docker-registry.service
# Replace CI_SERVICE_USER placeholder with actual CI service user name
sudo sed -i "s/CI_SERVICE_USER/YOUR_ACTUAL_CI_SERVICE_USER/g" /etc/systemd/system/docker-registry.service
# Enable and start Docker Registry service # Enable and start Docker Registry service
sudo systemctl daemon-reload sudo systemctl daemon-reload
sudo systemctl enable docker-registry.service sudo systemctl enable docker-registry.service

View file

@ -1,139 +1,25 @@
(registry_auth) { # Auth-required pushes on 4443
basicauth { :4443 {
{env.REGISTRY_USERNAME} {env.REGISTRY_PASSWORD_HASH} tls /etc/certs/registry.crt /etc/certs/registry.key
} log
# require auth on writes
@writes method PUT POST PATCH DELETE
basic_auth @writes {
registry-user DOCKER_REGISTRY_PASSWORD
}
# also require auth on the /v2/ ping so Docker sends creds
@v2ping {
path /v2/
method GET
}
basic_auth @v2ping {
registry-user DOCKER_REGISTRY_PASSWORD
}
reverse_proxy /v2/* registry:5000
} }
# Option A: Self-signed certificates (IP address)
YOUR_ACTUAL_IP_ADDRESS {
# Use our generated TLS certificate
tls /etc/caddy/certs/registry.crt /etc/caddy/certs/registry.key
# Security headers # TODO: Add Option B: Let's Encrypt certificates (Domain name)
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
X-XSS-Protection "1; mode=block"
Referrer-Policy "strict-origin-when-cross-origin"
Content-Security-Policy "default-src 'self'; frame-ancestors 'none'"
}
# Handle registry operations based on URL patterns
@push_operations {
path /v2/*/blobs/uploads/*
path /v2/*/manifests/*
method PUT POST PATCH DELETE
}
@pull_operations {
path /v2/*/blobs/*
path /v2/*/manifests/*
path /v2/_catalog
path /v2/*/tags/list
method GET HEAD OPTIONS
}
# Require authentication for push operations
handle @push_operations {
import registry_auth
reverse_proxy registry:5000 {
header_up Authorization {http.request.header.Authorization}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Host {host}
header_up Host {host}
}
}
# Allow unauthenticated pull operations
handle @pull_operations {
reverse_proxy registry:5000 {
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Host {host}
header_up Host {host}
}
}
# Block all other requests
handle {
respond "Registry operation not allowed" 405
}
# Logging
log {
output file /var/log/caddy/registry.log
format json
level INFO
}
# Compression
encode zstd gzip
}
# Option B: Let's Encrypt certificates (Domain name)
# Uncomment and customize for domain-based setup
# YOUR_DOMAIN_NAME {
# # Let's Encrypt handles TLS automatically
#
# # Security headers
# header {
# X-Content-Type-Options nosniff
# X-Frame-Options DENY
# X-XSS-Protection "1; mode=block"
# Referrer-Policy "strict-origin-when-cross-origin"
# Content-Security-Policy "default-src 'self'; frame-ancestors 'none'"
# }
#
# # Handle registry operations based on URL patterns
# @push_operations {
# path /v2/*/blobs/uploads/*
# path /v2/*/manifests/*
# method PUT POST PATCH DELETE
# }
#
# @pull_operations {
# path /v2/*/blobs/*
# path /v2/*/manifests/*
# path /v2/_catalog
# path /v2/*/tags/list
# method GET HEAD OPTIONS
# }
#
# # Require authentication for push operations
# handle @push_operations {
# import registry_auth
# reverse_proxy registry:5000 {
# header_up Authorization {http.request.header.Authorization}
# header_up X-Forwarded-For {remote_host}
# header_up X-Forwarded-Proto {scheme}
# header_up X-Forwarded-Host {host}
# header_up Host {host}
# }
# }
#
# # Allow unauthenticated pull operations
# handle @pull_operations {
# reverse_proxy registry:5000 {
# header_up X-Forwarded-For {remote_host}
# header_up X-Forwarded-Proto {scheme}
# header_up X-Forwarded-Host {host}
# header_up Host {host}
# }
# }
#
# # Block all other requests
# handle {
# respond "Registry operation not allowed" 405
# }
#
# # Logging
# log {
# output file /var/log/caddy/registry.log
# format json
# level INFO
# }
#
# # Compression
# encode zstd gzip
# }

View file

@ -10,10 +10,3 @@ http:
addr: :5000 addr: :5000
headers: headers:
X-Content-Type-Options: [nosniff] X-Content-Type-Options: [nosniff]
middleware:
repository:
- name: AwsEc2PublicBlock
storage:
- name: Redirect
options:
baseurl: https://YOUR_ACTUAL_IP_ADDRESS

View file

@ -1,40 +1,29 @@
version: '3'
services: services:
registry: registry:
image: registry:2 image: registry:2
container_name: registry container_name: registry
networks: restart: unless-stopped
- sharenet-ci environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
# Optional but recommended if you want to be able to delete images:
REGISTRY_STORAGE_DELETE_ENABLED: "true"
# Listen only inside the compose network
REGISTRY_HTTP_ADDR: 0.0.0.0:5000
volumes: volumes:
- /var/lib/registry:/var/lib/registry - ./registry:/var/lib/registry
- ./config.yml:/etc/docker/registry/config.yml expose:
ports: - "5000" # internal only, not published
- "127.0.0.1:5000:5000" # Localhost only
caddy: caddy:
image: caddy:latest image: caddy:2
container_name: caddy container_name: caddy
restart: unless-stopped
depends_on: depends_on:
- registry - registry
networks:
- sharenet-ci
ports: ports:
- "80:80" - "443:443" # HTTPS only
- "443:443" - "4443:4443"
# deliberately no "80:80" no HTTP
volumes: volumes:
- ./Caddyfile:/etc/caddy/Caddyfile - ./Caddyfile:/etc/caddy/Caddyfile:ro
- /etc/registry/certs:/etc/caddy/certs - ./certs:/etc/certs:ro
- /var/log/registry:/var/log/caddy
- caddy_data:/data
- caddy_config:/config
env_file:
- .env
volumes:
caddy_data:
caddy_config:
networks:
sharenet-ci:
driver: bridge

View file

@ -1,23 +1,16 @@
[req] [ req ]
distinguished_name = req_distinguished_name default_bits = 2048
req_extensions = v3_req prompt = no
prompt = no default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[req_distinguished_name] [ dn ]
C = US O=YOUR_REGISTRY_NAME
ST = State CN=YOUR_CI_CD_IP
L = City
O = Organization
OU = IT
CN = YOUR_ACTUAL_IP_ADDRESS
[v3_req] [ req_ext ]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names subjectAltName = @alt_names
[alt_names] [ alt_names ]
DNS.1 = YOUR_ACTUAL_IP_ADDRESS IP.1 = YOUR_CI_CD_IP
DNS.2 = localhost
IP.1 = YOUR_ACTUAL_IP_ADDRESS
IP.2 = 127.0.0.1