diff --git a/ansible/infra/910_docker_playbook.yml b/ansible/infra/910_docker_playbook.yml index f137b6a..8e8e430 100644 --- a/ansible/infra/910_docker_playbook.yml +++ b/ansible/infra/910_docker_playbook.yml @@ -25,7 +25,6 @@ name: - ca-certificates - curl - - gnupg state: present - name: Create directory for Docker GPG key diff --git a/ansible/infra_secrets.yml.example b/ansible/infra_secrets.yml.example index 14fd498..cddc58a 100644 --- a/ansible/infra_secrets.yml.example +++ b/ansible/infra_secrets.yml.example @@ -26,8 +26,3 @@ bitcoin_rpc_password: "CHANGE_ME_TO_SECURE_PASSWORD" # Mempool MariaDB credentials # Used by: services/mempool/deploy_mempool_playbook.yml mariadb_mempool_password: "CHANGE_ME_TO_SECURE_PASSWORD" - -# Forgejo Runner registration token -# Used by: services/forgejo-runner/deploy_forgejo_runner_playbook.yml -# See: services/forgejo-runner/SETUP.md for how to obtain this token -forgejo_runner_registration_token: "YOUR_RUNNER_TOKEN_HERE" diff --git a/ansible/services/forgejo-runner/SETUP.md b/ansible/services/forgejo-runner/SETUP.md deleted file mode 100644 index a66d295..0000000 --- a/ansible/services/forgejo-runner/SETUP.md +++ /dev/null @@ -1,28 +0,0 @@ -# Forgejo Runner Setup - -## Obtaining the Registration Token - -1. Log in to the Forgejo instance at `https://forgejo.contrapeso.xyz` -2. Go to **Site Administration** > **Actions** > **Runners** -3. Click **Create new runner** -4. Copy the registration token - -## Configuring the Token - -Paste the token into `ansible/infra_secrets.yml`: - -```yaml -forgejo_runner_registration_token: "YOUR_TOKEN_HERE" -``` - -## Running the Playbook - -```bash -ansible-playbook ansible/services/forgejo-runner/deploy_forgejo_runner_playbook.yml -``` - -## Verifying - -1. On the VM: `systemctl status forgejo-runner` should show active -2. In Forgejo: **Site Administration** > **Actions** > **Runners** should show the runner as online -3. In Uptime Kuma: the `forgejo-runner-healthcheck` push monitor should be receiving pings diff --git a/ansible/services/forgejo-runner/deploy_forgejo_runner_playbook.yml b/ansible/services/forgejo-runner/deploy_forgejo_runner_playbook.yml deleted file mode 100644 index a194178..0000000 --- a/ansible/services/forgejo-runner/deploy_forgejo_runner_playbook.yml +++ /dev/null @@ -1,392 +0,0 @@ -- name: Install Forgejo Runner on Debian 13 - hosts: forgejo_runner_local - become: yes - vars_files: - - ../../infra_vars.yml - - ../../services_config.yml - - ../../infra_secrets.yml - - ./forgejo_runner_vars.yml - vars: - uptime_kuma_api_url: "https://{{ subdomains.uptime_kuma }}.{{ root_domain }}" - ntfy_topic: "{{ service_settings.ntfy.topic }}" - healthcheck_interval_seconds: 60 - healthcheck_timeout_seconds: 90 - healthcheck_retries: 1 - healthcheck_script_dir: /opt/forgejo-runner-healthcheck - healthcheck_script_path: "{{ healthcheck_script_dir }}/forgejo_runner_healthcheck.sh" - healthcheck_log_file: "{{ healthcheck_script_dir }}/forgejo_runner_healthcheck.log" - healthcheck_service_name: forgejo-runner-healthcheck - - tasks: - # ── 1. Assert Docker is available ────────────────────────────────── - - name: Check if Docker is installed - command: docker --version - register: docker_check - changed_when: false - failed_when: docker_check.rc != 0 - - - name: Fail if Docker is not available - assert: - that: - - docker_check.rc == 0 - fail_msg: > - Docker is not installed or not in PATH. - Please install Docker before running this playbook. - - # ── 2. Download forgejo-runner binary ────────────────────────────── - - name: Download forgejo-runner binary - get_url: - url: "{{ forgejo_runner_url }}" - dest: "{{ forgejo_runner_bin_path }}" - mode: '0755' - - # ── 3. Create runner system user ─────────────────────────────────── - - name: Create runner system user - user: - name: "{{ forgejo_runner_user }}" - system: yes - shell: /usr/sbin/nologin - home: "{{ forgejo_runner_dir }}" - create_home: no - groups: docker - append: yes - comment: 'Forgejo Runner' - - # ── 4. Create working directory ──────────────────────────────────── - - name: Create forgejo-runner working directory - file: - path: "{{ forgejo_runner_dir }}" - state: directory - owner: "{{ forgejo_runner_user }}" - group: "{{ forgejo_runner_user }}" - mode: '0750' - - # ── 5. Generate default config ───────────────────────────────────── - - name: Check if config already exists - stat: - path: "{{ forgejo_runner_config_path }}" - register: config_stat - - - name: Generate default config - shell: "{{ forgejo_runner_bin_path }} generate-config > {{ forgejo_runner_config_path }}" - args: - chdir: "{{ forgejo_runner_dir }}" - when: not config_stat.stat.exists - - - name: Set config file ownership - file: - path: "{{ forgejo_runner_config_path }}" - owner: "{{ forgejo_runner_user }}" - group: "{{ forgejo_runner_user }}" - when: not config_stat.stat.exists - - # ── 6. Register runner ───────────────────────────────────────────── - - name: Check if runner is already registered - stat: - path: "{{ forgejo_runner_dir }}/.runner" - register: runner_stat - - - name: Register runner with Forgejo instance - command: > - {{ forgejo_runner_bin_path }} register --no-interactive - --instance {{ forgejo_instance_url }} - --token {{ forgejo_runner_registration_token }} - --name forgejo-runner-box - --labels "{{ forgejo_runner_labels }}" - args: - chdir: "{{ forgejo_runner_dir }}" - when: not runner_stat.stat.exists - - - name: Set runner registration file ownership - file: - path: "{{ forgejo_runner_dir }}/.runner" - owner: "{{ forgejo_runner_user }}" - group: "{{ forgejo_runner_user }}" - when: not runner_stat.stat.exists - - # ── 7. Create systemd service ────────────────────────────────────── - - name: Create forgejo-runner systemd service - copy: - dest: /etc/systemd/system/forgejo-runner.service - content: | - [Unit] - Description=Forgejo Runner - Documentation=https://forgejo.org/docs/latest/admin/actions/ - After=docker.service - Requires=docker.service - - [Service] - Type=simple - User={{ forgejo_runner_user }} - Group={{ forgejo_runner_user }} - WorkingDirectory={{ forgejo_runner_dir }} - ExecStart={{ forgejo_runner_bin_path }} daemon --config {{ forgejo_runner_config_path }} - Restart=on-failure - RestartSec=10 - - [Install] - WantedBy=multi-user.target - owner: root - group: root - mode: '0644' - - # ── 8. Reload systemd, enable and start ──────────────────────────── - - name: Reload systemd - systemd: - daemon_reload: yes - - - name: Enable and start forgejo-runner service - systemd: - name: forgejo-runner - enabled: yes - state: started - - # ── 9. Verify runner is active ───────────────────────────────────── - - name: Verify forgejo-runner is active - command: systemctl is-active forgejo-runner - register: runner_active - changed_when: false - - - name: Assert runner is running - assert: - that: - - runner_active.stdout == "active" - fail_msg: "forgejo-runner service is not active: {{ runner_active.stdout }}" - - # ── 10. Set up Uptime Kuma push monitor ──────────────────────────── - - name: Create Uptime Kuma push monitor setup script - copy: - dest: /tmp/setup_forgejo_runner_monitor.py - content: | - #!/usr/bin/env python3 - import sys - import json - from uptime_kuma_api import UptimeKumaApi - - def main(): - api_url = sys.argv[1] - username = sys.argv[2] - password = sys.argv[3] - group_name = sys.argv[4] - monitor_name = sys.argv[5] - monitor_description = sys.argv[6] - interval = int(sys.argv[7]) - retries = int(sys.argv[8]) - ntfy_topic = sys.argv[9] if len(sys.argv) > 9 else "alerts" - - api = UptimeKumaApi(api_url, timeout=60, wait_events=2.0) - api.login(username, password) - - # Get all monitors - monitors = api.get_monitors() - - # Get all notifications and find ntfy notification - notifications = api.get_notifications() - ntfy_notification = next((n for n in notifications if n.get('name') == f'ntfy ({ntfy_topic})'), None) - notification_id_list = {} - if ntfy_notification: - notification_id_list[ntfy_notification['id']] = True - - # Find or create group - group = next((m for m in monitors if m.get('name') == group_name and m.get('type') == 'group'), None) - if not group: - group_result = api.add_monitor(type='group', name=group_name) - # Refresh to get the full group object with id - monitors = api.get_monitors() - group = next((m for m in monitors if m.get('name') == group_name and m.get('type') == 'group'), None) - - # Find or create/update push monitor - existing_monitor = next((m for m in monitors if m.get('name') == monitor_name), None) - - monitor_data = { - 'type': 'push', - 'name': monitor_name, - 'parent': group['id'], - 'interval': interval, - 'upsideDown': False, - 'maxretries': retries, - 'description': monitor_description, - 'notificationIDList': notification_id_list - } - - if existing_monitor: - monitor = api.edit_monitor(existing_monitor['id'], **monitor_data) - # Refresh to get the full monitor object with pushToken - monitors = api.get_monitors() - monitor = next((m for m in monitors if m.get('name') == monitor_name), None) - else: - monitor_result = api.add_monitor(**monitor_data) - # Refresh to get the full monitor object with pushToken - monitors = api.get_monitors() - monitor = next((m for m in monitors if m.get('name') == monitor_name), None) - - result = { - 'monitor_id': monitor['id'], - 'push_token': monitor['pushToken'], - 'group_name': group_name, - 'group_id': group['id'], - 'monitor_name': monitor_name - } - print(json.dumps(result)) - - api.disconnect() - - if __name__ == '__main__': - main() - mode: '0755' - delegate_to: localhost - become: no - - - name: Run Uptime Kuma push monitor setup - command: > - {{ ansible_playbook_python }} - /tmp/setup_forgejo_runner_monitor.py - "{{ uptime_kuma_api_url }}" - "{{ uptime_kuma_username }}" - "{{ uptime_kuma_password }}" - "services" - "forgejo-runner-healthcheck" - "Forgejo Runner healthcheck - ping every {{ healthcheck_interval_seconds }}s" - "{{ healthcheck_timeout_seconds }}" - "{{ healthcheck_retries }}" - "{{ ntfy_topic }}" - register: monitor_setup_result - delegate_to: localhost - become: no - changed_when: false - - - name: Parse monitor setup result - set_fact: - monitor_info_parsed: "{{ monitor_setup_result.stdout | from_json }}" - - - name: Set push URL - set_fact: - uptime_kuma_push_url: "{{ uptime_kuma_api_url }}/api/push/{{ monitor_info_parsed.push_token }}" - - - name: Create healthcheck script directory - file: - path: "{{ healthcheck_script_dir }}" - state: directory - owner: root - group: root - mode: '0755' - - - name: Create forgejo-runner healthcheck script - copy: - dest: "{{ healthcheck_script_path }}" - content: | - #!/bin/bash - - # Forgejo Runner Healthcheck Script - # Checks if forgejo-runner is active and pings Uptime Kuma on success - - LOG_FILE="{{ healthcheck_log_file }}" - UPTIME_KUMA_URL="{{ uptime_kuma_push_url }}" - - log_message() { - echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE" - } - - main() { - if systemctl is-active --quiet forgejo-runner; then - log_message "forgejo-runner is active, sending ping" - response=$(curl -s -w "\n%{http_code}" "$UPTIME_KUMA_URL?status=up&msg=forgejo-runner%20is%20active" 2>&1) - http_code=$(echo "$response" | tail -n1) - if [ "$http_code" = "200" ] || [ "$http_code" = "201" ]; then - log_message "Ping sent successfully (HTTP $http_code)" - else - log_message "ERROR: Failed to send ping (HTTP $http_code)" - exit 1 - fi - else - log_message "ERROR: forgejo-runner is not active" - exit 1 - fi - } - - main - owner: root - group: root - mode: '0755' - - - name: Create healthcheck systemd service - copy: - dest: "/etc/systemd/system/{{ healthcheck_service_name }}.service" - content: | - [Unit] - Description=Forgejo Runner Healthcheck - After=network.target - - [Service] - Type=oneshot - ExecStart={{ healthcheck_script_path }} - User=root - StandardOutput=journal - StandardError=journal - - [Install] - WantedBy=multi-user.target - owner: root - group: root - mode: '0644' - - - name: Create healthcheck systemd timer - copy: - dest: "/etc/systemd/system/{{ healthcheck_service_name }}.timer" - content: | - [Unit] - Description=Run Forgejo Runner Healthcheck every minute - Requires={{ healthcheck_service_name }}.service - - [Timer] - OnBootSec=30sec - OnUnitActiveSec={{ healthcheck_interval_seconds }}sec - Persistent=true - - [Install] - WantedBy=timers.target - owner: root - group: root - mode: '0644' - - - name: Reload systemd for healthcheck units - systemd: - daemon_reload: yes - - - name: Enable and start healthcheck timer - systemd: - name: "{{ healthcheck_service_name }}.timer" - enabled: yes - state: started - - - name: Test healthcheck script - command: "{{ healthcheck_script_path }}" - register: healthcheck_test - changed_when: false - - - name: Verify healthcheck script works - assert: - that: - - healthcheck_test.rc == 0 - fail_msg: "Healthcheck script failed to execute properly" - - - name: Display deployment summary - debug: - msg: | - Forgejo Runner deployed successfully! - - Runner Name: forgejo-runner-box - Instance: {{ forgejo_instance_url }} - Working Directory: {{ forgejo_runner_dir }} - Service: forgejo-runner.service ({{ runner_active.stdout }}) - - Healthcheck Monitor: forgejo-runner-healthcheck - Healthcheck Interval: Every {{ healthcheck_interval_seconds }}s - Timeout: {{ healthcheck_timeout_seconds }}s - - - name: Clean up temporary monitor setup script - file: - path: /tmp/setup_forgejo_runner_monitor.py - state: absent - delegate_to: localhost - become: no diff --git a/ansible/services/forgejo-runner/forgejo_runner_vars.yml b/ansible/services/forgejo-runner/forgejo_runner_vars.yml deleted file mode 100644 index e618fca..0000000 --- a/ansible/services/forgejo-runner/forgejo_runner_vars.yml +++ /dev/null @@ -1,9 +0,0 @@ -forgejo_runner_version: "6.3.1" -forgejo_runner_arch: "linux-amd64" -forgejo_runner_url: "https://code.forgejo.org/forgejo/runner/releases/download/v{{ forgejo_runner_version }}/forgejo-runner-{{ forgejo_runner_version }}-{{ forgejo_runner_arch }}" -forgejo_runner_bin_path: "/usr/local/bin/forgejo-runner" -forgejo_runner_user: "runner" -forgejo_runner_dir: "/opt/forgejo-runner" -forgejo_runner_config_path: "{{ forgejo_runner_dir }}/config.yml" -forgejo_runner_labels: "docker:docker://node:20-bookworm,ubuntu-latest:docker://node:20-bookworm,ubuntu-22.04:docker://node:20-bookworm,ubuntu-24.04:docker://node:20-bookworm" -forgejo_instance_url: "https://forgejo.contrapeso.xyz"