Compare commits

..

13 Commits

127 changed files with 918 additions and 227 deletions

View File

@ -95,7 +95,7 @@ Now that you have defined the application settings, domain, and application ID,
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -0,0 +1,69 @@
import re
from ansible.errors import AnsibleFilterError
class FilterModule(object):
"""
Custom Ansible filter plugin:
- generate_all_domains: Flatten, dedupe, sort domains with optional www prefixes
- generate_base_sld_domains: Extract unique sld.tld domains from values and redirect sources
"""
def filters(self):
return {
'generate_all_domains': self.generate_all_domains,
'generate_base_sld_domains': self.generate_base_sld_domains,
}
@staticmethod
def generate_all_domains(domains_dict, include_www=True):
"""
Transform a dict of domains (values: str, list, dict) into a flat list,
optionally add 'www.' prefixes, dedupe and sort alphabetically.
Avoids infinite loops by snapshotting initial domain list for www prefixes.
"""
try:
flat = FilterModule._flatten_domain_values(domains_dict)
if include_www:
# Snapshot original list to avoid extending while iterating
original = list(flat)
flat.extend([f"www.{d}" for d in original])
return sorted(set(flat))
except Exception as exc:
raise AnsibleFilterError(f"generate_all_domains failed: {exc}")
@staticmethod
def generate_base_sld_domains(domains_dict, redirect_mappings):
"""
Flatten domains_dict and redirect_mappings, extract second-level + top-level domains.
redirect_mappings: list of dicts with key 'source'
"""
try:
flat = FilterModule._flatten_domain_values(domains_dict)
for mapping in redirect_mappings or []:
src = mapping.get('source')
if isinstance(src, str):
flat.append(src)
elif isinstance(src, list):
flat.extend(src)
pattern = re.compile(r'^(?:.*\.)?([^.]+\.[^.]+)$')
slds = {m.group(1) for d in flat if (m := pattern.match(d))}
return sorted(slds)
except Exception as exc:
raise AnsibleFilterError(f"generate_base_sld_domains failed: {exc}")
@staticmethod
def _flatten_domain_values(domains_dict):
"""
Helper to extract domain strings from dict values (str, list, dict).
"""
flat = []
for val in (domains_dict or {}).values():
if isinstance(val, str):
flat.append(val)
elif isinstance(val, list):
flat.extend(val)
elif isinstance(val, dict):
flat.extend(val.values())
return flat

View File

@ -0,0 +1,60 @@
from ansible.errors import AnsibleFilterError
class FilterModule(object):
'''Ansible filter plugin to retrieve the correct domain for a given application_id.'''
def filters(self):
return {
'get_domain': self.get_domain,
}
def get_domain(self, domains, application_id):
"""
Return the domain for application_id from the domains mapping:
- If value is a string, return it.
- If value is a dict, return its first value.
- If value is a list, return its first element.
- Otherwise, raise an error.
"""
# Ensure domains is a mapping
if not isinstance(domains, dict):
raise AnsibleFilterError(f"'domains' must be a dict, got {type(domains).__name__}")
if application_id not in domains:
raise AnsibleFilterError(f"application_id '{application_id}' not found in domains mapping")
val = domains[application_id]
# String case
if isinstance(val, str):
if not val:
raise AnsibleFilterError(f"domains['{application_id}'] is an empty string")
return val
# Dict case
if isinstance(val, dict):
try:
first_val = next(iter(val.values()))
except StopIteration:
raise AnsibleFilterError(f"domains['{application_id}'] dict is empty")
if not isinstance(first_val, str) or not first_val:
raise AnsibleFilterError(
f"first value of domains['{application_id}'] must be a non-empty string, got {first_val!r}"
)
return first_val
# List case
if isinstance(val, list):
if not val:
raise AnsibleFilterError(f"domains['{application_id}'] list is empty")
first = val[0]
if not isinstance(first, str) or not first:
raise AnsibleFilterError(
f"first element of domains['{application_id}'] must be a non-empty string, got {first!r}"
)
return first
# Other types
raise AnsibleFilterError(
f"domains['{application_id}'] has unsupported type {type(val).__name__}, must be str, dict or list"
)

View File

@ -1,8 +1,15 @@
import os
import yaml
from ansible.errors import AnsibleFilterError
class FilterModule(object):
"""
Custom filters for conditional domain assignments
Custom filters for conditional domain assignments, handling both direct group matches
and recursive role dependency resolution.
Determines if a given application_id (domain_key) should have its domain added by checking:
- If domain_key is explicitly listed in group_names, or
- If domain_key matches any application_id of roles reachable from active groups via dependencies.
"""
def filters(self):
@ -13,17 +20,67 @@ class FilterModule(object):
@staticmethod
def add_domain_if_group(domains_dict, domain_key, domain_value, group_names):
"""
Add {domain_key: domain_value} to domains_dict
only if domain_key is in group_names.
Add {domain_key: domain_value} to domains_dict if either:
1) domain_key is in group_names (direct inclusion), or
2) domain_key is among collected application_id values of roles
reachable from any group in group_names via recursive dependencies.
Usage in Jinja:
{{ {}
| add_domain_if_group('akaunting', 'akaunting.' ~ primary_domain, group_names) }}
Parameters:
domains_dict: existing dict of domains
domain_key: name of the application to check
domain_value: domain or dict/list of domains to assign
group_names: list of active group (role/application) names
"""
try:
result = dict(domains_dict)
# Direct group match: if the application name itself is in group_names
if domain_key in group_names:
result[domain_key] = domain_value
return result
# Setup roles directory path
plugin_dir = os.path.dirname(__file__)
project_root = os.path.abspath(os.path.join(plugin_dir, '..'))
roles_dir = os.path.join(project_root, 'roles')
# Collect all roles reachable from the active groups
def collect_roles(role_name, collected):
if role_name in collected:
return
collected.add(role_name)
meta_path = os.path.join(roles_dir, role_name, 'meta', 'main.yml')
if os.path.isfile(meta_path):
with open(meta_path) as f:
meta = yaml.safe_load(f) or {}
for dep in meta.get('dependencies', []):
if isinstance(dep, str):
dep_name = dep
elif isinstance(dep, dict):
dep_name = dep.get('role') or dep.get('name')
else:
continue
collect_roles(dep_name, collected)
included_roles = set()
for grp in group_names:
collect_roles(grp, included_roles)
# Gather application_ids from each included role
app_ids = set()
for role in included_roles:
vars_main = os.path.join(roles_dir, role, 'vars', 'main.yml')
if os.path.isfile(vars_main):
with open(vars_main) as f:
vars_data = yaml.safe_load(f) or {}
app_id = vars_data.get('application_id')
if app_id:
app_ids.add(app_id)
# Indirect inclusion: match by application_id
if domain_key in app_ids:
result[domain_key] = domain_value
return result
except Exception as exc:
raise AnsibleFilterError(f"add_domain_if_group failed: {exc}")

View File

@ -21,7 +21,7 @@ class FilterModule(object):
{{ redirect_list
| add_redirect_if_group('lam',
'ldap.' ~ primary_domain,
domains.lam,
domains | get_domain('lam'),
group_names) }}
"""
try:

55
filter_plugins/safe.py Normal file
View File

@ -0,0 +1,55 @@
from jinja2 import Undefined
def safe_placeholders(template: str, mapping: dict = None) -> str:
"""
Format a template like "{url}/logo.png".
If mapping is provided (not None) and ANY placeholder is missing or maps to None/empty string, the function will raise KeyError.
If mapping is None, missing placeholders or invalid templates return empty string.
Numerical zero or False are considered valid values.
Any other formatting errors return an empty string.
"""
# Non-string templates yield empty
if not isinstance(template, str):
return ''
class SafeDict(dict):
def __getitem__(self, key):
val = super().get(key, None)
# Treat None or empty string as missing
if val is None or (isinstance(val, str) and val == ''):
raise KeyError(key)
return val
def __missing__(self, key):
raise KeyError(key)
silent = mapping is None
data = mapping or {}
try:
return template.format_map(SafeDict(data))
except KeyError:
if silent:
return ''
raise
except Exception:
return ''
def safe_var(value):
"""
Ansible filter: returns the value unchanged unless it's Undefined or None,
in which case returns an empty string.
Catches all exceptions and yields ''.
"""
try:
if isinstance(value, Undefined) or value is None:
return ''
return value
except Exception:
return ''
class FilterModule(object):
def filters(self):
return {
'safe_var': safe_var,
'safe_placeholders': safe_placeholders,
}

View File

@ -0,0 +1,29 @@
# file: filter_plugins/safe_join.py
"""
Ansible filter plugin that joins a base string and a tail path safely.
If the base is falsy (None, empty, etc.), returns an empty string.
"""
def safe_join(base, tail):
"""
Safely join base and tail into a path or URL.
- base: the base string. If falsy, returns ''.
- tail: the string to append. Leading/trailing slashes are handled.
- On any exception, returns ''.
"""
try:
if not base:
return ''
base_str = str(base).rstrip('/')
tail_str = str(tail).lstrip('/')
return f"{base_str}/{tail_str}"
except Exception:
return ''
class FilterModule(object):
def filters(self):
return {
'safe_join': safe_join,
}

View File

@ -21,8 +21,7 @@ defaults_domains: >-
| add_domain_if_group('mailu', 'mail.' ~ primary_domain, group_names)
| add_domain_if_group('mastodon', ['microblog.' ~ primary_domain], group_names)
| add_domain_if_group('matomo', 'matomo.' ~ primary_domain, group_names)
| add_domain_if_group('matrix', 'matrix.' ~ primary_domain, group_names)
| add_domain_if_group('matrix', 'element.' ~ primary_domain, group_names)
| add_domain_if_group('matrix', {'synapse': 'matrix.' ~ primary_domain, 'element':'element.' ~ primary_domain}, group_names)
| add_domain_if_group('moodle', 'academy.' ~ primary_domain, group_names)
| add_domain_if_group('mediawiki', 'wiki.' ~ primary_domain, group_names)
| add_domain_if_group('nextcloud', 'cloud.' ~ primary_domain, group_names)

View File

@ -9,7 +9,7 @@
## Helper Variables:
_oidc_client_realm: "{{ oidc.client.realm if oidc.client is defined and oidc.client.realm is defined else primary_domain }}"
_oidc_client_issuer_url: "{{ web_protocol }}://{{domains.keycloak}}/realms/{{_oidc_client_realm}}"
_oidc_client_issuer_url: "{{ web_protocol }}://{{domains | get_domain('keycloak')}}/realms/{{_oidc_client_realm}}"
defaults_oidc:
client:

View File

@ -9,23 +9,31 @@ defaults_service_provider:
city: "Cybertown"
postal_code: "00001"
country: "Nexusland"
logo: "{{applications.assets_server.url}}/logo.png"
logo: "{{ applications.assets_server.url | safe_var | safe_join('logo.png') }}"
platform:
titel: "CyMaIS Demo"
subtitel: "The Future of Self-Hosted Infrastructure. Secure. Automated. Sovereign."
logo: "{{applications.assets_server.url}}/img/logo.png"
favicon: "{{applications.assets_server.url}}/img/favicon.ico"
logo: "{{ applications.assets_server.url | safe_var | safe_join('logo.png') }}"
favicon: "{{ applications.assets_server.url | safe_var | safe_join('favicon.ico') }}"
contact:
bluesky: "{{ '@' ~ users.administrator.username ~ '.' ~ domains.[application_id]['api'] if 'bluesky' in group_names else '' }}"
bluesky: >-
{{ ('@' ~ users.administrator.username ~ '.' ~ domains.bluesky.api)
if 'bluesky' in group_names else '' }}
email: "contact@{{ primary_domain }}"
mastodon: "{{ '@' ~ users.administrator.username ~ '@' ~ domains.mastodon if 'mastodon' in group_names else '' }}"
matrix: "{{ '@' ~ users.administrator.username ~ ':' ~ domains.synapse if 'matrix' in group_names else '' }}"
peertube: "{{ '@' ~ users.administrator.username ~ '@' ~ domains.peertube[0] if 'peertube' in group_names else '' }}"
pixelfed: "{{ '@' ~ users.administrator.username ~ '@' ~ domains.pixelfed if 'pixelfed' in group_names else '' }}"
mastodon: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('mastodon') if 'mastodon' in group_names else '' }}"
matrix: "{{ '@' ~ users.administrator.username ~ ':' ~ domains.matrix.synapse if 'matrix' in group_names else '' }}"
peertube: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('peertube') if 'peertube' in group_names else '' }}"
pixelfed: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('pixelfed') if 'pixelfed' in group_names else '' }}"
phone: "+0 000 000 404"
wordpress: "{{ '@' ~ users.administrator.username ~ '@' ~ domains.wordpress[0] if 'wordpress' in group_names else '' }}"
wordpress: "{{ '@' ~ users.administrator.username ~ '@' ~ domains | get_domain('wordpress') if 'wordpress' in group_names else '' }}"
legal:
editorial_responsible: "Johannes Gutenberg"
source_code: "https://github.com/kevinveenbirkenbach/cymais"
imprint: "{{ web_protocol }}://{{domains.html_server}}/imprint.html"
imprint: >-
{{ "{protocol}://{domain}/imprint.html"
| safe_placeholders({
'protocol': web_protocol,
'domain': domains.html_server
})
}}

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "include tasks update-repository-with-files.yml"

View File

@ -1,5 +1,5 @@
# You should change this to match your reverse proxy DNS name and protocol
APP_URL=https://{{domains[application_id]}}
APP_URL=https://{{domains | get_domain(application_id)}}
LOCALE={{ HOST_LL }}
# Don't change this unless you rename your database container or use rootless podman, in case of using rootless podman you should set it to 127.0.0.1 (NOT localhost)

View File

@ -10,13 +10,13 @@
domain: "{{ item }}"
http_port: "{{ ports.localhost.http[application_id] }}"
loop:
- "{{ domains.mailu }}"
- "{{ domains | get_domain('mailu') }}"
- "{{ domain }}"
- name: configure {{domains[application_id]}}.conf
- name: configure {{domains | get_domain(application_id)}}.conf
template:
src: roles/nginx-docker-reverse-proxy/templates/vhost/basic.conf.j2
dest: "{{nginx.directories.http.servers}}{{domains[application_id]}}.conf"
dest: "{{nginx.directories.http.servers}}{{domains | get_domain(application_id)}}.conf"
notify: restart nginx
- name: "include tasks update-repository-with-files.yml"

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -1,5 +1,5 @@
application_id: "baserow"
database_password: "{{ baserow_database_password }}"
database_type: "postgres"
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"

View File

@ -54,7 +54,7 @@
- name: Wait for BigBlueButton
wait_for:
host: "{{ domains.bigbluebutton }}"
host: "{{ domains | get_domain('bigbluebutton') }}"
port: 80
delay: 5
timeout: 600

View File

@ -37,7 +37,7 @@ FSESL_PASSWORD={{applications[application_id].credentials.fsesl_password}}
# CONNECTION
# ====================================
DOMAIN={{domains[application_id]}}
DOMAIN={{domains | get_domain(application_id)}}
EXTERNAL_IPv4={{networks.internet.ip4}}
# The following line is not tested and could lead to bugs:
@ -50,7 +50,7 @@ STUN_PORT={{ ports.public.stun[application_id] }}
# TURN SERVER
# uncomment and adjust following two lines to add an external TURN server
TURN_SERVER=turns:{{domains[application_id]}}:{{ ports.public.turn[application_id] }}?transport=tcp
TURN_SERVER=turns:{{domains | get_domain(application_id)}}:{{ ports.public.turn[application_id] }}?transport=tcp
TURN_SECRET={{applications[application_id].credentials.turn_secret}}
# Allowed SIP IPs
@ -290,6 +290,6 @@ DEFAULT_REGISTRATION=invite
OPENID_CONNECT_CLIENT_ID={{oidc.client.id}}
OPENID_CONNECT_CLIENT_SECRET={{oidc.client.secret}}
OPENID_CONNECT_ISSUER={{oidc.client.issuer_url}}
OPENID_CONNECT_REDIRECT=https://{{domains[application_id]}}
OPENID_CONNECT_REDIRECT=https://{{domains | get_domain(application_id)}}
# OPENID_CONNECT_UID_FIELD=sub default
{% endif %}

View File

@ -11,7 +11,7 @@ database:
name: "multiple_databases"
username: "postgres2"
urls:
api: "{{ web_protocol }}://{{domains.bigbluebutton}}/bigbluebutton/" # API Address used by Nextcloud Integration
api: "{{ web_protocol }}://{{domains | get_domain('bigbluebutton')}}/bigbluebutton/" # API Address used by Nextcloud Integration
features:
matomo: true
css: true

View File

@ -7,7 +7,7 @@ docker_compose_file_final: "{{ docker_compose.directories.instance }}docker-c
database_type: "postgres"
database_password: "{{ applications.bigbluebutton.credentials.postgresql_secret }}"
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
bbb_env_file_link: "{{ docker_compose.directories.instance }}.env"
bbb_env_file_origine: "{{ bbb_repository_directory }}.env"

View File

@ -10,8 +10,8 @@
domain: "{{ item.domain }}"
http_port: "{{ item.http_port }}"
loop:
- { domain: domains.[application_id]['api'], http_port: ports.localhost.http.bluesky_api }
- { domain: domains.[application_id]['web'], http_port: ports.localhost.http.bluesky_web }
- { domain: domains.[application_id].api, http_port: ports.localhost.http.bluesky_api }
- { domain: domains.[application_id].web, http_port: ports.localhost.http.bluesky_web }
# The following lines should be removed when the following issue is closed:
# https://github.com/bluesky-social/pds/issues/52

View File

@ -22,8 +22,8 @@ services:
dockerfile: Dockerfile
# It doesn't compile yet with this parameters. @todo Fix it
args:
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_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_SITE_NAME: "{{primary_domain | upper}} - Bluesky"
REACT_APP_SITE_DESCRIPTION: "Decentral Social "
ports:

View File

@ -1,6 +1,6 @@
PDS_HOSTNAME="{{domains.[application_id]['api']}}"
PDS_HOSTNAME="{{domains.[application_id].api}}"
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/
PDS_SERVICE_HANDLE_DOMAINS=".{{primary_domain}}"
@ -15,7 +15,7 @@ PDS_BLOBSTORE_DISK_LOCATION=/opt/pds/blocks
PDS_DATA_DIRECTORY: /opt/pds
PDS_BLOB_UPLOAD_LIMIT: 52428800
PDS_DID_PLC_URL=https://plc.directory
PDS_BSKY_APP_VIEW_URL=https://{{domains.[application_id]['web']}}
PDS_BSKY_APP_VIEW_DID=did:web:{{domains.[application_id]['web']}}
PDS_BSKY_APP_VIEW_URL=https://{{domains.[application_id].web}}
PDS_BSKY_APP_VIEW_DID=did:web:{{domains.[application_id].web}}
PDS_REPORT_SERVICE_URL=https://mod.bsky.app
PDS_REPORT_SERVICE_DID=did:plc:ar7c4by46qjdydhdevvrndac

View File

@ -16,7 +16,7 @@
- CMD-SHELL
- >
if [ ! -f /tmp/email_sent ]; then
echo 'Subject: testmessage from {{domains[application_id]}}\n\nSUCCESSFULL' | msmtp -t {{users.blackhole.email}} && touch /tmp/email_sent;
echo 'Subject: testmessage from {{domains | get_domain(application_id)}}\n\nSUCCESSFULL' | msmtp -t {{users.blackhole.email}} && touch /tmp/email_sent;
fi &&
curl -f http://localhost:80/ || exit 1
interval: 1m

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -16,7 +16,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
when: run_once_docker_discourse is not defined

View File

@ -41,7 +41,7 @@ env:
UNICORN_WORKERS: 8
## Required. Discourse will not work with a bare IP number.
DISCOURSE_HOSTNAME: {{domains[application_id]}}
DISCOURSE_HOSTNAME: {{domains | get_domain(application_id)}}
## Uncomment if you want the container to be started with the same
## hostname (-h option) as specified above (default "$hostname-$config")
@ -51,8 +51,10 @@ env:
DISCOURSE_DEVELOPER_EMAILS: {{users.administrator.email}}
# Set Logo
{% if service_provider.platform.logo | bool %}
DISCOURSE_LOGO_URL: "{{ service_provider.platform.logo }}"
DISCOURSE_LOGO_SMALL_URL: "{{ service_provider.platform.logo }}"
{% endif %}
# SMTP ADDRESS, username, and password are required
# WARNING the char '#' in SMTP password can cause problems!
@ -135,7 +137,7 @@ run:
- exec: rails r "SiteSetting.openid_connect_discovery_document = '{{oidc.client.discovery_document}}'"
- exec: rails r "SiteSetting.openid_connect_client_id = '{{oidc.client.id}}'"
- exec: rails r "SiteSetting.openid_connect_client_secret = '{{oidc.client.secret}}'"
- exec: rails r "SiteSetting.openid_connect_rp_initiated_logout_redirect = 'https://{{domains[application_id]}}'"
- exec: rails r "SiteSetting.openid_connect_rp_initiated_logout_redirect = 'https://{{domains | get_domain(application_id)}}'"
- exec: rails r "SiteSetting.openid_connect_allow_association_change = false"
- exec: rails r "SiteSetting.openid_connect_rp_initiated_logout = true"
{% endif %}

View File

@ -4,7 +4,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: create elasticsearch-sysctl.conf

View File

@ -11,7 +11,7 @@
ws_port: "{{ ports.localhost.websocket[application_id] }}"
client_max_body_size: "100m"
vhost_flavour: "ws_generic"
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -31,7 +31,7 @@ services:
driver: journald
environment:
- ESPOCRM_CONFIG_USE_WEB_SOCKET=true
- ESPOCRM_CONFIG_WEB_SOCKET_URL=ws://{{ domains[application_id] }}/ws
- ESPOCRM_CONFIG_WEB_SOCKET_URL=ws://{{ domains | get_domain(application_id) }}/ws
- ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBSCRIBER_DSN=tcp://*:7777
- ESPOCRM_CONFIG_WEB_SOCKET_ZERO_M_Q_SUBMISSION_DSN=tcp://websocket:7777
entrypoint: docker-websocket.sh

View File

@ -23,7 +23,7 @@ ESPOCRM_ADMIN_USERNAME={{ applications[application_id].users.administrator.usern
ESPOCRM_ADMIN_PASSWORD={{ applications[application_id].credentials.administrator_password }}
# Public base URL of the EspoCRM instance
ESPOCRM_SITE_URL={{ web_protocol }}://{{ domains[application_id] }}
ESPOCRM_SITE_URL={{ web_protocol }}://{{ domains | get_domain(application_id) }}
# ------------------------------------------------
# General UI & locale settings
@ -94,7 +94,7 @@ ESPOCRM_CONFIG_OIDC_TOKEN_ENDPOINT={{ oidc.client.token_url }}
ESPOCRM_CONFIG_OIDC_USER_INFO_ENDPOINT={{ oidc.client.user_info_url }}
ESPOCRM_CONFIG_OIDC_JWKS_ENDPOINT={{ oidc.client.certs }}
ESPOCRM_CONFIG_OIDC_AUTHORIZATION_REDIRECT_URI=https://{{ domains[application_id] }}/oidc/callback
ESPOCRM_CONFIG_OIDC_AUTHORIZATION_REDIRECT_URI=https://{{ domains | get_domain(application_id) }}/oidc/callback
#ESPOCRM_CONFIG_OIDC_SCOPES=openid,profile,email # Defined in main.yml
ESPOCRM_CONFIG_OIDC_CREATE_USER=true

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -1,8 +1,8 @@
# The configuration options can be found here:
# @see https://hub.docker.com/_/friendica
FRIENDICA_URL= https://{{domains[application_id]}}
HOSTNAME= {{domains[application_id]}}
FRIENDICA_URL= https://{{domains | get_domain(application_id)}}
HOSTNAME= {{domains | get_domain(application_id)}}
FRIENDICA_NO_VALIDATION={{no_validation | lower}}
# Debugging

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -40,7 +40,7 @@ FUNKWHALE_WEB_WORKERS=4
# Replace this by the definitive, public domain you will use for
# your instance. It cannot be changed after initial deployment
# without breaking your instance.
FUNKWHALE_HOSTNAME={{domains[application_id]}}
FUNKWHALE_HOSTNAME={{domains | get_domain(application_id)}}
FUNKWHALE_PROTOCOL=https
# Log level (debug, info, warning, error, critical)

View File

@ -6,7 +6,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -10,10 +10,10 @@ DB_USER={{database_username}}
DB_PASSWD={{database_password}}
SSH_PORT={{ports.public.ssh[application_id]}}
SSH_LISTEN_PORT=22
DOMAIN={{domains[application_id]}}
SSH_DOMAIN={{domains[application_id]}}
DOMAIN={{domains | get_domain(application_id)}}
SSH_DOMAIN={{domains | get_domain(application_id)}}
RUN_MODE="{{ 'dev' if (CYMAIS_ENVIRONMENT | lower) == 'development' else 'prod' }}"
ROOT_URL="{{ web_protocol }}://{{domains[application_id]}}/"
ROOT_URL="{{ web_protocol }}://{{domains | get_domain(application_id)}}/"
# Mail Configuration
# @see https://docs.gitea.com/next/installation/install-with-docker#managing-deployments-with-environment-variables

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -6,7 +6,7 @@ services:
web:
image: "gitlab/gitlab-ee:{{applications.gitlab.version}}"
hostname: '{{domains[application_id]}}'
hostname: '{{domains | get_domain(application_id)}}'
{% include 'roles/docker-compose/templates/services/base.yml.j2' %}
ports:
- "127.0.0.1:{{ports.localhost.http[application_id]}}:80"

View File

@ -2,7 +2,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "docker jenkins"

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
loop: "{{ domains }}"
loop_control:

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -14,7 +14,7 @@ services:
{% include 'templates/docker/container/depends-on-just-database.yml.j2' %}
{% include 'templates/docker/container/networks.yml.j2' %}
healthcheck:
test: ["CMD", "sh", "-c", "exec 3<>/dev/tcp/localhost/9000 && echo -e 'GET /health/live HTTP/1.1\\r\\nHost: {{domains.keycloak}}\\r\\nConnection: close\\r\\n\\r\\n' >&3 && cat <&3"]
test: ["CMD", "sh", "-c", "exec 3<>/dev/tcp/localhost/9000 && echo -e 'GET /health/live HTTP/1.1\\r\\nHost: {{domains | get_domain('keycloak')}}\\r\\nConnection: close\\r\\n\\r\\n' >&3 && cat <&3"]
interval: 30s
timeout: 10s
retries: 3

View File

@ -2,7 +2,7 @@
# Documentation can be found here:
# @see https://www.keycloak.org/server/containers
KC_HOSTNAME= https://{{domains[application_id]}}
KC_HOSTNAME= https://{{domains | get_domain(application_id)}}
KC_HTTP_ENABLED= true
# Health Checks

View File

@ -517,7 +517,7 @@
"/realms/{{realm}}/account/*"
],
"webOrigins": [
"{{ web_protocol }}://{{domains.keycloak}}"
"{{ web_protocol }}://{{domains | get_domain('keycloak')}}"
],
"notBefore": 0,
"bearerOnly": false,
@ -1663,7 +1663,7 @@
"replyTo": "",
"host": "{{system_email.host}}",
"from": "{{ users['no-reply'].email }}",
"fromDisplayName": "Keycloak Authentification System - {{domains.keycloak}}",
"fromDisplayName": "Keycloak Authentification System - {{domains | get_domain('keycloak')}}",
"envelopeFrom": "",
"ssl": "true",
"user": "{{ users['no-reply'].email }}"

View File

@ -6,7 +6,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -3,16 +3,16 @@
include_role:
name: docker-compose
- name: Create {{domains[application_id]}}.conf if LDAP is exposed to internet
- name: Create {{domains | get_domain(application_id)}}.conf if LDAP is exposed to internet
template:
src: "nginx.stream.conf.j2"
dest: "{{nginx.directories.streams}}{{domains[application_id]}}.conf"
dest: "{{nginx.directories.streams}}{{domains | get_domain(application_id)}}.conf"
notify: restart nginx
when: applications[application_id].network.public | bool
- name: Remove {{domains[application_id]}}.conf if LDAP is not exposed to internet
- name: Remove {{domains | get_domain(application_id)}}.conf if LDAP is not exposed to internet
file:
path: "{{ nginx.directories.streams }}{{ domains[application_id] }}.conf"
path: "{{ nginx.directories.streams }}{{ domains | get_domain(application_id) }}.conf"
state: absent
when: not applications[application_id].network.public | bool

View File

@ -16,7 +16,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: add config.toml

View File

@ -3,7 +3,7 @@ database_type: "postgres"
listmonk_settings:
- key: "app.root_url"
value: '"{{ web_protocol }}://{{ domains[application_id] }}"'
value: '"{{ web_protocol }}://{{ domains | get_domain(application_id) }}"'
- key: "app.notify_emails"
value: "{{ [ users.administrator.email ] | to_json }}"
@ -65,8 +65,9 @@ listmonk_settings:
# - key: "messengers"
# value: '[]'
- key: "app.logo_url"
value: '"{{ service_provider.platform.logo }}"'
- key: "app.logo_url"
value: '"{{ service_provider.platform.logo }}"'
when: service_provider.platform.logo | bool
- key: "app.site_name"
value: '"{{ service_provider.company.titel }} Mailing list"'
@ -115,8 +116,9 @@ listmonk_settings:
# - key: "app.concurrency"
# value: '10'
- key: "app.favicon_url"
value: '"{{ service_provider.platform.favicon }}"'
- key: "app.favicon_url"
value: '"{{ service_provider.platform.favicon }}"'
when: service_provider.platform.favicon | bool
# - key: "bounce.postmark"
# value: '{"enabled": false, "password": "", "username": ""}'

View File

@ -8,7 +8,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
nginx_docker_reverse_proxy_extra_configuration: "client_max_body_size 31M;"
when: run_once_docker_mailu is not defined

View File

@ -20,7 +20,7 @@ SUBNET={{networks.local.mailu.subnet}}
DOMAIN={{applications.mailu.domain}}
# Hostnames for this server, separated with comas
HOSTNAMES={{domains[application_id]}}
HOSTNAMES={{domains | get_domain(application_id)}}
# Postmaster local part (will append the main mail domain)
POSTMASTER=admin
@ -105,7 +105,7 @@ WEB_WEBMAIL=/webmail
SITENAME=Mailservices
# Linked Website URL
WEBSITE=https://{{domains[application_id]}}
WEBSITE=https://{{domains | get_domain(application_id)}}

View File

@ -10,5 +10,5 @@ cert_mount_directory: "{{docker_compose.directories.volumes}}certs/"
# @see https://github.com/heviat/Mailu-OIDC/tree/2024.06
docker_source: "{{ 'ghcr.io/heviat' if applications[application_id].features.oidc | bool else 'ghcr.io/mailu' }}"
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"

View File

@ -3,7 +3,7 @@
# @see https://github.com/mastodon/mastodon/blob/main/.env.production.sample
LOCAL_DOMAIN={{domains[application_id]}}
LOCAL_DOMAIN={{domains | get_domain(application_id)}}
ALTERNATE_DOMAINS="{{ domains.mastodon[1:] | join(',') }}"
SINGLE_USER_MODE={{applications.mastodon.single_user_mode}}
@ -67,7 +67,7 @@ OIDC_SCOPE="openid,profile,email"
# @see https://stackoverflow.com/questions/72108087/how-to-set-the-username-of-mastodon-by-log-in-via-keycloak
OIDC_UID_FIELD={{oidc.attributes.username}}
OIDC_CLIENT_ID={{oidc.client.id}}
OIDC_REDIRECT_URI=https://{{domains[application_id]}}/auth/auth/openid_connect/callback
OIDC_REDIRECT_URI=https://{{domains | get_domain(application_id)}}/auth/auth/openid_connect/callback
OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED=true
OIDC_CLIENT_SECRET={{oidc.client.secret}}
# uncomment to only use OIDC for login / registration buttons

View File

@ -8,7 +8,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
when: run_once_docker_matomo is not defined

View File

@ -3,4 +3,4 @@ application_id: "matomo"
database_type: "mariadb"
# I don't know if this is still necessary
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"

View File

@ -3,8 +3,8 @@
include_role:
name: nginx-domain-setup
loop:
- "{{domains.element}}"
- "{{domains.synapse}}"
- "{{domains.matrix.element}}"
- "{{domains.matrix.synapse}}"
loop_control:
loop_var: domain
@ -129,13 +129,13 @@
#- name: add log.config
# template:
# src: "log.config.j2"
# dest: "{{docker_compose.directories.instance}}{{domains.synapse}}.log.config"
# dest: "{{docker_compose.directories.instance}}{{domains.matrix.synapse}}.log.config"
# notify: recreate matrix
#
## https://github.com/matrix-org/synapse/issues/6303
#- name: set correct folder permissions
# command:
# cmd: "docker run --rm --mount type=volume,src=matrix_synapse_data,dst=/data -e SYNAPSE_SERVER_NAME={{domains.synapse}} -e SYNAPSE_REPORT_STATS=no --entrypoint /bin/sh matrixdotorg/synapse:latest -c 'chown -vR 991:991 /data'"
# cmd: "docker run --rm --mount type=volume,src=matrix_synapse_data,dst=/data -e SYNAPSE_SERVER_NAME={{domains.matrix.synapse}} -e SYNAPSE_REPORT_STATS=no --entrypoint /bin/sh matrixdotorg/synapse:latest -c 'chown -vR 991:991 /data'"
#
#- name: add docker-compose.yml
# template:

View File

@ -8,7 +8,7 @@
# because you can't change the Domain after deployment.
#
# Example value: example.com
matrix_domain: "{{domains.synapse}}"
matrix_domain: "{{domains.matrix.synapse}}"
# The Matrix homeserver software to install.
# See:

View File

@ -16,7 +16,7 @@
include_role:
name: nginx-https-get-cert-modify-all
vars:
domain: "{{domains.synapse}}"
domain: "{{domains.matrix.synapse}}"
http_port: "{{ports.localhost.http.synapse}}"
- name: create {{well_known_directory}}
@ -30,12 +30,12 @@
src: "well-known.j2"
dest: "{{well_known_directory}}server"
- name: create {{domains.synapse}}.conf
- name: create {{domains.matrix.synapse}}.conf
template:
src: "templates/nginx.conf.j2"
dest: "{{nginx.directories.http.servers}}{{domains.synapse}}.conf"
dest: "{{nginx.directories.http.servers}}{{domains.matrix.synapse}}.conf"
vars:
domain: "{{domains.synapse}}" # Didn't work in the past. May it works now. This does not seem to work @todo Check how to solve without declaring set_fact, seems a bug at templates
domain: "{{domains.matrix.synapse}}" # Didn't work in the past. May it works now. This does not seem to work @todo Check how to solve without declaring set_fact, seems a bug at templates
http_port: "{{ports.localhost.http.synapse}}"
notify: restart nginx
@ -43,7 +43,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{domains.element}}"
domain: "{{domains.matrix.element}}"
http_port: "{{ports.localhost.http.element}}"
- name: include create-and-seed-database.yml for multiple bridges
@ -94,13 +94,13 @@
- name: add synapse log configuration
template:
src: "synapse/log.config.j2"
dest: "{{docker_compose.directories.instance}}{{domains.synapse}}.log.config"
dest: "{{docker_compose.directories.instance}}{{domains.matrix.synapse}}.log.config"
notify: docker compose project setup
# https://github.com/matrix-org/synapse/issues/6303
- name: set correct folder permissions
command:
cmd: "docker run --rm --mount type=volume,src=matrix_synapse_data,dst=/data -e SYNAPSE_SERVER_NAME={{domains.synapse}} -e SYNAPSE_REPORT_STATS=no --entrypoint /bin/sh matrixdotorg/synapse:latest -c 'chown -vR 991:991 /data'"
cmd: "docker run --rm --mount type=volume,src=matrix_synapse_data,dst=/data -e SYNAPSE_SERVER_NAME={{domains.matrix.synapse}} -e SYNAPSE_REPORT_STATS=no --entrypoint /bin/sh matrixdotorg/synapse:latest -c 'chown -vR 991:991 /data'"
- name: add docker-compose.yml
template:

View File

@ -11,12 +11,12 @@ services:
volumes:
- synapse_data:/data
- ./homeserver.yaml:/data/homeserver.yaml:ro
- ./{{domains.synapse}}.log.config:/data/{{domains.synapse}}.log.config:ro
- ./{{domains.matrix.synapse}}.log.config:/data/{{domains.matrix.synapse}}.log.config:ro
{% for item in bridges %}
- {{docker_compose.directories.instance}}mautrix/{{item.bridge_name}}/registration.yaml:{{registration_file_folder}}{{item.bridge_name}}.registration.yaml:ro
{% endfor %}
environment:
- SYNAPSE_SERVER_NAME={{domains.synapse}}
- SYNAPSE_SERVER_NAME={{domains.matrix.synapse}}
- SYNAPSE_REPORT_STATS=no
ports:
- "127.0.0.1:{{ports.localhost.http.synapse}}:8008"
@ -91,7 +91,7 @@ services:
KEYV_URL: ''
KEYV_BOT_ENCRYPTION: 'false'
KEYV_BOT_STORAGE: 'true'
MATRIX_HOMESERVER_URL: 'https://{{domains.synapse}}'
MATRIX_HOMESERVER_URL: 'https://{{domains.matrix.synapse}}'
MATRIX_BOT_USERNAME: '@chatgptbot:{{applications[application_id].server_name}}'
MATRIX_ACCESS_TOKEN: '{{ applications[application_id].credentials.chatgpt_bridge_access_token | default('') }}'
MATRIX_BOT_PASSWORD: '{{applications[application_id].credentials.chatgpt_bridge_user_password}}'

View File

@ -1,8 +1,8 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "{{ web_protocol }}://{{domains.synapse}}",
"server_name": "{{domains.synapse}}"
"base_url": "{{ web_protocol }}://{{domains.matrix.synapse}}",
"server_name": "{{domains.matrix.synapse}}"
},
"m.identity_server": {
"base_url": "{{ web_protocol }}://{{primary_domain}}"

View File

@ -143,7 +143,7 @@ bridge:
sync_direct_chat_list: false
# Servers to always allow double puppeting from
double_puppet_server_map:
{{applications[application_id].server_name}}: {{domains.synapse}}
{{applications[application_id].server_name}}: {{domains.matrix.synapse}}
# Allow using double puppeting from any server with a valid client .well-known file.
double_puppet_allow_discovery: false
# Shared secrets for https://github.com/devture/matrix-synapse-shared-secret-auth

View File

@ -134,7 +134,7 @@ bridge:
double_puppet_allow_discovery: false
# Servers to allow double puppeting from, even if double_puppet_allow_discovery is false.
double_puppet_server_map:
{{applications[application_id].server_name}}: https://{{domains.synapse}}
{{applications[application_id].server_name}}: https://{{domains.matrix.synapse}}
# Shared secret for https://github.com/devture/matrix-synapse-shared-secret-auth
#
# If set, custom puppets will be enabled automatically for local users

View File

@ -141,7 +141,7 @@ bridge:
federate_rooms: true
# Servers to always allow double puppeting from
double_puppet_server_map:
{{applications[application_id].server_name}}: https://{{domains.synapse}}
{{applications[application_id].server_name}}: https://{{domains.matrix.synapse}}
# Allow using double puppeting from any server with a valid client .well-known file.
double_puppet_allow_discovery: false
# Shared secrets for https://github.com/devture/matrix-synapse-shared-secret-auth

View File

@ -118,7 +118,7 @@ bridge:
# Servers to always allow double puppeting from
double_puppet_server_map:
{{applications[application_id].server_name}}: https://{{domains.synapse}}
{{applications[application_id].server_name}}: https://{{domains.matrix.synapse}}
# Allow using double puppeting from any server with a valid client .well-known file.
double_puppet_allow_discovery: false
# Shared secrets for https://github.com/devture/matrix-synapse-shared-secret-auth

View File

@ -198,7 +198,7 @@ bridge:
sync_direct_chat_list: false
# Servers to always allow double puppeting from
double_puppet_server_map:
{{applications[application_id].server_name}}: https://{{domains.synapse}}
{{applications[application_id].server_name}}: https://{{domains.matrix.synapse}}
# Allow using double puppeting from any server with a valid client .well-known file.
double_puppet_allow_discovery: false
# Shared secrets for https://github.com/devture/matrix-synapse-shared-secret-auth

View File

@ -236,7 +236,7 @@ bridge:
force_active_delivery_receipts: false
# Servers to always allow double puppeting from
double_puppet_server_map:
{{applications[application_id].server_name}}: https://{{domains.synapse}}
{{applications[application_id].server_name}}: https://{{domains.matrix.synapse}}
# Allow using double puppeting from any server with a valid client .well-known file.
double_puppet_allow_discovery: false
# Shared secrets for https://github.com/devture/matrix-synapse-shared-secret-auth

View File

@ -1,10 +1,10 @@
server {
{# Somehow .j2 doesn't interpretate the passed variable right. For this reasons this redeclaration is necessary #}
{# Could be that this is related to the set_fact use #}
{% set domain = domains.synapse %}
{% set domain = domains.matrix.synapse %}
{% set http_port = ports.localhost.http.synapse %}
server_name {{domains.synapse}};
server_name {{domains.matrix.synapse}};
{% include 'roles/letsencrypt/templates/ssl_header.j2' %}
# For the federation port

View File

@ -17,15 +17,15 @@ database:
host: "{{database_host}}"
cp_min: 5
cp_max: 10
log_config: "/data/{{domains.synapse}}.log.config"
log_config: "/data/{{domains.matrix.synapse}}.log.config"
media_store_path: "/data/media_store"
registration_shared_secret: "{{applications[application_id].credentials.registration_shared_secret}}"
report_stats: true
macaroon_secret_key: "{{applications[application_id].credentials.macaroon_secret_key}}"
form_secret: "{{applications[application_id].credentials.form_secret}}"
signing_key_path: "/data/{{domains.synapse}}.signing.key"
web_client_location: "{{ web_protocol }}://{{domains.element}}"
public_baseurl: "{{ web_protocol }}://{{domains.synapse}}"
signing_key_path: "/data/{{domains.matrix.synapse}}.signing.key"
web_client_location: "{{ web_protocol }}://{{domains.matrix.element}}"
public_baseurl: "{{ web_protocol }}://{{domains.matrix.synapse}}"
trusted_key_servers:
- server_name: "matrix.org"
admin_contact: 'mailto:{{users.administrator.email}}'
@ -39,10 +39,10 @@ email:
#require_transport_security: true
enable_tls: "{{ system_email.tls | upper }}"
notif_from: "Your Friendly %(app)s homeserver <{{ users['no-reply'].email }}>"
app_name: "Matrix on {{domains.synapse}}"
app_name: "Matrix on {{domains.matrix.synapse}}"
enable_notifs: true
notif_for_new_users: false
client_base_url: "{{domains.synapse}}"
client_base_url: "{{domains.matrix.synapse}}"
validation_token_lifetime: 15m
{% if applications | is_feature_enabled('oidc',application_id) %}

View File

@ -8,7 +8,7 @@ handlers:
file:
class: logging.handlers.RotatingFileHandler
formatter: precise
filename: /data/{{domains.synapse}}.homeserver.log
filename: /data/{{domains.matrix.synapse}}.homeserver.log
maxBytes: 10485760
backupCount: 3
console:

View File

@ -1,3 +1,3 @@
{
"m.server": "{{domains.synapse}}:443"
"m.server": "{{domains.matrix.synapse}}:443"
}

View File

@ -25,9 +25,9 @@ csp:
whitelist:
connect-src:
- "{{ primary_domain }}"
- "{{ domains.matrix }}"
- "{{ domains.matrix.synapse | safe_var }}"
script-src:
- "{{ domains.matrix }}"
- "{{ domains.matrix.synapse | safe_var }}"
- "https://cdn.jsdelivr.net"
plugins:
# You need to enable them in the inventory file

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: add docker-compose.yml

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "Transfer Dockerfile to {{ docker_compose.directories.instance }}"

View File

@ -3,7 +3,7 @@
include_role:
name: docker-central-database
- name: "include tasks setup-domain.yml with {{domains[application_id]}}"
- name: "include tasks setup-domain.yml with {{domains | get_domain(application_id)}}"
include_tasks: setup-domain.yml
loop: "{{ mybb_domains + [source_domain] }}"
loop_control:

View File

@ -4,12 +4,12 @@
include_role:
name: nginx-https-get-cert
vars:
domain: "{{domains[application_id]}}"
domain: "{{domains | get_domain(application_id)}}"
- name: configure {{domains[application_id]}}.conf
- name: configure {{domains | get_domain(application_id)}}.conf
template:
src: "roles/nginx-docker-reverse-proxy/templates/vhost/basic.conf.j2"
dest: "{{nginx.directories.http.servers}}{{domains[application_id]}}.conf"
dest: "{{nginx.directories.http.servers}}{{domains | get_domain(application_id)}}.conf"
notify: restart nginx
vars:
nginx_docker_reverse_proxy_extra_configuration: "sub_filter '{{source_domain}}' '{{domains[application_id]}}';"
nginx_docker_reverse_proxy_extra_configuration: "sub_filter '{{source_domain}}' '{{domains | get_domain(application_id)}}';"

View File

@ -26,7 +26,7 @@
- name: create nextcloud nginx proxy configuration file
template:
src: "nginx/host.conf.j2"
dest: "{{nginx.directories.http.servers}}{{domains[application_id]}}.conf"
dest: "{{nginx.directories.http.servers}}{{domains | get_domain(application_id)}}.conf"
notify: restart nginx
- name: create internal nextcloud nginx configuration

View File

@ -21,7 +21,7 @@ return array (
'oidc_login_auto_redirect' => true,
// Redirect to this page after logging out the user
'oidc_login_logout_url' => 'https://{{domains[application_id]}}',
'oidc_login_logout_url' => 'https://{{domains | get_domain(application_id)}}',
// If set to true the user will be redirected to the
// logout endpoint of the OIDC provider after logout

View File

@ -29,10 +29,10 @@ NEXTCLOUD_ADMIN_PASSWORD= "{{applications[application_id].credentials.admi
# Security
NEXTCLOUD_TRUSTED_DOMAINS= "{{domains[application_id]}}"
NEXTCLOUD_TRUSTED_DOMAINS= "{{domains | get_domain(application_id)}}"
# Whitelist local docker gateway in Nextcloud to prevent brute-force throtteling
TRUSTED_PROXIES= "192.168.102.65"
OVERWRITECLIURL= "{{ web_protocol }}://{{domains[application_id]}}"
OVERWRITECLIURL= "{{ web_protocol }}://{{domains | get_domain(application_id)}}"
OVERWRITEPROTOCOL= "https"
# Redis Configuration

View File

@ -7,7 +7,7 @@ database_password: "{{applications.nextcloud.cr
database_type: "mariadb" # Database flavor
# Networking
domain: "{{ domains[application_id] }}" # Public domain at which Nextcloud will be accessable
domain: "{{ domains | get_domain(application_id) }}" # Public domain at which Nextcloud will be accessable
http_port: "{{ ports.localhost.http[application_id] }}" # Port at which nextcloud is reachable in the local network
# Control Node

View File

@ -25,7 +25,7 @@ plugin_configuration:
configkey: "custom_providers"
configvalue:
custom_oidc:
- name: "{{ domains.keycloak }}"
- name: "{{ domains | get_domain('keycloak') }}"
title: "keycloak"
style: "keycloak"
authorizeUrl: "{{ oidc.client.authorize_url }}"

View File

@ -15,7 +15,7 @@ nextcloud_system_config:
value: "{{ HOST_LL | upper }}"
- parameter: "trusted_domains 0"
value: "{{domains[application_id]}}"
value: "{{domains | get_domain(application_id)}}"
- parameter: "overwrite.cli.url"
value: "{{ web_protocol }}://{{domains[application_id]}}"
value: "{{ web_protocol }}://{{domains | get_domain(application_id)}}"

View File

@ -3,7 +3,7 @@ cookie_secret = "{{ applications[oauth2_proxy_application_id].creden
email_domains = "{{ primary_domain }}"
cookie_secure = "true" # True is necessary to force the cookie set via https
upstreams = "http://{{ applications[oauth2_proxy_application_id].oauth2_proxy.application }}:{{ applications[oauth2_proxy_application_id].oauth2_proxy.port }}"
cookie_domains = ["{{ domains[oauth2_proxy_application_id] }}", "{{ domains.keycloak }}"] # Required so cookie can be read on all subdomains.
cookie_domains = ["{{ domains[oauth2_proxy_application_id] }}", "{{ domains | get_domain('keycloak') }}"] # Required so cookie can be read on all subdomains.
whitelist_domains = [".{{ primary_domain }}"] # Required to allow redirection back to original requested target.
# keycloak provider

View File

@ -1,6 +1,6 @@
configuration_file: "oauth2-proxy-keycloak.cfg" # Needs to be set true in the roles which use it
version: "latest" # Docker Image version
redirect_url: "{{ web_protocol }}://{{domains.keycloak}}/auth/realms/{{primary_domain}}/protocol/openid-connect/auth" # The redirect URL for the OAuth2 flow. It should match the redirect URL configured in Keycloak.
redirect_url: "{{ web_protocol }}://{{domains | get_domain('keycloak')}}/auth/realms/{{primary_domain}}/protocol/openid-connect/auth" # The redirect URL for the OAuth2 flow. It should match the redirect URL configured in Keycloak.
allowed_roles: admin # Restrict it default to admin role. Use the vars/main.yml to open the specific role for other groups
features:
matomo: true

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "Create {{openproject_plugins_service}}"

View File

@ -7,7 +7,7 @@
# https://www.openproject.org/docs/installation-and-operations/configuration/environment/
#
OPENPROJECT_HTTPS=true
OPENPROJECT_HOST__NAME={{domains[application_id]}}
OPENPROJECT_HOST__NAME={{domains | get_domain(application_id)}}
OPENPROJECT_RAILS__RELATIVE__URL__ROOT=
IMAP_ENABLED=false
POSTGRES_PASSWORD="{{ database_password }}"

View File

@ -8,7 +8,7 @@ PEERTUBE_DB_SSL=false
PEERTUBE_DB_HOSTNAME={{database_host}}
# PeerTube server configuration
PEERTUBE_WEBSERVER_HOSTNAME={{domains[application_id]}}
PEERTUBE_WEBSERVER_HOSTNAME={{domains | get_domain(application_id)}}
PEERTUBE_TRUST_PROXY=["127.0.0.1", "loopback"]
PEERTUBE_SECRET={{applications[application_id].credentials.secret}}

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "configure pgadmin servers"

View File

@ -6,7 +6,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -1,3 +1,3 @@
# @See https://github.com/leenooks/phpLDAPadmin/wiki/Docker-Container
APP_URL= https://{{domains[application_id]}}
APP_URL= https://{{domains | get_domain(application_id)}}
LDAP_HOST= {{ldap.server.domain}}

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -5,10 +5,10 @@ APP_KEY={{applications[application_id].credentials.app_key}}
APP_NAME="{{applications.pixelfed.titel}}"
APP_ENV=production
APP_DEBUG={{enable_debug | string | lower }}
APP_URL=https://{{domains[application_id]}}
APP_DOMAIN="{{domains[application_id]}}"
ADMIN_DOMAIN="{{domains[application_id]}}"
SESSION_DOMAIN="{{domains[application_id]}}"
APP_URL=https://{{domains | get_domain(application_id)}}
APP_DOMAIN="{{domains | get_domain(application_id)}}"
ADMIN_DOMAIN="{{domains | get_domain(application_id)}}"
SESSION_DOMAIN="{{domains | get_domain(application_id)}}"
OPEN_REGISTRATION=false
ENFORCE_EMAIL_VERIFICATION=false

View File

@ -21,7 +21,7 @@ class LookupModule(LookupBase):
- Retrieves the description from galaxy_info.description in meta/main.yml
- Retrieves the icon class from galaxy_info.logo.class
- Retrieves the tags from galaxy_info.galaxy_tags
- Builds the URL using the 'domains' variable (e.g. domains[application_id])
- Builds the URL using the 'domains' variable (e.g. domains | get_domain(application_id))
- Sets the iframe flag from applications[application_id].features.iframe
Only cards whose application_id is included in the variable group_names are returned.
@ -90,15 +90,16 @@ class LookupModule(LookupBase):
applications = variables.get("applications", {})
domain_url = domains.get(application_id, "")
# Check if domain_url is a list. If so, select the first element.
if isinstance(domain_url, list):
domain_url = domain_url[0]
elif isinstance(domain_url, dict):
domain_url = next(iter(domain_url.values()))
# Construct the URL using the domain_url if available.
url = "https://" + domain_url if domain_url else ""
app_data = applications.get(application_id, {})
iframe = app_data.get("features", {}).get("iframe", False)
iframe = app_data.get("features", {}).get("portfolio_iframe", False)
# Build card dictionary
card = {

View File

@ -8,7 +8,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
when: run_once_docker_portfolio is not defined

View File

@ -36,19 +36,19 @@
description: Access the central admin console
icon:
class: fa-solid fa-shield-halved
url: https://{{domains.keycloak}}/admin
url: https://{{domains | get_domain('keycloak')}}/admin
iframe: {{ applications | is_feature_enabled('portfolio_iframe','keycloak') }}
- name: Profile
description: Update your personal admin settings
icon:
class: fa-solid fa-user-gear
url: https://{{ domains.keycloak }}/realms/{{oidc.client.id}}/account
url: https://{{ domains | get_domain('keycloak') }}/realms/{{oidc.client.id}}/account
iframe: {{ applications | is_feature_enabled('portfolio_iframe','keycloak') }}
- name: Logout
description: End your admin session securely
icon:
class: fa-solid fa-right-from-bracket
url: https://{{ domains.keycloak }}/realms/{{oidc.client.id}}/protocol/openid-connect/logout
url: https://{{ domains | get_domain('keycloak') }}/realms/{{oidc.client.id}}/protocol/openid-connect/logout
iframe: false
{% endif %}

View File

@ -23,7 +23,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -7,7 +7,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -5,7 +5,7 @@ APP_ENV=production
APP_DEBUG={{enable_debug | string | lower }}
# Please regenerate the APP_KEY value by calling `docker compose run --rm app php artisan key:generate --show`. Copy paste the value here
APP_KEY={{applications[application_id].credentials.app_key}}
APP_URL=https://{{domains[application_id]}}
APP_URL=https://{{domains | get_domain(application_id)}}
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones - TZ identifier
APP_TIMEZONE='{{ HOST_TIMEZONE }}'
APP_LOCALE={{ HOST_LL }}

View File

@ -19,7 +19,7 @@
include_role:
name: nginx-domain-setup
vars:
domain: "{{ domains[application_id] }}"
domain: "{{ domains | get_domain(application_id) }}"
http_port: "{{ ports.localhost.http[application_id] }}"
- name: "copy docker-compose.yml and env file"

View File

@ -13,7 +13,7 @@ services:
environment:
SPRING_PROFILES_ACTIVE: docker,postgresql,saml2
OPENJPA_REMOTE_COMMIT: sjvm
SERVICE_DISCOVERY_ADDRESS: {{ web_protocol }}://{{ domains[application_id] }}/{{syncope_paths[rest]}}/
SERVICE_DISCOVERY_ADDRESS: {{ web_protocol }}://{{ domains | get_domain(application_id) }}/{{syncope_paths[rest]}}/
# database variablen auslesen
console:
@ -25,7 +25,7 @@ services:
restart: always
environment:
SPRING_PROFILES_ACTIVE: docker,saml2
SERVICE_DISCOVERY_ADDRESS: {{ web_protocol }}://{{ domains[application_id] }}/{{syncope_paths[console]}}/
SERVICE_DISCOVERY_ADDRESS: {{ web_protocol }}://{{ domains | get_domain(application_id) }}/{{syncope_paths[console]}}/
enduser:
depends_on:
@ -36,5 +36,5 @@ services:
restart: always
environment:
SPRING_PROFILES_ACTIVE: docker,saml2
SERVICE_DISCOVERY_ADDRESS: {{ web_protocol }}://{{ domains[application_id] }}/{{syncope_paths[enduser]}}/
SERVICE_DISCOVERY_ADDRESS: {{ web_protocol }}://{{ domains | get_domain(application_id) }}/{{syncope_paths[enduser]}}/

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