--- - name: Deploy Uptime Kuma on GCP and Configure Non-Interactively vars: # GCP Configuration gcp_project: "your-gcp-project-id" gcp_region: "us-central1" gcp_zone: "us-central1-a" instance_name: "uptime-kuma-vm" machine_type: "e2-small" # 2GB RAM is plenty for Uptime Kuma static_ip_name: "uptime-kuma-ip" firewall_rule_name: "allow-uptime-kuma-3001" # 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.pip: name: uptime-kuma-api state: present # ------------------------------------------------------------- # 2. Allocate Static Public IP (Idempotent) # ------------------------------------------------------------- - name: Check if static IP exists ansible.builtin.command: > gcloud compute addresses describe {{ static_ip_name }} --region={{ gcp_region }} --project={{ gcp_project }} register: ip_check failed_when: false changed_when: false - name: Allocate static external IP in GCP ansible.builtin.command: > gcloud compute addresses create {{ static_ip_name }} --region={{ gcp_region }} --project={{ gcp_project }} --description="Static IP for Uptime Kuma" when: ip_check.rc != 0 # ------------------------------------------------------------- # 3. Create Firewall Rule (Port 3001) # ------------------------------------------------------------- - name: Check if firewall rule exists ansible.builtin.command: > gcloud compute firewall-rules describe {{ firewall_rule_name }} --project={{ gcp_project }} register: fw_check failed_when: false changed_when: false - name: Allow TCP traffic to port 3001 ansible.builtin.command: > gcloud compute firewall-rules create {{ firewall_rule_name }} --project={{ gcp_project }} --allow=tcp:3001 --target-tags=uptime-kuma --source-ranges=0.0.0.0/0 --description="Allow traffic to Uptime Kuma UI & API" when: fw_check.rc != 0 # ------------------------------------------------------------- # 4. Provision VM with Container-Optimized OS # ------------------------------------------------------------- - name: Check if instance already exists ansible.builtin.command: > gcloud compute instances describe {{ instance_name }} --zone={{ gcp_zone }} --project={{ gcp_project }} register: instance_check failed_when: false changed_when: false - name: Launch Compute Engine VM with Uptime Kuma container ansible.builtin.command: > gcloud compute instances create-with-container {{ instance_name }} --project={{ gcp_project }} --zone={{ gcp_zone }} --machine-type={{ machine_type }} --tags=uptime-kuma --address={{ static_ip_name }} --boot-disk-size=20GB --container-image=louislam/uptime-kuma:1 --container-mount-host-path=host-path=/var/uptime-kuma,mount-path=/app/data,mode=rw when: instance_check.rc != 0 # ------------------------------------------------------------- # 5. Fetch Public IP and Wait for Service Readiness # ------------------------------------------------------------- - name: Fetch instance public IP address ansible.builtin.command: > gcloud compute instances describe {{ instance_name }} --zone={{ gcp_zone }} --project={{ gcp_project }} --format="value(networkInterfaces[0].accessConfigs[0].natIP)" register: vm_ip changed_when: false - name: Display Uptime Kuma URL ansible.builtin.debug: msg: "Uptime Kuma is booting at: http://{{ vm_ip.stdout.strip() }}:3001" - name: Wait for Uptime Kuma to respond with HTTP 200 ansible.builtin.uri: url: "http://{{ vm_ip.stdout.strip() }}:3001" status_code: 200 register: readiness until: readiness.status == 200 retries: 30 delay: 6 # ------------------------------------------------------------- # 6. Non-Interactive Configuration via API # ------------------------------------------------------------- - name: Perform headless setup and add monitor ansible.builtin.command: cmd: > python3 -c " import sys from uptime_kuma_api import UptimeKumaApi, MonitorType kuma_url = 'http://{{ vm_ip.stdout.strip() }}:3001' api = UptimeKumaApi(kuma_url) # 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() " 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: http://{{ vm_ip.stdout.strip() }}:3001" - "Username: {{ kuma_admin_user }}"