--- - name: Deploy PDS hosts: pds become: yes vars_files: - vars/main.yml vars: pds_data_dir: /pds pds_image_tag: "0.4" pds_blob_upload_limit: 314572800 pds_rate_limits_enabled: true pds_invite_required: true pds_crawlers: https://relay.fire.hose.cam pds_backup_period: 24h pds_backup_s3_bucket: atprotopds-backup pds_backup_s3_region: bhs pds_backup_s3_endpoint: https://s3.bhs.io.cloud.ovh.net pds_backup_s3_access_key: "{{ pds_blobstore_s3_access_key }}" pds_backup_s3_secret_key: "{{ pds_blobstore_s3_secret_key }}" pds_grafana_image_tag: "13.1.1" tasks: - name: Run PDS installer (first time only) shell: >- echo "n" | bash <(curl -fsSL https://raw.githubusercontent.com/bluesky-social/pds/main/installer.sh) {{ pds_data_dir }} {{ pds_hostname }} {{ pds_admin_email }} args: creates: "{{ pds_data_dir }}/account.sqlite" executable: /bin/bash - name: Read existing secrets from pds.env shell: grep -E '^(PDS_JWT_SECRET|PDS_ADMIN_PASSWORD|PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX)=' {{ pds_data_dir }}/pds.env register: existing_secrets changed_when: false - name: Set secret facts set_fact: pds_jwt_secret: "{{ existing_secrets.stdout_lines | select('match', '^PDS_JWT_SECRET=') | first | regex_replace('^PDS_JWT_SECRET=', '') }}" pds_admin_password: "{{ existing_secrets.stdout_lines | select('match', '^PDS_ADMIN_PASSWORD=') | first | regex_replace('^PDS_ADMIN_PASSWORD=', '') }}" pds_plc_rotation_key: "{{ existing_secrets.stdout_lines | select('match', '^PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=') | first | regex_replace('^PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=', '') }}" - name: Install rclone apt: name: rclone state: present update_cache: yes - name: Create rclone config directory file: path: /etc/rclone state: directory mode: "0755" - name: Deploy rclone config template: src: templates/rclone.conf.j2 dest: /etc/rclone/rclone.conf mode: "0600" notify: apply changes - name: Deploy backup script template: src: templates/backup.sh.j2 dest: /usr/local/bin/backup.sh mode: "0755" notify: apply changes - name: Deploy backup service template: src: templates/backup.service.j2 dest: /etc/systemd/system/pds-backup.service mode: "0644" - name: Deploy backup timer template: src: templates/backup.timer.j2 dest: /etc/systemd/system/pds-backup.timer mode: "0644" - name: Enable backup timer systemd: name: pds-backup.timer enabled: yes state: started daemon_reload: yes - name: Pre-deploy backup shell: /usr/local/bin/backup.sh predeploy when: existing_secrets.stdout_lines | length > 0 - name: Deploy pds.env template: src: templates/pds.env.j2 dest: "{{ pds_data_dir }}/pds.env" mode: "0600" notify: apply changes - name: Deploy compose.yaml template: src: templates/compose.yaml.j2 dest: "{{ pds_data_dir }}/compose.yaml" mode: "0644" notify: apply changes - name: Deploy Caddyfile template: src: templates/Caddyfile.j2 dest: "{{ pds_data_dir }}/caddy/etc/caddy/Caddyfile" mode: "0644" notify: apply changes - name: Download pdsadmin get_url: url: https://raw.githubusercontent.com/bluesky-social/pds/main/pdsadmin.sh dest: /usr/local/bin/pdsadmin mode: "0755" - name: Flush handlers meta: flush_handlers - name: PDS Health check uri: url: "https://{{ pds_hostname }}/xrpc/_health" method: GET status_code: 200 retries: 3 delay: 5 - name: Check backup timer is active command: systemctl is-active pds-backup.timer changed_when: false - name: Check last backup run succeeded shell: systemctl show pds-backup.service -p ExecMainStatus --value register: pds_backup_exit_code changed_when: false failed_when: pds_backup_exit_code.stdout != "0" - name: Clone pds-operator repo git: repo: "{{ pds_operator_repo }}" dest: "{{ pds_data_dir }}/operator" version: "{{ pds_operator_version | default('main') }}" update: yes force: no when: pds_operator_enabled is defined and pds_operator_enabled | bool register: operator_repo notify: restart operator - name: Read operator session secret (if exists) shell: grep -E '^SESSION_SECRET=' {{ pds_data_dir }}/operator/.env 2>/dev/null | cut -d= -f2 register: operator_existing_secret changed_when: false failed_when: false when: pds_operator_enabled is defined and pds_operator_enabled | bool - name: Generate operator session secret (first run) shell: openssl rand -hex 32 register: operator_new_secret when: - pds_operator_enabled is defined and pds_operator_enabled | bool - operator_existing_secret.stdout | default('') | length == 0 - name: Set operator session secret fact set_fact: pds_operator_session_secret: "{{ operator_existing_secret.stdout if (operator_existing_secret.stdout | default('') | length > 0) else operator_new_secret.stdout }}" when: pds_operator_enabled is defined and pds_operator_enabled | bool - name: Create operator data directory file: path: "{{ pds_data_dir }}/operator/data" state: directory owner: "1000" group: "1000" mode: "0755" when: pds_operator_enabled is defined and pds_operator_enabled | bool - name: Deploy operator .env template: src: templates/pds-operator.env.j2 dest: "{{ pds_data_dir }}/operator/.env" mode: "0600" when: pds_operator_enabled is defined and pds_operator_enabled | bool notify: restart operator - name: Deploy operator compose template: src: templates/pds-operator-compose.yaml.j2 dest: "{{ pds_data_dir }}/operator/compose.yaml" mode: "0644" when: pds_operator_enabled is defined and pds_operator_enabled | bool notify: restart operator - name: Create cities labeler data directory file: path: "{{ pds_data_dir }}/cities/data" state: directory owner: "1000" group: "1000" mode: "0755" when: pds_cities_enabled is defined and pds_cities_enabled | bool - name: Deploy cities labeler .env template: src: templates/cities-labeler.env.j2 dest: "{{ pds_data_dir }}/cities/.env" mode: "0600" when: pds_cities_enabled is defined and pds_cities_enabled | bool notify: restart cities - name: Deploy cities labeler compose template: src: templates/cities-labeler-compose.yaml.j2 dest: "{{ pds_data_dir }}/cities/compose.yaml" mode: "0644" when: pds_cities_enabled is defined and pds_cities_enabled | bool notify: restart cities - name: Create monitoring directories file: path: "{{ item }}" state: directory mode: "0755" loop: - "{{ pds_data_dir }}/monitoring" - "{{ pds_data_dir }}/monitoring/grafana/provisioning/datasources" - "{{ pds_data_dir }}/monitoring/grafana/provisioning/dashboards" - "{{ pds_data_dir }}/monitoring/dashboards" when: pds_telemetry_enabled is defined and pds_telemetry_enabled | bool - name: Deploy monitoring compose template: src: templates/monitoring-compose.yaml.j2 dest: "{{ pds_data_dir }}/monitoring/compose.yaml" mode: "0644" when: pds_telemetry_enabled is defined and pds_telemetry_enabled | bool notify: restart monitoring - name: Deploy Prometheus config template: src: templates/prometheus.yml.j2 dest: "{{ pds_data_dir }}/monitoring/prometheus.yml" mode: "0644" when: pds_telemetry_enabled is defined and pds_telemetry_enabled | bool notify: restart monitoring - name: Deploy Grafana datasource provisioning template: src: templates/grafana-datasources.yml.j2 dest: "{{ pds_data_dir }}/monitoring/grafana/provisioning/datasources/prometheus.yml" mode: "0644" when: pds_telemetry_enabled is defined and pds_telemetry_enabled | bool notify: restart monitoring - name: Deploy Grafana dashboard provisioning template: src: templates/grafana-dashboards.yml.j2 dest: "{{ pds_data_dir }}/monitoring/grafana/provisioning/dashboards/pds.yml" mode: "0644" when: pds_telemetry_enabled is defined and pds_telemetry_enabled | bool notify: restart monitoring - name: Download PDS Overview dashboard get_url: url: https://raw.githubusercontent.com/bluesky-social/pds/main/monitoring/dashboards/pds-overview.json dest: "{{ pds_data_dir }}/monitoring/dashboards/pds-overview.json" mode: "0644" when: pds_telemetry_enabled is defined and pds_telemetry_enabled | bool notify: restart monitoring - name: Start monitoring stack shell: cd {{ pds_data_dir }}/monitoring && docker compose up -d when: pds_telemetry_enabled is defined and pds_telemetry_enabled | bool - name: Flush handlers (operator + cities + monitoring) meta: flush_handlers - name: Operator health check uri: url: "https://{{ pds_operator_hostname }}/oauth/client-metadata.json" method: GET status_code: 200 retries: 5 delay: 10 when: pds_operator_enabled is defined and pds_operator_enabled | bool - name: Cities labeler health check uri: url: "https://{{ pds_cities_hostname }}/xrpc/_health" method: GET status_code: 200 retries: 5 delay: 10 when: pds_cities_enabled is defined and pds_cities_enabled | bool handlers: - name: apply changes shell: cd {{ pds_data_dir }} && docker compose up -d && docker restart caddy - name: restart monitoring shell: cd {{ pds_data_dir }}/monitoring && docker compose up -d --force-recreate - name: restart operator shell: cd {{ pds_data_dir }}/operator && docker compose up -d --build - name: restart cities shell: cd {{ pds_data_dir }}/cities && docker compose pull && docker compose up -d