From 2d393ff46e834b749bbdfb6f4595e695ecf90cda Mon Sep 17 00:00:00 2001 From: patrick Date: Thu, 16 Jul 2026 21:43:52 -0400 Subject: [PATCH] convert repo to ansible collection patrickj.docker_compose_app --- README.md | 422 +---------------- create_app_role.sh | 2 +- galaxy.yml | 18 + roles/app/README.md | 427 ++++++++++++++++++ {defaults => roles/app/defaults}/main.yml | 0 {meta => roles/app/meta}/main.yml | 0 {tasks => roles/app/tasks}/backup.yml | 0 {tasks => roles/app/tasks}/deploy.yml | 0 {tasks => roles/app/tasks}/health_check.yml | 0 {tasks => roles/app/tasks}/main.yml | 0 {tasks => roles/app/tasks}/manage_compose.yml | 0 {tasks => roles/app/tasks}/restore.yml | 0 {tasks => roles/app/tasks}/setup.yml | 0 {tasks => roles/app/tasks}/update.yml | 0 14 files changed, 458 insertions(+), 411 deletions(-) create mode 100644 galaxy.yml create mode 100644 roles/app/README.md rename {defaults => roles/app/defaults}/main.yml (100%) rename {meta => roles/app/meta}/main.yml (100%) rename {tasks => roles/app/tasks}/backup.yml (100%) rename {tasks => roles/app/tasks}/deploy.yml (100%) rename {tasks => roles/app/tasks}/health_check.yml (100%) rename {tasks => roles/app/tasks}/main.yml (100%) rename {tasks => roles/app/tasks}/manage_compose.yml (100%) rename {tasks => roles/app/tasks}/restore.yml (100%) rename {tasks => roles/app/tasks}/setup.yml (100%) rename {tasks => roles/app/tasks}/update.yml (100%) diff --git a/README.md b/README.md index db271b2..9a8e098 100644 --- a/README.md +++ b/README.md @@ -1,427 +1,29 @@ -# Docker Compose App Role +# patrickj.docker_compose_app -A flexible Ansible role for deploying and managing Docker Compose applications with features including backup/restore and healthchecks. +Ansible collection providing a single reusable role for deploying and managing Docker Compose applications. -## Overview +## Contents -This role provides a standardized way to deploy containerized applications using Docker Compose. It handles directory creation, template rendering, and container lifecycle management. +- `patrickj.docker_compose_app.app` — the base role. See [`roles/app/README.md`](roles/app/README.md) for usage, variables, and examples. -## Features - -- **Template-based deployment** with Jinja2 templating -- **Dual backup system** (controller + remote host) -- **Health checks** and deployment verification -- **Multiple deployment modes** (template, file, or inline content) -- **Flexible directory management** -- **Configurable backup retention policies** - -## Quick Start - -### 1. Create a New Role - -Use the provided script to create a new application skeleton role: +## Installation ```bash -./create_app_role.sh my-app +ansible-galaxy collection install git+https://git.jaroszew.ski/ansible/ansible-role-docker-compose-app.git ``` -This creates: -``` -roles/my-app/ -├── defaults/main.yml # Default variables -├── meta/main.yml # Role metadata and dependencies -└── templates/ - └── compose.yml.j2 # Docker Compose template -``` - -### 2. Configure Your Application - -Edit `roles/my-app/defaults/main.yml`: +Or as a dependency in another collection's `galaxy.yml`: ```yaml ---- -app_role_name: my-app - -my_app_container_name: "{{ app_name | default('my-app') }}" -my_app_container_version: latest -my_app_restart_policy: "{{ app_restart_policy }}" -my_app_http_port: 8080 -my_app_data_path: "{{ app_dir }}/data" -my_app_config_path: "{{ app_dir }}/config" - -# Optional: directories to create -app_subdirectories: - - "{{ my_app_data_path }}" - - "{{ my_app_config_path }}" - -# Optional: backup configuration -app_backup_subdirectories: - - "{{ my_app_data_path }}" - - "{{ my_app_config_path }}" -``` - -### 3. Create Docker Compose Template - -Edit `roles/my-app/templates/compose.yml.j2`: - -```yaml ---- -services: - my-app: - image: "my-app:{{ my_app_container_version }}" - container_name: "{{ my_app_container_name }}" - restart: "{{ my_app_restart_policy }}" - ports: - - "{{ my_app_http_port }}:8080" - volumes: - - "{{ my_app_data_path }}:/data" - - "{{ my_app_config_path }}:/config" - environment: - - TZ={{ app_timezone | default('UTC') }} -``` - -### 4. Deploy Your Application - -Add to your playbook: - -```yaml ---- -- name: Deploy my application - hosts: localhost - roles: - - role: my-app -``` - -## Advanced Usage - -### Backup and Restore - -#### Create a New Backup - -Create an on-demand backup using tags: - -```bash -# Backup a specific application -ansible-playbook --tags backup playbook.yml -``` - -Configure backup retention and options in your role's meta vars: - -```yaml -# In roles/my-app/meta/main.yml dependencies: - - role: patrickj.docker_apps.docker_compose_app - vars: - app_backup_subdirectories: - - "{{ my_app_data_path }}" - - "{{ my_app_config_path }}" - app_backup_retention_days_controller: 90 # Keep backups for 90 days - app_backup_retention_days_remote: 7 # Keep remote backups for 7 days - app_backup_stop_services: true # Stop containers during backup + "patrickj.docker_compose_app": ">=1.0.0" ``` -#### Automated Backups +## Scaffolding a new consuming role -For scheduled backups: +`create_app_role.sh` at the repo root scaffolds a new "shim" role that depends on `patrickj.docker_compose_app.app`. Run it from the `roles/` directory of your consuming collection or playbook: ```bash -# Run daily backup at 2 AM - only runs backup tasks -0 2 * * * ansible-playbook -i inventory --tags backup my-playbook.yml +cd path/to/your/collection/roles +/path/to/this/repo/create_app_role.sh my-app ``` - -### Tag-Based Execution - -The role supports selective execution using tags: - -```bash -# Setup only - doesn't start the containers -ansible-playbook --tags setup playbook.yml - -# Full deployment - setup + start containers -ansible-playbook --tags deploy playbook.yml - -# Restore and deploy -ansible-playbook --tags restore,deploy playbook.yml - -# Backup only -ansible-playbook --tags backup playbook.yml - -# Update only -ansible-playbook --tags update playbook.yml - -# Backup then update -ansible-playbook --tags backup,update playbook.yml -``` - -#### Restore from Backup - -Restore from the latest backup: - -```bash -# Setup directories, restore from backup, then deploy -ansible-playbook --tags setup,restore,deploy playbook.yml -``` - -Configure restore options in your role's meta vars: - -```yaml -# In roles/my-app/meta/main.yml -dependencies: - - role: patrickj.docker_apps.docker_compose_app - vars: - app_restore_source: controller # or 'remote' - app_restore_max_age_days: 30 # Only restore backups newer than 30 days -``` - -Restore from a specific archive by setting the variable at runtime: - -```bash -ansible-playbook --tags restore playbook.yml \ - -e app_restore_archive=/path/to/specific/backup-20240315-120000.tar.gz -``` - -### Health Checks - -Configure health monitoring: - -```yaml -- role: my-app - vars: - app_name: my-app - app_health_check: true - app_health_check_method: http - app_health_check_url: "http://localhost:8080/health" - app_health_check_retries: 30 - app_health_check_delay: 10 -``` - -### Updates - -Update application containers using tags: - -```bash -# Update a specific application -ansible-playbook --tags update playbook.yml - -# Update all applications in a playbook -ansible-playbook --tags update site.yml -``` - -**Update process:** -1. Stops the application -2. Pulls images according to `app_compose_pull` (defaults to `policy`; set to `always` to force fresh pulls) -3. Recreates containers with new images -4. Runs health checks (if enabled) - - -### Rollbacks - -Rollback using the restore functionality: - -```bash -# First, create a backup then update -ansible-playbook --tags backup,update playbook.yml - -# If update fails, rollback from backup -ansible-playbook --tags restore playbook.yml -``` - -**Important Notes:** -- Updates do NOT create automatic backups - create backups manually beforehand -- Rollbacks must be triggered manually using the restore functionality -- Using `latest` tags prevents effective rollbacks since the old image is overwritten -- For production, use specific version tags instead of `latest` - - -### Multiple Instances - -Deploy multiple instances of the same application: - -```yaml -- role: jellyfin - vars: - app_name: jellyfin-movies - jellyfin_http_port: 8096 - -- role: jellyfin - vars: - app_name: jellyfin-tv - jellyfin_http_port: 8097 -``` - - -### Custom Templates and Files - -#### Override template location: - -```yaml -- role: my-app - vars: - app_compose_template: /path/to/custom/compose.yml.j2 -``` - -#### Use a static compose file: - -If you have an existing `docker-compose.yml` file that doesn't need templating: - -```yaml -- role: my-app - vars: - app_name: my-app - app_compose_file: /path/to/existing/docker-compose.yml -``` - -The file will be copied as-is to the application directory without Jinja2 processing. - -#### Use inline content: - -```yaml -- role: patrickj.docker_apps.docker_compose_app - vars: - app_name: simple-app - app_role_name: simple-app - app_compose_content: | - services: - app: - image: nginx:alpine - ports: - - "80:80" -``` - -## Configuration Reference - -### Required Externals - -These variables have no defaults and must be set by the calling playbook (typically as group_vars or host_vars). They are consumed by the defaults shown further down; if you override every derived variable that uses them, you can leave the corresponding external unset. - -| Variable | Description | Consumed by | -|----------|-------------|-------------| -| `host_root_path` | Base directory on the **target host** under which each app's directory is created (e.g. `/srv/apps`, `/opt/docker`) | `app_dir` | -| `backup_path` | Base directory on the **controller** where fetched backup archives are stored (e.g. `~/backups`) | `app_backup_path` | -| `app_roles_path` | Absolute path to the roles directory that contains your per-app shim roles; used so this role can locate the shim role's `templates/` directory (e.g. `{{ playbook_dir }}/roles`) | `app_templates_path` | -| `app_role_name` | Name of the per-app shim role that depends on this one (e.g. `my-app`, `jellyfin`); combined with `app_roles_path` to find its `templates/` directory | `app_templates_path` | - -### Core Variables - -| Variable | Default | Description | -|----------|---------|-------------| -| `app_name` | Required | Unique application instance name | -| `app_dir` | `{{ host_root_path }}/{{ app_name }}` | Application directory on the target host | -| `app_uid` | `{{ ansible_facts.user_uid }}` | File ownership UID | -| `app_gid` | `{{ ansible_facts.user_gid }}` | File ownership GID | -| `app_permission_mode` | `"0640"` | File permission mode | - -### Deployment Options - -| Variable | Default | Description | -|----------|---------|-------------| -| `app_compose_template` | `{{ app_templates_path }}/compose.yml.j2` | Template file path | -| `app_compose_file` | - | Static compose file path | -| `app_compose_content` | - | Inline compose content | -| `app_compose_validate` | `true` | Validate compose syntax | -| `app_compose_pull` | `policy` | Image pull strategy (also used by `update` — set to `always` to force pulls on update) | -| `app_compose_recreate` | `auto` | Container recreate strategy | -| `app_compose_project_name` | `{{ app_dir \| basename }}` | Compose project name; override when your compose file sets a non-default project name | - -### Backup Configuration - -| Variable | Default | Description | -|----------|---------|-------------| -| `app_backup_subdirectories` | `[]` | Specific directories to backup | -| `app_backup_stop_services` | `true` | Stop containers during backup | -| `app_backup_retention_days_controller` | `90` | Controller backup retention | -| `app_backup_retention_days_remote` | `7` | Remote backup retention | - -### Restore Configuration - -| Variable | Default | Description | -|----------|---------|-------------| -| `app_restore_source` | `controller` | Restore source (`controller`/`remote`) | -| `app_restore_archive` | - | Specific archive file to restore (overrides latest) | -| `app_restore_max_age_days` | `30` | Maximum backup age for restore (when finding latest) | - -### Health Check Configuration - -| Variable | Default | Description | -|----------|---------|-------------| -| `app_health_check` | `true` | Enable health checks | -| `app_health_check_method` | `docker` | Check method (`docker`/`http`) | -| `app_container_name` | `{{ app_name }}` | Container name inspected by the `docker` health check; override when your compose service uses a different `container_name` | -| `app_health_check_url` | - | HTTP endpoint for health check | -| `app_health_check_retries` | `30` | Number of check retries | -| `app_health_check_delay` | `10` | Delay between checks (seconds) | -| `app_health_check_status_codes` | `[200, 201, 202]` | Valid HTTP status codes | - -### Directory Management - -| Variable | Default | Description | -|----------|---------|-------------| -| `app_subdirectories` | `[]` | Directories to create in app_dir | -| `app_extra_templates` | `[]` | Additional templates to render | - -Example `app_extra_templates`: -```yaml -app_extra_templates: - - src: config.json.j2 - dest: "{{ app_dir }}/config/app.json" - - src: env.j2 - dest: "{{ app_dir }}/.env" -``` - - -## Best Practices - -1. **Use semantic versioning** for container tags instead of `latest` -2. **Test restore procedures** regularly to ensure backups are valid -3. **Use specific directories** for backups instead of entire app directory -4. **Monitor disk usage** on backup storage locations - -## Architecture - -The role is organized into logical task files for selective execution: - -``` -├── setup.yml # Validation, directories, and templates -├── restore.yml # Backup restoration logic -├── deploy.yml # Docker Compose deployment and startup -├── health_check.yml # Health monitoring and verification -├── backup.yml # Backup creation and management -├── update.yml # Container update and image pulling -└── manage_compose.yml # Docker Compose lifecycle management -``` - -### Task Execution Flow - -1. **Setup** (`setup.yml`) - [setup, deploy] - - Docker/Compose validation - - Variable validation and security checks - - Directory creation - - Additional template deployment - -2. **Restore** (`restore.yml`) - [restore, never] - - Backup file selection and validation - - Service stopping - - Archive extraction - - Service restart - -3. **Deploy** (`deploy.yml`) - [deploy] - - Docker Compose file creation - - Container startup and management - -4. **Health Check** (`health_check.yml`) - [deploy, healthcheck] - - Service health verification - - Endpoint monitoring - -5. **Backup** (`backup.yml`) - [backup, never] - - Service stopping (optional) - - Archive creation - - Backup copying and cleanup - - Service restart - -6. **Update** (`update.yml`) - [update, never] - - Service stopping - - Image pulling - - Container recreation - - Health verification - -Each task file is designed to be idempotent and can be run multiple times safely. \ No newline at end of file diff --git a/create_app_role.sh b/create_app_role.sh index 5746ed5..e6e819e 100755 --- a/create_app_role.sh +++ b/create_app_role.sh @@ -80,7 +80,7 @@ galaxy_info: license: MIT dependencies: - - role: docker_compose_app + - role: patrickj.docker_compose_app.app vars: app_role_name: $arg diff --git a/galaxy.yml b/galaxy.yml new file mode 100644 index 0000000..f3d67b5 --- /dev/null +++ b/galaxy.yml @@ -0,0 +1,18 @@ +--- +namespace: patrickj +name: docker_compose_app +version: 1.0.0 +readme: README.md +authors: + - Patrick Jaroszewski +description: Base Ansible role for deploying Docker Compose applications +license: + - MIT +tags: + - docker + - compose + - containers +dependencies: + "community.docker": ">=1.10.0" +repository: https://git.jaroszew.ski/ansible/ansible-role-docker-compose-app +issues: https://git.jaroszew.ski/ansible/ansible-role-docker-compose-app/issues diff --git a/roles/app/README.md b/roles/app/README.md new file mode 100644 index 0000000..db271b2 --- /dev/null +++ b/roles/app/README.md @@ -0,0 +1,427 @@ +# Docker Compose App Role + +A flexible Ansible role for deploying and managing Docker Compose applications with features including backup/restore and healthchecks. + +## Overview + +This role provides a standardized way to deploy containerized applications using Docker Compose. It handles directory creation, template rendering, and container lifecycle management. + +## Features + +- **Template-based deployment** with Jinja2 templating +- **Dual backup system** (controller + remote host) +- **Health checks** and deployment verification +- **Multiple deployment modes** (template, file, or inline content) +- **Flexible directory management** +- **Configurable backup retention policies** + +## Quick Start + +### 1. Create a New Role + +Use the provided script to create a new application skeleton role: + +```bash +./create_app_role.sh my-app +``` + +This creates: +``` +roles/my-app/ +├── defaults/main.yml # Default variables +├── meta/main.yml # Role metadata and dependencies +└── templates/ + └── compose.yml.j2 # Docker Compose template +``` + +### 2. Configure Your Application + +Edit `roles/my-app/defaults/main.yml`: + +```yaml +--- +app_role_name: my-app + +my_app_container_name: "{{ app_name | default('my-app') }}" +my_app_container_version: latest +my_app_restart_policy: "{{ app_restart_policy }}" +my_app_http_port: 8080 +my_app_data_path: "{{ app_dir }}/data" +my_app_config_path: "{{ app_dir }}/config" + +# Optional: directories to create +app_subdirectories: + - "{{ my_app_data_path }}" + - "{{ my_app_config_path }}" + +# Optional: backup configuration +app_backup_subdirectories: + - "{{ my_app_data_path }}" + - "{{ my_app_config_path }}" +``` + +### 3. Create Docker Compose Template + +Edit `roles/my-app/templates/compose.yml.j2`: + +```yaml +--- +services: + my-app: + image: "my-app:{{ my_app_container_version }}" + container_name: "{{ my_app_container_name }}" + restart: "{{ my_app_restart_policy }}" + ports: + - "{{ my_app_http_port }}:8080" + volumes: + - "{{ my_app_data_path }}:/data" + - "{{ my_app_config_path }}:/config" + environment: + - TZ={{ app_timezone | default('UTC') }} +``` + +### 4. Deploy Your Application + +Add to your playbook: + +```yaml +--- +- name: Deploy my application + hosts: localhost + roles: + - role: my-app +``` + +## Advanced Usage + +### Backup and Restore + +#### Create a New Backup + +Create an on-demand backup using tags: + +```bash +# Backup a specific application +ansible-playbook --tags backup playbook.yml +``` + +Configure backup retention and options in your role's meta vars: + +```yaml +# In roles/my-app/meta/main.yml +dependencies: + - role: patrickj.docker_apps.docker_compose_app + vars: + app_backup_subdirectories: + - "{{ my_app_data_path }}" + - "{{ my_app_config_path }}" + app_backup_retention_days_controller: 90 # Keep backups for 90 days + app_backup_retention_days_remote: 7 # Keep remote backups for 7 days + app_backup_stop_services: true # Stop containers during backup +``` + +#### Automated Backups + +For scheduled backups: + +```bash +# Run daily backup at 2 AM - only runs backup tasks +0 2 * * * ansible-playbook -i inventory --tags backup my-playbook.yml +``` + +### Tag-Based Execution + +The role supports selective execution using tags: + +```bash +# Setup only - doesn't start the containers +ansible-playbook --tags setup playbook.yml + +# Full deployment - setup + start containers +ansible-playbook --tags deploy playbook.yml + +# Restore and deploy +ansible-playbook --tags restore,deploy playbook.yml + +# Backup only +ansible-playbook --tags backup playbook.yml + +# Update only +ansible-playbook --tags update playbook.yml + +# Backup then update +ansible-playbook --tags backup,update playbook.yml +``` + +#### Restore from Backup + +Restore from the latest backup: + +```bash +# Setup directories, restore from backup, then deploy +ansible-playbook --tags setup,restore,deploy playbook.yml +``` + +Configure restore options in your role's meta vars: + +```yaml +# In roles/my-app/meta/main.yml +dependencies: + - role: patrickj.docker_apps.docker_compose_app + vars: + app_restore_source: controller # or 'remote' + app_restore_max_age_days: 30 # Only restore backups newer than 30 days +``` + +Restore from a specific archive by setting the variable at runtime: + +```bash +ansible-playbook --tags restore playbook.yml \ + -e app_restore_archive=/path/to/specific/backup-20240315-120000.tar.gz +``` + +### Health Checks + +Configure health monitoring: + +```yaml +- role: my-app + vars: + app_name: my-app + app_health_check: true + app_health_check_method: http + app_health_check_url: "http://localhost:8080/health" + app_health_check_retries: 30 + app_health_check_delay: 10 +``` + +### Updates + +Update application containers using tags: + +```bash +# Update a specific application +ansible-playbook --tags update playbook.yml + +# Update all applications in a playbook +ansible-playbook --tags update site.yml +``` + +**Update process:** +1. Stops the application +2. Pulls images according to `app_compose_pull` (defaults to `policy`; set to `always` to force fresh pulls) +3. Recreates containers with new images +4. Runs health checks (if enabled) + + +### Rollbacks + +Rollback using the restore functionality: + +```bash +# First, create a backup then update +ansible-playbook --tags backup,update playbook.yml + +# If update fails, rollback from backup +ansible-playbook --tags restore playbook.yml +``` + +**Important Notes:** +- Updates do NOT create automatic backups - create backups manually beforehand +- Rollbacks must be triggered manually using the restore functionality +- Using `latest` tags prevents effective rollbacks since the old image is overwritten +- For production, use specific version tags instead of `latest` + + +### Multiple Instances + +Deploy multiple instances of the same application: + +```yaml +- role: jellyfin + vars: + app_name: jellyfin-movies + jellyfin_http_port: 8096 + +- role: jellyfin + vars: + app_name: jellyfin-tv + jellyfin_http_port: 8097 +``` + + +### Custom Templates and Files + +#### Override template location: + +```yaml +- role: my-app + vars: + app_compose_template: /path/to/custom/compose.yml.j2 +``` + +#### Use a static compose file: + +If you have an existing `docker-compose.yml` file that doesn't need templating: + +```yaml +- role: my-app + vars: + app_name: my-app + app_compose_file: /path/to/existing/docker-compose.yml +``` + +The file will be copied as-is to the application directory without Jinja2 processing. + +#### Use inline content: + +```yaml +- role: patrickj.docker_apps.docker_compose_app + vars: + app_name: simple-app + app_role_name: simple-app + app_compose_content: | + services: + app: + image: nginx:alpine + ports: + - "80:80" +``` + +## Configuration Reference + +### Required Externals + +These variables have no defaults and must be set by the calling playbook (typically as group_vars or host_vars). They are consumed by the defaults shown further down; if you override every derived variable that uses them, you can leave the corresponding external unset. + +| Variable | Description | Consumed by | +|----------|-------------|-------------| +| `host_root_path` | Base directory on the **target host** under which each app's directory is created (e.g. `/srv/apps`, `/opt/docker`) | `app_dir` | +| `backup_path` | Base directory on the **controller** where fetched backup archives are stored (e.g. `~/backups`) | `app_backup_path` | +| `app_roles_path` | Absolute path to the roles directory that contains your per-app shim roles; used so this role can locate the shim role's `templates/` directory (e.g. `{{ playbook_dir }}/roles`) | `app_templates_path` | +| `app_role_name` | Name of the per-app shim role that depends on this one (e.g. `my-app`, `jellyfin`); combined with `app_roles_path` to find its `templates/` directory | `app_templates_path` | + +### Core Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `app_name` | Required | Unique application instance name | +| `app_dir` | `{{ host_root_path }}/{{ app_name }}` | Application directory on the target host | +| `app_uid` | `{{ ansible_facts.user_uid }}` | File ownership UID | +| `app_gid` | `{{ ansible_facts.user_gid }}` | File ownership GID | +| `app_permission_mode` | `"0640"` | File permission mode | + +### Deployment Options + +| Variable | Default | Description | +|----------|---------|-------------| +| `app_compose_template` | `{{ app_templates_path }}/compose.yml.j2` | Template file path | +| `app_compose_file` | - | Static compose file path | +| `app_compose_content` | - | Inline compose content | +| `app_compose_validate` | `true` | Validate compose syntax | +| `app_compose_pull` | `policy` | Image pull strategy (also used by `update` — set to `always` to force pulls on update) | +| `app_compose_recreate` | `auto` | Container recreate strategy | +| `app_compose_project_name` | `{{ app_dir \| basename }}` | Compose project name; override when your compose file sets a non-default project name | + +### Backup Configuration + +| Variable | Default | Description | +|----------|---------|-------------| +| `app_backup_subdirectories` | `[]` | Specific directories to backup | +| `app_backup_stop_services` | `true` | Stop containers during backup | +| `app_backup_retention_days_controller` | `90` | Controller backup retention | +| `app_backup_retention_days_remote` | `7` | Remote backup retention | + +### Restore Configuration + +| Variable | Default | Description | +|----------|---------|-------------| +| `app_restore_source` | `controller` | Restore source (`controller`/`remote`) | +| `app_restore_archive` | - | Specific archive file to restore (overrides latest) | +| `app_restore_max_age_days` | `30` | Maximum backup age for restore (when finding latest) | + +### Health Check Configuration + +| Variable | Default | Description | +|----------|---------|-------------| +| `app_health_check` | `true` | Enable health checks | +| `app_health_check_method` | `docker` | Check method (`docker`/`http`) | +| `app_container_name` | `{{ app_name }}` | Container name inspected by the `docker` health check; override when your compose service uses a different `container_name` | +| `app_health_check_url` | - | HTTP endpoint for health check | +| `app_health_check_retries` | `30` | Number of check retries | +| `app_health_check_delay` | `10` | Delay between checks (seconds) | +| `app_health_check_status_codes` | `[200, 201, 202]` | Valid HTTP status codes | + +### Directory Management + +| Variable | Default | Description | +|----------|---------|-------------| +| `app_subdirectories` | `[]` | Directories to create in app_dir | +| `app_extra_templates` | `[]` | Additional templates to render | + +Example `app_extra_templates`: +```yaml +app_extra_templates: + - src: config.json.j2 + dest: "{{ app_dir }}/config/app.json" + - src: env.j2 + dest: "{{ app_dir }}/.env" +``` + + +## Best Practices + +1. **Use semantic versioning** for container tags instead of `latest` +2. **Test restore procedures** regularly to ensure backups are valid +3. **Use specific directories** for backups instead of entire app directory +4. **Monitor disk usage** on backup storage locations + +## Architecture + +The role is organized into logical task files for selective execution: + +``` +├── setup.yml # Validation, directories, and templates +├── restore.yml # Backup restoration logic +├── deploy.yml # Docker Compose deployment and startup +├── health_check.yml # Health monitoring and verification +├── backup.yml # Backup creation and management +├── update.yml # Container update and image pulling +└── manage_compose.yml # Docker Compose lifecycle management +``` + +### Task Execution Flow + +1. **Setup** (`setup.yml`) - [setup, deploy] + - Docker/Compose validation + - Variable validation and security checks + - Directory creation + - Additional template deployment + +2. **Restore** (`restore.yml`) - [restore, never] + - Backup file selection and validation + - Service stopping + - Archive extraction + - Service restart + +3. **Deploy** (`deploy.yml`) - [deploy] + - Docker Compose file creation + - Container startup and management + +4. **Health Check** (`health_check.yml`) - [deploy, healthcheck] + - Service health verification + - Endpoint monitoring + +5. **Backup** (`backup.yml`) - [backup, never] + - Service stopping (optional) + - Archive creation + - Backup copying and cleanup + - Service restart + +6. **Update** (`update.yml`) - [update, never] + - Service stopping + - Image pulling + - Container recreation + - Health verification + +Each task file is designed to be idempotent and can be run multiple times safely. \ No newline at end of file diff --git a/defaults/main.yml b/roles/app/defaults/main.yml similarity index 100% rename from defaults/main.yml rename to roles/app/defaults/main.yml diff --git a/meta/main.yml b/roles/app/meta/main.yml similarity index 100% rename from meta/main.yml rename to roles/app/meta/main.yml diff --git a/tasks/backup.yml b/roles/app/tasks/backup.yml similarity index 100% rename from tasks/backup.yml rename to roles/app/tasks/backup.yml diff --git a/tasks/deploy.yml b/roles/app/tasks/deploy.yml similarity index 100% rename from tasks/deploy.yml rename to roles/app/tasks/deploy.yml diff --git a/tasks/health_check.yml b/roles/app/tasks/health_check.yml similarity index 100% rename from tasks/health_check.yml rename to roles/app/tasks/health_check.yml diff --git a/tasks/main.yml b/roles/app/tasks/main.yml similarity index 100% rename from tasks/main.yml rename to roles/app/tasks/main.yml diff --git a/tasks/manage_compose.yml b/roles/app/tasks/manage_compose.yml similarity index 100% rename from tasks/manage_compose.yml rename to roles/app/tasks/manage_compose.yml diff --git a/tasks/restore.yml b/roles/app/tasks/restore.yml similarity index 100% rename from tasks/restore.yml rename to roles/app/tasks/restore.yml diff --git a/tasks/setup.yml b/roles/app/tasks/setup.yml similarity index 100% rename from tasks/setup.yml rename to roles/app/tasks/setup.yml diff --git a/tasks/update.yml b/roles/app/tasks/update.yml similarity index 100% rename from tasks/update.yml rename to roles/app/tasks/update.yml