D5.3 Private Registry ΌΔ Ansible đïž
΀Îč Ξα ÏÏÎčÎŹÎŸÎżÏ ÎŒÎ”
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Private Docker Registry â
â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â nextcloud (registry server) â â
â â â â
â â ââââââââââââââââââââââ ââââââââââââââââââââââ â â
â â â registry:2 â â nginx (SSL/Auth) â â â
â â â :5000 (internal) â â :443 (external) â â â
â â ââââââââââââââââââââââ ââââââââââââââââââââââ â â
â â â â
â â /opt/registry/ â â
â â âââ data/ â image storage â â
â â âââ auth/ â htpasswd â â
â â âââ certs/ â SSL certificates â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â
â Clients: â
â docker login registry.example.com â
â docker push registry.example.com/myapp:1.0.0 â
â docker pull registry.example.com/myapp:1.0.0 â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
ÎÎżÎŒÎź Role
# ÎηΌÎčÎżÏ
Ïγία registry role
cd ~/ansible/roles
ansible-galaxy role init registry
tree ~/ansible/roles/registry/
# registry/
# âââ defaults/
# â âââ main.yml
# âââ handlers/
# â âââ main.yml
# âââ tasks/
# â âââ main.yml
# â âââ setup.yml
# â âââ auth.yml
# â âââ deploy.yml
# â âââ verify.yml
# âââ templates/
# âââ registry-compose.yml.j2
# âââ nginx-registry.conf.j2
defaults/main.yml
cat > ~/ansible/roles/registry/defaults/main.yml << 'EOF'
---
# ============================================================
# Private Registry Defaults
# ============================================================
# ââ Registry Settings âââââââââââââââââââââââââ
registry_name: registry
registry_port: 5000 # internal port
registry_ext_port: 443 # external port (SSL)
registry_hostname: "{{ inventory_hostname }}"
# ââ Storage âââââââââââââââââââââââââââââââââââ
registry_base_dir: /opt/registry
registry_data_dir: /opt/registry/data
registry_auth_dir: /opt/registry/auth
registry_certs_dir: /opt/registry/certs
registry_logs_dir: /opt/registry/logs
# ââ Authentication ââââââââââââââââââââââââââââ
registry_auth_enabled: true
registry_users: []
# Format:
# - username: myuser
# password: "{{ vault_registry_pass }}"
# ââ SSL âââââââââââââââââââââââââââââââââââââââ
registry_ssl_enabled: true
registry_ssl_self_signed: true # â true ÎłÎčα self-signed
registry_ssl_cert_days: 3650 # 10 ÏÏÏΜÎčα
# ââ Images ââââââââââââââââââââââââââââââââââââ
registry_image: registry:2
nginx_image: nginx:1.25.3-alpine
# ââ Resources âââââââââââââââââââââââââââââââââ
registry_memory: "256m"
registry_cpus: "0.25"
nginx_memory: "64m"
nginx_cpus: "0.25"
# ââ Garbage Collection ââââââââââââââââââââââââ
registry_gc_enabled: true
registry_gc_schedule: "0 2 * * 0" # ÎÏ
ÏÎčαÎșÎź 02:00
EOF
tasks/main.yml
cat > ~/ansible/roles/registry/tasks/main.yml << 'EOF'
---
# ============================================================
# Private Registry â Main Entry Point
# ============================================================
- name: Setup registry infrastructure
ansible.builtin.import_tasks:
file: setup.yml
tags: [setup, registry]
- name: Configure authentication
ansible.builtin.import_tasks:
file: auth.yml
tags: [auth, registry]
- name: Deploy registry
ansible.builtin.import_tasks:
file: deploy.yml
tags: [deploy, registry]
- name: Verify registry
ansible.builtin.import_tasks:
file: verify.yml
tags: [verify, registry]
EOF
tasks/setup.yml
cat > ~/ansible/roles/registry/tasks/setup.yml << 'EOF'
---
# ============================================================
# Registry Setup â Directories & Certificates
# ============================================================
# ââ Directories âââââââââââââââââââââââââââââââ
- name: Create registry directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
mode: '0755'
owner: root
group: root
loop:
- "{{ registry_base_dir }}"
- "{{ registry_data_dir }}"
- "{{ registry_auth_dir }}"
- "{{ registry_certs_dir }}"
- "{{ registry_logs_dir }}"
# ââ Self-signed SSL certificate âââââââââââââââ
- name: Generate self-signed SSL certificate
ansible.builtin.command:
cmd: >
openssl req -newkey rsa:4096 -nodes -sha256
-keyout {{ registry_certs_dir }}/registry.key
-x509
-days {{ registry_ssl_cert_days }}
-out {{ registry_certs_dir }}/registry.crt
-subj "/CN={{ registry_hostname }}"
-addext "subjectAltName=DNS:{{ registry_hostname }},IP:{{ ansible_facts['default_ipv4']['address'] }}"
args:
creates: "{{ registry_certs_dir }}/registry.crt"
when: registry_ssl_self_signed
register: cert_created
- name: Set certificate permissions
ansible.builtin.file:
path: "{{ item.path }}"
mode: "{{ item.mode }}"
loop:
- path: "{{ registry_certs_dir }}/registry.crt"
mode: '0644'
- path: "{{ registry_certs_dir }}/registry.key"
mode: '0600'
when: registry_ssl_self_signed
# ââ Trust certificate (ÎłÎčα Docker) ââââââââââââ
- name: Create Docker certs directory
ansible.builtin.file:
path: "/etc/docker/certs.d/{{ registry_hostname }}:{{ registry_ext_port }}"
state: directory
mode: '0755'
- name: Copy certificate to Docker certs
ansible.builtin.copy:
src: "{{ registry_certs_dir }}/registry.crt"
dest: "/etc/docker/certs.d/{{ registry_hostname }}:{{ registry_ext_port }}/ca.crt"
remote_src: true
mode: '0644'
# ââ Install htpasswd tool âââââââââââââââââââââ
- name: Install apache2-utils (ÎłÎčα htpasswd)
ansible.builtin.apt:
name: apache2-utils
state: present
when: ansible_facts['os_family'] == "Debian"
- name: Install httpd-tools (ÎłÎčα htpasswd)
ansible.builtin.dnf:
name: httpd-tools
state: present
when: ansible_facts['os_family'] == "RedHat"
- name: Install apache2-utils (openSUSE)
community.general.zypper:
name: apache2-utils
state: present
when: ansible_facts['os_family'] == "Suse"
EOF
tasks/auth.yml
cat > ~/ansible/roles/registry/tasks/auth.yml << 'EOF'
---
# ============================================================
# Registry Authentication â htpasswd
# ============================================================
# ââ ÎηΌÎčÎżÏ
Ïγία htpasswd αÏÏΔίοÏ
âââââââââââââââ
- name: Create htpasswd file
ansible.builtin.file:
path: "{{ registry_auth_dir }}/htpasswd"
state: touch
mode: '0600'
owner: root
when: registry_users | length == 0
# ââ Î ÏÎżÏΞΟÎșη users ââââââââââââââââââââââââââââ
- name: Add registry users
ansible.builtin.command:
cmd: >
htpasswd
{% if not htpasswd_stat.stat.exists %}
-Bbc
{% else %}
-Bb
{% endif %}
{{ registry_auth_dir }}/htpasswd
{{ item.username }}
{{ item.password }}
loop: "{{ registry_users }}"
loop_control:
label: "{{ item.username }}"
no_log: true
register: htpasswd_result
vars:
htpasswd_stat:
stat:
exists: true
- name: Check htpasswd file
ansible.builtin.stat:
path: "{{ registry_auth_dir }}/htpasswd"
register: htpasswd_file
- name: Set htpasswd permissions
ansible.builtin.file:
path: "{{ registry_auth_dir }}/htpasswd"
mode: '0600'
owner: root
when: htpasswd_file.stat.exists
- name: Show auth status
ansible.builtin.debug:
msg: >
Registry auth:
{{ 'â
' + (registry_users | length | string) + ' users configured'
if registry_users | length > 0
else 'â ïž No users configured!' }}
EOF
tasks/deploy.yml
cat > ~/ansible/roles/registry/tasks/deploy.yml << 'EOF'
---
# ============================================================
# Registry Deployment ΌΔ Docker Compose
# ============================================================
# ââ Render compose file âââââââââââââââââââââââ
- name: Render registry docker-compose.yml
ansible.builtin.template:
src: registry-compose.yml.j2
dest: "{{ registry_base_dir }}/docker-compose.yml"
mode: '0644'
# ââ Render nginx config âââââââââââââââââââââââ
- name: Render nginx configuration
ansible.builtin.template:
src: nginx-registry.conf.j2
dest: "{{ registry_base_dir }}/nginx.conf"
mode: '0644'
# ââ Pull images âââââââââââââââââââââââââââââââ
- name: Pull registry images
community.docker.docker_image:
name: "{{ item.name }}"
tag: "{{ item.tag }}"
source: pull
loop:
- { name: registry, tag: "2" }
- { name: nginx, tag: "1.25.3-alpine" }
loop_control:
label: "{{ item.name }}:{{ item.tag }}"
# ââ Deploy stack ââââââââââââââââââââââââââââââ
- name: Deploy registry stack
community.docker.docker_compose_v2:
project_src: "{{ registry_base_dir }}"
project_name: "{{ registry_name }}"
state: present
register: registry_deploy
# ââ Wait for registry âââââââââââââââââââââââââ
- name: Wait for registry to start
community.docker.docker_container_info:
name: "{{ registry_name }}_registry"
register: reg_info
until: >
reg_info.container is defined and
reg_info.container.State.Running == true
retries: 12
delay: 5
# ââ Wait for nginx ââââââââââââââââââââââââââââ
- name: Wait for nginx proxy to start
community.docker.docker_container_info:
name: "{{ registry_name }}_nginx"
register: nginx_info
until: >
nginx_info.container is defined and
nginx_info.container.State.Running == true
retries: 6
delay: 5
# ââ Setup garbage collection ââââââââââââââââââ
- name: Deploy registry GC script
ansible.builtin.copy:
dest: /usr/local/bin/registry-gc.sh
mode: '0755'
owner: root
content: |
#!/bin/bash
# Registry Garbage Collection
echo "=== Registry GC $(date) ==="
docker compose \
-f {{ registry_base_dir }}/docker-compose.yml \
-p {{ registry_name }} \
exec -T registry \
registry garbage-collect \
/etc/docker/registry/config.yml
echo "=== GC complete ==="
when: registry_gc_enabled
- name: Schedule registry GC
ansible.builtin.cron:
name: "Registry garbage collection"
minute: "{{ registry_gc_schedule.split()[0] }}"
hour: "{{ registry_gc_schedule.split()[1] }}"
day: "{{ registry_gc_schedule.split()[2] }}"
month: "{{ registry_gc_schedule.split()[3] }}"
weekday: "{{ registry_gc_schedule.split()[4] }}"
user: root
job: "/usr/local/bin/registry-gc.sh >> /var/log/registry-gc.log 2>&1"
state: present
when: registry_gc_enabled
EOF
templates/registry-compose.yml.j2
cat > ~/ansible/roles/registry/templates/registry-compose.yml.j2 << 'EOF'
{# Private Registry Docker Compose #}
{# Managed by Ansible â DO NOT EDIT! #}
version: "3.8"
services:
# ââââââââââââââââââââââââââââââââââââââââââ
# REGISTRY â Storage Backend
# ââââââââââââââââââââââââââââââââââââââââââ
registry:
image: {{ registry_image }}
container_name: {{ registry_name }}_registry
restart: unless-stopped
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
REGISTRY_HTTP_ADDR: 0.0.0.0:5000
REGISTRY_HTTP_SECRET: {{ vault_registry_http_secret }}
{% if registry_auth_enabled %}
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: "Registry Realm"
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
{% endif %}
REGISTRY_STORAGE_DELETE_ENABLED: "true"
volumes:
- {{ registry_data_dir }}:/var/lib/registry
- {{ registry_auth_dir }}:/auth:ro
- /etc/localtime:/etc/localtime:ro
networks:
- registry_net
deploy:
resources:
limits:
memory: {{ registry_memory }}
cpus: "{{ registry_cpus }}"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "--no-check-certificate", "http://localhost:5000/v2/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
# ââââââââââââââââââââââââââââââââââââââââââ
# NGINX â SSL Proxy
# ââââââââââââââââââââââââââââââââââââââââââ
nginx:
image: {{ nginx_image }}
container_name: {{ registry_name }}_nginx
restart: unless-stopped
ports:
- "{{ registry_ext_port }}:443"
volumes:
- {{ registry_base_dir }}/nginx.conf:/etc/nginx/nginx.conf:ro
- {{ registry_certs_dir }}:/etc/nginx/certs:ro
- {{ registry_logs_dir }}:/var/log/nginx
- /etc/localtime:/etc/localtime:ro
networks:
- registry_net
depends_on:
registry:
condition: service_healthy
deploy:
resources:
limits:
memory: {{ nginx_memory }}
cpus: "{{ nginx_cpus }}"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "--no-check-certificate", "https://localhost/v2/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 15s
networks:
registry_net:
name: {{ registry_name }}_net
driver: bridge
internal: false
EOF
templates/nginx-registry.conf.j2
cat > ~/ansible/roles/registry/templates/nginx-registry.conf.j2 << 'EOF'
{# Nginx config for Docker Registry #}
{# Managed by Ansible â DO NOT EDIT! #}
user nginx;
worker_processes 1;
pid /var/run/nginx.pid;
events {
worker_connections 512;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/registry_access.log;
error_log /var/log/nginx/registry_error.log warn;
# ââ Large image uploads âââââââââââââââââââ
client_max_body_size 0; # â no limit ÎłÎčα images!
chunked_transfer_encoding on;
server {
listen 443 ssl;
server_name {{ registry_hostname }};
# ââ SSL âââââââââââââââââââââââââââââââ
ssl_certificate /etc/nginx/certs/registry.crt;
ssl_certificate_key /etc/nginx/certs/registry.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# ââ Security headers ââââââââââââââââââ
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
# ââ Registry proxy ââââââââââââââââââââ
location /v2/ {
# ââ Auth check ââââââââââââââââââââ
{% if registry_auth_enabled %}
auth_basic "Docker Registry";
auth_basic_user_file /etc/nginx/certs/../../../auth/htpasswd;
{% endif %}
# ââ Proxy settings ââââââââââââââââ
proxy_pass http://registry:5000;
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;
# ââ Timeouts ÎłÎčα ÎŒÎ”ÎłÎŹÎ»Î± images ââââ
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
# ââ Buffer settings âââââââââââââââ
proxy_buffering off;
proxy_request_buffering off;
}
# ââ Health check ââââââââââââââââââââââ
location /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
}
}
# ââ HTTP â HTTPS redirect âââââââââââââââââ
server {
listen 80;
server_name {{ registry_hostname }};
return 301 https://$host$request_uri;
}
}
EOF
tasks/verify.yml
cat > ~/ansible/roles/registry/tasks/verify.yml << 'EOF'
---
# ============================================================
# Registry Verification
# ============================================================
# ââ Basic connectivity ââââââââââââââââââââââââ
- name: Check registry API (internal)
ansible.builtin.uri:
url: "http://localhost:5000/v2/"
status_code: [200, 401]
validate_certs: false
register: reg_api_check
ignore_errors: true
- name: Check registry API (external SSL)
ansible.builtin.uri:
url: "https://localhost:{{ registry_ext_port }}/v2/"
status_code: [200, 401]
validate_certs: false
register: reg_ssl_check
ignore_errors: true
# ââ Authenticated check âââââââââââââââââââââââ
- name: Check registry ΌΔ credentials
ansible.builtin.uri:
url: "https://localhost:{{ registry_ext_port }}/v2/"
status_code: 200
validate_certs: false
url_username: "{{ registry_users[0].username }}"
url_password: "{{ registry_users[0].password }}"
force_basic_auth: true
register: reg_auth_check
when: registry_users | length > 0
no_log: true
ignore_errors: true
# ââ Test push & pull ââââââââââââââââââââââââââ
- name: Login ÏÏÎż private registry
community.docker.docker_login:
registry_url: "https://{{ registry_hostname }}:{{ registry_ext_port }}"
username: "{{ registry_users[0].username }}"
password: "{{ registry_users[0].password }}"
tls_verify: false
no_log: true
when: registry_users | length > 0
register: login_result
- name: Pull test image
community.docker.docker_image:
name: alpine
tag: "3.19"
source: pull
when: login_result is not failed
- name: Tag ÎłÎčα private registry
community.docker.docker_image:
name: "alpine:3.19"
repository: "{{ registry_hostname }}:{{ registry_ext_port }}/test/alpine"
tag: "3.19"
source: local
when: login_result is not failed
- name: Push test image ÏÏÎż registry
community.docker.docker_image:
name: "{{ registry_hostname }}:{{ registry_ext_port }}/test/alpine"
tag: "3.19"
source: local
push: true
tls_verify: false
when: login_result is not failed
register: push_test
- name: Delete local test image
community.docker.docker_image:
name: "{{ registry_hostname }}:{{ registry_ext_port }}/test/alpine"
tag: "3.19"
state: absent
force_absent: true
when: login_result is not failed
- name: Pull test image αÏÏ registry
community.docker.docker_image:
name: "{{ registry_hostname }}:{{ registry_ext_port }}/test/alpine"
tag: "3.19"
source: pull
tls_verify: false
when: login_result is not failed
register: pull_test
- name: Logout
community.docker.docker_login:
registry_url: "https://{{ registry_hostname }}:{{ registry_ext_port }}"
username: "{{ registry_users[0].username }}"
state: absent
no_log: true
when: registry_users | length > 0
# ââ List catalog ââââââââââââââââââââââââââââââ
- name: Get registry catalog
ansible.builtin.uri:
url: "https://localhost:{{ registry_ext_port }}/v2/_catalog"
status_code: 200
validate_certs: false
url_username: "{{ registry_users[0].username }}"
url_password: "{{ registry_users[0].password }}"
force_basic_auth: true
register: catalog
when: registry_users | length > 0
no_log: true
ignore_errors: true
# ââ Report ââââââââââââââââââââââââââââââââââââ
- name: Registry Verification Report
ansible.builtin.debug:
msg:
- "ââââââââââââââââââââââââââââââââââââââââ"
- "â REGISTRY VERIFICATION â"
- "â âââââââââââââââââââââââââââââââââââââââŁ"
- "â Host : {{ registry_hostname }}"
- "â Port : {{ registry_ext_port }}"
- "â SSL : {{ 'â
Enabled' if registry_ssl_enabled else 'â Disabled' }}"
- "â Auth : {{ 'â
Enabled' if registry_auth_enabled else 'â Disabled' }}"
- "â âââââââââââââââââââââââââââââââââââââââŁ"
- "â CHECKS: â"
- "â API : {{ 'â
OK' if not reg_api_check.failed else 'â Failed' }}"
- "â SSL : {{ 'â
OK' if not reg_ssl_check.failed else 'â Failed' }}"
- "â Auth : {{ 'â
OK' if not reg_auth_check.failed else 'â N/A' }}"
- "â Push : {{ 'â
OK' if not push_test.failed else 'â Failed' }}"
- "â Pull : {{ 'â
OK' if not pull_test.failed else 'â Failed' }}"
- "â âââââââââââââââââââââââââââââââââââââââŁ"
- "â Catalog: {{ catalog.json.repositories | default([]) | join(', ') | default('empty') }}"
- "ââââââââââââââââââââââââââââââââââââââââ"
EOF
handlers/main.yml
cat > ~/ansible/roles/registry/handlers/main.yml << 'EOF'
---
- name: Restart registry
ansible.builtin.command:
cmd: >
docker compose
-f {{ registry_base_dir }}/docker-compose.yml
-p {{ registry_name }}
restart registry
ignore_errors: "{{ ansible_check_mode }}"
- name: Reload nginx
ansible.builtin.command:
cmd: >
docker compose
-f {{ registry_base_dir }}/docker-compose.yml
-p {{ registry_name }}
exec -T nginx nginx -s reload
ignore_errors: "{{ ansible_check_mode }}"
EOF
Vault Variables ÎłÎčα Registry
cat > /tmp/registry_vault.yml << 'EOF'
---
vault_registry_http_secret: "RegistrySecret@2026#SuperLong!"
vault_registry_admin_pass: "AdminPass@2026!"
vault_registry_user_pass: "UserPass@2026!"
EOF
# Î ÏÎżÏΞΟÎșη ÏÏÎż Ï
ÏÎŹÏÏÎżÎœ vault
ansible-vault edit \
~/ansible/inventory/group_vars/all/vault.yml
# â Î ÏÏÏΞΔÏΔ Ïα ÏαÏαÏÎŹÎœÏ
Deployment Playbook
cat > ~/ansible/playbooks/private-registry.yml << 'EOF'
---
# ============================================================
# Private Docker Registry Deployment
# ============================================================
- name: Deploy Private Docker Registry
hosts: "{{ target | default('all_managed') }}"
become: true
gather_facts: true
pre_tasks:
- name: Registry deployment info
ansible.builtin.debug:
msg:
- "ââââââââââââââââââââââââââââââââââ"
- "Private Docker Registry Deployment"
- "ââââââââââââââââââââââââââââââââââ"
- "Host: {{ inventory_hostname }}"
- "IP : {{ ansible_facts['default_ipv4']['address'] }}"
- "Port: {{ registry_ext_port | default(443) }}"
- "ââââââââââââââââââââââââââââââââââ"
tags: always
- name: Open firewall port (Debian/ferm)
ansible.builtin.lineinfile:
path: /etc/ferm/ferm.conf
regexp: ".*{{ registry_ext_port | default(443) }}.*"
line: " proto tcp dport {{ registry_ext_port | default(443) }} ACCEPT;"
insertafter: "chain INPUT"
when:
- ansible_facts['os_family'] == "Debian"
notify: Restart ferm
ignore_errors: true
roles:
- role: registry
vars:
registry_hostname: "{{ inventory_hostname }}"
registry_ext_port: 443
registry_auth_enabled: true
registry_users:
- username: admin
password: "{{ vault_registry_admin_pass }}"
- username: deploy
password: "{{ vault_registry_user_pass }}"
registry_ssl_self_signed: true
registry_gc_enabled: true
tags: registry
post_tasks:
- name: Registry Access Info
ansible.builtin.debug:
msg:
- "ââââââââââââââââââââââââââââââââââââââââ"
- "â REGISTRY DEPLOYMENT COMPLETE! đ â"
- "â âââââââââââââââââââââââââââââââââââââââŁ"
- "â Registry URL: â"
- "â {{ inventory_hostname }}:443"
- "â âââââââââââââââââââââââââââââââââââââââŁ"
- "â Usage: â"
- "â docker login {{ inventory_hostname }}"
- "â docker tag myapp:1.0 {{ inventory_hostname }}/myapp:1.0"
- "â docker push {{ inventory_hostname }}/myapp:1.0"
- "â âââââââââââââââââââââââââââââââââââââââŁ"
- "â Note: Self-signed cert â add to â"
- "â /etc/docker/certs.d/ on clients! â"
- "ââââââââââââââââââââââââââââââââââââââââ"
tags: always
handlers:
- name: Restart ferm
ansible.builtin.service:
name: ferm
state: restarted
when: ansible_facts['os_family'] == "Debian"
ignore_errors: "{{ ansible_check_mode }}"
EOF
ÎÎșÏÎλΔÏη
# ââ Syntax check ââââââââââââââââââââââââââââââ
ansible-playbook playbooks/private-registry.yml \
--syntax-check
# ââ Dry run âââââââââââââââââââââââââââââââââââ
ansible-playbook playbooks/private-registry.yml \
--check \
--limit nextcloud
# ââ Full deployment âââââââââââââââââââââââââââ
ansible-playbook playbooks/private-registry.yml \
--limit nextcloud \
-v
# ââ ÎÏÎœÎż setup ââââââââââââââââââââââââââââââââ
ansible-playbook playbooks/private-registry.yml \
--tags setup \
--limit nextcloud
# ââ ÎÏÎœÎż verify âââââââââââââââââââââââââââââââ
ansible-playbook playbooks/private-registry.yml \
--tags verify \
--limit nextcloud
Client Configuration
# ΣΔ ÎșΏΞΔ Docker client ÏÎżÏ
ÏÏηÏÎčÎŒÎżÏÎżÎčΔί ÏÎż registry:
# ââ Copy certificate ââââââââââââââââââââââââââ
sudo mkdir -p /etc/docker/certs.d/nextcloud:443
sudo scp ansible@nextcloud:/opt/registry/certs/registry.crt \
/etc/docker/certs.d/nextcloud:443/ca.crt
# ââ Login âââââââââââââââââââââââââââââââââââââ
docker login nextcloud:443
# Username: admin
# Password: ***
# ââ Push ââââââââââââââââââââââââââââââââââââââ
docker tag nginx:alpine nextcloud:443/nginx:alpine
docker push nextcloud:443/nginx:alpine
# ââ Pull ââââââââââââââââââââââââââââââââââââââ
docker pull nextcloud:443/nginx:alpine
ÎŁÏÎœÎżÏη D5.3
Private Registry ΌΔ Ansible
âââ Components:
â âââ registry:2 â image storage (internal)
â âââ nginx â SSL proxy (external :443)
â
âââ Security:
â âââ SSL: self-signed certificate
â âââ Auth: htpasswd (bcrypt)
â âââ Internal network (registry_net)
â
âââ Setup:
â âââ Directories: data, auth, certs, logs
â âââ SSL cert: openssl req -newkey rsa:4096
â âââ htpasswd: htpasswd -Bbc
â
âââ Features:
â âââ Garbage collection (cron)
â âââ Storage delete enabled
â âââ Pull-through cache ready
â
âââ Client:
âââ Copy cert â /etc/docker/certs.d/
âââ docker login
âââ docker push/pull