Renamed general and mode constants and implemented a check to verify that constants are just defined ones over the whole repository

This commit is contained in:
Kevin Veen-Birkenbach 2025-08-13 19:10:44 +02:00
parent 004507e233
commit db0e030900
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E
171 changed files with 474 additions and 345 deletions

View File

@ -189,7 +189,7 @@ def parse_args():
def main(): def main():
args = parse_args() args = parse_args()
primary_domain = '{{ primary_domain }}' primary_domain = '{{ PRIMARY_DOMAIN }}'
become_pwd = '{{ lookup("password", "/dev/null length=42 chars=ascii_letters,digits") }}' become_pwd = '{{ lookup("password", "/dev/null length=42 chars=ascii_letters,digits") }}'
try: try:

View File

@ -191,13 +191,13 @@ def main():
validate_application_ids(args.inventory, args.id) validate_application_ids(args.inventory, args.id)
modes = { modes = {
"mode_reset": args.reset, "MODE_RESET": args.reset,
"mode_test": args.test, "MODE_TEST": args.test,
"mode_update": args.update, "MODE_UPDATE": args.update,
"mode_backup": args.backup, "MODE_BACKUP": args.backup,
"mode_cleanup": args.cleanup, "MODE_CLEANUP": args.cleanup,
"mode_logs": args.logs, "MODE_LOGS": args.logs,
"enable_debug": args.debug, "MODE_DEBUG": args.debug,
"host_type": args.host_type "host_type": args.host_type
} }

View File

@ -4,7 +4,7 @@ class FilterModule(object):
def filters(self): def filters(self):
return {'alias_domains_map': self.alias_domains_map} return {'alias_domains_map': self.alias_domains_map}
def alias_domains_map(self, apps, primary_domain): def alias_domains_map(self, apps, PRIMARY_DOMAIN):
""" """
Build a map of application IDs to their alias domains. Build a map of application IDs to their alias domains.
@ -42,7 +42,7 @@ class FilterModule(object):
domains_cfg = cfg.get('server',{}).get('domains',{}) domains_cfg = cfg.get('server',{}).get('domains',{})
entry = domains_cfg.get('canonical') entry = domains_cfg.get('canonical')
if entry is None: if entry is None:
canonical_map[app_id] = [default_domain(app_id, primary_domain)] canonical_map[app_id] = [default_domain(app_id, PRIMARY_DOMAIN)]
elif isinstance(entry, dict): elif isinstance(entry, dict):
canonical_map[app_id] = list(entry.values()) canonical_map[app_id] = list(entry.values())
elif isinstance(entry, list): elif isinstance(entry, list):
@ -69,7 +69,7 @@ class FilterModule(object):
# otherwise, compute aliases # otherwise, compute aliases
aliases = parse_entry(domains_cfg, 'aliases', app_id) or [] aliases = parse_entry(domains_cfg, 'aliases', app_id) or []
default = default_domain(app_id, primary_domain) default = default_domain(app_id, PRIMARY_DOMAIN)
has_aliases = 'aliases' in domains_cfg has_aliases = 'aliases' in domains_cfg
has_canon = 'canonical' in domains_cfg has_canon = 'canonical' in domains_cfg

View File

@ -9,7 +9,7 @@ class FilterModule(object):
def filters(self): def filters(self):
return {'canonical_domains_map': self.canonical_domains_map} return {'canonical_domains_map': self.canonical_domains_map}
def canonical_domains_map(self, apps, primary_domain): def canonical_domains_map(self, apps, PRIMARY_DOMAIN):
""" """
Maps applications to their canonical domains, checking for conflicts Maps applications to their canonical domains, checking for conflicts
and ensuring all domains are valid and unique across applications. and ensuring all domains are valid and unique across applications.
@ -30,7 +30,7 @@ class FilterModule(object):
domains_cfg = cfg.get('server',{}).get('domains',{}) domains_cfg = cfg.get('server',{}).get('domains',{})
if not domains_cfg or 'canonical' not in domains_cfg: if not domains_cfg or 'canonical' not in domains_cfg:
self._add_default_domain(app_id, primary_domain, seen_domains, result) self._add_default_domain(app_id, PRIMARY_DOMAIN, seen_domains, result)
continue continue
canonical_domains = domains_cfg['canonical'] canonical_domains = domains_cfg['canonical']
@ -38,13 +38,13 @@ class FilterModule(object):
return result return result
def _add_default_domain(self, app_id, primary_domain, seen_domains, result): def _add_default_domain(self, app_id, PRIMARY_DOMAIN, seen_domains, result):
""" """
Add the default domain for an application if no canonical domains are defined. Add the default domain for an application if no canonical domains are defined.
Ensures the domain is unique across applications. Ensures the domain is unique across applications.
""" """
entity_name = get_entity_name(app_id) entity_name = get_entity_name(app_id)
default_domain = f"{entity_name}.{primary_domain}" default_domain = f"{entity_name}.{PRIMARY_DOMAIN}"
if default_domain in seen_domains: if default_domain in seen_domains:
raise AnsibleFilterError( raise AnsibleFilterError(
f"Domain '{default_domain}' is already configured for " f"Domain '{default_domain}' is already configured for "

View File

@ -7,7 +7,7 @@ class FilterModule(object):
def filters(self): def filters(self):
return {'domain_mappings': self.domain_mappings} return {'domain_mappings': self.domain_mappings}
def domain_mappings(self, apps, primary_domain): def domain_mappings(self, apps, PRIMARY_DOMAIN):
""" """
Build a flat list of redirect mappings for all apps: Build a flat list of redirect mappings for all apps:
- source: each alias domain - source: each alias domain
@ -43,7 +43,7 @@ class FilterModule(object):
domains_cfg = cfg.get('server',{}).get('domains',{}) domains_cfg = cfg.get('server',{}).get('domains',{})
entry = domains_cfg.get('canonical') entry = domains_cfg.get('canonical')
if entry is None: if entry is None:
canonical_map[app_id] = [default_domain(app_id, primary_domain)] canonical_map[app_id] = [default_domain(app_id, PRIMARY_DOMAIN)]
elif isinstance(entry, dict): elif isinstance(entry, dict):
canonical_map[app_id] = list(entry.values()) canonical_map[app_id] = list(entry.values())
elif isinstance(entry, list): elif isinstance(entry, list):
@ -61,11 +61,11 @@ class FilterModule(object):
alias_map[app_id] = [] alias_map[app_id] = []
continue continue
if isinstance(domains_cfg, dict) and not domains_cfg: if isinstance(domains_cfg, dict) and not domains_cfg:
alias_map[app_id] = [default_domain(app_id, primary_domain)] alias_map[app_id] = [default_domain(app_id, PRIMARY_DOMAIN)]
continue continue
aliases = parse_entry(domains_cfg, 'aliases', app_id) or [] aliases = parse_entry(domains_cfg, 'aliases', app_id) or []
default = default_domain(app_id, primary_domain) default = default_domain(app_id, PRIMARY_DOMAIN)
has_aliases = 'aliases' in domains_cfg has_aliases = 'aliases' in domains_cfg
has_canonical = 'canonical' in domains_cfg has_canonical = 'canonical' in domains_cfg
@ -84,7 +84,7 @@ class FilterModule(object):
mappings = [] mappings = []
for app_id, sources in alias_map.items(): for app_id, sources in alias_map.items():
canon_list = canonical_map.get(app_id, []) canon_list = canonical_map.get(app_id, [])
target = canon_list[0] if canon_list else default_domain(app_id, primary_domain) target = canon_list[0] if canon_list else default_domain(app_id, PRIMARY_DOMAIN)
for src in sources: for src in sources:
if src == target: if src == target:
# skip self-redirects # skip self-redirects

View File

@ -19,7 +19,7 @@ class FilterModule(object):
Usage in Jinja: Usage in Jinja:
{{ redirect_list {{ redirect_list
| add_redirect_if_group('lam', | add_redirect_if_group('lam',
'ldap.' ~ primary_domain, 'ldap.' ~ PRIMARY_DOMAIN,
domains | get_domain('web-app-lam'), domains | get_domain('web-app-lam'),
group_names) }} group_names) }}
""" """

View File

@ -1,4 +1,4 @@
INFINITO_ENVIRONMENT: "production" # Possible values: production, development ENVIRONMENT: "production" # Possible values: production, development
# If true, sensitive credentials will be masked or hidden from all Ansible task logs # If true, sensitive credentials will be masked or hidden from all Ansible task logs
# Recommendet to set to true # Recommendet to set to true
@ -19,49 +19,46 @@ HOST_THOUSAND_SEPARATOR: "."
HOST_DECIMAL_MARK: "," HOST_DECIMAL_MARK: ","
# Deployment mode # Deployment mode
deployment_mode: "single" # Use single, if you deploy on one server. Use cluster if you setup in cluster mode. DEPLOYMENT_MODE: "single" # Use single, if you deploy on one server. Use cluster if you setup in cluster mode.
# Web
WEB_PROTOCOL: "https" # Web protocol type. Use https or http. If you run local you need to change it to http WEB_PROTOCOL: "https" # Web protocol type. Use https or http. If you run local you need to change it to http
WEB_PORT: "{{ 443 if WEB_PROTOCOL == 'https' else 80 }}" # Default port web applications will listen to WEB_PORT: "{{ 443 if WEB_PROTOCOL == 'https' else 80 }}" # Default port web applications will listen to
## Domain # Domain
primary_domain_tld: "localhost" # Top Level Domain of the server PRIMARY_DOMAIN: "localhost" # Primary Domain of the server
primary_domain_sld: "infinito" # Second Level Domain of the server PRIMARY_DOMAIN_tld: "{{ (PRIMARY_DOMAIN == 'localhost') | ternary('localhost', PRIMARY_DOMAIN.split('.')[-1]) }}" # Top Level Domain of the server
primary_domain: "{{primary_domain_sld}}.{{primary_domain_tld}}" # Primary Domain of the server PRIMARY_DOMAIN_SLD: "{{ (PRIMARY_DOMAIN == 'localhost') | ternary('localhost', PRIMARY_DOMAIN.split('.')[-2]) }}" # Second Level Domain of the server
# Server Tact Variables # Server Tact Variables
## Ours in which the server is "awake" (100% working). Rest of the time is reserved for maintanance ## Ours in which the server is "awake" (100% working). Rest of the time is reserved for maintanance
hours_server_awake: "0..23" HOURS_SERVER_AWAKE: "0..23"
## Random delay for systemd timers to avoid peak loads. ## Random delay for systemd timers to avoid peak loads.
randomized_delay_sec: "5min" RANDOMIZED_DELAY_SEC: "5min"
# Runtime Variables for Process Control # Runtime Variables for Process Control
activate_all_timers: false # Activates all timers, independend if the handlers had been triggered ACTIVATE_ALL_TIMERS: false # Activates all timers, independend if the handlers had been triggered
# This enables debugging in ansible and in the apps DNS_PROVIDER: cloudflare # The DNS Provider\Registrar for the domain
# You SHOULD NOT enable this on production servers
enable_debug: false
dns_provider: cloudflare # The DNS Provider\Registrar for the domain
# Which ACME method to use: webroot, cloudflare, or hetzner # Which ACME method to use: webroot, cloudflare, or hetzner
certbot_acme_challenge_method: "cloudflare" CERTBOT_ACME_CHALLENGE_METHOD: "cloudflare"
certbot_credentials_dir: /etc/certbot CERTBOT_CREDENTIALS_DIR: /etc/certbot
certbot_credentials_file: "{{ certbot_credentials_dir }}/{{ certbot_acme_challenge_method }}.ini" CERTBOT_CREDENTIALS_FILE: "{{ CERTBOT_CREDENTIALS_DIR }}/{{ CERTBOT_ACME_CHALLENGE_METHOD }}.ini"
certbot_dns_api_token: "" # Define in inventory file: More information here: group_vars/all/docs/CLOUDFLARE_API_TOKEN.md CERTBOT_DNS_API_TOKEN: "" # Define in inventory file: More information here: group_vars/all/docs/CLOUDFLARE_API_TOKEN.md
certbot_dns_propagation_wait_seconds: 300 # How long should the script wait for DNS propagation before continuing CERTBOT_DNS_PROPAGATION_WAIT_SECONDS: 300 # How long should the script wait for DNS propagation before continuing
certbot_flavor: san # Possible options: san (recommended, with a dns flavor like cloudflare, or hetzner), wildcard(doesn't function with www redirect), dedicated CERTBOT_FLAVOR: san # Possible options: san (recommended, with a dns flavor like cloudflare, or hetzner), wildcard(doesn't function with www redirect), dedicated
# Path where Certbot stores challenge webroot files # Path where Certbot stores challenge webroot files
letsencrypt_webroot_path: "/var/lib/letsencrypt/" LETSENCRYPT_WEBROOT_PATH: "/var/lib/letsencrypt/"
# Base directory containing Certbot configuration, account data, and archives # Base directory containing Certbot configuration, account data, and archives
letsencrypt_base_path: "/etc/letsencrypt/" LETSENCRYPT_BASE_PATH: "/etc/letsencrypt/"
# Symlink directory for the current active certificate and private key # Symlink directory for the current active certificate and private key
letsencrypt_live_path: "{{ letsencrypt_base_path }}live/" LETSENCRYPT_LIVE_PATH: "{{ LETSENCRYPT_BASE_PATH }}live/"
## Docker Role Specific Parameters ## Docker Role Specific Parameters
DOCKER_RESTART_POLICY: "unless-stopped" DOCKER_RESTART_POLICY: "unless-stopped"

View File

@ -1,8 +1,9 @@
# Mode # Mode
# The following modes can be combined with each other # The following modes can be combined with each other
mode_reset: false # Cleans up all Infinito.Nexus files. It's necessary to run to whole playbook and not particial roles when using this function. MODE_RESET: false # Cleans up all Infinito.Nexus files. It's necessary to run to whole playbook and not particial roles when using this function.
mode_test: false # Executes test routines instead of productive routines MODE_TEST: false # Executes test routines instead of productive routines
mode_update: true # Executes updates MODE_UPDATE: true # Executes updates
mode_backup: true # Activates the backup before the update procedure MODE_BACKUP: true # Activates the backup before the update procedure
mode_cleanup: true # Cleanup unused files and configurations MODE_CLEANUP: true # Cleanup unused files and configurations
MODE_DEBUG: false # This enables debugging in ansible and in the apps, You SHOULD NOT enable this on production servers

View File

@ -1,7 +1,7 @@
# Email Configuration # Email Configuration
default_system_email: default_system_email:
domain: "{{primary_domain}}" domain: "{{PRIMARY_DOMAIN}}"
host: "mail.{{primary_domain}}" host: "mail.{{PRIMARY_DOMAIN}}"
port: 465 port: 465
tls: true # true for TLS and false for SSL tls: true # true for TLS and false for SSL
start_tls: false start_tls: false

View File

@ -3,10 +3,10 @@
on_calendar_health_btrfs: "*-*-* 00:00:00" # Check once per day the btrfs for errors on_calendar_health_btrfs: "*-*-* 00:00:00" # Check once per day the btrfs for errors
on_calendar_health_journalctl: "*-*-* 00:00:00" # Check once per day the journalctl for errors on_calendar_health_journalctl: "*-*-* 00:00:00" # Check once per day the journalctl for errors
on_calendar_health_disc_space: "*-*-* 06,12,18,00:00:00" # Check four times per day if there is sufficient disc space on_calendar_health_disc_space: "*-*-* 06,12,18,00:00:00" # Check four times per day if there is sufficient disc space
on_calendar_health_docker_container: "*-*-* {{ hours_server_awake }}:00:00" # Check once per hour if the docker containers are healthy on_calendar_health_docker_container: "*-*-* {{ HOURS_SERVER_AWAKE }}:00:00" # Check once per hour if the docker containers are healthy
on_calendar_health_docker_volumes: "*-*-* {{ hours_server_awake }}:15:00" # Check once per hour if the docker volumes are healthy on_calendar_health_docker_volumes: "*-*-* {{ HOURS_SERVER_AWAKE }}:15:00" # Check once per hour if the docker volumes are healthy
on_calendar_health_csp_crawler: "*-*-* {{ hours_server_awake }}:30:00" # Check once per hour if all CSP are fullfilled available on_calendar_health_csp_crawler: "*-*-* {{ HOURS_SERVER_AWAKE }}:30:00" # Check once per hour if all CSP are fullfilled available
on_calendar_health_nginx: "*-*-* {{ hours_server_awake }}:45:00" # Check once per hour if all webservices are available on_calendar_health_nginx: "*-*-* {{ HOURS_SERVER_AWAKE }}:45:00" # Check once per hour if all webservices are available
on_calendar_health_msmtp: "*-*-* 00:00:00" # Check once per day SMTP Server on_calendar_health_msmtp: "*-*-* 00:00:00" # Check once per day SMTP Server
## Schedule for Cleanup Tasks ## Schedule for Cleanup Tasks
@ -19,7 +19,7 @@ on_calendar_backup_docker_to_local: "*-*-* 03:30:00"
on_calendar_backup_remote_to_local: "*-*-* 21:30:00" on_calendar_backup_remote_to_local: "*-*-* 21:30:00"
## Schedule for Maintenance Tasks ## Schedule for Maintenance Tasks
on_calendar_heal_docker: "*-*-* {{ hours_server_awake }}:30:00" # Heal unhealthy docker instances once per hour on_calendar_heal_docker: "*-*-* {{ HOURS_SERVER_AWAKE }}:30:00" # Heal unhealthy docker instances once per hour
on_calendar_renew_lets_encrypt_certificates: "*-*-* 12,00:30:00" # Renew Mailu certificates twice per day on_calendar_renew_lets_encrypt_certificates: "*-*-* 12,00:30:00" # Renew Mailu certificates twice per day
on_calendar_deploy_certificates: "*-*-* 13,01:30:00" # Deploy letsencrypt certificates twice per day to docker containers on_calendar_deploy_certificates: "*-*-* 13,01:30:00" # Deploy letsencrypt certificates twice per day to docker containers
on_calendar_msi_keyboard_color: "*-*-* *:*:00" # Change the keyboard color every minute on_calendar_msi_keyboard_color: "*-*-* *:*:00" # Change the keyboard color every minute

View File

@ -8,7 +8,7 @@
# @see https://en.wikipedia.org/wiki/OpenID_Connect # @see https://en.wikipedia.org/wiki/OpenID_Connect
## Helper Variables: ## Helper Variables:
_oidc_client_realm: "{{ oidc.client.realm if oidc.client is defined and oidc.client.realm is defined else primary_domain }}" _oidc_client_realm: "{{ oidc.client.realm if oidc.client is defined and oidc.client.realm is defined else PRIMARY_DOMAIN }}"
_oidc_url: "{{ _oidc_url: "{{
(oidc.url (oidc.url
if (oidc is defined and oidc.url is defined) if (oidc is defined and oidc.url is defined)
@ -16,7 +16,7 @@ _oidc_url: "{{
) )
}}" }}"
_oidc_client_issuer_url: "{{ _oidc_url }}/realms/{{_oidc_client_realm}}" _oidc_client_issuer_url: "{{ _oidc_url }}/realms/{{_oidc_client_realm}}"
_oidc_client_id: "{{ oidc.client.id if oidc.client is defined and oidc.client.id is defined else primary_domain }}" _oidc_client_id: "{{ oidc.client.id if oidc.client is defined and oidc.client.id is defined else PRIMARY_DOMAIN }}"
defaults_oidc: defaults_oidc:
url: "{{ _oidc_url }}" url: "{{ _oidc_url }}"
@ -33,7 +33,7 @@ defaults_oidc:
change_credentials: "{{_oidc_client_issuer_url}}account/account-security/signing-in" # URL for managing or changing user credentials change_credentials: "{{_oidc_client_issuer_url}}account/account-security/signing-in" # URL for managing or changing user credentials
certs: "{{_oidc_client_issuer_url}}/protocol/openid-connect/certs" # JSON Web Key Set (JWKS) certs: "{{_oidc_client_issuer_url}}/protocol/openid-connect/certs" # JSON Web Key Set (JWKS)
reset_credentials: "{{_oidc_client_issuer_url}}/login-actions/reset-credentials?client_id={{ _oidc_client_id }}" # Password reset url reset_credentials: "{{_oidc_client_issuer_url}}/login-actions/reset-credentials?client_id={{ _oidc_client_id }}" # Password reset url
button_text: "SSO Login ({{primary_domain | upper}})" # Default button text button_text: "SSO Login ({{PRIMARY_DOMAIN | upper}})" # Default button text
attributes: attributes:
# Attribut to identify the user # Attribut to identify the user
username: "preferred_username" username: "preferred_username"

View File

@ -5,12 +5,12 @@
# Helper Variables: # Helper Variables:
# Keep in mind to mapp this variables if there is ever the possibility for the user to define them in the inventory # Keep in mind to mapp this variables if there is ever the possibility for the user to define them in the inventory
_ldap_dn_base: "dc={{primary_domain_sld}},dc={{primary_domain_tld}}" _ldap_dn_base: "dc={{PRIMARY_DOMAIN_SLD}},dc={{PRIMARY_DOMAIN_tld}}"
_ldap_docker_network_enabled: "{{ applications | get_app_conf('svc-db-openldap', 'network.docker') }}" _ldap_docker_network_enabled: "{{ applications | get_app_conf('svc-db-openldap', 'network.docker') }}"
_ldap_protocol: "{{ 'ldap' if _ldap_docker_network_enabled else 'ldaps' }}" _ldap_protocol: "{{ 'ldap' if _ldap_docker_network_enabled else 'ldaps' }}"
_ldap_server_port: "{{ ports.localhost[_ldap_protocol]['svc-db-openldap'] }}" _ldap_server_port: "{{ ports.localhost[_ldap_protocol]['svc-db-openldap'] }}"
_ldap_name: "{{ applications | get_app_conf('svc-db-openldap', 'docker.services.openldap.name') }}" _ldap_name: "{{ applications | get_app_conf('svc-db-openldap', 'docker.services.openldap.name') }}"
_ldap_domain: "{{ primary_domain }}" # LDAP is jsut listening to a port not to a dedicated domain, so primary domain should be sufficient _ldap_domain: "{{ PRIMARY_DOMAIN }}" # LDAP is jsut listening to a port not to a dedicated domain, so primary domain should be sufficient
_ldap_user_id: "uid" _ldap_user_id: "uid"
_ldap_filters_users_all: "(|(objectclass=inetOrgPerson))" _ldap_filters_users_all: "(|(objectclass=inetOrgPerson))"

View File

@ -19,7 +19,7 @@ defaults_service_provider:
web-app-bluesky: >- web-app-bluesky: >-
{{ ('@' ~ users.contact.username ~ '.' ~ domains['web-app-bluesky'].api) {{ ('@' ~ users.contact.username ~ '.' ~ domains['web-app-bluesky'].api)
if 'web-app-bluesky' in group_names else '' }} if 'web-app-bluesky' in group_names else '' }}
email: "{{ users.contact.username ~ '@' ~ primary_domain if 'web-app-mailu' in group_names else '' }}" email: "{{ users.contact.username ~ '@' ~ PRIMARY_DOMAIN if 'web-app-mailu' in group_names else '' }}"
mastodon: "{{ '@' ~ users.contact.username ~ '@' ~ domains | get_domain('web-app-mastodon') if 'web-app-mastodon' in group_names else '' }}" mastodon: "{{ '@' ~ users.contact.username ~ '@' ~ domains | get_domain('web-app-mastodon') if 'web-app-mastodon' in group_names else '' }}"
matrix: "{{ '@' ~ users.contact.username ~ ':' ~ domains['web-app-matrix'].synapse if 'web-app-matrix' in group_names else '' }}" matrix: "{{ '@' ~ users.contact.username ~ ':' ~ domains['web-app-matrix'].synapse if 'web-app-matrix' in group_names else '' }}"
peertube: "{{ '@' ~ users.contact.username ~ '@' ~ domains | get_domain('web-app-peertube') if 'web-app-peertube' in group_names else '' }}" peertube: "{{ '@' ~ users.contact.username ~ '@' ~ domains | get_domain('web-app-peertube') if 'web-app-peertube' in group_names else '' }}"

View File

@ -1,10 +1,10 @@
# Cloudflare API Token for Ansible (`certbot_dns_api_token`) # Cloudflare API Token for Ansible (`CERTBOT_DNS_API_TOKEN`)
This document explains how to generate and use a Cloudflare API Token for DNS automation and certificate operations in Ansible (e.g., with Certbot). This document explains how to generate and use a Cloudflare API Token for DNS automation and certificate operations in Ansible (e.g., with Certbot).
## Purpose ## Purpose
The `certbot_dns_api_token` variable must contain a valid Cloudflare API Token. The `CERTBOT_DNS_API_TOKEN` variable must contain a valid Cloudflare API Token.
This token is used for all DNS operations and ACME (SSL/TLS certificate) challenges that require access to your Cloudflare-managed domains. This token is used for all DNS operations and ACME (SSL/TLS certificate) challenges that require access to your Cloudflare-managed domains.
**Never commit your API token to a public repository. Always keep it secure!** **Never commit your API token to a public repository. Always keep it secure!**
@ -58,4 +58,4 @@ Add the following permissions:
Set the token in your Ansible inventory or secrets file: Set the token in your Ansible inventory or secrets file:
```yaml ```yaml
certbot_dns_api_token: "cf_your_generated_token_here" CERTBOT_DNS_API_TOKEN: "cf_your_generated_token_here"

View File

@ -15,7 +15,7 @@
- name: Warn if repo is not reachable - name: Warn if repo is not reachable
debug: debug:
msg: "Warning: Repository is not reachable." msg: "Warning: Repository is not reachable."
when: git_result.failed and enable_debug | bool when: git_result.failed and MODE_DEBUG | bool
- name: Ensure systemd user directory exists - name: Ensure systemd user directory exists
file: file:

View File

@ -8,7 +8,7 @@ Refer to the [Docker Compose documentation](https://docs.docker.com/compose/), t
## Overview ## Overview
This role creates a flexible directory layout for managing Docker Compose projects across environments. It ensures directories are initialized, optionally reset, and kept clean using internal flags like `mode_reset` or `mode_cleanup`. This role creates a flexible directory layout for managing Docker Compose projects across environments. It ensures directories are initialized, optionally reset, and kept clean using internal flags like `MODE_RESET` or `MODE_CLEANUP`.
## Purpose ## Purpose
@ -17,7 +17,7 @@ To offer a centralized, extensible system for managing containerized application
## Features ## Features
- **Dynamic Directory Structure:** Creates per-application instance folders for Compose setups. - **Dynamic Directory Structure:** Creates per-application instance folders for Compose setups.
- **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-proxy-7-4-core` and other Infinito.Nexus service roles. - **Integration Support:** Compatible with `srv-proxy-7-4-core` and other Infinito.Nexus service roles.

View File

@ -10,7 +10,7 @@
- name: "reset (if enabled)" - name: "reset (if enabled)"
include_tasks: 01_reset.yml include_tasks: 01_reset.yml
when: mode_reset | bool when: MODE_RESET | bool
# This could lead to problems in docker-compose directories which are based on a git repository # This could lead to problems in docker-compose directories which are based on a git repository
# @todo Verify that this isn't the case. E.g. in accounting # @todo Verify that this isn't the case. E.g. in accounting

View File

@ -16,7 +16,7 @@
url: "{{ cf_api_url }}?name={{ domain | to_primary_domain }}" url: "{{ cf_api_url }}?name={{ domain | to_primary_domain }}"
method: GET method: GET
headers: headers:
Authorization: "Bearer {{ certbot_dns_api_token }}" Authorization: "Bearer {{ CERTBOT_DNS_API_TOKEN }}"
Content-Type: "application/json" Content-Type: "application/json"
return_content: yes return_content: yes
register: cf_zone_lookup_dev register: cf_zone_lookup_dev
@ -43,8 +43,8 @@
- name: activate cloudflare cache development mode - name: activate cloudflare cache development mode
include_tasks: "cloudflare/02_enable_cf_dev_mode.yml" include_tasks: "cloudflare/02_enable_cf_dev_mode.yml"
when: (INFINITO_ENVIRONMENT | lower) == 'development' when: (ENVIRONMENT | lower) == 'development'
- name: purge cloudflare domain cache - name: purge cloudflare domain cache
include_tasks: "cloudflare/01_cleanup.yml" include_tasks: "cloudflare/01_cleanup.yml"
when: mode_cleanup | bool when: MODE_CLEANUP | bool

View File

@ -3,7 +3,7 @@
url: "https://api.cloudflare.com/client/v4/zones/{{ cf_zone_id }}/purge_cache" url: "https://api.cloudflare.com/client/v4/zones/{{ cf_zone_id }}/purge_cache"
method: POST method: POST
headers: headers:
Authorization: "Bearer {{ certbot_dns_api_token }}" Authorization: "Bearer {{ CERTBOT_DNS_API_TOKEN }}"
Content-Type: "application/json" Content-Type: "application/json"
body: body:
purge_everything: true purge_everything: true

View File

@ -1,7 +1,7 @@
# roles/srv-proxy-6-6-domain/tasks/02_enable_cf_dev_mode.yml # roles/srv-proxy-6-6-domain/tasks/02_enable_cf_dev_mode.yml
--- ---
# Enables Cloudflare Development Mode (bypasses cache for ~3 hours). # Enables Cloudflare Development Mode (bypasses cache for ~3 hours).
# Uses the same auth token as in 01_cleanup.yml: certbot_dns_api_token # Uses the same auth token as in 01_cleanup.yml: CERTBOT_DNS_API_TOKEN
# Assumes `domain` and (optionally) `cf_zone_id` are available. # Assumes `domain` and (optionally) `cf_zone_id` are available.
# Safe to run repeatedly; only changes when the mode is not already "on". # Safe to run repeatedly; only changes when the mode is not already "on".
@ -10,7 +10,7 @@
url: "https://api.cloudflare.com/client/v4/zones/{{ cf_zone_id }}/settings/development_mode" url: "https://api.cloudflare.com/client/v4/zones/{{ cf_zone_id }}/settings/development_mode"
method: GET method: GET
headers: headers:
Authorization: "Bearer {{ certbot_dns_api_token }}" Authorization: "Bearer {{ CERTBOT_DNS_API_TOKEN }}"
Content-Type: "application/json" Content-Type: "application/json"
return_content: yes return_content: yes
register: cf_dev_mode_current register: cf_dev_mode_current
@ -20,7 +20,7 @@
url: "https://api.cloudflare.com/client/v4/zones/{{ cf_zone_id }}/settings/development_mode" url: "https://api.cloudflare.com/client/v4/zones/{{ cf_zone_id }}/settings/development_mode"
method: PATCH method: PATCH
headers: headers:
Authorization: "Bearer {{ certbot_dns_api_token }}" Authorization: "Bearer {{ CERTBOT_DNS_API_TOKEN }}"
Content-Type: "application/json" Content-Type: "application/json"
body: body:
value: "on" value: "on"

View File

@ -7,7 +7,7 @@
when: run_once_srv_proxy_6_6_domain is not defined when: run_once_srv_proxy_6_6_domain is not defined
- include_tasks: "01_cloudflare.yml" - include_tasks: "01_cloudflare.yml"
when: dns_provider == "cloudflare" when: DNS_PROVIDER == "cloudflare"
- include_tasks: "{{ playbook_dir }}/tasks/utils/load_handlers.yml" - include_tasks: "{{ playbook_dir }}/tasks/utils/load_handlers.yml"
vars: vars:

View File

@ -49,7 +49,7 @@ This script:
**Usage:** **Usage:**
```sh ```sh
sh srv-proxy-6-6-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

@ -4,33 +4,33 @@ If you enabled `enable_wildcard_certificate`, follow these steps to manually req
### **1⃣ Run the Certbot Command 🖥️** ### **1⃣ Run the Certbot Command 🖥️**
```sh ```sh
certbot certonly --manual --preferred-challenges=dns --agree-tos \ certbot certonly --manual --preferred-challenges=dns --agree-tos \
--email administrator@primary_domain -d primary_domain -d "*.primary_domain" --email administrator@PRIMARY_DOMAIN -d PRIMARY_DOMAIN -d "*.PRIMARY_DOMAIN"
``` ```
### **2⃣ Add DNS TXT Record for Validation 📜** ### **2⃣ Add DNS TXT Record for Validation 📜**
Certbot will prompt you to add a DNS TXT record: Certbot will prompt you to add a DNS TXT record:
``` ```
Please create a TXT record under the name: Please create a TXT record under the name:
_acme-challenge.primary_domain. _acme-challenge.PRIMARY_DOMAIN.
with the following value: with the following value:
9oVizYIYVGlZ3VtWQIKRS5UghyXiqGoUNlCtIE7LiA 9oVizYIYVGlZ3VtWQIKRS5UghyXiqGoUNlCtIE7LiA
``` ```
**Go to your DNS provider** and create a new **TXT record**: **Go to your DNS provider** and create a new **TXT record**:
- **Host:** `_acme-challenge.primary_domain` - **Host:** `_acme-challenge.PRIMARY_DOMAIN`
- **Value:** `"9oVizYIYVGlZ3VtWQIKRS5UghyXiqGoUNlCtIE7LiA"` - **Value:** `"9oVizYIYVGlZ3VtWQIKRS5UghyXiqGoUNlCtIE7LiA"`
- **TTL:** Set to **300 seconds (or lowest possible)** - **TTL:** Set to **300 seconds (or lowest possible)**
**Verify the DNS record** before continuing: **Verify the DNS record** before continuing:
```sh ```sh
dig TXT _acme-challenge.primary_domain @8.8.8.8 dig TXT _acme-challenge.PRIMARY_DOMAIN @8.8.8.8
``` ```
### **3⃣ Complete the Certificate Request ✅** ### **3⃣ Complete the Certificate Request ✅**
Once the DNS changes have propagated, **press Enter** in the Certbot terminal. Once the DNS changes have propagated, **press Enter** in the Certbot terminal.
If successful, Certbot will save the certificates under: If successful, Certbot will save the certificates under:
``` ```
/etc/letsencrypt/live/primary_domain/ /etc/letsencrypt/live/PRIMARY_DOMAIN/
``` ```
- **fullchain.pem** → The certificate - **fullchain.pem** → The certificate
- **privkey.pem** → The private key - **privkey.pem** → The private key

View File

@ -12,11 +12,11 @@ docker_compose_instance_directory="$2"
docker_compose_cert_directory="$docker_compose_instance_directory/volumes/certs" docker_compose_cert_directory="$docker_compose_instance_directory/volumes/certs"
# Copy certificates # Copy certificates
cp -RvL "{{ letsencrypt_live_path }}/$ssl_cert_folder/"* "$docker_compose_cert_directory" || exit 1 cp -RvL "{{ LETSENCRYPT_LIVE_PATH }}/$ssl_cert_folder/"* "$docker_compose_cert_directory" || exit 1
# This code is optimized for mailu # This code is optimized for mailu
cp -v "{{ letsencrypt_live_path }}/$ssl_cert_folder/privkey.pem" "$docker_compose_cert_directory/key.pem" || exit 1 cp -v "{{ LETSENCRYPT_LIVE_PATH }}/$ssl_cert_folder/privkey.pem" "$docker_compose_cert_directory/key.pem" || exit 1
cp -v "{{ letsencrypt_live_path }}/$ssl_cert_folder/fullchain.pem" "$docker_compose_cert_directory/cert.pem" || exit 1 cp -v "{{ LETSENCRYPT_LIVE_PATH }}/$ssl_cert_folder/fullchain.pem" "$docker_compose_cert_directory/cert.pem" || exit 1
# Set correct reading rights # Set correct reading rights
chmod a+r -v "$docker_compose_cert_directory/"* chmod a+r -v "$docker_compose_cert_directory/"*

View File

@ -24,7 +24,7 @@ The Nginx HTTPS Certificate Retrieval role ensures that your Nginx-served domain
- **ACME Challenge Selection:** Supports DNS plugins or webroot method automatically. - **ACME Challenge Selection:** Supports DNS plugins or webroot method automatically.
- **Wildcard Certificate Management:** Issues wildcard certificates when configured, saving effort for subdomain-heavy deployments. - **Wildcard Certificate Management:** Issues wildcard certificates when configured, saving effort for subdomain-heavy deployments.
- **Safe Cleanup:** Ensures that no unused certificates are left behind. - **Safe Cleanup:** Ensures that no unused certificates are left behind.
- **Flexible Control:** Supports `mode_test` for staging environment testing and `mode_cleanup` for cert cleanup operations. - **Flexible Control:** Supports `MODE_TEST` for staging environment testing and `MODE_CLEANUP` for cert cleanup operations.
## 🔗 Learn More ## 🔗 Learn More

View File

@ -1,7 +1,7 @@
- name: "Check if certificate already exists for {{ domain }}" - name: "Check if certificate already exists for {{ domain }}"
cert_check_exists: cert_check_exists:
domain: "{{ domain }}" domain: "{{ domain }}"
cert_base_path: "{{ letsencrypt_live_path }}" cert_base_path: "{{ LETSENCRYPT_LIVE_PATH }}"
register: cert_check register: cert_check
- name: "receive certificate for {{ domain }}" - name: "receive certificate for {{ domain }}"
@ -10,21 +10,21 @@
--agree-tos --agree-tos
--email {{ users.administrator.email }} --email {{ users.administrator.email }}
--non-interactive --non-interactive
{% if certbot_acme_challenge_method != "webroot" %} {% if CERTBOT_ACME_CHALLENGE_METHOD != "webroot" %}
--dns-{{ certbot_acme_challenge_method }} --dns-{{ CERTBOT_ACME_CHALLENGE_METHOD }}
--dns-{{ certbot_acme_challenge_method }}-credentials {{ certbot_credentials_file }} --dns-{{ CERTBOT_ACME_CHALLENGE_METHOD }}-credentials {{ CERTBOT_CREDENTIALS_FILE }}
--dns-{{ certbot_acme_challenge_method }}-propagation-seconds {{ certbot_dns_propagation_wait_seconds }} --dns-{{ CERTBOT_ACME_CHALLENGE_METHOD }}-propagation-seconds {{ CERTBOT_DNS_PROPAGATION_WAIT_SECONDS }}
{% else %} {% else %}
--webroot --webroot
-w {{ letsencrypt_webroot_path }} -w {{ LETSENCRYPT_WEBROOT_PATH }}
{% endif %} {% endif %}
{% if wildcard_domain is defined and ( wildcard_domain | bool ) %} {% if wildcard_domain is defined and ( wildcard_domain | bool ) %}
-d {{ primary_domain }} -d {{ PRIMARY_DOMAIN }}
-d *.{{ primary_domain }} -d *.{{ PRIMARY_DOMAIN }}
{% else %} {% else %}
-d {{ domain }} -d {{ domain }}
{% endif %} {% endif %}
{{ '--test-cert' if mode_test | bool else '' }} {{ '--test-cert' if MODE_TEST | bool else '' }}
register: certbot_result register: certbot_result
changed_when: "'Certificate not yet due for renewal' not in certbot_result.stdout" changed_when: "'Certificate not yet due for renewal' not in certbot_result.stdout"
when: not cert_check.exists when: not cert_check.exists

View File

@ -10,15 +10,15 @@
certbundle certbundle
--domains "{{ current_play_domains_all | join(',') }}" --domains "{{ current_play_domains_all | join(',') }}"
--certbot-email "{{ users.administrator.email }}" --certbot-email "{{ users.administrator.email }}"
--certbot-acme-challenge-method "{{ certbot_acme_challenge_method }}" --certbot-acme-challenge-method "{{ CERTBOT_ACME_CHALLENGE_METHOD }}"
--chunk-size 100 --chunk-size 100
{% if certbot_acme_challenge_method != 'webroot' %} {% if CERTBOT_ACME_CHALLENGE_METHOD != 'webroot' %}
--certbot-credentials-file "{{ certbot_credentials_file }}" --certbot-credentials-file "{{ CERTBOT_CREDENTIALS_FILE }}"
--certbot-dns-propagation-seconds "{{ certbot_dns_propagation_wait_seconds }}" --certbot-dns-propagation-seconds "{{ CERTBOT_DNS_PROPAGATION_WAIT_SECONDS }}"
{% else %} {% else %}
--letsencrypt-webroot-path "{{ letsencrypt_webroot_path }}" --letsencrypt-webroot-path "{{ LETSENCRYPT_WEBROOT_PATH }}"
{% endif %} {% endif %}
{{ '--mode-test' if mode_test | bool else '' }} {{ '--mode-test' if MODE_TEST | bool else '' }}
register: certbundle_result register: certbundle_result
changed_when: "'Certificate not yet due for renewal' not in certbundle_result.stdout" changed_when: "'Certificate not yet due for renewal' not in certbundle_result.stdout"
failed_when: > failed_when: >

View File

@ -3,7 +3,7 @@
vars: vars:
wildcard_domain: true wildcard_domain: true
when: when:
- domain.split('.') | length == (primary_domain.split('.') | length + 1) and domain.endswith(primary_domain) - domain.split('.') | length == (PRIMARY_DOMAIN.split('.') | length + 1) and domain.endswith(PRIMARY_DOMAIN)
- run_once_receive_certificate is not defined - run_once_receive_certificate is not defined
- name: "Load dedicated certificate for domain" - name: "Load dedicated certificate for domain"
@ -11,7 +11,7 @@
vars: vars:
wildcard_domain: false wildcard_domain: false
when: when:
- not (domain.split('.') | length == (primary_domain.split('.') | length + 1) and domain.endswith(primary_domain)) - not (domain.split('.') | length == (PRIMARY_DOMAIN.split('.') | length + 1) and domain.endswith(PRIMARY_DOMAIN))
- name: run the receive_certificate tasks once - name: run the receive_certificate tasks once
set_fact: set_fact:

View File

@ -6,20 +6,20 @@
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
when: run_once_srv_web_6_6_tls_core is not defined when: run_once_srv_web_6_6_tls_core is not defined
- name: "Include flavor '{{ certbot_flavor }}' for '{{ domain }}'" - 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 }}"
# command: >- # command: >-
# certbot delete --cert-name {{ domain }} --non-interactive # certbot delete --cert-name {{ domain }} --non-interactive
# when: # when:
# - mode_cleanup | bool # - MODE_CLEANUP | bool
# # Cleanup mode is enabled # # Cleanup mode is enabled
# - certbot_flavor != 'dedicated' # - CERTBOT_FLAVOR != 'dedicated'
# # Wildcard certificate is enabled # # Wildcard certificate is enabled
# - domain.split('.') | length == (primary_domain.split('.') | length + 1) and domain.endswith(primary_domain) # - domain.split('.') | length == (PRIMARY_DOMAIN.split('.') | length + 1) and domain.endswith(PRIMARY_DOMAIN)
# # AND: The domain is a direct first-level subdomain of the primary domain # # AND: The domain is a direct first-level subdomain of the primary domain
# - domain != primary_domain # - domain != PRIMARY_DOMAIN
# # The domain is not the primary domain # # The domain is not the primary domain
# register: certbot_result # register: certbot_result
# 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)
@ -28,8 +28,8 @@
- 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: "{{ letsencrypt_live_path }}" cert_base_path: "{{ LETSENCRYPT_LIVE_PATH }}"
debug: "{{ enable_debug | default(false) }}" debug: "{{ MODE_DEBUG | default(false) }}"
register: cert_folder_result register: cert_folder_result
delegate_to: "{{ inventory_hostname }}" delegate_to: "{{ inventory_hostname }}"
changed_when: false changed_when: false

View File

@ -14,11 +14,11 @@ This Ansible role installs and configures **Nginx** as a core HTTP/stream server
* **Configurable reset and cleanup** modes to purge and recreate directories. * **Configurable reset and cleanup** modes to purge and recreate directories.
* **Custom `nginx.conf`** template with sensible defaults for performance and security. * **Custom `nginx.conf`** template with sensible defaults for performance and security.
* **Stream proxy support**: includes `stream` block for TCP/UDP proxies. * **Stream proxy support**: includes `stream` block for TCP/UDP proxies.
* **Cache directory management**: cleanup and recreation based on `mode_cleanup`. * **Cache directory management**: cleanup and recreation based on `MODE_CLEANUP`.
## Debugging Tips ## Debugging Tips
* **General logs**: `journalctl -f -u nginx` * **General logs**: `journalctl -f -u nginx`
* **Filter by host**: `journalctl -u nginx -f | grep "{{ inventory_hostname }}"` * **Filter by host**: `journalctl -u nginx -f | grep "{{ inventory_hostname }}"`
* **Enable detailed format**: set `enable_debug: true` and reload Nginx. * **Enable detailed format**: set `MODE_DEBUG: true` and reload Nginx.

View File

@ -20,7 +20,7 @@
- name: "reset (if enabled)" - name: "reset (if enabled)"
include_tasks: 02_reset.yml include_tasks: 02_reset.yml
when: mode_reset | bool when: MODE_RESET | bool
- name: Ensure nginx configuration directories are present - name: Ensure nginx configuration directories are present
file: file:

View File

@ -1,4 +1,4 @@
- name: "Delete {{nginx.directories.configuration}} directory, when mode_reset" - name: "Delete {{nginx.directories.configuration}} directory, when MODE_RESET"
file: file:
path: "{{ nginx.directories.configuration }}" path: "{{ nginx.directories.configuration }}"
state: absent state: absent

View File

@ -4,7 +4,7 @@
path: "{{ item.value }}" path: "{{ item.value }}"
state: absent state: absent
when: when:
- mode_cleanup | bool - MODE_CLEANUP | bool
- run_once_nginx_reverse_proxy is not defined - run_once_nginx_reverse_proxy is not defined
loop: "{{ nginx.directories.cache | dict2items }}" loop: "{{ nginx.directories.cache | dict2items }}"
loop_control: loop_control:

View File

@ -24,7 +24,7 @@ http
# -------------------------------------------------------------------------------- # --------------------------------------------------------------------------------
{# logging and debugging #} {# logging and debugging #}
{% if enable_debug | bool %} {% if MODE_DEBUG | bool %}
{# individual log format for better debugging #} {# individual log format for better debugging #}
log_format debug '$host - $remote_addr [$time_local] ' log_format debug '$host - $remote_addr [$time_local] '
'"$request" $status $body_bytes_sent ' '"$request" $status $body_bytes_sent '

View File

@ -45,8 +45,8 @@ All tasks are idempotent—once your certificates are in place and your configur
- A working `srv-web-7-4-core` setup. - A working `srv-web-7-4-core` setup.
- DNS managed via Cloudflare (for CAA record tasks) or equivalent ACME DNS flow. - DNS managed via Cloudflare (for CAA record tasks) or equivalent ACME DNS flow.
- Variables: - Variables:
- `letsencrypt_webroot_path` - `LETSENCRYPT_WEBROOT_PATH`
- `letsencrypt_live_path` - `LETSENCRYPT_LIVE_PATH`
- `on_calendar_renew_lets_encrypt_certificates` - `on_calendar_renew_lets_encrypt_certificates`
--- ---

View File

@ -6,34 +6,34 @@
- name: install certbot DNS plugin - name: install certbot DNS plugin
community.general.pacman: community.general.pacman:
name: "certbot-dns-{{ certbot_acme_challenge_method }}" name: "certbot-dns-{{ CERTBOT_ACME_CHALLENGE_METHOD }}"
state: present state: present
when: when:
- run_once_srv_web_7_7_certbot is not defined - run_once_srv_web_7_7_certbot is not defined
- certbot_acme_challenge_method != 'webroot' - CERTBOT_ACME_CHALLENGE_METHOD != 'webroot'
- name: Ensure /etc/certbot directory exists - name: Ensure /etc/certbot directory exists
file: file:
path: "{{ certbot_credentials_dir }}" path: "{{ CERTBOT_CREDENTIALS_DIR }}"
state: directory state: directory
owner: root owner: root
group: root group: root
mode: '0755' mode: '0755'
when: when:
- run_once_srv_web_7_7_certbot is not defined - run_once_srv_web_7_7_certbot is not defined
- certbot_acme_challenge_method != 'webroot' - CERTBOT_ACME_CHALLENGE_METHOD != 'webroot'
- name: Install plugin credentials file - name: Install plugin credentials file
copy: copy:
dest: "{{ certbot_credentials_file }}" dest: "{{ CERTBOT_CREDENTIALS_FILE }}"
content: | content: |
dns_{{ certbot_acme_challenge_method }}_api_token = {{ certbot_dns_api_token }} dns_{{ CERTBOT_ACME_CHALLENGE_METHOD }}_api_token = {{ CERTBOT_DNS_API_TOKEN }}
owner: root owner: root
group: root group: root
mode: '0600' mode: '0600'
when: when:
- run_once_srv_web_7_7_certbot is not defined - run_once_srv_web_7_7_certbot is not defined
- certbot_acme_challenge_method != 'webroot' - CERTBOT_ACME_CHALLENGE_METHOD != 'webroot'
- name: run the certbot role once - name: run the certbot role once
set_fact: set_fact:

View File

@ -10,7 +10,7 @@ Looping over a provided list of domains (`cloudflare_domains`), this role:
- Determines the zone name by extracting the last two labels of each domain. - Determines the zone name by extracting the last two labels of each domain.
- Ensures an A-record for each domain points to the specified IP (`cloudflare_target_ip`). - Ensures an A-record for each domain points to the specified IP (`cloudflare_target_ip`).
- Honors the `proxied` flag to switch between DNS-only and Cloudflare-proxied modes. - Honors the `proxied` flag to switch between DNS-only and Cloudflare-proxied modes.
- Provides an optional debug task (`enable_debug`) to output the domain list before changes. - Provides an optional debug task (`MODE_DEBUG`) to output the domain list before changes.
Ideal for environments where bulk or dynamic DNS updates are needed, this role abstracts away the complexity of Cloudflares zone and record API. Ideal for environments where bulk or dynamic DNS updates are needed, this role abstracts away the complexity of Cloudflares zone and record API.
@ -23,7 +23,7 @@ Cloudflare DNS Records delivers an idempotent, scalable solution for managing A-
- **Automatic Zone Detection:** Parses each domain to derive its zone (`example.com`) without manual intervention. - **Automatic Zone Detection:** Parses each domain to derive its zone (`example.com`) without manual intervention.
- **Bulk Record Management:** Creates or updates A-records for all entries in `cloudflare_domains`. - **Bulk Record Management:** Creates or updates A-records for all entries in `cloudflare_domains`.
- **Proxy Toggle:** Configure `proxied: true` or `false` per record to switch between DNS-only and proxied modes. - **Proxy Toggle:** Configure `proxied: true` or `false` per record to switch between DNS-only and proxied modes.
- **Debug Support:** Enable `enable_debug` to print the domain list for validation before execution. - **Debug Support:** Enable `MODE_DEBUG` to print the domain list for validation before execution.
- **Flexible Authentication:** Supports both API token (`api_token`) and Global API key + email. - **Flexible Authentication:** Supports both API token (`api_token`) and Global API key + email.
- **Low-TTL Option:** Use `ttl: 1` for rapid DNS propagation during dynamic updates. - **Low-TTL Option:** Use `ttl: 1` for rapid DNS propagation during dynamic updates.

View File

@ -2,7 +2,7 @@
- name: Create or update Cloudflare A-record for {{ item }} - name: Create or update Cloudflare A-record for {{ item }}
community.general.cloudflare_dns: community.general.cloudflare_dns:
api_token: "{{ certbot_dns_api_token }}" api_token: "{{ CERTBOT_DNS_API_TOKEN }}"
zone: "{{ item.split('.')[-2:] | join('.') }}" zone: "{{ item.split('.')[-2:] | join('.') }}"
state: present state: present
type: A type: A

View File

@ -10,7 +10,7 @@
set_fact: set_fact:
inj_enabled: inj_enabled:
javascript: "{{ applications | get_app_conf(application_id, 'features.javascript', False) }}" javascript: "{{ applications | get_app_conf(application_id, 'features.javascript', False) }}"
logout: "{{ (applications | get_app_conf(application_id, 'features.logout', False) or domain == primary_domain) }}" logout: "{{ (applications | get_app_conf(application_id, 'features.logout', False) or domain == PRIMARY_DOMAIN) }}"
css: "{{ applications | get_app_conf(application_id, 'features.css', False) }}" css: "{{ applications | get_app_conf(application_id, 'features.css', False) }}"
matomo: "{{ applications | get_app_conf(application_id, 'features.matomo', False) }}" matomo: "{{ applications | get_app_conf(application_id, 'features.matomo', False) }}"
port_ui: "{{ applications | get_app_conf(application_id, 'features.port-ui-desktop', False) }}" port_ui: "{{ applications | get_app_conf(application_id, 'features.port-ui-desktop', False) }}"
@ -39,7 +39,7 @@
set_fact: set_fact:
inj_enabled: inj_enabled:
javascript: "{{ applications | get_app_conf(application_id, 'features.javascript', False) }}" javascript: "{{ applications | get_app_conf(application_id, 'features.javascript', False) }}"
logout: "{{ (applications | get_app_conf(application_id, 'features.logout', False) or domain == primary_domain) }}" logout: "{{ (applications | get_app_conf(application_id, 'features.logout', False) or domain == PRIMARY_DOMAIN) }}"
css: "{{ applications | get_app_conf(application_id, 'features.css', False) }}" css: "{{ applications | get_app_conf(application_id, 'features.css', False) }}"
matomo: "{{ applications | get_app_conf(application_id, 'features.matomo', False) }}" matomo: "{{ applications | get_app_conf(application_id, 'features.matomo', False) }}"
port_ui: "{{ applications | get_app_conf(application_id, 'features.port-ui-desktop', False) }}" port_ui: "{{ applications | get_app_conf(application_id, 'features.port-ui-desktop', False) }}"

View File

@ -16,7 +16,7 @@ This Ansible role injects a custom JavaScript snippet into all HTML responses se
Activates only when you enable the `javascript` feature for a given application, keeping your server blocks clean and performant. Activates only when you enable the `javascript` feature for a given application, keeping your server blocks clean and performant.
- **Debug Mode** - **Debug Mode**
Supports an `enable_debug` flag that appends optional `console.log` statements for easier troubleshooting in staging or development. Supports an `MODE_DEBUG` flag that appends optional `console.log` statements for easier troubleshooting in staging or development.
## Author ## Author

View File

@ -2,6 +2,6 @@ document.addEventListener('DOMContentLoaded', function() {
initLogoutPatch( initLogoutPatch(
'{{ oidc.client.logout_url }}', '{{ oidc.client.logout_url }}',
'{{ WEB_PROTOCOL }}', '{{ WEB_PROTOCOL }}',
'{{ primary_domain }}' '{{ PRIMARY_DOMAIN }}'
); );
}); });

View File

@ -12,7 +12,7 @@
domain: "{{ domain }}" domain: "{{ domain }}"
base_domain: "{{ base_domain }}" base_domain: "{{ base_domain }}"
matomo_verification_url: "{{ matomo_verification_url }}" matomo_verification_url: "{{ matomo_verification_url }}"
when: enable_debug | bool when: MODE_DEBUG | bool
- name: "Check if site {{ domain }} is allready registered at Matomo" - name: "Check if site {{ domain }} is allready registered at Matomo"
uri: uri:

View File

@ -14,6 +14,6 @@ _paq.push(["enableLinkTracking"]);
g.async=true; g.src=u+"matomo.js"; s.parentNode.insertBefore(g,s); g.async=true; g.src=u+"matomo.js"; s.parentNode.insertBefore(g,s);
})(); })();
{% if enable_debug | bool %} {% if MODE_DEBUG | bool %}
console.log("Matomo is loaded."); console.log("Matomo is loaded.");
{% endif %} {% endif %}

View File

@ -1,5 +1,5 @@
(function() { (function() {
var primary = "{{ primary_domain }}"; var primary = "{{ PRIMARY_DOMAIN }}";
var allowedOrigin = "https://{{ domains | get_domain('web-app-port-ui') }}"; var allowedOrigin = "https://{{ domains | get_domain('web-app-port-ui') }}";
function notifyParent() { function notifyParent() {
@ -43,6 +43,6 @@
}; };
})(); })();
{% if enable_debug | bool %} {% if MODE_DEBUG | bool %}
console.log("[iframe-sync] Sender for iframe messages is active."); console.log("[iframe-sync] Sender for iframe messages is active.");
{% endif %} {% endif %}

View File

@ -11,4 +11,4 @@
- name: "Set CAA records for all base domains" - name: "Set CAA records for all base domains"
include_tasks: 01_set-caa-records.yml include_tasks: 01_set-caa-records.yml
when: dns_provider == 'cloudflare' when: DNS_PROVIDER == 'cloudflare'

View File

@ -1,14 +1,14 @@
--- ---
- name: "Validate certbot_dns_api_token" - name: "Validate CERTBOT_DNS_API_TOKEN"
fail: fail:
msg: > msg: >
The variable "certbot_dns_api_token" must be defined and cannot be empty! The variable "CERTBOT_DNS_API_TOKEN" must be defined and cannot be empty!
when: (certbot_dns_api_token|default('')|trim) == '' when: (CERTBOT_DNS_API_TOKEN|default('')|trim) == ''
- name: "Ensure all CAA records are present" - name: "Ensure all CAA records are present"
community.general.cloudflare_dns: community.general.cloudflare_dns:
api_token: "{{ certbot_dns_api_token }}" api_token: "{{ CERTBOT_DNS_API_TOKEN }}"
zone: "{{ item.0 }}" zone: "{{ item.0 }}"
record: "@" record: "@"
type: CAA type: CAA

View File

@ -9,7 +9,7 @@ server
#letsencrypt #letsencrypt
location ^~ /.well-known/acme-challenge/ { location ^~ /.well-known/acme-challenge/ {
allow all; allow all;
root {{ letsencrypt_webroot_path }}; root {{ LETSENCRYPT_WEBROOT_PATH }};
default_type "text/plain"; default_type "text/plain";
try_files $uri =404; try_files $uri =404;
} }

View File

@ -1,3 +1,3 @@
ssl_certificate {{ [ letsencrypt_live_path, ssl_cert_folder] | path_join }}/fullchain.pem; ssl_certificate {{ [ LETSENCRYPT_LIVE_PATH, ssl_cert_folder] | path_join }}/fullchain.pem;
ssl_certificate_key {{ [ letsencrypt_live_path, ssl_cert_folder] | path_join }}/privkey.pem; ssl_certificate_key {{ [ LETSENCRYPT_LIVE_PATH, ssl_cert_folder] | path_join }}/privkey.pem;
ssl_trusted_certificate {{ [ letsencrypt_live_path, ssl_cert_folder] | path_join }}/chain.pem; ssl_trusted_certificate {{ [ LETSENCRYPT_LIVE_PATH, ssl_cert_folder] | path_join }}/chain.pem;

View File

@ -10,6 +10,6 @@
- {{ nginx.directories.configuration }}:{{ nginx.directories.configuration }}:ro - {{ nginx.directories.configuration }}:{{ nginx.directories.configuration }}:ro
- {{ nginx.directories.data.www }}:{{ nginx.directories.data.www }}:ro - {{ nginx.directories.data.www }}:{{ nginx.directories.data.www }}:ro
- {{ nginx.directories.data.well_known }}:{{ nginx.directories.data.well_known }}:ro - {{ nginx.directories.data.well_known }}:{{ nginx.directories.data.well_known }}:ro
- {{ letsencrypt_webroot_path }}:{{ letsencrypt_webroot_path }}:ro - {{ LETSENCRYPT_WEBROOT_PATH }}:{{ LETSENCRYPT_WEBROOT_PATH }}:ro
- {{ letsencrypt_base_path }}:{{ letsencrypt_base_path }}:ro - {{ LETSENCRYPT_BASE_PATH }}:{{ LETSENCRYPT_BASE_PATH }}:ro
command: ["openresty", "-g", "daemon off;"] command: ["openresty", "-g", "daemon off;"]

View File

@ -12,7 +12,7 @@
- name: "reset (if enabled)" - name: "reset (if enabled)"
include_tasks: 03_reset.yml include_tasks: 03_reset.yml
when: mode_reset | bool when: MODE_RESET | bool
- name: configure sys-bkp-docker-2-loc-everything.infinito.service - name: configure sys-bkp-docker-2-loc-everything.infinito.service
template: template:

View File

@ -11,7 +11,7 @@
database_host: "{{ database_host | default('undefined') }}" database_host: "{{ database_host | default('undefined') }}"
database_username: "{{ database_username | default('undefined') }}" database_username: "{{ database_username | default('undefined') }}"
database_password: "{{ database_password | default('undefined') }}" database_password: "{{ database_password | default('undefined') }}"
when: enable_debug | bool when: MODE_DEBUG | bool
- name: "fail if not all required database variables are defined" - name: "fail if not all required database variables are defined"
fail: fail:

View File

@ -14,7 +14,7 @@
vars: vars:
domain: "{{ item }}" domain: "{{ item }}"
when: when:
- mode_cleanup | bool - MODE_CLEANUP | bool
## The revoking just works for the base domain ## The revoking just works for the base domain
#- name: "Revoke Certbot certificate for {{ item }}" #- name: "Revoke Certbot certificate for {{ item }}"
@ -25,7 +25,7 @@
# loop_control: # loop_control:
# label: "{{ item }}" # label: "{{ item }}"
# when: # when:
# - mode_cleanup | bool # - MODE_CLEANUP | bool
# - run_once_sys_cln_domains is not defined # - run_once_sys_cln_domains is not defined
# register: certbot_revoke_result # register: certbot_revoke_result
# failed_when: > # failed_when: >
@ -43,7 +43,7 @@
# loop_control: # loop_control:
# label: "{{ item }}" # label: "{{ item }}"
# when: # when:
# - mode_cleanup | bool # - MODE_CLEANUP | bool
# - run_once_sys_cln_domains is not defined # - run_once_sys_cln_domains is not defined
# register: certbot_delete_result # register: certbot_delete_result
# failed_when: > # failed_when: >

View File

@ -4,7 +4,7 @@ This Ansible role handles resetting and cleaning up “Infinito.Nexus” systemd
## Description ## Description
When enabled via the `mode_reset` flag, this role will: When enabled via the `MODE_RESET` flag, this role will:
1. Run its reset tasks exactly once per play (`run_once_sys_rst_daemon` guard). 1. Run its reset tasks exactly once per play (`run_once_sys_rst_daemon` guard).
2. Find all `/etc/systemd/system/*.infinito.service` units. 2. Find all `/etc/systemd/system/*.infinito.service` units.

View File

@ -1,6 +1,6 @@
- name: "reset (if enabled)" - name: "reset (if enabled)"
include_tasks: reset.yml include_tasks: reset.yml
when: mode_reset | bool and run_once_sys_rst_daemon is not defined when: MODE_RESET | bool and run_once_sys_rst_daemon is not defined
- name: run {{ role_name }} once - name: run {{ role_name }} once
set_fact: set_fact:

View File

@ -19,7 +19,7 @@ This Ansible role configures the OpenSSH daemon (`sshd`) by deploying a template
- **Security Defaults** - **Security Defaults**
- Disables password (`PasswordAuthentication no`) and root login (`PermitRootLogin no`) - Disables password (`PasswordAuthentication no`) and root login (`PermitRootLogin no`)
- Enforces public-key authentication (`PubkeyAuthentication yes`) - Enforces public-key authentication (`PubkeyAuthentication yes`)
- Conditionally sets `LogLevel` to `DEBUG3` when `enable_debug` is true - Conditionally sets `LogLevel` to `DEBUG3` when `MODE_DEBUG` is true
- **Systemd Integration** - **Systemd Integration**
Handles daemon reload and service restart seamlessly on configuration changes. Handles daemon reload and service restart seamlessly on configuration changes.

View File

@ -25,7 +25,7 @@
# Logging # Logging
#SyslogFacility AUTH #SyslogFacility AUTH
LogLevel {% if enable_debug | bool %}DEBUG3{% else %}INFO{% endif %} LogLevel {% if MODE_DEBUG | bool %}DEBUG3{% else %}INFO{% endif %}
# Authentication: # Authentication:

View File

@ -9,7 +9,7 @@ This role configures a systemd timer to periodically start a corresponding servi
Optimized for automated task scheduling in a [systemd](https://en.wikipedia.org/wiki/Systemd) environment, this role: Optimized for automated task scheduling in a [systemd](https://en.wikipedia.org/wiki/Systemd) environment, this role:
- Generates a timer unit file for a given service (using the `service_name` variable). - Generates a timer unit file for a given service (using the `service_name` variable).
- Reloads and restarts the timer using systemd to ensure that changes take effect. - Reloads and restarts the timer using systemd to ensure that changes take effect.
- Supports dynamic configuration of scheduling parameters via variables like `on_calendar` and `randomized_delay_sec`. - Supports dynamic configuration of scheduling parameters via variables like `on_calendar` and `RANDOMIZED_DELAY_SEC`.
## Purpose ## Purpose

View File

@ -1,7 +1,7 @@
- name: "reset (if enabled)" - name: "reset (if enabled)"
include_tasks: 01_reset.yml include_tasks: 01_reset.yml
when: mode_reset | bool and run_once_sys_timer is not defined when: MODE_RESET | bool and run_once_sys_timer is not defined
- name: run {{ role_name }} once - name: run {{ role_name }} once
set_fact: set_fact:
@ -20,5 +20,5 @@
name: "{{ sys_timer_file }}" name: "{{ sys_timer_file }}"
state: restarted state: restarted
enabled: yes enabled: yes
when: dummy_timer.changed or activate_all_timers | bool when: dummy_timer.changed or ACTIVATE_ALL_TIMERS | bool

View File

@ -3,7 +3,7 @@ Description=Timer to start {{service_name}}.infinito.service
[Timer] [Timer]
OnCalendar={{on_calendar}} OnCalendar={{on_calendar}}
RandomizedDelaySec={{randomized_delay_sec}} RandomizedDelaySec={{RANDOMIZED_DELAY_SEC}}
Persistent={{ persistent | default('false') }} Persistent={{ persistent | default('false') }}
[Install] [Install]

View File

@ -8,7 +8,7 @@
name: sys-bkp-docker-2-loc-everything.infinito.service name: sys-bkp-docker-2-loc-everything.infinito.service
state: started state: started
when: when:
- mode_backup | bool - MODE_BACKUP | bool
- name: create {{update_docker_script}} - name: create {{update_docker_script}}
template: template:

View File

@ -149,7 +149,7 @@ def update_mastodon():
Runs the database migration for Mastodon to ensure all required tables are up to date. Runs the database migration for Mastodon to ensure all required tables are up to date.
""" """
print("Starting Mastodon database migration.") print("Starting Mastodon database migration.")
run_command("docker compose exec -T web bash -c 'RAILS_ENV={{ INFINITO_ENVIRONMENT | lower }} bin/rails db:migrate'") run_command("docker compose exec -T web bash -c 'RAILS_ENV={{ ENVIRONMENT | lower }} bin/rails db:migrate'")
print("Mastodon database migration complete.") print("Mastodon database migration complete.")
def upgrade_listmonk(): def upgrade_listmonk():

View File

@ -2,7 +2,7 @@ users:
administrator: administrator:
description: "System Administrator" description: "System Administrator"
username: "administrator" username: "administrator"
email: "administrator@{{ primary_domain }}" email: "administrator@{{ PRIMARY_DOMAIN }}"
password: "{{ ansible_become_password }}" password: "{{ ansible_become_password }}"
uid: 1001 uid: 1001
gid: 1001 gid: 1001

View File

@ -2,10 +2,10 @@
users: users:
sld: sld:
description: "Auto Generated Account to reserve the SLD" description: "Auto Generated Account to reserve the SLD"
username: "{{ primary_domain.split('.')[0] }}" username: "{{ PRIMARY_DOMAIN.split('.')[0] }}"
tld: tld:
description: "Auto Generated Account to reserve the TLD" description: "Auto Generated Account to reserve the TLD"
username: "{{ primary_domain.split('.')[1] }}" username: "{{ PRIMARY_DOMAIN.split('.')[1] }}"
root: root:
username: root username: root
uid: 0 uid: 0

View File

@ -1,5 +1,5 @@
company: company:
name: "Akaunting on {{ primary_domain | upper }}" # @todo load automatic based on service_provider infos, this will fail name: "Akaunting on {{ PRIMARY_DOMAIN | upper }}" # @todo load automatic based on service_provider infos, this will fail
email: "{{ users.administrator.email }}" # @todo load automatic based on service_provider infos, this will fail email: "{{ users.administrator.email }}" # @todo load automatic based on service_provider infos, this will fail
setup_admin_email: "{{ users.administrator.email }}" setup_admin_email: "{{ users.administrator.email }}"
features: features:
@ -11,7 +11,7 @@ features:
server: server:
domains: domains:
canonical: canonical:
- "accounting.{{ primary_domain }}" - "accounting.{{ PRIMARY_DOMAIN }}"
docker: docker:
services: services:
database: database:

View File

@ -16,4 +16,4 @@ docker:
server: server:
domains: domains:
canonical: canonical:
- "tickets.{{ primary_domain }}" - "tickets.{{ PRIMARY_DOMAIN }}"

View File

@ -21,4 +21,4 @@ docker:
server: server:
domains: domains:
canonical: canonical:
- baserow.{{ primary_domain }} - baserow.{{ PRIMARY_DOMAIN }}

View File

@ -18,7 +18,7 @@ server:
unsafe-inline: true unsafe-inline: true
domains: domains:
canonical: canonical:
- "meet.{{ primary_domain }}" - "meet.{{ PRIMARY_DOMAIN }}"
credentials: {} credentials: {}
docker: docker:

View File

@ -1,6 +1,6 @@
ENABLE_COTURN=true ENABLE_COTURN=true
COTURN_TLS_CERT_PATH={{ [ letsencrypt_live_path, ssl_cert_folder] | path_join }}/fullchain.pem COTURN_TLS_CERT_PATH={{ [ LETSENCRYPT_LIVE_PATH, ssl_cert_folder] | path_join }}/fullchain.pem
COTURN_TLS_KEY_PATH={{ [ letsencrypt_live_path, ssl_cert_folder] | path_join }}/privkey.pem COTURN_TLS_KEY_PATH={{ [ LETSENCRYPT_LIVE_PATH, ssl_cert_folder] | path_join }}/privkey.pem
ENABLE_GREENLIGHT={{ applications | get_app_conf(application_id, 'enable_greenlight', True) }} ENABLE_GREENLIGHT={{ applications | get_app_conf(application_id, 'enable_greenlight', True) }}
# Enable Webhooks # Enable Webhooks

View File

@ -1,3 +1,3 @@
users: users:
administrator: administrator:
email: "administrator@{{ primary_domain }}" email: "administrator@{{ PRIMARY_DOMAIN }}"

View File

@ -11,8 +11,8 @@ features:
server: server:
domains: domains:
canonical: canonical:
web: "bskyweb.{{ primary_domain }}" web: "bskyweb.{{ PRIMARY_DOMAIN }}"
api: "bluesky.{{ primary_domain }}" api: "bluesky.{{ PRIMARY_DOMAIN }}"
docker: docker:
services: services:
database: database:

View File

@ -24,7 +24,7 @@
args: args:
REACT_APP_PDS_URL: "{{ WEB_PROTOCOL }}://{{domains[application_id].api}}" # URL des PDS REACT_APP_PDS_URL: "{{ WEB_PROTOCOL }}://{{domains[application_id].api}}" # URL des PDS
REACT_APP_API_URL: "{{ WEB_PROTOCOL }}://{{domains[application_id].api}}" # API-URL des PDS REACT_APP_API_URL: "{{ WEB_PROTOCOL }}://{{domains[application_id].api}}" # API-URL des PDS
REACT_APP_SITE_NAME: "{{primary_domain | upper}} - Bluesky" REACT_APP_SITE_NAME: "{{PRIMARY_DOMAIN | upper}} - Bluesky"
REACT_APP_SITE_DESCRIPTION: "Decentral Social " REACT_APP_SITE_DESCRIPTION: "Decentral Social "
ports: ports:
- "127.0.0.1:{{ports.localhost.http['web-app-bluesky_web']}}:8100" - "127.0.0.1:{{ports.localhost.http['web-app-bluesky_web']}}:8100"

View File

@ -3,7 +3,7 @@ PDS_ADMIN_EMAIL="{{applications.bluesky.users.administrator.email}}"
PDS_SERVICE_DID="did:web:{{domains[application_id].api}}" PDS_SERVICE_DID="did:web:{{domains[application_id].api}}"
# See https://mattdyson.org/blog/2024/11/self-hosting-bluesky-pds/ # See https://mattdyson.org/blog/2024/11/self-hosting-bluesky-pds/
PDS_SERVICE_HANDLE_DOMAINS=".{{primary_domain}}" PDS_SERVICE_HANDLE_DOMAINS=".{{PRIMARY_DOMAIN}}"
PDS_JWT_SECRET="{{ bluesky_jwt_secret }}" PDS_JWT_SECRET="{{ bluesky_jwt_secret }}"
PDS_ADMIN_PASSWORD="{{bluesky_admin_password}}" PDS_ADMIN_PASSWORD="{{bluesky_admin_password}}"
PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX="{{ bluesky_rotation_key }}" PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX="{{ bluesky_rotation_key }}"

View File

@ -1,3 +1,3 @@
users: users:
administrator: administrator:
email: "administrator@{{ primary_domain }}" email: "administrator@{{ PRIMARY_DOMAIN }}"

View File

@ -1,7 +1,7 @@
server: server:
domains: domains:
canonical: canonical:
- "collabora.{{ primary_domain }}" - "collabora.{{ PRIMARY_DOMAIN }}"
docker: docker:
services: services:
redis: redis:

View File

@ -16,10 +16,10 @@ server:
unsafe-inline: true unsafe-inline: true
whitelist: whitelist:
font-src: font-src:
- "http://*.{{primary_domain}}" - "http://*.{{PRIMARY_DOMAIN}}"
domains: domains:
canonical: canonical:
- "forum.{{ primary_domain }}" - "forum.{{ PRIMARY_DOMAIN }}"
docker: docker:
services: services:
database: database:

View File

@ -1,6 +1,6 @@
- name: "reset (if enabled)" - name: "reset (if enabled)"
include_tasks: 02_reset.yml include_tasks: 02_reset.yml
when: mode_reset | bool when: MODE_RESET | bool
# Necessary for building: https://chat.openai.com/share/99d258cc-294b-4924-8eef-02fe419bb838 # Necessary for building: https://chat.openai.com/share/99d258cc-294b-4924-8eef-02fe419bb838
- name: install which - name: install which

View File

@ -3,4 +3,4 @@ features:
server: server:
domains: domains:
canonical: canonical:
- elk.{{ primary_domain }} - elk.{{ PRIMARY_DOMAIN }}

View File

@ -18,17 +18,17 @@ server:
unsafe-eval: true unsafe-eval: true
whitelist: whitelist:
connect-src: connect-src:
- wss://espocrm.{{ primary_domain }} - wss://espocrm.{{ PRIMARY_DOMAIN }}
- "data:" - "data:"
frame-src: frame-src:
- https://s.espocrm.com/ - https://s.espocrm.com/
domains: domains:
aliases: aliases:
- "crm.{{ primary_domain }}" - "crm.{{ PRIMARY_DOMAIN }}"
canonical: canonical:
- espocrm.{{ primary_domain }} - espocrm.{{ PRIMARY_DOMAIN }}
email: email:
from_name: "Customer Relationship Management ({{ primary_domain }})" from_name: "Customer Relationship Management ({{ PRIMARY_DOMAIN }})"
docker: docker:
services: services:
database: database:

View File

@ -41,7 +41,7 @@ ESPOCRM_CONFIG_DEFAULT_CURRENCY={{ HOST_CURRENCY }}
# ------------------------------------------------ # ------------------------------------------------
# Logger # Logger
# ------------------------------------------------ # ------------------------------------------------
ESPOCRM_CONFIG_LOGGER_LEVEL={{ 'DEBUG' if enable_debug | bool else 'INFO' }} ESPOCRM_CONFIG_LOGGER_LEVEL={{ 'DEBUG' if MODE_DEBUG | bool else 'INFO' }}
ESPOCRM_CONFIG_LOGGER_PATH=php://stdout ESPOCRM_CONFIG_LOGGER_PATH=php://stdout
ESPOCRM_CONFIG_LOGGER_ROTATION=false ESPOCRM_CONFIG_LOGGER_ROTATION=false

View File

@ -12,7 +12,7 @@ features:
server: server:
domains: domains:
canonical: canonical:
- "social.{{ primary_domain }}" - "social.{{ PRIMARY_DOMAIN }}"
csp: csp:
flags: flags:
script-src-elem: script-src-elem:

View File

@ -6,8 +6,8 @@ HOSTNAME={{domains | get_domain(application_id)}}
FRIENDICA_NO_VALIDATION={{friendica_no_validation | lower}} FRIENDICA_NO_VALIDATION={{friendica_no_validation | lower}}
# Debugging # Debugging
FRIENDICA_DEBUGGING={{ (enable_debug | bool) | lower }}{{"\n"}} FRIENDICA_DEBUGGING={{ (MODE_DEBUG | bool) | lower }}{{"\n"}}
FRIENDICA_LOGLEVEL={% if enable_debug | bool %}9{% else %}5{% endif %}{{"\n"}} FRIENDICA_LOGLEVEL={% if MODE_DEBUG | bool %}9{% else %}5{% endif %}{{"\n"}}
FRIENDICA_LOGGER=syslog FRIENDICA_LOGGER=syslog
# Database Configuration # Database Configuration

View File

@ -23,10 +23,10 @@ features:
server: server:
domains: domains:
canonical: canonical:
- "audio.{{ primary_domain }}" - "audio.{{ PRIMARY_DOMAIN }}"
aliases: aliases:
- "music.{{ primary_domain }}" - "music.{{ PRIMARY_DOMAIN }}"
- "sound.{{ primary_domain }}" - "sound.{{ PRIMARY_DOMAIN }}"
csp: csp:
flags: flags:
style-src: style-src:

View File

@ -40,10 +40,10 @@ FUNKWHALE_HOSTNAME={{domains | get_domain(application_id)}}
FUNKWHALE_PROTOCOL={{ WEB_PROTOCOL }} FUNKWHALE_PROTOCOL={{ WEB_PROTOCOL }}
# Log level (debug, info, warning, error, critical) # Log level (debug, info, warning, error, critical)
LOGLEVEL={% if enable_debug | bool %}debug{% else %}error{% endif %} LOGLEVEL={% if MODE_DEBUG | bool %}debug{% else %}error{% endif %}
# Could be that this is redundant # Could be that this is redundant
DJANGO_LOGLEVEL={% if enable_debug | bool %}debug{% else %}error{% endif %} DJANGO_LOGLEVEL={% if MODE_DEBUG | bool %}debug{% else %}error{% endif %}
# Configure e-mail sending using this variale # Configure e-mail sending using this variale
# By default, funkwhale will output e-mails sent to stdout # By default, funkwhale will output e-mails sent to stdout

View File

@ -36,9 +36,9 @@ server:
- "data:" - "data:"
domains: domains:
aliases: aliases:
- "git.{{ primary_domain }}" - "git.{{ PRIMARY_DOMAIN }}"
canonical: canonical:
- gitea.{{ primary_domain }} - gitea.{{ PRIMARY_DOMAIN }}
docker: docker:
services: services:
database: database:

View File

@ -2,7 +2,7 @@
shell: | shell: |
docker exec -i --user {{ gitea_user }} {{ gitea_container }} \ docker exec -i --user {{ gitea_user }} {{ gitea_container }} \
gitea admin auth list \ gitea admin auth list \
| awk -v name="LDAP ({{ primary_domain }})" '$0 ~ name {print $1; exit}' | awk -v name="LDAP ({{ PRIMARY_DOMAIN }})" '$0 ~ name {print $1; exit}'
args: args:
chdir: "{{ docker_compose.directories.instance }}" chdir: "{{ docker_compose.directories.instance }}"
register: ldap_source_id_raw register: ldap_source_id_raw

View File

@ -54,14 +54,14 @@
- name: Execute Cleanup Routines - name: Execute Cleanup Routines
include_tasks: 03_cleanup.yml include_tasks: 03_cleanup.yml
when: mode_cleanup when: MODE_CLEANUP
- name: Include DNS role to register Gitea domain(s) - name: Include DNS role to register Gitea domain(s)
include_role: include_role:
name: srv-web-7-7-dns-records name: srv-web-7-7-dns-records
vars: vars:
cloudflare_api_token: "{{ certbot_dns_api_token }}" cloudflare_api_token: "{{ CERTBOT_DNS_API_TOKEN }}"
cloudflare_domains: "{{ [ domains | get_domain(application_id) ] }}" cloudflare_domains: "{{ [ domains | get_domain(application_id) ] }}"
cloudflare_target_ip: "{{ networks.internet.ip4 }}" cloudflare_target_ip: "{{ networks.internet.ip4 }}"
cloudflare_proxied: false cloudflare_proxied: false
when: dns_provider == 'cloudflare' when: DNS_PROVIDER == 'cloudflare'

View File

@ -13,7 +13,7 @@
docker exec -i --user {{ gitea_user }} {{ gitea_container }} \ docker exec -i --user {{ gitea_user }} {{ gitea_container }} \
gitea admin auth list \ gitea admin auth list \
| tail -n +2 \ | tail -n +2 \
| grep -F "LDAP ({{ primary_domain }})" \ | grep -F "LDAP ({{ PRIMARY_DOMAIN }})" \
| awk '{print $1; exit}' | awk '{print $1; exit}'
args: args:
chdir: "{{ docker_compose.directories.instance }}" chdir: "{{ docker_compose.directories.instance }}"

View File

@ -3,7 +3,7 @@
# General # General
DOMAIN={{domains | get_domain(application_id)}} DOMAIN={{domains | get_domain(application_id)}}
RUN_MODE="{{ 'dev' if (INFINITO_ENVIRONMENT | lower) == 'development' else 'prod' }}" RUN_MODE="{{ 'dev' if (ENVIRONMENT | lower) == 'development' else 'prod' }}"
ROOT_URL="{{ domains | get_url(application_id, WEB_PROTOCOL) }}/" ROOT_URL="{{ domains | get_url(application_id, WEB_PROTOCOL) }}/"
APP_NAME="{{ applications | get_app_conf(application_id, 'title', True) }}" APP_NAME="{{ applications | get_app_conf(application_id, 'title', True) }}"
USER_UID=1000 USER_UID=1000
@ -11,7 +11,7 @@ USER_GID=1000
# Logging configuration # Logging configuration
GITEA__log__MODE=console GITEA__log__MODE=console
GITEA__log__LEVEL={% if enable_debug | bool %}Debug{% else %}Info{% endif %} GITEA__log__LEVEL={% if MODE_DEBUG | bool %}Debug{% else %}Info{% endif %}
# Database # Database
DB_TYPE=mysql DB_TYPE=mysql

View File

@ -1,7 +1,7 @@
application_id: "web-app-gitea" application_id: "web-app-gitea"
database_type: "mariadb" database_type: "mariadb"
gitea_ldap_auth_args: gitea_ldap_auth_args:
- '--name "LDAP ({{ primary_domain }})"' - '--name "LDAP ({{ PRIMARY_DOMAIN }})"'
- '--host "{{ ldap.server.domain }}"' - '--host "{{ ldap.server.domain }}"'
- '--port {{ ldap.server.port }}' - '--port {{ ldap.server.port }}'
- '--security-protocol "{{ ldap.server.security | trim or "unencrypted" }}"' - '--security-protocol "{{ ldap.server.security | trim or "unencrypted" }}"'

View File

@ -18,4 +18,4 @@ credentials:
server: server:
domains: domains:
canonical: canonical:
- gitlab.{{ primary_domain }} - gitlab.{{ PRIMARY_DOMAIN }}

View File

@ -3,4 +3,4 @@ features:
server: server:
domains: domains:
canonical: canonical:
- jenkins.{{ primary_domain }} - jenkins.{{ PRIMARY_DOMAIN }}

View File

@ -9,7 +9,7 @@ features:
server: server:
domains: domains:
canonical: canonical:
- "cms.{{ primary_domain }}" - "cms.{{ PRIMARY_DOMAIN }}"
docker: docker:
services: services:
database: database:

View File

@ -28,7 +28,7 @@ server:
- "*" # For frontend channel logout it's necessary that iframes can be loaded - "*" # For frontend channel logout it's necessary that iframes can be loaded
domains: domains:
canonical: canonical:
- "auth.{{ primary_domain }}" - "auth.{{ PRIMARY_DOMAIN }}"
scopes: scopes:
rbac_roles: rbac_roles rbac_roles: rbac_roles
nextcloud: nextcloud nextcloud: nextcloud

View File

@ -25,7 +25,7 @@ KC_BOOTSTRAP_ADMIN_USERNAME= "{{applications | get_app_conf(application_id, '
KC_BOOTSTRAP_ADMIN_PASSWORD= "{{applications | get_app_conf(application_id, 'credentials.administrator_password', True)}}" KC_BOOTSTRAP_ADMIN_PASSWORD= "{{applications | get_app_conf(application_id, 'credentials.administrator_password', True)}}"
# Enable detailed logs # Enable detailed logs
{% if enable_debug | bool %} {% if MODE_DEBUG | bool %}
KC_LOG_LEVEL=DEBUG KC_LOG_LEVEL=DEBUG
KC_LOG_CONSOLE_ENABLED=true KC_LOG_CONSOLE_ENABLED=true
{% endif %} {% endif %}

View File

@ -836,7 +836,7 @@
{# The following line should be covered by 02_update_client_redirects.yml #} {# The following line should be covered by 02_update_client_redirects.yml #}
"redirectUris": {{ domains | redirect_uris(applications, WEB_PROTOCOL) | tojson }}, "redirectUris": {{ domains | redirect_uris(applications, WEB_PROTOCOL) | tojson }},
"webOrigins": [ "webOrigins": [
"{{ WEB_PROTOCOL }}://*.{{primary_domain}}" "{{ WEB_PROTOCOL }}://*.{{PRIMARY_DOMAIN}}"
], ],
"notBefore": 0, "notBefore": 0,
"bearerOnly": false, "bearerOnly": false,
@ -853,7 +853,7 @@
"oidc.ciba.grant.enabled": "false", "oidc.ciba.grant.enabled": "false",
"client.secret.creation.time": "0", "client.secret.creation.time": "0",
"backchannel.logout.session.required": "true", "backchannel.logout.session.required": "true",
"post.logout.redirect.uris": "{{ WEB_PROTOCOL }}://{{primary_domain}}/*##+", "post.logout.redirect.uris": "{{ WEB_PROTOCOL }}://{{PRIMARY_DOMAIN}}/*##+",
"frontchannel.logout.session.required": "true", "frontchannel.logout.session.required": "true",
"oauth2.device.authorization.grant.enabled": "false", "oauth2.device.authorization.grant.enabled": "false",
"display.on.consent.screen": "false", "display.on.consent.screen": "false",

View File

@ -5,7 +5,7 @@ database_type: "postgres"
# Keycloak # Keycloak
keycloak_container: "{{ applications | get_app_conf(application_id, 'docker.services.keycloak.name') }}" # Name of the keycloak docker container keycloak_container: "{{ applications | get_app_conf(application_id, 'docker.services.keycloak.name') }}" # Name of the keycloak docker container
keycloak_docker_import_directory: "/opt/keycloak/data/import/" # Directory in which keycloak import files are placed in the running docker container keycloak_docker_import_directory: "/opt/keycloak/data/import/" # Directory in which keycloak import files are placed in the running docker container
keycloak_realm: "{{ primary_domain}}" # This is the name of the default realm which is used by the applications keycloak_realm: "{{ PRIMARY_DOMAIN}}" # This is the name of the default realm which is used by the applications
keycloak_master_api_user: "{{ applications | get_app_conf(application_id, 'users.administrator') }}" # Master Administrator keycloak_master_api_user: "{{ applications | get_app_conf(application_id, 'users.administrator') }}" # Master Administrator
keycloak_master_api_user_name: "{{ keycloak_master_api_user.username }}" # Master Administrator Username keycloak_master_api_user_name: "{{ keycloak_master_api_user.username }}" # Master Administrator Username
keycloak_master_api_user_password: "{{ keycloak_master_api_user.password }}" # Master Administrator Password keycloak_master_api_user_password: "{{ keycloak_master_api_user.password }}" # Master Administrator Password
@ -15,7 +15,7 @@ keycloak_server_host: "127.0.0.1:{{ ports.localhost.http[applicati
keycloak_server_host_url: "http://{{ keycloak_server_host }}" keycloak_server_host_url: "http://{{ keycloak_server_host }}"
keycloak_image: "{{ applications | get_app_conf(application_id, 'docker.services.keycloak.image') }}" # Keycloak docker image keycloak_image: "{{ applications | get_app_conf(application_id, 'docker.services.keycloak.image') }}" # Keycloak docker image
keycloak_version: "{{ applications | get_app_conf(application_id, 'docker.services.keycloak.version') }}" # Keycloak docker version keycloak_version: "{{ applications | get_app_conf(application_id, 'docker.services.keycloak.version') }}" # Keycloak docker version
keycloak_debug_enabled: "{{ enable_debug }}" keycloak_debug_enabled: "{{ MODE_DEBUG }}"
keycloak_redirect_features: ["features.oauth2","features.oidc"] keycloak_redirect_features: ["features.oauth2","features.oidc"]
keycloak_client_id: "{{ oidc.client.id }}" keycloak_client_id: "{{ oidc.client.id }}"
keycloak_ldap_component_name: "{{ ldap.server.domain }}" # Name of the LDAP User Federation component in Keycloak (as shown in UI) keycloak_ldap_component_name: "{{ ldap.server.domain }}" # Name of the LDAP User Federation component in Keycloak (as shown in UI)

View File

@ -27,7 +27,7 @@ server:
unsafe-inline: true unsafe-inline: true
domains: domains:
aliases: aliases:
- "ldap.{{primary_domain}}" - "ldap.{{PRIMARY_DOMAIN}}"
canonical: canonical:
- lam.{{ primary_domain }} - lam.{{ PRIMARY_DOMAIN }}

View File

@ -24,7 +24,7 @@ server:
flags: {} # Flags which should be set flags: {} # Flags which should be set
domains: domains:
canonical: canonical:
- "libretranslate.{{ primary_domain }}" - "libretranslate.{{ PRIMARY_DOMAIN }}"
aliases: [] # Alias redirections to the first element of the canonical domains aliases: [] # Alias redirections to the first element of the canonical domains
rbac: rbac:
roles: {} roles: {}

View File

@ -9,7 +9,7 @@ features:
server: server:
domains: domains:
canonical: canonical:
- "newsletter.{{ primary_domain }}" - "newsletter.{{ PRIMARY_DOMAIN }}"
docker: docker:
services: services:
database: database:

View File

@ -1,7 +1,7 @@
oidc: oidc:
email_by_username: true # If true, then the mail is set by the username. If wrong then the OIDC user email is used email_by_username: true # If true, then the mail is set by the username. If wrong then the OIDC user email is used
enable_user_creation: true # Users will be created if not existing enable_user_creation: true # Users will be created if not existing
domain: "{{ primary_domain }}" # The main domain from which mails will be send \ email suffix behind @ domain: "{{ PRIMARY_DOMAIN }}" # The main domain from which mails will be send \ email suffix behind @
features: features:
matomo: true matomo: true
css: false css: false
@ -12,7 +12,7 @@ features:
server: server:
domains: domains:
canonical: canonical:
- "mail.{{ primary_domain }}" - "mail.{{ PRIMARY_DOMAIN }}"
csp: csp:
flags: flags:
style-src: style-src:

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