--- - name: Deploy Uptime Kuma on GCP and Configure Non-Interactively hosts: all vars: # GCP Configuration gcp_project: "your-gcp-project-id" gcp_region: "us-central1" service_name: "uptime-kuma" ar_repo_name: "dockerhub" data_bucket_name: "{{ gcp_project }}-uptime-kuma-data" # Uptime Kuma Credentials & Target kuma_admin_user: "admin" kuma_admin_pass: "ChangeMeImmediately123!" target_monitor_name: "Target Web App" target_monitor_url: "https://example.com" tasks: # ------------------------------------------------------------- # 1. Local Prerequisites # ------------------------------------------------------------- - name: Ensure uptime-kuma-api Python library is installed locally ansible.builtin.shell: executable: /bin/bash cmd: | apt update apt install python3-pip -y python3 -m pip install --user uptime-kuma-api --break-system-packages python3 -m pip install uptime-kuma-api --break-system-packages register: pip_install changed_when: "'Successfully installed' in pip_install.stdout" # ------------------------------------------------------------- # 2. Enable APIs, Storage Bucket and Docker Hub Mirror # ------------------------------------------------------------- - name: Enable required GCP APIs, create data bucket and Docker Hub remote repo ansible.builtin.shell: executable: /bin/bash cmd: | if [ -f '/home/builder/google-cloud-sdk/path.bash.inc' ]; then . '/home/builder/google-cloud-sdk/path.bash.inc'; fi set -e gcloud services enable run.googleapis.com artifactregistry.googleapis.com storage.googleapis.com \ --project={{ gcp_project }} if ! gcloud storage buckets describe gs://{{ data_bucket_name }} --project={{ gcp_project }} >/dev/null 2>&1; then gcloud storage buckets create gs://{{ data_bucket_name }} \ --project={{ gcp_project }} --location={{ gcp_region }} echo BUCKET_CREATED fi if ! gcloud artifacts repositories describe {{ ar_repo_name }} \ --location={{ gcp_region }} --project={{ gcp_project }} >/dev/null 2>&1; then gcloud artifacts repositories create {{ ar_repo_name }} \ --repository-format=docker --mode=remote-repository \ --remote-docker-repo=DOCKER-HUB \ --location={{ gcp_region }} --project={{ gcp_project }} echo REPO_CREATED fi register: prereq_output changed_when: "'CREATED' in prereq_output.stdout" # ------------------------------------------------------------- # 3. Deploy to Cloud Run (idempotent: deploy updates in place) # ------------------------------------------------------------- # Kuma uses SQLite and websockets: one always-on instance, CPU always allocated. - name: Deploy Uptime Kuma to Cloud Run ansible.builtin.shell: executable: /bin/bash cmd: | if [ -f '/home/builder/google-cloud-sdk/path.bash.inc' ]; then . '/home/builder/google-cloud-sdk/path.bash.inc'; fi gcloud run deploy {{ service_name }} \ --project={{ gcp_project }} \ --region={{ gcp_region }} \ --image={{ gcp_region }}-docker.pkg.dev/{{ gcp_project }}/{{ ar_repo_name }}/louislam/uptime-kuma:1 \ --port=3001 \ --cpu=1 --memory=1Gi \ --min-instances=1 --max-instances=1 \ --no-cpu-throttling \ --execution-environment=gen2 \ --allow-unauthenticated \ --add-volume=name=kuma-data,type=cloud-storage,bucket={{ data_bucket_name }} \ --add-volume-mount=volume=kuma-data,mount-path=/app/data register: deploy_output # ------------------------------------------------------------- # 4. Fetch Service URL and Wait for Readiness # ------------------------------------------------------------- - name: Fetch Cloud Run service URL ansible.builtin.shell: executable: /bin/bash cmd: | if [ -f '/home/builder/google-cloud-sdk/path.bash.inc' ]; then . '/home/builder/google-cloud-sdk/path.bash.inc'; fi gcloud run services describe {{ service_name }} \ --region={{ gcp_region }} \ --project={{ gcp_project }} \ --format="value(status.url)" register: kuma_url changed_when: false - name: Display Uptime Kuma URL ansible.builtin.debug: msg: "Uptime Kuma is running at: {{ kuma_url.stdout.strip() }}" - name: Wait for Uptime Kuma to respond with HTTP 200 ansible.builtin.uri: url: "{{ kuma_url.stdout.strip() }}" status_code: 200 register: readiness until: readiness.status == 200 retries: 30 delay: 6 # ------------------------------------------------------------- # 5. Non-Interactive Configuration via API # ------------------------------------------------------------- - name: Perform headless setup and add monitor ansible.builtin.shell: cmd: | python3 -c " import sys from uptime_kuma_api import UptimeKumaApi, MonitorType api = UptimeKumaApi('{{ kuma_url.stdout.strip() }}') # 1. Initial admin account creation if not yet initialized if api.need_setup(): api.setup('{{ kuma_admin_user }}', '{{ kuma_admin_pass }}') print('ADMIN_CREATED') # 2. Login api.login('{{ kuma_admin_user }}', '{{ kuma_admin_pass }}') # 3. Add monitor idempotently current_monitors = [m['name'] for m in api.get_monitors()] if '{{ target_monitor_name }}' not in current_monitors: api.add_monitor( type=MonitorType.HTTP, name='{{ target_monitor_name }}', url='{{ target_monitor_url }}', interval=60 ) print('MONITOR_ADDED') else: print('MONITOR_ALREADY_EXISTS') api.disconnect() " executable: /bin/bash register: setup_output changed_when: "'MONITOR_ADDED' in setup_output.stdout" - name: Show setup summary ansible.builtin.debug: msg: - "Setup Status: {{ setup_output.stdout.strip() }}" - "Access UI at: {{ kuma_url.stdout.strip() }}" - "Username: {{ kuma_admin_user }}"