Files
michaelschiemer/deployment/ansible/playbooks/setup-infrastructure.yml

211 lines
6.9 KiB
YAML

---
- name: Deploy Infrastructure Stacks on Production Server
hosts: production
become: no
gather_facts: yes
vars:
stacks_base_path: "~/deployment/stacks"
wait_timeout: 60
tasks:
- name: Check if deployment stacks directory exists
stat:
path: "{{ stacks_base_path }}"
register: stacks_dir
- name: Fail if stacks directory doesn't exist
fail:
msg: "Deployment stacks directory not found at {{ stacks_base_path }}"
when: not stacks_dir.stat.exists
# Create external network required by all stacks
- name: Create traefik-public network
community.docker.docker_network:
name: traefik-public
driver: bridge
state: present
# 1. Deploy Traefik (Reverse Proxy & SSL)
- name: Deploy Traefik stack
community.docker.docker_compose_v2:
project_src: "{{ stacks_base_path }}/traefik"
state: present
pull: always
register: traefik_output
- name: Wait for Traefik to be ready
wait_for:
timeout: "{{ wait_timeout }}"
when: traefik_output.changed
- name: Check Traefik logs for readiness hint
shell: docker compose logs traefik 2>&1 | grep -Ei "(configuration loaded|traefik[[:space:]]v|Starting provider|Server configuration loaded)" || true
args:
chdir: "{{ stacks_base_path }}/traefik"
register: traefik_logs
until: traefik_logs.stdout != ""
retries: 6
delay: 10
changed_when: false
ignore_errors: yes
# 2. Deploy PostgreSQL (Database)
- name: Deploy PostgreSQL stack
community.docker.docker_compose_v2:
project_src: "{{ stacks_base_path }}/postgresql"
state: present
pull: always
register: postgres_output
- name: Wait for PostgreSQL to be ready
wait_for:
timeout: "{{ wait_timeout }}"
when: postgres_output.changed
- name: Check PostgreSQL logs for readiness
shell: docker compose logs postgres 2>&1 | grep -Ei "(ready to accept connections|database system is ready)" || true
args:
chdir: "{{ stacks_base_path }}/postgresql"
register: postgres_logs
until: postgres_logs.stdout != ""
retries: 6
delay: 10
changed_when: false
ignore_errors: yes
# 3. Deploy Docker Registry (Private Registry)
- name: Ensure Registry auth directory exists
file:
path: "{{ stacks_base_path }}/registry/auth"
state: directory
mode: '0755'
become: yes
- name: Create Registry htpasswd file if missing
shell: |
if [ ! -f {{ stacks_base_path }}/registry/auth/htpasswd ]; then
docker run --rm --entrypoint htpasswd httpd:2 -Bbn admin registry-secure-password-2025 > {{ stacks_base_path }}/registry/auth/htpasswd
chmod 644 {{ stacks_base_path }}/registry/auth/htpasswd
fi
args:
executable: /bin/bash
become: yes
changed_when: true
register: registry_auth_created
- name: Deploy Docker Registry stack
community.docker.docker_compose_v2:
project_src: "{{ stacks_base_path }}/registry"
state: present
pull: always
register: registry_output
- name: Wait for Docker Registry to be ready
wait_for:
timeout: "{{ wait_timeout }}"
when: registry_output.changed
- name: Check Registry logs for readiness
shell: docker compose logs registry 2>&1 | grep -Ei "(listening on|listening at|http server)" || true
args:
chdir: "{{ stacks_base_path }}/registry"
register: registry_logs
until: registry_logs.stdout != ""
retries: 6
delay: 10
changed_when: false
ignore_errors: yes
- name: Verify Registry is accessible
uri:
url: "http://127.0.0.1:5000/v2/_catalog"
user: admin
password: registry-secure-password-2025
status_code: 200
timeout: 5
register: registry_check
ignore_errors: yes
changed_when: false
- name: Display Registry status
debug:
msg: "Registry accessibility: {{ 'SUCCESS' if registry_check.status == 200 else 'FAILED - may need manual check' }}"
# 4. Deploy Gitea (CRITICAL - Git Server + MySQL + Redis)
- name: Deploy Gitea stack
community.docker.docker_compose_v2:
project_src: "{{ stacks_base_path }}/gitea"
state: present
pull: always
register: gitea_output
- name: Wait for Gitea to be ready
wait_for:
timeout: "{{ wait_timeout }}"
when: gitea_output.changed
- name: Check Gitea logs for readiness
shell: docker compose logs gitea 2>&1 | grep -Ei "(Listen:|Server is running|Starting server)" || true
args:
chdir: "{{ stacks_base_path }}/gitea"
register: gitea_logs
until: gitea_logs.stdout != ""
retries: 12
delay: 10
changed_when: false
ignore_errors: yes
# 5. Deploy Monitoring (Portainer + Grafana + Prometheus)
- name: Deploy Monitoring stack
community.docker.docker_compose_v2:
project_src: "{{ stacks_base_path }}/monitoring"
state: present
pull: always
register: monitoring_output
- name: Wait for Monitoring to be ready
wait_for:
timeout: "{{ wait_timeout }}"
when: monitoring_output.changed
# Verification
- name: List all running containers
command: >
docker ps --format 'table {{ "{{" }}.Names{{ "}}" }}\t{{ "{{" }}.Status{{ "}}" }}\t{{ "{{" }}.Ports{{ "}}" }}'
register: docker_ps_output
- name: Display running containers
debug:
msg: "{{ docker_ps_output.stdout_lines }}"
- name: Verify Gitea accessibility via HTTPS
uri:
url: https://git.michaelschiemer.de
method: GET
validate_certs: no
status_code: 200
timeout: 10
register: gitea_http_check
ignore_errors: yes
- name: Display Gitea accessibility status
debug:
msg: "Gitea HTTPS check: {{ 'SUCCESS' if gitea_http_check.status == 200 else 'FAILED - Status: ' + (gitea_http_check.status|string) }}"
- name: Summary
debug:
msg:
- "=== Infrastructure Deployment Complete ==="
- "Traefik: {{ 'Deployed' if traefik_output.changed else 'Already running' }}"
- "PostgreSQL: {{ 'Deployed' if postgres_output.changed else 'Already running' }}"
- "Docker Registry: {{ 'Deployed' if registry_output.changed else 'Already running' }}"
- "Gitea: {{ 'Deployed' if gitea_output.changed else 'Already running' }}"
- "Monitoring: {{ 'Deployed' if monitoring_output.changed else 'Already running' }}"
- ""
- "Next Steps:"
- "1. Access Gitea at: https://git.michaelschiemer.de"
- "2. Complete Gitea setup wizard if first-time deployment"
- "3. Navigate to Admin > Actions > Runners to get registration token"
- "4. Continue with Phase 1 - Gitea Runner Setup"