diff --git a/roles/uptime_kuma/.ansible-lint b/roles/uptime_kuma/.ansible-lint new file mode 100644 index 0000000..f865478 --- /dev/null +++ b/roles/uptime_kuma/.ansible-lint @@ -0,0 +1,16 @@ +--- +profile: production +strict: true + +# Enable checking of loop variable prefixes in roles +loop_var_prefix: "^(__|{role}_)" + +skip_list: + - var-naming[no-role-prefix] + +warn_list: + - role-name[path] + - var-naming[no-role-prefix] + +exclude_paths: + - .github/ diff --git a/roles/uptime_kuma/.gitignore b/roles/uptime_kuma/.gitignore new file mode 100644 index 0000000..3361b6d --- /dev/null +++ b/roles/uptime_kuma/.gitignore @@ -0,0 +1,13 @@ +# IDE + +.vscode +.idea + +# test files + +ansible.cfg +inventory.yml +playbook.yml + +old/ +uptime-kuma-data/ diff --git a/roles/uptime_kuma/.yamllint b/roles/uptime_kuma/.yamllint new file mode 100644 index 0000000..611db54 --- /dev/null +++ b/roles/uptime_kuma/.yamllint @@ -0,0 +1,8 @@ +--- +rules: + brackets: + forbid: false + min-spaces-inside: 0 + max-spaces-inside: 2 + min-spaces-inside-empty: -1 + max-spaces-inside-empty: 2 diff --git a/roles/uptime_kuma/README.md b/roles/uptime_kuma/README.md new file mode 100644 index 0000000..5406e34 --- /dev/null +++ b/roles/uptime_kuma/README.md @@ -0,0 +1,49 @@ +ansible-uptime-kuma +========= + +[![linters](https://github.com/corvus-migratorius/ansible-uptime-kuma/actions/workflows/linters.yaml/badge.svg)](https://github.com/corvus-migratorius/ansible-uptime-kuma/actions/workflows/linters.yaml) +[![kics](https://github.com/corvus-migratorius/ansible-uptime-kuma/actions/workflows/kics.yml/badge.svg)](https://github.com/corvus-migratorius/ansible-uptime-kuma/actions/workflows/kics.yml) +[![molecule](https://github.com/corvus-migratorius/ansible-uptime-kuma/actions/workflows/molecule.yaml/badge.svg)](https://github.com/corvus-migratorius/ansible-uptime-kuma/actions/workflows/molecule.yaml) + +Deploy and confugure a containerized instance of [uptime-kuma](https://github.com/louislam/uptime-kuma). + +Requirements +------------ + +None + +Role Variables +-------------- + +- `kuma_img_version`: Kuma container version +- `kuma_project_dir`: where to put Docker Compose file and keep Kuma's data +- `kuma_port`: listening port for Kuma API and web interface +- `kuma_api_version`: version of the Python API +- `kuma_limit_cpus`: CPU cores limit for Kuma +- `kuma_limit_ram`: RAM limit for Kuma +- `kuma_tg_notif_name`: Name for Telegram notification method +- `kuma_tg_notif_is_default`: make this notification method default (default: `true`) +- `kuma_tg_notif_apply_existing`: connect all existing monitors to this notification method (default: `true`) +- `kuma_tg_bot_token`: Telegram bot token for the bot that will be delivering messages +- `kuma_tg_chat_id`: Telegram chat/group where the bot should deliver messages (bot must be a member there) +- `kuma_tg_notif_state`: `present` (default) or `absent` + +Dependencies +------------ + +- `genlab.docker_ubuntu` + +Example Playbook +---------------- + +See `molecule/default/converge`. + +License +------- + +BSD + +Author Information +------------------ + +corvus-migratorius@proton.me diff --git a/roles/uptime_kuma/conda.dev.yml b/roles/uptime_kuma/conda.dev.yml new file mode 100644 index 0000000..59bd312 --- /dev/null +++ b/roles/uptime_kuma/conda.dev.yml @@ -0,0 +1,11 @@ +--- +name: ansible-uptime-kuma +channels: + - conda-forge +dependencies: + - actionlint + - python~=3.12.0 + - pip>=24.2 + - pip: + - -r requirements.txt + - -r requirements.ci.txt diff --git a/roles/uptime_kuma/conda.prod.yml b/roles/uptime_kuma/conda.prod.yml new file mode 100644 index 0000000..bf4fdff --- /dev/null +++ b/roles/uptime_kuma/conda.prod.yml @@ -0,0 +1,9 @@ +--- +name: ansible-uptime-kuma +channels: + - conda-forge +dependencies: + - python~=3.12.0 + - pip>=24.2 + - pip: + - -r requirements.txt diff --git a/roles/uptime_kuma/defaults/main.yml b/roles/uptime_kuma/defaults/main.yml new file mode 100644 index 0000000..d6abd4a --- /dev/null +++ b/roles/uptime_kuma/defaults/main.yml @@ -0,0 +1,8 @@ +--- +kuma_img_version: "1.23.16-alpine" +kuma_project_dir: "/uptime-kuma" +kuma_port: 3001 +kuma_api_version: "1.2.0" +kuma_limit_cpus: 2 +kuma_limit_ram: "2G" +kuma_default_notification_names: [] diff --git a/roles/uptime_kuma/handlers/main.yml b/roles/uptime_kuma/handlers/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/uptime_kuma/handlers/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/uptime_kuma/meta/main.yml b/roles/uptime_kuma/meta/main.yml new file mode 100644 index 0000000..8e8cf31 --- /dev/null +++ b/roles/uptime_kuma/meta/main.yml @@ -0,0 +1,17 @@ +--- +galaxy_info: + role_name: "uptime_kuma" + namespace: genlab + author: "Alexander Gorelyshev" + company: "Genlab, LLC" + description: "" + license: "MIT" + min_ansible_version: "2.1" + + platforms: + - name: "Ubuntu" + versions: ["focal", "jammy"] + + galaxy_tags: [] + +dependencies: [] diff --git a/roles/uptime_kuma/molecule/default/converge.yml b/roles/uptime_kuma/molecule/default/converge.yml new file mode 100644 index 0000000..a911411 --- /dev/null +++ b/roles/uptime_kuma/molecule/default/converge.yml @@ -0,0 +1,25 @@ +# kics-scan ignore +--- +- name: Converge + hosts: all + vars: + test_admin_username: admin + test_admin_password: SDjj3$k4g9dhsjd__1dj + roles: + - genlab.docker_ubuntu + tasks: + - name: "Test the role" + tags: [role] + ansible.builtin.include_role: + name: "genlab.uptime_kuma" + vars: + kuma_api_username: "{{ test_admin_username }}" + kuma_api_password: "{{ test_admin_password }}" + kuma_tg_bot_token: 8161628020:AAF9doUFKSwdK4NZ8z58zVpqq0H1EdrKnI1 + kuma_tg_chat_id: -4877676122 + kuma_default_notification_names: ["Telegram alerts"] + kuma_monitors: + - name: "push-test" + type: push + interval: 30 + description: "Test push monitor" diff --git a/roles/uptime_kuma/molecule/default/molecule.yml b/roles/uptime_kuma/molecule/default/molecule.yml new file mode 100644 index 0000000..fd2f06d --- /dev/null +++ b/roles/uptime_kuma/molecule/default/molecule.yml @@ -0,0 +1,27 @@ +--- +dependency: + name: galaxy + +driver: + name: docker + +platforms: + - name: ubuntu + image: geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2204}-ansible:latest + pre_build_image: true + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + +provisioner: + name: ansible + +verifier: + name: ansible + +lint: | + set -e + yamllint . + ansible-lint . diff --git a/roles/uptime_kuma/molecule/default/verify.yml b/roles/uptime_kuma/molecule/default/verify.yml new file mode 100644 index 0000000..3802e0a --- /dev/null +++ b/roles/uptime_kuma/molecule/default/verify.yml @@ -0,0 +1,51 @@ +# kics-scan disable=2e8d4922-8362-4606-8c14-aa10466a1ce3 +--- +- name: Verify + hosts: all + gather_facts: false + any_errors_fatal: true + vars: + test_admin_username: admin + # kics-scan ignore-line + test_admin_password: SDjj3$k4g9dhsjd__1dj + + pre_tasks: + - name: "Include default vars" + ansible.builtin.include_vars: + dir: '{{ lookup("env", "MOLECULE_PROJECT_DIRECTORY") }}/defaults/' + extensions: + - 'yml' + + tasks: + - name: "Verify uptime-kuma responds to HTTP requests" + register: this + until: this is ansible.builtin.success + retries: 3 + delay: 3 + ansible.builtin.uri: + url: "http://127.0.0.1:{{ kuma_port }}" + method: GET + status_code: 200 + + - name: "Get monitor information" + register: monitors + lucasheld.uptime_kuma.monitor_info: + api_url: http://127.0.0.1:3001 + api_username: "{{ test_admin_username }}" + api_password: "{{ test_admin_password }}" + + - name: "Get test monitor information" + failed_when: monitor_info is not defined + ansible.builtin.set_fact: + monitor_info: "{{ monitors.monitors | selectattr('name', 'equalto', 'push-test') | list | first }}" + + - name: "Check test monitor configuration" + loop: + - {key: "type", value: "push"} + - {key: "interval", value: 30} + - {key: "description", value: "Test push monitor"} + - {key: notificationIDList, value: [1]} # names are not stored, only integer IDs + ansible.builtin.assert: + that: "monitor_info[item.key] == item.value" + success_msg: "Test monitor has correctly configured {{ item.key }}: {{ item.value }}" + fail_msg: "Incorrect test monitor configuration for {{ item.key }}: expected {{ item.value }}, got: {{ monitor_info[item.key] }}" diff --git a/roles/uptime_kuma/renovate.json b/roles/uptime_kuma/renovate.json new file mode 100644 index 0000000..5db72dd --- /dev/null +++ b/roles/uptime_kuma/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ] +} diff --git a/roles/uptime_kuma/requirements.ci.txt b/roles/uptime_kuma/requirements.ci.txt new file mode 100644 index 0000000..1e96bd8 --- /dev/null +++ b/roles/uptime_kuma/requirements.ci.txt @@ -0,0 +1,6 @@ +ansible-lint~=25.2.1 +docker~=7.1.0 +molecule~=24.12.0 +molecule-plugins[docker]~=23.6.0 +requests==2.31.0 # pinned to the latest version not breaking Docker SDK +yamllint~=1.35.1 diff --git a/roles/uptime_kuma/requirements.txt b/roles/uptime_kuma/requirements.txt new file mode 100644 index 0000000..90d4055 --- /dev/null +++ b/roles/uptime_kuma/requirements.txt @@ -0,0 +1 @@ +ansible diff --git a/roles/uptime_kuma/requirements.yml b/roles/uptime_kuma/requirements.yml new file mode 100644 index 0000000..3d40a1c --- /dev/null +++ b/roles/uptime_kuma/requirements.yml @@ -0,0 +1,8 @@ +--- +roles: + - name: genlab.docker_ubuntu + src: https://github.com/corvus-migratorius/ansible-docker-ubuntu.git + +collections: + - name: lucasheld.uptime_kuma + version: "1.2.0" diff --git a/roles/uptime_kuma/tasks/configure.yml b/roles/uptime_kuma/tasks/configure.yml new file mode 100644 index 0000000..f46e5e5 --- /dev/null +++ b/roles/uptime_kuma/tasks/configure.yml @@ -0,0 +1,66 @@ +--- +- name: "Wait for uptime-kuma to start" + ansible.builtin.wait_for: + port: "{{ kuma_port }}" + timeout: 30 + +- name: "Set up uptime-kuma credentials" + lucasheld.uptime_kuma.setup: + api_url: http://127.0.0.1:{{ kuma_port }} + api_username: "{{ kuma_api_username }}" + api_password: "{{ kuma_api_password }}" + +- name: "Login with credentials once and register the result" + register: result + lucasheld.uptime_kuma.login: + api_url: http://127.0.0.1:{{ kuma_port }} + api_username: "{{ kuma_api_username }}" + api_password: "{{ kuma_api_password }}" + +- name: "Extract the token from the result and set it as fact" + ansible.builtin.set_fact: + kuma_api_token: "{{ result.token }}" + +- name: "Configure Telegram notification method" + when: + - kuma_tg_bot_token is defined + - kuma_tg_chat_id is defined + lucasheld.uptime_kuma.notification: + api_url: http://127.0.0.1:{{ kuma_port }} + api_token: "{{ kuma_api_token }}" + type: telegram + name: "{{ kuma_tg_notif_name | default('Telegram alerts') }}" + isDefault: "{{ kuma_tg_notif_is_default | default(true) }}" + applyExisting: "{{ kuma_tg_notif_apply_existing | default(true) }}" + telegramBotToken: "{{ kuma_tg_bot_token }}" + telegramChatID: "{{ kuma_tg_chat_id }}" + state: "present" + +- name: "Create monitor groups" + when: kuma_monitor_groups is defined + loop: "{{ kuma_monitor_groups }}" + lucasheld.uptime_kuma.monitor: + api_url: http://127.0.0.1:{{ kuma_port }} + api_token: "{{ kuma_api_token }}" + type: "group" + name: "{{ item }}" + +- name: "Create monitors" + loop: "{{ kuma_monitors }}" + lucasheld.uptime_kuma.monitor: + api_url: http://127.0.0.1:{{ kuma_port }} + api_token: "{{ kuma_api_token }}" + type: "{{ item.type }}" + name: "{{ item.name }}" + upsideDown: "{{ item.upside_down | default(false) }}" + url: "{{ item.url | default(omit) }}" + hostname: "{{ item.hostname | default(omit) }}" + port: "{{ item.port | default(omit) }}" + interval: "{{ item.interval | default(60) }}" + description: "{{ item.description | default(omit) }}" + parent_name: "{{ item.parent_name | default(omit) }}" + notification_names: "{{ item.notification_names | default(kuma_default_notification_names) }}" + state: "{{ kuma_tg_notif_state | default('present') }}" + ignoreTls: "{{ item.ignore_tls | default(false) }}" + jsonPath: "{{ item.query | default(omit) }}" + expectedValue: "{{ item.expected_value | default(omit) }}" diff --git a/roles/uptime_kuma/tasks/deploy.yml b/roles/uptime_kuma/tasks/deploy.yml new file mode 100644 index 0000000..200f3f3 --- /dev/null +++ b/roles/uptime_kuma/tasks/deploy.yml @@ -0,0 +1,27 @@ +--- +- name: "Ensure project directory exists" + ansible.builtin.file: + path: "{{ kuma_project_dir }}" + state: directory + owner: root + group: root + mode: "0770" + +- name: "Push the Compose file" + ansible.builtin.template: + src: "docker-compose.yml.j2" + dest: "{{ kuma_project_dir }}/docker-compose.yml" + owner: root + group: root + mode: "0660" + +- name: "Deploy uptime-kuma via Docker Compose" + community.docker.docker_compose_v2: + state: present + project_src: "{{ kuma_project_dir }}" + +- name: "Install Python dependencies" + ansible.builtin.pip: + name: "uptime-kuma-api" + version: "{{ kuma_api_version }}" + break_system_packages: true diff --git a/roles/uptime_kuma/tasks/main.yml b/roles/uptime_kuma/tasks/main.yml new file mode 100644 index 0000000..8af4cdf --- /dev/null +++ b/roles/uptime_kuma/tasks/main.yml @@ -0,0 +1,6 @@ +--- +- name: "Include deployment tasks" + ansible.builtin.include_tasks: "deploy.yml" + +- name: "Include configuration tasks" + ansible.builtin.include_tasks: "configure.yml" diff --git a/roles/uptime_kuma/templates/docker-compose.yml.j2 b/roles/uptime_kuma/templates/docker-compose.yml.j2 new file mode 100644 index 0000000..a2d8e7a --- /dev/null +++ b/roles/uptime_kuma/templates/docker-compose.yml.j2 @@ -0,0 +1,37 @@ +# kics-scan disable=ce76b7d0-9e77-464d-b86f-c5c48e03e22d +--- +services: + uptime-kuma: + image: louislam/uptime-kuma:{{ kuma_img_version }} + container_name: uptime-kuma + volumes: + - {{ kuma_project_dir }}/data:/app/data + restart: unless-stopped + cap_drop: + - ALL + cap_add: + - CAP_NET_ADMIN + - CAP_NET_RAW + - CAP_SETGID + - CAP_SETUID + security_opt: + - no-new-privileges:true + network_mode: host + healthcheck: + test: ["CMD-SHELL", "node extra/healthcheck.js"] + interval: 60s + timeout: 10s + retries: 3 + logging: + driver: journald + options: + tag: uptime-kuma + deploy: + replicas: 1 + resources: + limits: + cpus: {{ kuma_limit_cpus }} + memory: {{ kuma_limit_ram }} + +volumes: + uptime-kuma-data: diff --git a/roles/uptime_kuma/vars/main.yml b/roles/uptime_kuma/vars/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/uptime_kuma/vars/main.yml @@ -0,0 +1 @@ +---