Compare commits

...

14 Commits

280 changed files with 870 additions and 494 deletions

View File

@@ -3,11 +3,17 @@ APPLICATIONS_OUT := ./group_vars/all/04_applications.yml
APPLICATIONS_SCRIPT := ./cli/generate_applications.py APPLICATIONS_SCRIPT := ./cli/generate_applications.py
USERS_OUT := ./group_vars/all/03_users.yml USERS_OUT := ./group_vars/all/03_users.yml
USERS_SCRIPT := ./cli/generate_users.py USERS_SCRIPT := ./cli/generate_users.py
INCLUDES_OUT := ./tasks/utils/server-roles.yml
INCLUDES_SCRIPT := ./cli/generate_playbook.py INCLUDES_SCRIPT := ./cli/generate_playbook.py
# Define the prefixes for which we want individual role-include files
INCLUDE_GROUPS := "drv-" "svc-" "desk-" "web-" "util-"
# Directory where these include-files will be written
INCLUDES_OUT_DIR := ./tasks/groups
# Compute extra users as before
EXTRA_USERS := $(shell \ EXTRA_USERS := $(shell \
find $(ROLES_DIR) -maxdepth 1 -type d -name '*' -printf '%f\n' \ find $(ROLES_DIR) -maxdepth 1 -type d -printf '%f\n' \
| sed -E 's/.*-//' \ | sed -E 's/.*-//' \
| grep -E -x '[a-z0-9]+' \ | grep -E -x '[a-z0-9]+' \
| sort -u \ | sort -u \
@@ -17,27 +23,34 @@ EXTRA_USERS := $(shell \
.PHONY: build install test .PHONY: build install test
build: build:
@echo "🔧 Generating applications defaults → $(APPLICATIONS_OUT) from roles in $(ROLES_DIR)" @echo "🔧 Generating users defaults → $(USERS_OUT)"
python3 $(USERS_SCRIPT) --roles-dir $(ROLES_DIR) --output $(USERS_OUT) --extra-users "$(EXTRA_USERS)" python3 $(USERS_SCRIPT) \
--roles-dir $(ROLES_DIR) \
--output $(USERS_OUT) \
--extra-users "$(EXTRA_USERS)"
@echo "✅ Users defaults written to $(USERS_OUT)\n" @echo "✅ Users defaults written to $(USERS_OUT)\n"
python3 $(APPLICATIONS_SCRIPT) --roles-dir $(ROLES_DIR) --output-file $(APPLICATIONS_OUT)
@echo "🔧 Generating applications defaults → $(APPLICATIONS_OUT)"
python3 $(APPLICATIONS_SCRIPT) \
--roles-dir $(ROLES_DIR) \
--output-file $(APPLICATIONS_OUT)
@echo "✅ Applications defaults written to $(APPLICATIONS_OUT)\n" @echo "✅ Applications defaults written to $(APPLICATIONS_OUT)\n"
@echo "🔧 Generating users defaults → $(USERS_OUT) from roles in $(ROLES_DIR)"
@echo "🔧 Generating Docker role includes → $(INCLUDES_OUT)" @echo "🔧 Generating role-include files for each group…"
@mkdir -p $(dir $(INCLUDES_OUT)) @mkdir -p $(INCLUDES_OUT_DIR)
python3 $(INCLUDES_SCRIPT) $(ROLES_DIR) -o $(INCLUDES_OUT) \ @$(foreach grp,$(INCLUDE_GROUPS), \
-p web-app \ out=$(INCLUDES_OUT_DIR)/$(grp)roles.yml; \
-p web-svc \ echo "→ Building $$out (pattern: '$(grp)')…"; \
-p svc-openldap \ python3 $(INCLUDES_SCRIPT) $(ROLES_DIR) \
-p svc-rdbms-postgres \ -p $(grp) -o $$out; \
-p svc-rdbms-mariadb echo "$$out"; \
@echo "✅ Docker role includes written to $(INCLUDES_OUT)" )
install: build install: build
@echo "⚙️ Install complete." @echo "⚙️ Install complete."
test: test:
@echo "🧪 Running Python Tests..." @echo "🧪 Running Python tests"
python -m unittest discover -s tests python -m unittest discover -s tests
@echo "📑 Syntax Checking Ansible Playbook..." @echo "📑 Checking Ansible syntax…"
ansible-playbook playbook.yml --syntax-check ansible-playbook playbook.yml --syntax-check

83
cli/ensure_vars_main.py Normal file
View File

@@ -0,0 +1,83 @@
#!/usr/bin/env python3
"""
Script to ensure each Ansible role under ../roles/ with a given prefix has a vars/main.yml
containing the correct application_id. Can preview actions or overwrite mismatches.
"""
import argparse
import sys
import yaml
from pathlib import Path
def process_role(role_dir: Path, prefix: str, preview: bool, overwrite: bool):
name = role_dir.name
if not name.startswith(prefix):
return
# Expected application_id is role name minus prefix
expected_id = name[len(prefix):]
vars_dir = role_dir / "vars"
vars_file = vars_dir / "main.yml"
if vars_file.exists():
# Load existing variables
try:
existing = yaml.safe_load(vars_file.read_text()) or {}
except yaml.YAMLError as e:
print(f"Error parsing YAML in {vars_file}: {e}", file=sys.stderr)
return
actual_id = existing.get("application_id")
if actual_id == expected_id:
# Already correct
return
if overwrite:
# Update only application_id
existing["application_id"] = expected_id
if preview:
print(f"[PREVIEW] Would update {vars_file}: application_id -> {expected_id}")
else:
with open(vars_file, "w") as f:
yaml.safe_dump(existing, f, default_flow_style=False, sort_keys=False)
print(f"Updated {vars_file}: application_id -> {expected_id}")
else:
print(f"Mismatch in {vars_file}: application_id='{actual_id}', expected='{expected_id}'")
else:
# Create new vars/main.yml
if preview:
print(f"[PREVIEW] Would create {vars_file} with application_id: {expected_id}")
else:
vars_dir.mkdir(parents=True, exist_ok=True)
content = {"application_id": expected_id}
with open(vars_file, "w") as f:
yaml.safe_dump(content, f, default_flow_style=False, sort_keys=False)
print(f"Created {vars_file} with application_id: {expected_id}")
def main():
parser = argparse.ArgumentParser(
description="Ensure vars/main.yml for roles with a given prefix has correct application_id"
)
parser.add_argument(
"--prefix", required=True,
help="Role name prefix to filter (e.g. 'web-', 'svc-', 'desk-')"
)
parser.add_argument(
"--preview", action="store_true",
help="Show what would be done without making changes"
)
parser.add_argument(
"--overwrite", action="store_true",
help="If vars/main.yml exists but application_id mismatches, overwrite only that key"
)
args = parser.parse_args()
# Determine roles directory relative to this script
script_dir = Path(__file__).resolve().parent
roles_dir = (script_dir.parent / "roles").resolve()
if not roles_dir.is_dir():
print(f"Roles directory not found: {roles_dir}", file=sys.stderr)
sys.exit(1)
for role in sorted(roles_dir.iterdir()):
if role.is_dir():
process_role(role, args.prefix, args.preview, args.overwrite)
if __name__ == "__main__":
main()

58
cli/invokable_paths.py Executable file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/env python3
"""
CLI for extracting invokable role paths from a nested roles YAML file using argparse.
Assumes a default roles file at the project root if none is provided.
"""
import os
import sys
# ─── Determine project root ───
if "__file__" in globals():
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
else:
project_root = os.getcwd()
# Ensure project root on PYTHONPATH so 'filter_plugins' can be imported
sys.path.insert(0, project_root)
import argparse
import yaml
from filter_plugins.invokable_paths import get_invokable_paths
def main():
parser = argparse.ArgumentParser(
description="Extract invokable role paths from a nested roles YAML file."
)
parser.add_argument(
"roles_file",
nargs='?',
default=None,
help="Path to the roles YAML file (default: roles/categories.yml at project root)"
)
parser.add_argument(
"--suffix", "-s",
help="Optional suffix to append to each invokable path.",
default=None
)
args = parser.parse_args()
try:
paths = get_invokable_paths(args.roles_file, args.suffix)
except FileNotFoundError as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
except yaml.YAMLError as e:
print(f"Error parsing YAML: {e}", file=sys.stderr)
sys.exit(1)
except ValueError as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
for p in paths:
print(p)
if __name__ == "__main__":
main()

View File

@@ -5,7 +5,7 @@ from ansible.errors import AnsibleFilterError
class FilterModule(object): class FilterModule(object):
def filters(self): def filters(self):
# module_utils-Verzeichnis ermitteln und zum Import-Pfad hinzufügen # module_util-Verzeichnis ermitteln und zum Import-Pfad hinzufügen
plugin_dir = os.path.dirname(__file__) plugin_dir = os.path.dirname(__file__)
project_root = os.path.dirname(plugin_dir) project_root = os.path.dirname(plugin_dir)
module_utils = os.path.join(project_root, 'module_utils') module_utils = os.path.join(project_root, 'module_utils')

View File

@@ -8,7 +8,7 @@ class FilterModule(object):
return {'get_url': self.get_url} return {'get_url': self.get_url}
def get_url(self, domains, application_id, protocol): def get_url(self, domains, application_id, protocol):
# 1) module_utils-Verzeichnis in den Pfad aufnehmen # 1) module_util-Verzeichnis in den Pfad aufnehmen
plugin_dir = os.path.dirname(__file__) plugin_dir = os.path.dirname(__file__)
project_root = os.path.dirname(plugin_dir) project_root = os.path.dirname(plugin_dir)
module_utils = os.path.join(project_root, 'module_utils') module_utils = os.path.join(project_root, 'module_utils')

View File

@@ -0,0 +1,71 @@
import os
import yaml
from typing import Dict, List, Optional
def get_invokable_paths(
roles_file: Optional[str] = None,
suffix: Optional[str] = None
) -> List[str]:
"""
Load nested roles YAML from the given file (or default at project root) and return
dash-joined paths where 'invokable' is True. Appends suffix if provided.
:param roles_file: Optional path to YAML file. Defaults to '<project_root>/roles/categories.yml'.
:param suffix: Optional suffix to append to each invokable path.
:return: List of invokable paths.
:raises FileNotFoundError: If the YAML file cannot be found.
:raises yaml.YAMLError: If the YAML file cannot be parsed.
:raises ValueError: If the root of the YAML is not a dictionary.
"""
# Determine default roles_file if not provided
if not roles_file:
script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(script_dir)
roles_file = os.path.join(project_root, 'roles', 'categories.yml')
# Load and validate YAML
try:
with open(roles_file, 'r') as f:
data = yaml.safe_load(f) or {}
except FileNotFoundError:
raise FileNotFoundError(f"Roles file not found: {roles_file}")
except yaml.YAMLError as e:
raise yaml.YAMLError(f"Error parsing YAML {roles_file}: {e}")
if not isinstance(data, dict):
raise ValueError("YAML root is not a dictionary")
# Unwrap if single 'roles' key
roles = data
if 'roles' in roles and isinstance(roles['roles'], dict) and len(roles) == 1:
roles = roles['roles']
def _recurse(subroles: Dict[str, dict], parent: List[str] = None) -> List[str]:
parent = parent or []
found: List[str] = []
METADATA = {'title', 'description', 'icon', 'invokable'}
for key, cfg in subroles.items():
path = parent + [key]
if cfg.get('invokable', False):
p = '-'.join(path)
if suffix:
p += suffix
found.append(p)
# Recurse into non-metadata child dicts
children = {
ck: cv for ck, cv in cfg.items()
if ck not in METADATA and isinstance(cv, dict)
}
if children:
found.extend(_recurse(children, path))
return found
return _recurse(roles)
class FilterModule:
def filters(self):
return {'invokable_paths': get_invokable_paths}

View File

@@ -24,19 +24,19 @@ For a complete list of role categories and detailed definitions, see:
## Webserver & HTTP ## Webserver & HTTP
- **srv-web-core** - **srv-web-7-4-core**
Installs and configures the base Nginx server. Installs and configures the base Nginx server.
- **srv-web-tls-*** - **srv-web-6-6-tls-***
Manages TLS certificates and renewal (formerly “https”; e.g. `srv-web-tls-deploy`, `srv-web-tls-renew`). Manages TLS certificates and renewal (formerly “https”; e.g. `srv-web-6-6-tls-deploy`, `srv-web-6-6-tls-renew`).
- **srv-web-proxy-*** - **srv-web-proxy-***
Proxy and vhost orchestration roles (domain setup, OAuth2 proxy, etc.) Proxy and vhost orchestration roles (domain setup, OAuth2 proxy, etc.)
- **srv-web-injector-*** - **srv-web-7-7-inj-***
HTML response modifiers: CSS, JS, Matomo tracking, iframe notifier. HTML response modifiers: CSS, JS, Matomo tracking, iframe notifier.
- **srv-web-composer** - **srv-web-7-6-composer**
Aggregates multiple sub-filters into one include for your vhost. Aggregates multiple sub-filters into one include for your vhost.
- **web-svc-*** - **web-svc-***

View File

@@ -1,184 +1,105 @@
categories: roles:
core: core:
title: "Core & System" title: "Core & System"
description: "Fundamental system configuration" description: "Fundamental system configuration"
icon: "fas fa-cogs" icon: "fas fa-cogs"
invokable: false
drv:
title: "Drivers"
description: "Roles for installing and configuring hardware drivers—covering printers, graphics, input devices, and other peripheral support."
icon: "fas fa-microchip"
invokable: true
gen: gen:
title: "gen-*" title: "Generic"
description: "Helper roles & installers (git, locales, timer, etc.)" description: "Helper roles & installers (git, locales, timer, etc.)"
icon: "fas fa-wrench" icon: "fas fa-wrench"
invokable: false
desk: desk:
title: "desk-*" title: "Desktop"
description: "Desktop environment roles & apps (GNOME, browser, LibreOffice, etc.)" description: "Desktop environment roles & apps (GNOME, browser, LibreOffice, etc.)"
icon: "fas fa-desktop" icon: "fas fa-desktop"
invokable: true
desk: util:
applications: title: "Utilities"
title: "Desktop Applications" description: "General-purpose utility roles for both desktop and server environments—providing helper functions, customizations, and optimizations for applications, workflows, and infrastructure."
description: "Setup & utilities for desktop apps"
icon: "fas fa-desktop"
utils:
title: "utils-desk-*"
description: "Utility roles for desktop tools & development"
icon: "fas fa-tools" icon: "fas fa-tools"
invokable: false
desk:
title: "Desktop Utilities"
description: "Utility roles for configuring and optimizing desktop applications and workflows—covering browsers, design tools, development environments, office suites, and gaming setups."
icon: "fas fa-tools"
invokable: true
srv: srv:
web: title: "Server Utilities"
core: description: "Utility roles for server-side configuration and management—covering corporate identity provisioning, network helpers, and other service-oriented toolkits."
title: "srv-web-core" icon: "fas fa-cogs"
description: "Install & configure base Nginx server" invokable: true
srv:
title: "Server"
description: "General server roles for provisioning and managing server infrastructure—covering web servers, proxy servers, network services, and other backend components."
icon: "fas fa-server" icon: "fas fa-server"
tls: invokable: false
title: "srv-web-tls-*"
description: "Deploy & renew TLS certificates"
icon: "fas fa-lock"
proxy:
title: "srv-web-proxy-*"
description: "Proxy & vhost orchestration"
icon: "fas fa-project-diagram"
injector:
core:
title: "srv-web-injector-compose"
description: "Inject core HTML modifiers"
icon: "fas fa-code"
css:
title: "srv-web-injector-css"
description: "Inject CSS into responses"
icon: "fas fa-paint-brush"
iframe:
title: "srv-web-injector-iframe"
description: "Inject iframe notifier"
icon: "fas fa-window-maximize"
javascript:
title: "srv-web-injector-javascript"
description: "Inject JS into responses"
icon: "fas fa-code"
matomo:
title: "srv-web-injector-matomo"
description: "Inject Matomo tracking code"
icon: "fas fa-chart-pie"
composer:
title: "srv-web-composer"
description: "Compose multiple filters into one include"
icon: "fas fa-layer-group"
web: web:
svc: title: "Webserver"
title: "web-svc-*" description: "Web-server roles for installing and configuring Nginx (core, TLS, injection filters, composer modules)."
description: "Static content servers (assets, HTML, legal, files)" icon: "fas fa-server"
icon: "fas fa-file" invokable: false
app: proxy:
title: "web-app-*" title: "Proxy Server"
description: "Deployable web applications (GitLab, Nextcloud, Mastodon, etc.)" description: "Proxy-server roles for virtual-host orchestration and reverse-proxy setups."
icon: "fas fa-docker" icon: "fas fa-project-diagram"
invokable: false
net: web:
general: title: "Web Infrastructure"
title: "net-*" description: "Roles for managing web infrastructure—covering static content services and deployable web applications."
description: "Network setup (DNS, Let's Encrypt HTTP, WireGuard, etc.)"
icon: "fas fa-globe" icon: "fas fa-globe"
svc: svc:
title: "svc-*" title: "Services"
description: "Static content servers (assets, HTML, legal, files)"
icon: "fas fa-file"
invokable: true
app:
title: "Applications"
description: "Deployable web applications (GitLab, Nextcloud, Mastodon, etc.)"
icon: "fas fa-docker"
invokable: true
net:
title: "Network"
description: "Network setup (DNS, Let's Encrypt HTTP, WireGuard, etc.)"
icon: "fas fa-globe"
invokable: true
svc:
title: "Services"
description: "Docker infrastructure services (DBMS, LDAP, Redis, etc.)" description: "Docker infrastructure services (DBMS, LDAP, Redis, etc.)"
icon: "fas fa-database" icon: "fas fa-database"
wireguard: invokable: true
core: mon:
title: "net-wireguard-core" title: "Monitoring"
description: "Core WireGuard configuration" description: "Roles for system monitoring and health checks—encompassing bot-style automated checks and core low-level monitors for logs, containers, disk usage, and more."
icon: "fas fa-network-wired"
firewalled:
title: "net-wireguard-firewalled"
description: "WireGuard with firewall rules"
icon: "fas fa-shield-alt"
plain:
title: "net-wireguard-plain"
description: "WireGuard without extra firewall"
icon: "fas fa-network-wired"
monitoring:
bot:
title: "mon-bot-*"
description: "Bot-style health checks (disk, Docker, webserver, etc.)"
icon: "fas fa-robot"
core:
title: "monitor-core-*"
description: "Low-level monitors (journalctl, containers, disk space, etc.)"
icon: "fas fa-chart-area" icon: "fas fa-chart-area"
invokable: false
alerting: alert:
title: "Alerting" title: "Alerting"
description: "Notification handlers for system events" description: "Notification handlers for system events"
icon: "fas fa-bell" icon: "fas fa-bell"
subcategories: invokable: false
email: maint:
title: "alert-email"
description: "Send alerts via email"
icon: "fas fa-envelope"
telegram:
title: "alert-telegram"
description: "Send alerts via Telegram"
icon: "fab fa-telegram-plane"
compose:
title: "alert-compose"
description: "Compose multiple alert handlers"
icon: "fas fa-project-diagram"
maintenance:
title: "Maintenance & Healing" title: "Maintenance & Healing"
description: "Periodic maintenance & auto-recovery" description: "Periodic maintenance & auto-recovery"
icon: "fas fa-tools" icon: "fas fa-tools"
subcategories: invokable: true
general: bkp:
title: "maint-*"
description: "Periodic tasks (Btrfs balancing, swapfile, etc.)"
icon: "fas fa-sync-alt"
docker:
title: "maint-docker-*"
description: "Automated Docker recovery & restarts"
icon: "fas fa-docker"
cleanup:
title: "cln-*"
description: "Housekeeping tasks (backups, certs, logs, etc.)"
icon: "fas fa-broom"
backup:
title: "Backup & Restore" title: "Backup & Restore"
description: "Backup strategies & restore procedures" description: "Backup strategies & restore procedures"
icon: "fas fa-hdd" icon: "fas fa-hdd"
subcategories: invokable: false
general: update:
title: "bkp-*"
description: "Local & remote backups (files, volumes, DBs)"
icon: "fas fa-cloud-upload-alt"
updates:
title: "Updates & Package Management" title: "Updates & Package Management"
description: "OS & package updates" description: "OS & package updates"
icon: "fas fa-sync" icon: "fas fa-sync"
subcategories: invokable: true
os: user:
title: "update-*"
description: "Automatic OS & package updates (apt, Docker, pip, etc.)"
icon: "fas fa-download"
pkgmgr:
title: "pkgmgr-*"
description: "Language/platform package managers (npm, pip, AUR, etc.)"
icon: "fas fa-box-open"
users:
title: "Users & Access" title: "Users & Access"
description: "User accounts & access control" description: "User accounts & access control"
icon: "fas fa-users" icon: "fas fa-users"
subcategories: invokable: false
general:
title: "user-*"
description: "Create user accounts & SSH keys"
icon: "fas fa-user"
administrator:
title: "user-administrator"
description: "Config for admin users"
icon: "fas fa-user-shield"
root:
title: "user-root"
description: "Config for root user"
icon: "fas fa-user-shield"

View File

@@ -21,5 +21,5 @@ galaxy_info:
issue_tracker_url: "https://s.veen.world/cymaisissues" issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- srv-web-core - srv-web-7-4-core
- core-daemon - core-daemon

View File

@@ -8,4 +8,4 @@ This role builds on `cmp-db-docker` by adding a reverse-proxy frontend for HTTP
Leverages the `cmp-db-docker` role to stand up your containerized database (PostgreSQL, MariaDB, etc.) with backups and user management. Leverages the `cmp-db-docker` role to stand up your containerized database (PostgreSQL, MariaDB, etc.) with backups and user management.
- **Reverse Proxy** - **Reverse Proxy**
Includes the `srv-web-proxy-domain` role to configure a proxy (e.g. nginx) for routing HTTP(S) traffic to your database UI or management endpoint. Includes the `srv-proxy-6-6-domain` role to configure a proxy (e.g. nginx) for routing HTTP(S) traffic to your database UI or management endpoint.

View File

@@ -1,7 +1,7 @@
galaxy_info: galaxy_info:
author: "Kevin Veen-Birkenbach" author: "Kevin Veen-Birkenbach"
description: > description: >
Extends cmp-db-docker by adding an HTTP reverse proxy via srv-web-proxy-domain. Extends cmp-db-docker by adding an HTTP reverse proxy via srv-proxy-6-6-domain.
company: | company: |
Kevin Veen-Birkenbach Kevin Veen-Birkenbach
Consulting & Coaching Solutions Consulting & Coaching Solutions

View File

@@ -2,9 +2,9 @@
include_role: include_role:
name: cmp-db-docker name: cmp-db-docker
- name: "include role srv-web-proxy-domain for {{application_id}}" - name: "include role srv-proxy-6-6-domain for {{application_id}}"
include_role: include_role:
name: srv-web-proxy-domain name: srv-proxy-6-6-domain
vars: vars:
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"

View File

@@ -1,18 +1,18 @@
# Database Docker Composition # Database Docker Composition
This role combines the central RDBMS role (`svc-rdbms-central`) with Docker Compose to deliver a ready-to-use containerized database environment. This role combines the central RDBMS role (`cmp-rdbms-orchestrator`) with Docker Compose to deliver a ready-to-use containerized database environment.
## Features ## Features
- **Central RDBMS Integration** - **Central RDBMS Integration**
Includes the `svc-rdbms-central` role, which handles backups, restores, user and permission management for your relational database system (PostgreSQL, MariaDB, etc.). Includes the `cmp-rdbms-orchestrator` role, which handles backups, restores, user and permission management for your relational database system (PostgreSQL, MariaDB, etc.).
- **Docker Compose** - **Docker Compose**
Utilizes the standalone `docker-compose` role to define and bring up containers, networks, and volumes automatically. Utilizes the standalone `docker-compose` role to define and bring up containers, networks, and volumes automatically.
- **Variable Load Order** - **Variable Load Order**
1. Docker Compose variables (`roles/docker-compose/vars/docker-compose.yml`) 1. Docker Compose variables (`roles/docker-compose/vars/docker-compose.yml`)
2. Database variables (`roles/svc-rdbms-central/vars/database.yml`) 2. Database variables (`roles/cmp-rdbms-orchestrator/vars/database.yml`)
Ensures compose ports and volumes are defined before the database role consumes them. Ensures compose ports and volumes are defined before the database role consumes them.
The role will load both sub-roles and satisfy all dependencies transparently. The role will load both sub-roles and satisfy all dependencies transparently.
@@ -22,4 +22,4 @@ The role will load both sub-roles and satisfy all dependencies transparently.
1. **Set Fact** `database_application_id` to work around lazyloading ordering. 1. **Set Fact** `database_application_id` to work around lazyloading ordering.
2. **Include Vars** in the specified order. 2. **Include Vars** in the specified order.
3. **Invoke** `docker-compose` role to create containers, networks, and volumes. 3. **Invoke** `docker-compose` role to create containers, networks, and volumes.
4. **Invoke** `svc-rdbms-central` role to provision the database, backups, and users. 4. **Invoke** `cmp-rdbms-orchestrator` role to provision the database, backups, and users.

View File

@@ -14,4 +14,4 @@
- name: "Load central rdbms for {{ application_id }}" - name: "Load central rdbms for {{ application_id }}"
include_role: include_role:
name: svc-rdbms-central name: cmp-rdbms-orchestrator

View File

@@ -1,2 +1,2 @@
cmp_db_docker_vars_file_db: "{{ playbook_dir }}/roles/svc-rdbms-central/vars/database.yml" cmp_db_docker_vars_file_db: "{{ playbook_dir }}/roles/cmp-rdbms-orchestrator/vars/database.yml"
cmp_db_docker_vars_file_docker: "{{ playbook_dir }}/roles/docker-compose/vars/docker-compose.yml" cmp_db_docker_vars_file_docker: "{{ playbook_dir }}/roles/docker-compose/vars/docker-compose.yml"

View File

@@ -8,4 +8,4 @@ This role combines the standard Docker Compose setup with a reverse-proxy for an
Brings up containers, networks, and volumes via the `docker-compose` role. Brings up containers, networks, and volumes via the `docker-compose` role.
- **Reverse Proxy** - **Reverse Proxy**
Uses the `srv-web-proxy-domain` role to expose your application under a custom domain and port. Uses the `srv-proxy-6-6-domain` role to expose your application under a custom domain and port.

View File

@@ -1,7 +1,7 @@
galaxy_info: galaxy_info:
author: "Kevin Veen-Birkenbach" author: "Kevin Veen-Birkenbach"
description: > description: >
Combines the docker-compose role with srv-web-proxy-domain to Combines the docker-compose role with srv-proxy-6-6-domain to
deploy applications behind a reverse proxy. deploy applications behind a reverse proxy.
company: | company: |
Kevin Veen-Birkenbach Kevin Veen-Birkenbach

View File

@@ -2,9 +2,9 @@
include_role: include_role:
name: docker-compose name: docker-compose
- name: "include role srv-web-proxy-domain for {{application_id}}" - name: "include role srv-proxy-6-6-domain for {{application_id}}"
include_role: include_role:
name: srv-web-proxy-domain name: srv-proxy-6-6-domain
vars: vars:
domain: "{{ domains | get_domain(application_id) }}" domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}" http_port: "{{ ports.localhost.http[application_id] }}"

View File

@@ -0,0 +1 @@
{% include 'roles/cmp-rdbms-orchestrator/templates/services/' + database_type + '.yml.j2' %}

View File

@@ -0,0 +1 @@
application_id: bluray-player

View File

@@ -0,0 +1 @@
application_id: docker

View File

@@ -14,7 +14,7 @@ galaxy_info:
- browser - browser
repository: "https://github.com/kevinveenbirkenbach/cymais" repository: "https://github.com/kevinveenbirkenbach/cymais"
issue_tracker_url: "https://github.com/kevinveenbirkenbach/cymais/issues" issue_tracker_url: "https://github.com/kevinveenbirkenbach/cymais/issues"
documentation: "https://github.com/kevinveenbirkenbach/cymais/tree/main/roles/utils-desk-browser-firefox" documentation: "https://github.com/kevinveenbirkenbach/cymais/tree/main/roles/desk-firefox"
min_ansible_version: "2.9" min_ansible_version: "2.9"
platforms: platforms:
- name: Archlinux - name: Archlinux

View File

@@ -0,0 +1 @@
application_id: git

View File

@@ -1 +1,2 @@
auto_start_directory: "/home/{{users.client.username}}/.config/autostart/" auto_start_directory: /home/{{users.client.username}}/.config/autostart/
application_id: gnome-caffeine

View File

@@ -1 +1 @@
application_id: "gnome" application_id: gnome-extensions

View File

@@ -0,0 +1 @@
application_id: gnome-terminal

View File

@@ -0,0 +1 @@
application_id: gnucash

View File

@@ -0,0 +1 @@
application_id: jrnl

View File

@@ -0,0 +1 @@
application_id: keepassxc

View File

@@ -0,0 +1,3 @@
user_home_directory: /home/{{users.client.username}}/
cloud_directory: '{{user_home_directory}}Clouds/{{cloud_fqdn}}/{{users.client.username}}/'
application_id: nextcloud-client

View File

@@ -1,2 +0,0 @@
user_home_directory: "/home/{{users.client.username}}/" # Home directory of the user
cloud_directory: "{{user_home_directory}}Clouds/{{cloud_fqdn}}/{{users.client.username}}/" # Folder which contains the cloud data

View File

@@ -0,0 +1 @@
application_id: obs

View File

@@ -0,0 +1 @@
application_id: qbittorrent

View File

@@ -2,3 +2,4 @@ retroarch_packages:
- retroarch - retroarch
- retroarch-assets-xmb - retroarch-assets-xmb
- retroarch-assets-ozone - retroarch-assets-ozone
application_id: retroarch

View File

@@ -0,0 +1 @@
application_id: spotify

View File

@@ -0,0 +1 @@
application_id: ssh

View File

@@ -0,0 +1 @@
application_id: torbrowser

View File

@@ -0,0 +1 @@
application_id: virtual-box

View File

@@ -0,0 +1 @@
application_id: zoom

View File

@@ -20,7 +20,7 @@ To offer a centralized, extensible system for managing containerized application
- **Reset Logic:** Cleans previous Compose project files and data when `mode_reset` is enabled. - **Reset Logic:** Cleans previous Compose project files and data when `mode_reset` is enabled.
- **Handlers for Runtime Control:** Automatically builds, sets up, or restarts containers based on handlers. - **Handlers for Runtime Control:** Automatically builds, sets up, or restarts containers based on handlers.
- **Template-ready Service Files:** Predefined service base and health check templates. - **Template-ready Service Files:** Predefined service base and health check templates.
- **Integration Support:** Compatible with `srv-web-proxy-core` and other CyMaIS service roles. - **Integration Support:** Compatible with `srv-proxy-7-4-core` and other CyMaIS service roles.
## Administration Tips ## Administration Tips

View File

@@ -2,7 +2,7 @@
services: services:
{# Load Database #} {# Load Database #}
{% if applications[application_id].docker.services.database.enabled | default(false) | bool %} {% if applications[application_id].docker.services.database.enabled | default(false) | bool %}
{% include 'roles/svc-rdbms-central/templates/services/main.yml.j2' %} {% include 'roles/cmp-rdbms-orchestrator/templates/services/main.yml.j2' %}
{% endif %} {% endif %}
{# Load Redis #} {# Load Redis #}
{% if applications[application_id].docker.services.redis.enabled | default(false) | bool %} {% if applications[application_id].docker.services.redis.enabled | default(false) | bool %}

View File

@@ -0,0 +1 @@
application_id: epson-multiprinter

View File

@@ -0,0 +1 @@
application_id: intel

View File

@@ -0,0 +1 @@
application_id: lid-switch

View File

@@ -0,0 +1 @@
application_id: msi-keyboard-color

View File

@@ -0,0 +1 @@
application_id: non-free

View File

@@ -23,4 +23,4 @@ galaxy_info:
issue_tracker_url: "https://s.veen.world/cymaisissues" issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- srv-web-tls-renew - srv-web-6-6-tls-renew

View File

@@ -6,11 +6,11 @@ This role bootstraps **per-domain Nginx configuration**: it requests TLS certifi
## Overview ## Overview
A higher-level orchestration wrapper, *srv-web-proxy-domain* ties together several lower-level roles: A higher-level orchestration wrapper, *srv-proxy-6-6-domain* ties together several lower-level roles:
1. **`srv-web-injector-compose`** applies global tweaks and includes. 1. **`srv-web-7-7-inj-compose`** applies global tweaks and includes.
2. **`srv-web-tls-core`** obtains Lets Encrypt certificates. 2. **`srv-web-6-6-tls-core`** obtains Lets Encrypt certificates.
3. **Domain template deployment** copies a Jinja2 vHost from *srv-web-proxy-core*. 3. **Domain template deployment** copies a Jinja2 vHost from *srv-proxy-7-4-core*.
4. **`web-app-oauth2-proxy`** *(optional)* protects the site with OAuth2. 4. **`web-app-oauth2-proxy`** *(optional)* protects the site with OAuth2.
The result is a complete, reproducible domain rollout in a single playbook task. The result is a complete, reproducible domain rollout in a single playbook task.

View File

@@ -2,4 +2,4 @@
vhost_flavour: "basic" # valid: basic | ws_generic vhost_flavour: "basic" # valid: basic | ws_generic
# build the full template path from the flavour # build the full template path from the flavour
vhost_template_src: "roles/srv-web-proxy-core/templates/vhost/{{ vhost_flavour }}.conf.j2" vhost_template_src: "roles/srv-proxy-7-4-core/templates/vhost/{{ vhost_flavour }}.conf.j2"

View File

@@ -24,4 +24,4 @@ galaxy_info:
issue_tracker_url: https://s.veen.world/cymaisissues issue_tracker_url: https://s.veen.world/cymaisissues
documentation: https://s.veen.world/cymais documentation: https://s.veen.world/cymais
dependencies: dependencies:
- srv-web-proxy-core - srv-proxy-7-4-core

View File

@@ -1,6 +1,6 @@
- name: "include role for {{domain}} to receive certificates and do the modification routines" - name: "include role for {{domain}} to receive certificates and do the modification routines"
include_role: include_role:
name: srv-web-composer name: srv-web-7-6-composer
- name: "Copy nginx config to {{ configuration_destination }}" - name: "Copy nginx config to {{ configuration_destination }}"
template: template:

View File

@@ -21,7 +21,7 @@ This Ansible role simplifies the deployment of **Let's Encrypt certificates** in
### **1⃣ Main Tasks** ### **1⃣ Main Tasks**
1. **Add Deployment Script** 1. **Add Deployment Script**
- Copies `srv-web-proxy-tls-deploy.sh` to the administrator scripts directory. - Copies `srv-proxy-6-6-tls-deploy.sh` to the administrator scripts directory.
2. **Create Certificate Directory** 2. **Create Certificate Directory**
- Ensures `cert_mount_directory` exists with proper permissions. - Ensures `cert_mount_directory` exists with proper permissions.
@@ -34,14 +34,14 @@ This Ansible role simplifies the deployment of **Let's Encrypt certificates** in
### **2⃣ Handlers** ### **2⃣ Handlers**
- **Restart Nginx Service** - **Restart Nginx Service**
- Restarts `srv-web-proxy-tls-deploy` whenever a certificate update occurs. - Restarts `srv-proxy-6-6-tls-deploy` whenever a certificate update occurs.
--- ---
## **🔧 Deploying Certificates into Docker Containers** ## **🔧 Deploying Certificates into Docker Containers**
The role **automates copying certificates** into Docker Compose setups. The role **automates copying certificates** into Docker Compose setups.
### **1⃣ Deployment Script (`srv-web-proxy-tls-deploy.sh`)** ### **1⃣ Deployment Script (`srv-proxy-6-6-tls-deploy.sh`)**
This script: This script:
- **Copies certificates** to the correct container directory. - **Copies certificates** to the correct container directory.
- **Reloads Nginx** inside all running containers. - **Reloads Nginx** inside all running containers.
@@ -49,7 +49,7 @@ This script:
**Usage:** **Usage:**
```sh ```sh
sh srv-web-proxy-tls-deploy.sh primary_domain /path/to/docker/compose sh srv-proxy-6-6-tls-deploy.sh primary_domain /path/to/docker/compose
``` ```
--- ---

View File

@@ -0,0 +1,7 @@
---
- name: "restart srv-proxy-6-6-tls-deploy.cymais.service"
systemd:
name: srv-proxy-6-6-tls-deploy.{{application_id}}.cymais.service
state: restarted
enabled: yes
daemon_reload: yes

View File

@@ -15,7 +15,7 @@ galaxy_info:
- systemd - systemd
repository: "https://github.com/kevinveenbirkenbach/cymais" repository: "https://github.com/kevinveenbirkenbach/cymais"
issue_tracker_url: "https://github.com/kevinveenbirkenbach/cymais/issues" issue_tracker_url: "https://github.com/kevinveenbirkenbach/cymais/issues"
documentation: "https://github.com/kevinveenbirkenbach/cymais/tree/main/roles/srv-web-proxy-tls-deploy" documentation: "https://github.com/kevinveenbirkenbach/cymais/tree/main/roles/srv-proxy-6-6-tls-deploy"
min_ansible_version: "2.9" min_ansible_version: "2.9"
platforms: platforms:
- name: Any - name: Any

View File

@@ -1,9 +1,9 @@
- name: add srv-web-proxy-tls-deploy.sh - name: add srv-proxy-6-6-tls-deploy.sh
copy: copy:
src: "srv-web-proxy-tls-deploy.sh" src: "srv-proxy-6-6-tls-deploy.sh"
dest: "{{nginx_docker_cert_deploy_script}}" dest: "{{nginx_docker_cert_deploy_script}}"
when: run_once_nginx_docker_cert_deploy is not defined when: run_once_nginx_docker_cert_deploy is not defined
notify: restart srv-web-proxy-tls-deploy.cymais.service notify: restart srv-proxy-6-6-tls-deploy.cymais.service
- name: run the nginx_docker_cert_deploy tasks once - name: run the nginx_docker_cert_deploy tasks once
set_fact: set_fact:
@@ -15,18 +15,18 @@
path: "{{cert_mount_directory}}" path: "{{cert_mount_directory}}"
state: directory state: directory
mode: 0755 mode: 0755
notify: restart srv-web-proxy-tls-deploy.cymais.service notify: restart srv-proxy-6-6-tls-deploy.cymais.service
- name: configure srv-web-proxy-tls-deploy.cymais.service - name: configure srv-proxy-6-6-tls-deploy.cymais.service
template: template:
src: "srv-web-proxy-tls-deploy.service.j2" src: "srv-proxy-6-6-tls-deploy.service.j2"
dest: "/etc/systemd/system/srv-web-proxy-tls-deploy.{{application_id}}.cymais.service" dest: "/etc/systemd/system/srv-proxy-6-6-tls-deploy.{{application_id}}.cymais.service"
notify: restart srv-web-proxy-tls-deploy.cymais.service notify: restart srv-proxy-6-6-tls-deploy.cymais.service
- name: "include role for gen-timer for {{service_name}}" - name: "include role for gen-timer for {{service_name}}"
include_role: include_role:
name: gen-timer name: gen-timer
vars: vars:
on_calendar: "{{on_calendar_deploy_certificates}}" on_calendar: "{{on_calendar_deploy_certificates}}"
service_name: "srv-web-proxy-tls-deploy.{{application_id}}" service_name: "srv-proxy-6-6-tls-deploy.{{application_id}}"
persistent: "true" persistent: "true"

View File

@@ -4,4 +4,4 @@ OnFailure=alert-compose.cymais@%n.service
[Service] [Service]
Type=oneshot Type=oneshot
ExecStart=/usr/bin/bash {{path_administrator_scripts}}/srv-web-proxy-tls-deploy.sh {{ssl_cert_folder}} {{docker_compose.directories.instance}} ExecStart=/usr/bin/bash {{path_administrator_scripts}}/srv-proxy-6-6-tls-deploy.sh {{ssl_cert_folder}} {{docker_compose.directories.instance}}

View File

@@ -1 +1 @@
nginx_docker_cert_deploy_script: "{{path_administrator_scripts}}srv-web-proxy-tls-deploy.sh" nginx_docker_cert_deploy_script: "{{path_administrator_scripts}}srv-proxy-6-6-tls-deploy.sh"

View File

@@ -16,7 +16,7 @@ The goal of this role is to deliver a **hassle-free, production-ready reverse pr
## Features ## Features
- **Automatic TLS & HSTS** — integrates with the *srv-web-https* role for certificate management. - **Automatic TLS & HSTS** — integrates with the *srv-web-7-6-https* role for certificate management.
- **Flexible vHost templates***basic* and *ws_generic* flavours cover standard HTTP and WebSocket applications. - **Flexible vHost templates***basic* and *ws_generic* flavours cover standard HTTP and WebSocket applications.
- **Security headers** — sensible defaults plus optional X-Frame-Options / CSP based on application settings. - **Security headers** — sensible defaults plus optional X-Frame-Options / CSP based on application settings.
- **WebSocket & HTTP/2 aware** — upgrades, keep-alive tuning, and gzip already configured. - **WebSocket & HTTP/2 aware** — upgrades, keep-alive tuning, and gzip already configured.

View File

@@ -24,5 +24,5 @@ galaxy_info:
issue_tracker_url: https://s.veen.world/cymaisissues issue_tracker_url: https://s.veen.world/cymaisissues
documentation: https://s.veen.world/cymais documentation: https://s.veen.world/cymais
dependencies: dependencies:
- srv-web-https - srv-web-7-6-https
- srv-web-core - srv-web-7-4-core

View File

@@ -14,7 +14,7 @@ location {{location | default("/")}}
proxy_set_header X-Forwarded-Port 443; proxy_set_header X-Forwarded-Port 443;
proxy_set_header Accept-Encoding ""; proxy_set_header Accept-Encoding "";
{% include 'roles/srv-web-proxy-core/templates/headers/content_security_policy.conf.j2' %} {% include 'roles/srv-proxy-7-4-core/templates/headers/content_security_policy.conf.j2' %}
# WebSocket specific header # WebSocket specific header
proxy_http_version 1.1; proxy_http_version 1.1;

View File

@@ -6,7 +6,7 @@ server
{% include 'roles/web-app-oauth2-proxy/templates/endpoint.conf.j2'%} {% include 'roles/web-app-oauth2-proxy/templates/endpoint.conf.j2'%}
{% endif %} {% endif %}
{% include 'roles/srv-web-injector-compose/templates/global.includes.conf.j2'%} {% include 'roles/srv-web-7-7-inj-compose/templates/global.includes.conf.j2'%}
{% if proxy_extra_configuration is defined %} {% if proxy_extra_configuration is defined %}
{# Additional Domain Specific Configuration #} {# Additional Domain Specific Configuration #}
@@ -22,38 +22,38 @@ server
{# 1. Expose everything by default, then protect blacklisted paths #} {# 1. Expose everything by default, then protect blacklisted paths #}
{% set oauth2_proxy_enabled = false %} {% set oauth2_proxy_enabled = false %}
{% set location = "/" %} {% set location = "/" %}
{% include 'roles/srv-web-proxy-core/templates/location/proxy_basic.conf.j2' %} {% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
{% for loc in acl.blacklist %} {% for loc in acl.blacklist %}
{% set oauth2_proxy_enabled = true %} {% set oauth2_proxy_enabled = true %}
{% set location = loc %} {% set location = loc %}
{% include 'roles/srv-web-proxy-core/templates/location/proxy_basic.conf.j2' %} {% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
{% endfor %} {% endfor %}
{% elif acl.whitelist is defined %} {% elif acl.whitelist is defined %}
{# 2. Protect everything by default, then expose whitelisted paths #} {# 2. Protect everything by default, then expose whitelisted paths #}
{% set oauth2_proxy_enabled = true %} {% set oauth2_proxy_enabled = true %}
{% set location = "/" %} {% set location = "/" %}
{% include 'roles/srv-web-proxy-core/templates/location/proxy_basic.conf.j2' %} {% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
{% for loc in acl.whitelist %} {% for loc in acl.whitelist %}
{% set oauth2_proxy_enabled = false %} {% set oauth2_proxy_enabled = false %}
{% set location = loc %} {% set location = loc %}
{% include 'roles/srv-web-proxy-core/templates/location/proxy_basic.conf.j2' %} {% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
{% endfor %} {% endfor %}
{% else %} {% else %}
{# 3. OAuth2 enabled but no (or empty) ACL — protect all #} {# 3. OAuth2 enabled but no (or empty) ACL — protect all #}
{% set oauth2_proxy_enabled = true %} {% set oauth2_proxy_enabled = true %}
{% set location = "/" %} {% set location = "/" %}
{% include 'roles/srv-web-proxy-core/templates/location/proxy_basic.conf.j2' %} {% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
{% endif %} {% endif %}
{% else %} {% else %}
{# 4. OAuth2 completely disabled — expose all #} {# 4. OAuth2 completely disabled — expose all #}
{% set oauth2_proxy_enabled = false %} {% set oauth2_proxy_enabled = false %}
{% set location = "/" %} {% set location = "/" %}
{% include 'roles/srv-web-proxy-core/templates/location/proxy_basic.conf.j2' %} {% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
{% endif %} {% endif %}
} }

View File

@@ -7,7 +7,7 @@ server {
server_name {{ domain }}; server_name {{ domain }};
{% include 'roles/net-letsencrypt/templates/ssl_header.j2' %} {% include 'roles/net-letsencrypt/templates/ssl_header.j2' %}
{% include 'roles/srv-web-injector-compose/templates/global.includes.conf.j2' %} {% include 'roles/srv-web-7-7-inj-compose/templates/global.includes.conf.j2' %}
client_max_body_size {{ client_max_body_size | default('100m') }}; client_max_body_size {{ client_max_body_size | default('100m') }};
keepalive_timeout 70; keepalive_timeout 70;
@@ -24,7 +24,7 @@ server {
add_header Strict-Transport-Security "max-age=31536000"; add_header Strict-Transport-Security "max-age=31536000";
{% include 'roles/srv-web-proxy-core/templates/location/proxy_basic.conf.j2' %} {% include 'roles/srv-proxy-7-4-core/templates/location/proxy_basic.conf.j2' %}
{% if ws_path is defined %} {% if ws_path is defined %}
location {{ ws_path }} { location {{ ws_path }} {

View File

@@ -28,4 +28,4 @@ galaxy_info:
issue_tracker_url: "https://s.veen.world/cymaisissues" issue_tracker_url: "https://s.veen.world/cymaisissues"
documentation: "https://s.veen.world/cymais" documentation: "https://s.veen.world/cymais"
dependencies: dependencies:
- srv-web-https - srv-web-7-6-https

View File

@@ -1,4 +1,4 @@
- name: "Include flavor" - name: "Include flavor '{{ certbot_flavor }}' for '{{ domain }}'"
include_tasks: "{{ role_path }}/tasks/flavors/{{ certbot_flavor }}.yml" include_tasks: "{{ role_path }}/tasks/flavors/{{ certbot_flavor }}.yml"
#- name: "Cleanup dedicated cert for {{ domain }}" #- name: "Cleanup dedicated cert for {{ domain }}"
@@ -17,7 +17,7 @@
# failed_when: certbot_result.rc != 0 and ("No certificate found with name" not in certbot_result.stderr) # failed_when: certbot_result.rc != 0 and ("No certificate found with name" not in certbot_result.stderr)
# changed_when: certbot_result.rc == 0 and ("No certificate found with name" not in certbot_result.stderr) # changed_when: certbot_result.rc == 0 and ("No certificate found with name" not in certbot_result.stderr)
- name: Find SSL cert folder for domain - name: "Find SSL cert folder for '{{ domain }}'"
cert_folder_find: cert_folder_find:
domain: "{{ domain }}" domain: "{{ domain }}"
cert_base_path: "{{ certbot_cert_path }}" cert_base_path: "{{ certbot_cert_path }}"
@@ -26,12 +26,12 @@
delegate_to: "{{ inventory_hostname }}" delegate_to: "{{ inventory_hostname }}"
changed_when: false changed_when: false
- name: Set fact - name: "Set ssl_cert_folder fact to '{{ cert_folder_result.folder }}'"
set_fact: set_fact:
ssl_cert_folder: "{{ cert_folder_result.folder }}" ssl_cert_folder: "{{ cert_folder_result.folder }}"
changed_when: false changed_when: false
- name: Ensure ssl_cert_folder is set - name: "Ensure ssl_cert_folder is set for domain {{ domain }}"
fail: fail:
msg: "No certificate folder found for domain {{ domain }}" msg: "No certificate folder found for domain {{ domain }}"
when: ssl_cert_folder is undefined or ssl_cert_folder is none when: ssl_cert_folder is undefined or ssl_cert_folder is none

Some files were not shown because too many files have changed in this diff Show More