From 5c53dbdaf29dd5c6fb74057b9377d5406170e665 Mon Sep 17 00:00:00 2001 From: Patrick Toal Date: Fri, 13 Mar 2026 23:48:33 -0400 Subject: [PATCH] Add CLAUDE files. Add upgrade --- .../agents/ansible-idempotency-reviewer.md | 12 + .gitignore | 1 + CLAUDE.md | 79 ++ TODO.txt | 1 - playbooks/files/container-compose.yml | 837 ------------------ playbooks/install_appwrite.yml | 81 +- playbooks/tasks/patch_appwrite_compose.yml | 30 + playbooks/tasks/upgrade_appwrite_step.yml | 79 ++ playbooks/upgrade_appwrite.yml | 53 ++ 9 files changed, 314 insertions(+), 859 deletions(-) create mode 100644 .claude/agents/ansible-idempotency-reviewer.md create mode 100644 CLAUDE.md delete mode 100644 playbooks/files/container-compose.yml create mode 100644 playbooks/tasks/patch_appwrite_compose.yml create mode 100644 playbooks/tasks/upgrade_appwrite_step.yml create mode 100644 playbooks/upgrade_appwrite.yml diff --git a/.claude/agents/ansible-idempotency-reviewer.md b/.claude/agents/ansible-idempotency-reviewer.md new file mode 100644 index 0000000..da790d4 --- /dev/null +++ b/.claude/agents/ansible-idempotency-reviewer.md @@ -0,0 +1,12 @@ +--- +name: ansible-idempotency-reviewer +description: Reviews Ansible playbooks for idempotency issues. Use when adding new tasks or before running playbooks against production. Flags POST-only API calls missing 409 handling, uri tasks without state checks, shell/command tasks without creates/removes/changed_when, and non-idempotent register/when patterns. +--- + +You are an Ansible idempotency expert. When given a playbook or task list: +1. Identify tasks that will fail or produce unintended side effects on re-runs +2. For `ansible.builtin.uri` POST calls, check for `status_code: [201, 409]` or equivalent guard +3. Flag `ansible.builtin.shell`/`command` tasks lacking `creates:`, `removes:`, or `changed_when: false` +4. Suggest idempotent alternatives for each flagged task +5. Note tasks that are inherently non-idempotent and require manual intervention + diff --git a/.gitignore b/.gitignore index 1160c24..cc39e69 100644 --- a/.gitignore +++ b/.gitignore @@ -271,3 +271,4 @@ secrets.yml .swp # Ignore vscode .vscode/ +.ansible/.lock diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..1abf079 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,79 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What This Repo Does + +Ansible automation for the BAB (Borrow a Boat) project backend. Manages the full lifecycle of an Appwrite-based backend running on a single RHEL 9 host (`bab1.mgmt.toal.ca`) via Ansible Automation Platform. Do not refer to AWX. Also contains Ansible EDA rulebooks for event-driven automation triggered by Gitea webhooks and Alertmanager alerts. + +## Common Commands + +Run a playbook via ansible-navigator (preferred — uses execution environment): +```bash +ansible-navigator run playbooks/.yml --mode stdout +``` + +Run with extra vars (required by several playbooks): +```bash +ansible-navigator run playbooks/deploy_application.yml --mode stdout -e artifact_url= +``` + +Lint all playbooks: +```bash +ansible-navigator lint playbooks/ --mode stdout +``` + +Install required collections: +```bash +ansible-galaxy collection install -r requirements.yml +``` + +## Architecture + +### Inventory and Credentials +There is no inventory file in this repo. For development, a static inventory is located in ~/Dev/inventories/bab-inventory/. In production, inventory and credentials (Appwrite API keys, ServiceNow instance, vault password) are managed externally in AAP. + +Sensitive files are gitignored: `ansible.cfg`, `secrets.yml`, `.vault_password`. + +### Playbook Roles + +| Playbook | Purpose | Notable vars | +|---|---|---| +| `install_appwrite.yml` | Full RHEL 9 host setup: Docker, Appwrite container via compose | — | +| `install_nginx.yml` | Nginx via `nginxinc.nginx_core` role + firewalld | — | +| `configure_act_runner.yml` | Gitea Act Runner as systemd user unit (rootless) | `runner_user` | +| `deploy_application.yml` | Downloads a release tarball and extracts to nginx webroot | `artifact_url` | +| `provision_database.yml` | Creates Appwrite database, collections, and attributes via REST API | Appwrite vars | +| `provision_users.yml` | Creates users in Appwrite via REST API (Argon2 hashed) | `bab_users` list | +| `load_data.yml` | Loads seed data from `playbooks/files/database/*.json` into Appwrite | Appwrite vars | +| `read_database.yml` | Dumps Appwrite collection data to `playbooks/files/database/` | Appwrite vars, targets `appwrite:&dev` | +| `clean_logs.yml` | Removes large test log files from `/var/log` | — | +| `investigate_high_cpu.yml` | Captures process data and opens ServiceNow incident + problem | `snow_instance`, EDA event vars | +| `update_certificates.yml` | Requests and installs TLS certs from Red Hat IdM (IPA) | `ipa_admin_password`, cert path vars | + +### Event-Driven Ansible (EDA) Rulebooks + +`rulebooks/gitea_webhook.yml` — listens for Gitea push webhooks carrying an `artifact_url` and triggers the `bab-deploy-application` AAP job template. + +`rulebooks/alertmanager_listener.yml` — listens on port 9101 for Prometheus Alertmanager events; routes to AAP job templates for log cleanup (`root filesystem over 80% full`) and CPU investigation (`ProcessCPUHog`). Scoped to `org == "OYS"`. + +### Appwrite API Pattern + +Playbooks that talk to Appwrite use `ansible.builtin.uri` delegated to `localhost`, with `module_defaults` at the play level to set shared headers (`X-Appwrite-Project`, `X-Appwrite-Key`, `X-Appwrite-Response-Format`). All mutating calls use `status_code: [201, 409]` to tolerate re-runs — but true idempotency is incomplete (noted in `provision_database.yml`). + +### Templates and Static Files + +- `playbooks/templates/` — Jinja2 templates: `act_runner.service` (systemd unit for Gitea runner), `appwrite_attribute_template.json.j2` (Appwrite schema helper), `cpuhog_ticket.j2` (ServiceNow ticket body) +- `playbooks/files/database/` — JSON seed data files used by `load_data.yml` and written by `read_database.yml` + +### Collections Used + +- `community.docker` — Docker image pulls and container management +- `community.general` — RHSM repo management +- `ansible.posix` — firewalld +- `nginxinc.nginx_core` — Nginx install and config roles +- `servicenow.itsm` — Incident and problem creation +- `redhat.rhel_idm` — IPA certificate requests +- `community.crypto` — TLS key/CSR generation +- `ansible.utils` — `remove_keys` filter used in `load_data.yml` +- `ansible.eda` — webhook and alertmanager sources \ No newline at end of file diff --git a/TODO.txt b/TODO.txt index 2a49913..fb02314 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,4 +1,3 @@ - Build template for ENV file with secrets management -- Deploy podman-compose.yml file (template this, too) - Build systemd auto-startup - podman-compose startup. diff --git a/playbooks/files/container-compose.yml b/playbooks/files/container-compose.yml deleted file mode 100644 index a6929c8..0000000 --- a/playbooks/files/container-compose.yml +++ /dev/null @@ -1,837 +0,0 @@ -# WARNING! -x-logging: &x-logging - logging: - driver: 'json-file' - options: - max-file: '5' - max-size: '10m' -version: '3' - -services: - traefik: - image: docker.io/traefik:2.9 - container_name: appwrite-traefik - <<: *x-logging - command: - - --providers.file.directory=/storage/config - - --providers.file.watch=true - - --providers.docker=true - - --providers.docker.exposedByDefault=false - - --providers.docker.constraints=Label(`traefik.constraint-label-stack`,`appwrite`) - - --entrypoints.appwrite_web.address=:80 - - --entrypoints.appwrite_websecure.address=:443 - - --entrypoints.appwrite_websecure.forwardedHeaders.trustedIPs=10.0.0.0/8 - - --entrypoints.appwrite_websecure.proxyProtocol.trustedIPs=10.0.0.0/8 -# - --entrypoints.appwrite_web.forwardedHeaders.trustedIPs=192.168.2.1/32 -# - --entrypoints.appwrite_web.proxyProtocol.trustedIPs=192.168.2.1/32 -# - --entrypoints.appwrite_websecure.forwardedHeaders.trustedIPs=192.168.2.1/32 -# - --entrypoints.appwrite_websecure.proxyProtocol.trustedIPs=192.168.2.1/32 - - --accesslog=true - restart: unless-stopped - ports: - - 8080:80 - - 8443:443 - security_opt: - - label=disable - volumes: - - /run/user/1000/podman/podman.sock:/var/run/docker.sock:z - - appwrite-config:/storage/config:ro - - appwrite-certificates:/storage/certificates:ro - depends_on: - - appwrite - networks: - - gateway - - appwrite - - appwrite: - image: docker.io/appwrite/appwrite:1.4.13 - container_name: appwrite - <<: *x-logging - restart: unless-stopped - networks: - - appwrite - labels: - - traefik.enable=true - - traefik.constraint-label-stack=appwrite - - traefik.docker.network=appwrite - - traefik.http.services.appwrite_api.loadbalancer.server.port=80 - #http - - traefik.http.routers.appwrite_api_http.entrypoints=appwrite_web - - traefik.http.routers.appwrite_api_http.rule=PathPrefix(`/`) - - traefik.http.routers.appwrite_api_http.service=appwrite_api - # https - - traefik.http.routers.appwrite_api_https.entrypoints=appwrite_websecure - - traefik.http.routers.appwrite_api_https.rule=PathPrefix(`/`) - - traefik.http.routers.appwrite_api_https.service=appwrite_api - - traefik.http.routers.appwrite_api_https.tls=true - volumes: - - appwrite-uploads:/storage/uploads:rw - - appwrite-cache:/storage/cache:rw - - appwrite-config:/storage/config:rw - - appwrite-certificates:/storage/certificates:rw - - appwrite-functions:/storage/functions:rw - depends_on: - - mariadb - - redis -# - clamav - - influxdb -# entrypoint: -# - php -# - -e -# - app/http.php -# - -dopcache.preload=opcache.preload=/usr/src/code/app/preload.php - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_LOCALE=${_APP_LOCALE} - - _APP_CONSOLE_WHITELIST_ROOT=${_APP_CONSOLE_WHITELIST_ROOT} - - _APP_CONSOLE_WHITELIST_EMAILS=${_APP_CONSOLE_WHITELIST_EMAILS} - - _APP_CONSOLE_WHITELIST_IPS=${_APP_CONSOLE_WHITELIST_IPS} - - _APP_SYSTEM_EMAIL_NAME=${_APP_SYSTEM_EMAIL_NAME} - - _APP_SYSTEM_EMAIL_ADDRESS=${_APP_SYSTEM_EMAIL_ADDRESS} - - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${_APP_SYSTEM_SECURITY_EMAIL_ADDRESS} - - _APP_SYSTEM_RESPONSE_FORMAT=${_APP_SYSTEM_RESPONSE_FORMAT} - - _APP_OPTIONS_ABUSE=${_APP_OPTIONS_ABUSE} - - _APP_OPTIONS_ROUTER_PROTECTION=${_APP_OPTIONS_ROUTER_PROTECTION} - - _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS} - - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=${_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_DOMAIN=${_APP_DOMAIN} - - _APP_DOMAIN_TARGET=${_APP_DOMAIN_TARGET} - - _APP_DOMAIN_FUNCTIONS=${_APP_DOMAIN_FUNCTIONS} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - _APP_SMTP_HOST=${_APP_SMTP_HOST} - - _APP_SMTP_PORT=${_APP_SMTP_PORT} - - _APP_SMTP_SECURE=${_APP_SMTP_SECURE} - - _APP_SMTP_USERNAME=${_APP_SMTP_USERNAME} - - _APP_SMTP_PASSWORD=${_APP_SMTP_PASSWORD} - - _APP_USAGE_STATS=${_APP_USAGE_STATS} - - _APP_INFLUXDB_HOST=${_APP_INFLUXDB_HOST} - - _APP_INFLUXDB_PORT=${_APP_INFLUXDB_PORT} - - _APP_STORAGE_LIMIT=${_APP_STORAGE_LIMIT} - - _APP_STORAGE_PREVIEW_LIMIT=${_APP_STORAGE_PREVIEW_LIMIT} - - _APP_STORAGE_ANTIVIRUS=${_APP_STORAGE_ANTIVIRUS} - - _APP_STORAGE_ANTIVIRUS_HOST=${_APP_STORAGE_ANTIVIRUS_HOST} - - _APP_STORAGE_ANTIVIRUS_PORT=${_APP_STORAGE_ANTIVIRUS_PORT} - - _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE} - - _APP_STORAGE_S=${_APP_STORAGE_S3_ACCESS_KEY} - - _APP_STORAGE_S=${_APP_STORAGE_S3_SECRET} - - _APP_STORAGE_S=${_APP_STORAGE_S3_REGION} - - _APP_STORAGE_S=${_APP_STORAGE_S3_BUCKET} - - _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY} - - _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET} - - _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION} - - _APP_STORAGE_DO_SPACES_BUCKET=${_APP_STORAGE_DO_SPACES_BUCKET} - - _APP_STORAGE_BACKBLAZE_ACCESS_KEY=${_APP_STORAGE_BACKBLAZE_ACCESS_KEY} - - _APP_STORAGE_BACKBLAZE_SECRET=${_APP_STORAGE_BACKBLAZE_SECRET} - - _APP_STORAGE_BACKBLAZE_REGION=${_APP_STORAGE_BACKBLAZE_REGION} - - _APP_STORAGE_BACKBLAZE_BUCKET=${_APP_STORAGE_BACKBLAZE_BUCKET} - - _APP_STORAGE_LINODE_ACCESS_KEY=${_APP_STORAGE_LINODE_ACCESS_KEY} - - _APP_STORAGE_LINODE_SECRET=${_APP_STORAGE_LINODE_SECRET} - - _APP_STORAGE_LINODE_REGION=${_APP_STORAGE_LINODE_REGION} - - _APP_STORAGE_LINODE_BUCKET=${_APP_STORAGE_LINODE_BUCKET} - - _APP_STORAGE_WASABI_ACCESS_KEY=${_APP_STORAGE_WASABI_ACCESS_KEY} - - _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET} - - _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION} - - _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET} - - _APP_FUNCTIONS_SIZE_LIMIT=${_APP_FUNCTIONS_SIZE_LIMIT} - - _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT} - - _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT} - - _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS} - - _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY} - - _APP_FUNCTIONS_RUNTIMES=${_APP_FUNCTIONS_RUNTIMES} - - _APP_EXECUTOR_SECRET=${_APP_EXECUTOR_SECRET} - - _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - _APP_STATSD_HOST=${_APP_STATSD_HOST} - - _APP_STATSD_PORT=${_APP_STATSD_PORT} - - _APP_MAINTENANCE_INTERVAL=${_APP_MAINTENANCE_INTERVAL} - - _APP_MAINTENANCE_RETENTION_EXECUTION=${_APP_MAINTENANCE_RETENTION_EXECUTION} - - _APP_MAINTENANCE_RETENTION_CACHE=${_APP_MAINTENANCE_RETENTION_CACHE} - - _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE} - - _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT} - - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=${_APP_MAINTENANCE_RETENTION_USAGE_HOURLY} - - _APP_MAINTENANCE_RETENTION_SCHEDULES=${_APP_MAINTENANCE_RETENTION_SCHEDULES} - - _APP_SMS_PROVIDER=${_APP_SMS_PROVIDER} - - _APP_SMS_FROM=${_APP_SMS_FROM} - - _APP_GRAPHQL_MAX_BATCH_SIZE=${_APP_GRAPHQL_MAX_BATCH_SIZE} - - _APP_GRAPHQL_MAX_COMPLEXITY=${_APP_GRAPHQL_MAX_COMPLEXITY} - - _APP_GRAPHQL_MAX_DEPTH=${_APP_GRAPHQL_MAX_DEPTH} - - _APP_VCS_GITHUB_APP_NAME=${_APP_VCS_GITHUB_APP_NAME} - - _APP_VCS_GITHUB_PRIVATE_KEY=${_APP_VCS_GITHUB_PRIVATE_KEY} - - _APP_VCS_GITHUB_APP_ID=${_APP_VCS_GITHUB_APP_ID} - - _APP_VCS_GITHUB_WEBHOOK_SECRET=${_APP_VCS_GITHUB_WEBHOOK_SECRET} - - _APP_VCS_GITHUB_CLIENT_SECRET=${_APP_VCS_GITHUB_CLIENT_SECRET} - - _APP_VCS_GITHUB_CLIENT_ID=${_APP_VCS_GITHUB_CLIENT_ID} - - _APP_MIGRATIONS_FIREBASE_CLIENT_ID=${_APP_MIGRATIONS_FIREBASE_CLIENT_ID} - - _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=${_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET} - - _APP_ASSISTANT_OPENAI_API_KEY=${_APP_ASSISTANT_OPENAI_API_KEY} - - appwrite-realtime: - image: docker.io/appwrite/appwrite:1.4.13 - entrypoint: realtime - container_name: appwrite-realtime - <<: *x-logging - restart: unless-stopped - labels: - - "traefik.enable=true" - - "traefik.constraint-label-stack=appwrite" - - "traefik.docker.network=appwrite" - - "traefik.http.services.appwrite_realtime.loadbalancer.server.port=80" - #ws - - traefik.http.routers.appwrite_realtime_ws.entrypoints=appwrite_web - - traefik.http.routers.appwrite_realtime_ws.rule=PathPrefix(`/v1/realtime`) - - traefik.http.routers.appwrite_realtime_ws.service=appwrite_realtime - # wss - - traefik.http.routers.appwrite_realtime_wss.entrypoints=appwrite_websecure - - traefik.http.routers.appwrite_realtime_wss.rule=PathPrefix(`/v1/realtime`) - - traefik.http.routers.appwrite_realtime_wss.service=appwrite_realtime - - traefik.http.routers.appwrite_realtime_wss.tls=true - networks: - - appwrite - depends_on: - - mariadb - - redis - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPTIONS_ABUSE=${_APP_OPTIONS_ABUSE} - - _APP_OPTIONS_ROUTER_PROTECTION=${_APP_OPTIONS_ROUTER_PROTECTION} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - _APP_USAGE_STATS=${_APP_USAGE_STATS} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - appwrite-worker-audits: - image: docker.io/appwrite/appwrite:1.4.13 - entrypoint: worker-audits - <<: *x-logging - container_name: appwrite-worker-audits - restart: unless-stopped - networks: - - appwrite - depends_on: - - redis - - mariadb - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - appwrite-worker-webhooks: - entrypoint: worker-webhooks - <<: *x-logging - container_name: appwrite-worker-webhooks - image: docker.io/appwrite/appwrite:1.4.13 - networks: - - appwrite -# volumes: -# - ./app:/usr/src/code/app -# - ./src:/usr/src/code/src - depends_on: - - redis - - mariadb - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${_APP_SYSTEM_SECURITY_EMAIL_ADDRESS} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - appwrite-worker-deletes: - image: docker.io/appwrite/appwrite:1.4.13 - entrypoint: worker-deletes - <<: *x-logging - container_name: appwrite-worker-deletes - restart: unless-stopped - networks: - - appwrite - depends_on: - - redis - - mariadb - volumes: - - appwrite-uploads:/storage/uploads:rw - - appwrite-cache:/storage/cache:rw - - appwrite-functions:/storage/functions:rw - - appwrite-builds:/storage/builds:rw - - appwrite-certificates:/storage/certificates:rw - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE} - - _APP_STORAGE_S=${_APP_STORAGE_S3_ACCESS_KEY} - - _APP_STORAGE_S=${_APP_STORAGE_S3_SECRET} - - _APP_STORAGE_S=${_APP_STORAGE_S3_REGION} - - _APP_STORAGE_S=${_APP_STORAGE_S3_BUCKET} - - _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY} - - _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET} - - _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION} - - _APP_STORAGE_DO_SPACES_BUCKET=${_APP_STORAGE_DO_SPACES_BUCKET} - - _APP_STORAGE_BACKBLAZE_ACCESS_KEY=${_APP_STORAGE_BACKBLAZE_ACCESS_KEY} - - _APP_STORAGE_BACKBLAZE_SECRET=${_APP_STORAGE_BACKBLAZE_SECRET} - - _APP_STORAGE_BACKBLAZE_REGION=${_APP_STORAGE_BACKBLAZE_REGION} - - _APP_STORAGE_BACKBLAZE_BUCKET=${_APP_STORAGE_BACKBLAZE_BUCKET} - - _APP_STORAGE_LINODE_ACCESS_KEY=${_APP_STORAGE_LINODE_ACCESS_KEY} - - _APP_STORAGE_LINODE_SECRET=${_APP_STORAGE_LINODE_SECRET} - - _APP_STORAGE_LINODE_REGION=${_APP_STORAGE_LINODE_REGION} - - _APP_STORAGE_LINODE_BUCKET=${_APP_STORAGE_LINODE_BUCKET} - - _APP_STORAGE_WASABI_ACCESS_KEY=${_APP_STORAGE_WASABI_ACCESS_KEY} - - _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET} - - _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION} - - _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - _APP_EXECUTOR_SECRET=${_APP_EXECUTOR_SECRET} - - _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST} - - appwrite-worker-databases: - image: docker.io/appwrite/appwrite:1.4.13 - entrypoint: worker-databases - <<: *x-logging - container_name: appwrite-worker-databases - restart: unless-stopped - networks: - - appwrite - depends_on: - - redis - - mariadb - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - appwrite-worker-builds: - image: docker.io/appwrite/appwrite:1.4.13 - entrypoint: worker-builds - <<: *x-logging - container_name: appwrite-worker-builds - restart: unless-stopped - networks: - - appwrite - depends_on: - - redis - - mariadb - volumes: - - appwrite-functions:/storage/functions:rw - - appwrite-builds:/storage/builds:rw - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_EXECUTOR_SECRET=${_APP_EXECUTOR_SECRET} - - _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - _APP_VCS_GITHUB_APP_NAME=${_APP_VCS_GITHUB_APP_NAME} - - _APP_VCS_GITHUB_PRIVATE_KEY=${_APP_VCS_GITHUB_PRIVATE_KEY} - - _APP_VCS_GITHUB_APP_ID=${_APP_VCS_GITHUB_APP_ID} - - _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT} - - _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT} - - _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS} - - _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY} - - _APP_FUNCTIONS_SIZE_LIMIT=${_APP_FUNCTIONS_SIZE_LIMIT} - - _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS} - - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=${_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS} - - _APP_DOMAIN=${_APP_DOMAIN} - - _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE} - - _APP_STORAGE_S=${_APP_STORAGE_S3_ACCESS_KEY} - - _APP_STORAGE_S=${_APP_STORAGE_S3_SECRET} - - _APP_STORAGE_S=${_APP_STORAGE_S3_REGION} - - _APP_STORAGE_S=${_APP_STORAGE_S3_BUCKET} - - _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY} - - _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET} - - _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION} - - _APP_STORAGE_DO_SPACES_BUCKET=${_APP_STORAGE_DO_SPACES_BUCKET} - - _APP_STORAGE_BACKBLAZE_ACCESS_KEY=${_APP_STORAGE_BACKBLAZE_ACCESS_KEY} - - _APP_STORAGE_BACKBLAZE_SECRET=${_APP_STORAGE_BACKBLAZE_SECRET} - - _APP_STORAGE_BACKBLAZE_REGION=${_APP_STORAGE_BACKBLAZE_REGION} - - _APP_STORAGE_BACKBLAZE_BUCKET=${_APP_STORAGE_BACKBLAZE_BUCKET} - - _APP_STORAGE_LINODE_ACCESS_KEY=${_APP_STORAGE_LINODE_ACCESS_KEY} - - _APP_STORAGE_LINODE_SECRET=${_APP_STORAGE_LINODE_SECRET} - - _APP_STORAGE_LINODE_REGION=${_APP_STORAGE_LINODE_REGION} - - _APP_STORAGE_LINODE_BUCKET=${_APP_STORAGE_LINODE_BUCKET} - - _APP_STORAGE_WASABI_ACCESS_KEY=${_APP_STORAGE_WASABI_ACCESS_KEY} - - _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET} - - _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION} - - _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET} - - appwrite-worker-certificates: - entrypoint: worker-certificates - <<: *x-logging - container_name: appwrite-worker-certificates - image: docker.io/appwrite/appwrite:1.4.13 - networks: - - appwrite - depends_on: - - redis - - mariadb - volumes: - - appwrite-config:/storage/config:rw - - appwrite-certificates:/storage/certificates:rw - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_DOMAIN=${_APP_DOMAIN} - - _APP_DOMAIN_TARGET=${_APP_DOMAIN_TARGET} - - _APP_DOMAIN_FUNCTIONS=${_APP_DOMAIN_FUNCTIONS} - - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${_APP_SYSTEM_SECURITY_EMAIL_ADDRESS} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - appwrite-worker-functions: - entrypoint: worker-functions - <<: *x-logging - container_name: appwrite-worker-functions - image: docker.io/appwrite/appwrite:1.4.13 - networks: - - appwrite - depends_on: - - redis - - mariadb - - openruntimes-executor - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT} - - _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT} - - _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS} - - _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY} - - _APP_EXECUTOR_SECRET=${_APP_EXECUTOR_SECRET} - - _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST} - - _APP_USAGE_STATS=${_APP_USAGE_STATS} - - _APP_DOCKER_HUB_USERNAME=${_APP_DOCKER_HUB_USERNAME} - - _APP_DOCKER_HUB_PASSWORD=${_APP_DOCKER_HUB_PASSWORD} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - appwrite-worker-mails: - image: docker.io/appwrite/appwrite:1.4.13 - entrypoint: worker-mails - <<: *x-logging - container_name: appwrite-worker-mails - restart: unless-stopped - networks: - - appwrite - depends_on: - - redis - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_SYSTEM_EMAIL_NAME=${_APP_SYSTEM_EMAIL_NAME} - - _APP_SYSTEM_EMAIL_ADDRESS=${_APP_SYSTEM_EMAIL_ADDRESS} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_SMTP_HOST=${_APP_SMTP_HOST} - - _APP_SMTP_PORT=${_APP_SMTP_PORT} - - _APP_SMTP_SECURE=${_APP_SMTP_SECURE} - - _APP_SMTP_USERNAME=${_APP_SMTP_USERNAME} - - _APP_SMTP_PASSWORD=${_APP_SMTP_PASSWORD} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - appwrite-worker-messaging: - image: docker.io/appwrite/appwrite:1.4.13 - entrypoint: worker-messaging - <<: *x-logging - container_name: appwrite-worker-messaging - restart: unless-stopped - networks: - - appwrite - depends_on: - - redis - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_SMS_PROVIDER=${_APP_SMS_PROVIDER} - - _APP_SMS_FROM=${_APP_SMS_FROM} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - appwrite-worker-migrations: - image: docker.io/appwrite/appwrite:1.4.13 - entrypoint: worker-migrations - <<: *x-logging - container_name: appwrite-worker-migrations - restart: unless-stopped - networks: - - appwrite - depends_on: - - mariadb - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_DOMAIN=${_APP_DOMAIN} - - _APP_DOMAIN_TARGET=${_APP_DOMAIN_TARGET} - - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${_APP_SYSTEM_SECURITY_EMAIL_ADDRESS} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - _APP_MIGRATIONS_FIREBASE_CLIENT_ID=${_APP_MIGRATIONS_FIREBASE_CLIENT_ID} - - _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=${_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET} - - appwrite-maintenance: - image: docker.io/appwrite/appwrite:1.4.13 - entrypoint: maintenance - <<: *x-logging - container_name: appwrite-maintenance - restart: unless-stopped - networks: - - appwrite - depends_on: - - redis - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_DOMAIN=${_APP_DOMAIN} - - _APP_DOMAIN_TARGET=${_APP_DOMAIN_TARGET} - - _APP_DOMAIN_FUNCTIONS=${_APP_DOMAIN_FUNCTIONS} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - _APP_MAINTENANCE_INTERVAL=${_APP_MAINTENANCE_INTERVAL} - - _APP_MAINTENANCE_RETENTION_EXECUTION=${_APP_MAINTENANCE_RETENTION_EXECUTION} - - _APP_MAINTENANCE_RETENTION_CACHE=${_APP_MAINTENANCE_RETENTION_CACHE} - - _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE} - - _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT} - - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=${_APP_MAINTENANCE_RETENTION_USAGE_HOURLY} - - _APP_MAINTENANCE_RETENTION_SCHEDULES=${_APP_MAINTENANCE_RETENTION_SCHEDULES} - - appwrite-usage: - image: docker.io/appwrite/appwrite:1.4.13 - entrypoint: usage - <<: *x-logging - container_name: appwrite-usage - restart: unless-stopped - networks: - - appwrite - depends_on: - - influxdb - - mariadb - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - _APP_INFLUXDB_HOST=${_APP_INFLUXDB_HOST} - - _APP_INFLUXDB_PORT=${_APP_INFLUXDB_PORT} - - _APP_USAGE_AGGREGATION_INTERVAL=${_APP_USAGE_AGGREGATION_INTERVAL} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_USAGE_STATS=${_APP_USAGE_STATS} - - _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - appwrite-schedule: - image: docker.io/appwrite/appwrite:1.4.13 - entrypoint: schedule - <<: *x-logging - container_name: appwrite-schedule - restart: unless-stopped - networks: - - appwrite - depends_on: - - mariadb - - redis - environment: - - _APP_ENV=${_APP_ENV} - - _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} - - _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1} - - _APP_REDIS_HOST=${_APP_REDIS_HOST} - - _APP_REDIS_PORT=${_APP_REDIS_PORT} - - _APP_REDIS_USER=${_APP_REDIS_USER} - - _APP_REDIS_PASS=${_APP_REDIS_PASS} - - _APP_DB_HOST=${_APP_DB_HOST} - - _APP_DB_PORT=${_APP_DB_PORT} - - _APP_DB_SCHEMA=${_APP_DB_SCHEMA} - - _APP_DB_USER=${_APP_DB_USER} - - _APP_DB_PASS=${_APP_DB_PASS} - - appwrite-assistant: - image: docker.io/appwrite/assistant:0.2.2 - container_name: appwrite-assistant - restart: unless-stopped - networks: - - appwrite - environment: - - _APP_ASSISTANT_OPENAI_API_KEY=${_APP_ASSISTANT_OPENAI_API_KEY} - - openruntimes-executor: - container_name: openruntimes-executor - hostname: appwrite-executor - <<: *x-logging - restart: unless-stopped - stop_signal: SIGINT - image: docker.io/openruntimes/executor:0.4.5 - networks: - - appwrite - - runtimes - security_opt: - - label=disable - volumes: - - /run/user/1000/podman/podman.sock:/var/run/docker.sock:z - - appwrite-builds:/storage/builds:rw - - appwrite-functions:/storage/functions:rw - # Host mount nessessary to share files between executor and runtimes. - # It's not possible to share mount file between 2 containers without host mount (copying is too slow) - - /home/ptoal/appwrite/tmp:/tmp:z - environment: - - OPR_EXECUTOR_INACTIVE_TRESHOLD=${_APP_FUNCTIONS_INACTIVE_THRESHOLD}} - - OPR_EXECUTOR_MAINTENANCE_INTERVAL=${_APP_FUNCTIONS_MAINTENANCE_INTERVAL} - - OPR_EXECUTOR_NETWORK=${_APP_FUNCTIONS_RUNTIMES_NETWORK} - - OPR_EXECUTOR_DOCKER_HUB_USERNAME=${_APP_DOCKER_HUB_USERNAME} - - OPR_EXECUTOR_DOCKER_HUB_PASSWORD=${_APP_DOCKER_HUB_PASSWORD} - - OPR_EXECUTOR_ENV=${_APP_ENV} - - OPR_EXECUTOR_RUNTIMES=${_APP_FUNCTIONS_RUNTIMES} - - OPR_EXECUTOR_SECRET=${_APP_EXECUTOR_SECRET} - - OPR_EXECUTOR_RUNTIME_VERSIONS=v2,v3 - - OPR_EXECUTOR_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} - - OPR_EXECUTOR_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} - - OPR_EXECUTOR_STORAGE_DEVICE=${_APP_STORAGE_DEVICE} - - OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY} - - OPR_EXECUTOR_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET} - - OPR_EXECUTOR_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION} - - OPR_EXECUTOR_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET} - - OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY} - - OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET} - - OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION} - - OPR_EXECUTOR_STORAGE_DO_SPACES_BUCKET=${_APP_STORAGE_DO_SPACES_BUCKET} - - OPR_EXECUTOR_STORAGE_BACKBLAZE_ACCESS_KEY=${_APP_STORAGE_BACKBLAZE_ACCESS_KEY} - - OPR_EXECUTOR_STORAGE_BACKBLAZE_SECRET=${_APP_STORAGE_BACKBLAZE_SECRET} - - OPR_EXECUTOR_STORAGE_BACKBLAZE_REGION=${_APP_STORAGE_BACKBLAZE_REGION} - - OPR_EXECUTOR_STORAGE_BACKBLAZE_BUCKET=${_APP_STORAGE_BACKBLAZE_BUCKET} - - OPR_EXECUTOR_STORAGE_LINODE_ACCESS_KEY=${_APP_STORAGE_LINODE_ACCESS_KEY} - - OPR_EXECUTOR_STORAGE_LINODE_SECRET=${_APP_STORAGE_LINODE_SECRET} - - OPR_EXECUTOR_STORAGE_LINODE_REGION=${_APP_STORAGE_LINODE_REGION} - - OPR_EXECUTOR_STORAGE_LINODE_BUCKET=${_APP_STORAGE_LINODE_BUCKET} - - OPR_EXECUTOR_STORAGE_WASABI_ACCESS_KEY=${_APP_STORAGE_WASABI_ACCESS_KEY} - - OPR_EXECUTOR_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET} - - OPR_EXECUTOR_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION} - - OPR_EXECUTOR_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET} - -# openruntimes-proxy: -# container_name: openruntimes-proxy -# hostname: proxy -# <<: *x-logging -# stop_signal: SIGINT -# image: docker.io/openruntimes/proxy:0.3.1 -# networks: -# - appwrite -# - runtimes -# environment: -# - OPR_PROXY_WORKER_PER_CORE=${_APP_WORKER_PER_CORE} -# - OPR_PROXY_ENV=${_APP_ENV} -# - OPR_PROXY_EXECUTOR_SECRET=${_APP_EXECUTOR_SECRET} -# - OPR_PROXY_SECRET=${_APP_EXECUTOR_SECRET} -# - OPR_PROXY_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER} -# - OPR_PROXY_LOGGING_CONFIG=${_APP_LOGGING_CONFIG} -# - OPR_PROXY_ALGORITHM=random -# - OPR_PROXY_EXECUTORS=appwrite-executor -# - OPR_PROXY_HEALTHCHECK_INTERVAL=10000 -# - OPR_PROXY_MAX_TIMEOUT=600 -# - OPR_PROXY_HEALTHCHECK=enabled - - mariadb: - image: docker.io/mariadb:10.7 # fix issues when upgrading using: mysql_upgrade -u root -p - container_name: appwrite-mariadb - <<: *x-logging - restart: unless-stopped - networks: - - appwrite - volumes: - - appwrite-mariadb:/var/lib/mysql:rw - environment: - - MYSQL_ROOT_PASSWORD=${_APP_DB_ROOT_PASS} - - MYSQL_DATABASE=${_APP_DB_SCHEMA} - - MYSQL_USER=${_APP_DB_USER} - - MYSQL_PASSWORD=${_APP_DB_PASS} - command: 'mysqld --innodb-flush-method=fsync' - - # smtp: - # image: appwrite/smtp:1.2.0 - # container_name: appwrite-smtp - # restart: unless-stopped - # networks: - # - appwrite - # environment: - # - LOCAL_DOMAINS=@ - # - RELAY_FROM_HOSTS=192.168.0.0/16 ; *.yourdomain.com - # - SMARTHOST_HOST=smtp - # - SMARTHOST_PORT=587 - - redis: - image: docker.io/redis:7.0.4-alpine - <<: *x-logging - container_name: appwrite-redis - restart: unless-stopped - command: > - redis-server - --maxmemory 512mb - --maxmemory-policy allkeys-lru - --maxmemory-samples 5 - networks: - - appwrite - volumes: - - appwrite-redis:/data:rw - -# clamav: -# image: docker.io/appwrite/clamav:1.2.0 -# container_name: appwrite-clamav -# networks: -# - appwrite -# volumes: -# - appwrite-uploads:/storage/uploads - - influxdb: - image: docker.io/appwrite/influxdb:1.5.0 - container_name: appwrite-influxdb - <<: *x-logging - restart: unless-stopped - networks: - - appwrite - volumes: - - appwrite-influxdb:/var/lib/influxdb:rw - - telegraf: - image: docker.io/appwrite/telegraf:1.4.0 - container_name: appwrite-telegraf - <<: *x-logging - restart: unless-stopped - networks: - - appwrite - environment: - - _APP_INFLUXDB_HOST=${_APP_INFLUXDB_HOST} - - _APP_INFLUXDB_PORT=${_APP_INFLUXDB_PORT} - -networks: - gateway: - name: gateway - appwrite: - name: appwrite - runtimes: - name: runtimes - -volumes: - appwrite-mariadb: - appwrite-redis: - appwrite-cache: - appwrite-uploads: - appwrite-certificates: - appwrite-functions: - appwrite-builds: - appwrite-influxdb: - appwrite-config: - # appwrite-chronograf: - diff --git a/playbooks/install_appwrite.yml b/playbooks/install_appwrite.yml index ef64303..29a373e 100644 --- a/playbooks/install_appwrite.yml +++ b/playbooks/install_appwrite.yml @@ -21,36 +21,75 @@ state: present fingerprint: 'FF8A D134 4597 106E CE81 3B91 8A38 72BF 3228 467C' + - name: Add Docker CE repository + ansible.builtin.yum_repository: + name: docker-ce + description: Docker CE Stable + baseurl: https://download.docker.com/linux/rhel/9/$basearch/stable + gpgcheck: true + gpgkey: https://download.docker.com/linux/rhel/gpg + enabled: true + - name: Dependencies are installed ansible.builtin.dnf: name: - - podman + - docker-ce + - docker-ce-cli + - containerd.io + - docker-compose-plugin - https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm state: present - - name: Ensure podman-compose installed - ansible.builtin.dnf: - name: - - podman-compose - -- name: Userspace setup - hosts: bab1.mgmt.toal.ca - tasks: - - - name: Ensure podman socket enabled + - name: Ensure Docker service is enabled and started ansible.builtin.systemd: - name: podman.socket - scope: user + name: docker enabled: true state: started - - name: Ensure appwrite image pulled from docker hub - containers.podman.podman_image: - name: docker.io/appwrite/appwrite - tag: 1.7.4 + - name: Ensure ansible user is in docker group + ansible.builtin.user: + name: "{{ ansible_user }}" + groups: docker + append: true - - name: Ensure podman-compose.yml deployed - ansible.builtin.copy: - src: files/container-compose.yml - dest: /home/ptoal/appwrite +- name: Userspace setup + hosts: bab1.mgmt.toal.ca + vars: + appwrite_version: "1.7.4" + appwrite_dir: /home/ptoal/appwrite + appwrite_socket: /var/run/docker.sock + appwrite_web_port: 8080 + appwrite_websecure_port: 8443 + + tasks: + - name: Ensure appwrite image pulled from docker hub + community.docker.docker_image: + name: appwrite/appwrite + tag: "{{ appwrite_version }}" + source: pull + + - name: Ensure appwrite directory exists + ansible.builtin.file: + path: "{{ appwrite_dir }}" + state: directory + mode: '0755' + + - name: Download official docker-compose.yml for Appwrite {{ appwrite_version }} + ansible.builtin.get_url: + url: "https://raw.githubusercontent.com/appwrite/appwrite/{{ appwrite_version }}/docker-compose.yml" + dest: "{{ appwrite_dir }}/docker-compose.yml" mode: '0644' + force: true + + - name: Apply site-specific customizations to docker-compose.yml + ansible.builtin.include_tasks: tasks/patch_appwrite_compose.yml + + - name: Start Appwrite stack + ansible.builtin.command: + argv: + - docker + - compose + - up + - -d + chdir: "{{ appwrite_dir }}" + changed_when: true diff --git a/playbooks/tasks/patch_appwrite_compose.yml b/playbooks/tasks/patch_appwrite_compose.yml new file mode 100644 index 0000000..6df30d8 --- /dev/null +++ b/playbooks/tasks/patch_appwrite_compose.yml @@ -0,0 +1,30 @@ +--- +# Applies site-specific customizations to docker-compose.yml after it has been +# written by the Appwrite upgrade container or downloaded fresh during install. +# +# Required variables (define in calling play): +# appwrite_dir - absolute path to the appwrite directory on the host +# appwrite_socket - host path to the container socket +# appwrite_web_port - host port to map to container port 80 (default 8080) +# appwrite_websecure_port - host port to map to container port 443 (default 8443) + +- name: Remap traefik HTTP port + ansible.builtin.replace: + path: "{{ appwrite_dir }}/docker-compose.yml" + regexp: '- "?80:80"?' + replace: "- {{ appwrite_web_port }}:80" + +- name: Remap traefik HTTPS port + ansible.builtin.replace: + path: "{{ appwrite_dir }}/docker-compose.yml" + regexp: '- "?443:443"?' + replace: "- {{ appwrite_websecure_port }}:443" + +- name: Add host tmp mount to openruntimes-executor for docker file sharing + # Inserts after the last occurrence of appwrite-builds:/storage/builds:rw, + # which is in the openruntimes-executor volumes section. + ansible.builtin.lineinfile: + path: "{{ appwrite_dir }}/docker-compose.yml" + line: " - {{ appwrite_dir }}/tmp:/tmp:z" + insertafter: "appwrite-builds:/storage/builds:rw" + state: present diff --git a/playbooks/tasks/upgrade_appwrite_step.yml b/playbooks/tasks/upgrade_appwrite_step.yml new file mode 100644 index 0000000..c492606 --- /dev/null +++ b/playbooks/tasks/upgrade_appwrite_step.yml @@ -0,0 +1,79 @@ +--- +# Performs one upgrade+migrate cycle for a single Appwrite target version. +# Called in a loop from upgrade_appwrite.yml with loop_var: appwrite_target_version. + +- name: "Pull appwrite/appwrite:{{ appwrite_target_version }} image" + community.docker.docker_image: + name: appwrite/appwrite + tag: "{{ appwrite_target_version }}" + source: pull + +- name: "Run Appwrite upgrade container for {{ appwrite_target_version }}" + # Runs with -i so stdin can answer all interactive prompts. + # Prompt order: overwrite confirmation, HTTP port, HTTPS port, API key, + # Appwrite hostname, CNAME hostname, SSL email — all accept defaults except overwrite. + # The container writes docker-compose.yml then attempts docker compose up internally; + # that step fails because we manage the socket/service lifecycle ourselves. + # We only fail this task if the compose file backup was not created (file not written). + ansible.builtin.command: + argv: + - docker + - run + - --rm + - -i + - --volume + - "{{ appwrite_socket }}:/var/run/docker.sock" + - --volume + - "{{ appwrite_dir }}:/usr/src/code/appwrite:rw" + - --entrypoint=upgrade + - "appwrite/appwrite:{{ appwrite_target_version }}" + stdin: "y\n\n\n\n\n\n\n" + register: upgrade_container_result + changed_when: true + failed_when: "'creating backup' not in upgrade_container_result.stdout" + +- name: Re-apply site customizations after upgrade container rewrote docker-compose.yml + ansible.builtin.include_tasks: patch_appwrite_compose.yml + +- name: "Bring up Appwrite stack at {{ appwrite_target_version }}" + ansible.builtin.command: + argv: + - docker + - compose + - up + - -d + chdir: "{{ appwrite_dir }}" + changed_when: true + +- name: Wait for appwrite container to be running + ansible.builtin.command: + argv: + - docker + - compose + - ps + - --status + - running + - --services + chdir: "{{ appwrite_dir }}" + register: running_services + until: "'appwrite' in running_services.stdout" + retries: 30 + delay: 10 + changed_when: false + +- name: "Run database migration for {{ appwrite_target_version }}" + ansible.builtin.command: + argv: + - docker + - compose + - exec + - -T + - appwrite + - migrate + chdir: "{{ appwrite_dir }}" + register: migration_result + changed_when: true + +- name: Show migration output + ansible.builtin.debug: + var: migration_result.stdout_lines diff --git a/playbooks/upgrade_appwrite.yml b/playbooks/upgrade_appwrite.yml new file mode 100644 index 0000000..a4de5c2 --- /dev/null +++ b/playbooks/upgrade_appwrite.yml @@ -0,0 +1,53 @@ +--- +- name: Upgrade Appwrite + hosts: bab1.mgmt.toal.ca + vars: + appwrite_dir: /home/ptoal/appwrite + appwrite_socket: /var/run/docker.sock + appwrite_web_port: 8080 + appwrite_websecure_port: 8443 + # Sequential upgrade path: cannot skip minor versions. + upgrade_path: + - "1.6.2" + - "1.7.4" + + tasks: + - name: Get current Appwrite container info + community.docker.docker_container_info: + name: appwrite + register: appwrite_container_info + + - name: Set current Appwrite version fact + ansible.builtin.set_fact: + current_appwrite_version: >- + {{ appwrite_container_info.container.Config.Image.split(':') | last + if appwrite_container_info.exists + else '0.0.0' }} + + - name: Show current Appwrite version + ansible.builtin.debug: + msg: "Current Appwrite version: {{ current_appwrite_version }}" + + - name: Back up MariaDB data volume before upgrade + ansible.builtin.command: + argv: + - docker + - run + - --rm + - --volume + - appwrite-mariadb:/data:ro + - --volume + - "{{ appwrite_dir }}:/backup" + - alpine + - tar + - czf + - /backup/mariadb-backup-pre-upgrade.tar.gz + - /data + changed_when: true + + - name: Upgrade through each intermediate version + ansible.builtin.include_tasks: tasks/upgrade_appwrite_step.yml + loop: "{{ upgrade_path }}" + loop_control: + loop_var: appwrite_target_version + when: appwrite_target_version is version(current_appwrite_version, '>')