Renamed the mariadb, openldap and postgres database

This commit is contained in:
Kevin Veen-Birkenbach 2025-07-12 16:06:13 +02:00
parent e174523fc6
commit 3b03c5171d
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E
84 changed files with 210 additions and 106 deletions

View File

@ -15,7 +15,7 @@ Every business is unique, and so is CyMaIS! With a modular architecture, it adap
With automated updates, system health checks, and security audits, CyMaIS ensures your infrastructure is always up-to-date and running smoothly. Roles such as `sys-hlth-docker-container`, `sys-hlth-btrfs`, and `sys-hlth-webserver` help monitor system integrity. With automated updates, system health checks, and security audits, CyMaIS ensures your infrastructure is always up-to-date and running smoothly. Roles such as `sys-hlth-docker-container`, `sys-hlth-btrfs`, and `sys-hlth-webserver` help monitor system integrity.
## Uncompromised Security 🔒 ## Uncompromised Security 🔒
Security is a top priority! CyMaIS includes robust security features like full-disk encryption recommendations, 2FA enforcement, encrypted server deployments (`web-app-keycloak`, `svc-openldap`), and secure backup solutions (`sys-bkp-remote-to-local`, `svc-sys-bkp-data-to-usb`). Security is a top priority! CyMaIS includes robust security features like full-disk encryption recommendations, 2FA enforcement, encrypted server deployments (`web-app-keycloak`, `svc-db-openldap`), and secure backup solutions (`sys-bkp-remote-to-local`, `svc-sys-bkp-data-to-usb`).
## User-Friendly with Expert Support 👩‍💻 ## User-Friendly with Expert Support 👩‍💻
No need to be a Linux or Docker expert! CyMaIS simplifies deployment with intuitive role-based automation. Documentation and community support make IT administration accessible to all experience levels. No need to be a Linux or Docker expert! CyMaIS simplifies deployment with intuitive role-based automation. Documentation and community support make IT administration accessible to all experience levels.

View File

@ -16,7 +16,7 @@ ports:
gitea: 4188 gitea: 4188
snipe-it: 4189 snipe-it: 4189
ldap: ldap:
openldap: 389 svc-db-openldap: 389
http: http:
nextcloud: 8001 nextcloud: 8001
gitea: 8002 gitea: 8002
@ -73,7 +73,7 @@ ports:
gitea: 2201 gitea: 2201
gitlab: 2202 gitlab: 2202
ldaps: ldaps:
ldap: 636 svc-db-openldap: 636
stun: stun:
bigbluebutton: 3478 # Not sure if it's right placed here or if it should be moved to localhost section bigbluebutton: 3478 # Not sure if it's right placed here or if it should be moved to localhost section
turn: turn:

View File

@ -30,7 +30,7 @@ defaults_networks:
subnet: 192.168.101.144/28 subnet: 192.168.101.144/28
keycloak: keycloak:
subnet: 192.168.101.160/28 subnet: 192.168.101.160/28
openldap: svc-db-openldap:
subnet: 192.168.101.176/28 subnet: 192.168.101.176/28
listmonk: listmonk:
subnet: 192.168.101.192/28 subnet: 192.168.101.192/28
@ -96,9 +96,9 @@ defaults_networks:
# /24 Networks / 254 Usable Clients # /24 Networks / 254 Usable Clients
bigbluebutton: bigbluebutton:
subnet: 10.7.7.0/24 # This variable does not have an impact. It's just there for documentation reasons, because this network is used in bbb subnet: 10.7.7.0/24 # This variable does not have an impact. It's just there for documentation reasons, because this network is used in bbb
postgres: svc-db-postgres:
subnet: 192.168.200.0/24 subnet: 192.168.200.0/24
mariadb: svc-db-mariadb:
subnet: 192.168.201.0/24 subnet: 192.168.201.0/24
central_ldap: svc-db-openldap:
subnet: 192.168.202.0/24 subnet: 192.168.202.0/24

View File

@ -6,7 +6,7 @@
# 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_server_port: "{% if applications.openldap.network.docker | bool %}{{ ports.localhost.ldap.openldap }}{% else %}{{ ports.localhost.ldaps.ldap }}{% endif %}" _ldap_server_port: "{% if applications['svc-db-openldap'].network.docker | bool %}{{ ports.localhost.ldap[application_id] }}{% else %}{{ ports.localhost.ldaps[application_id] }}{% endif %}"
_ldap_user_id: "uid" _ldap_user_id: "uid"
_ldap_filters_users_all: "(|(objectclass=inetOrgPerson))" _ldap_filters_users_all: "(|(objectclass=inetOrgPerson))"
@ -25,7 +25,7 @@ ldap:
# The DN used to authenticate for regular directory operations under # The DN used to authenticate for regular directory operations under
# the data tree (adding users, modifying attributes, creating OUs, etc.). # the data tree (adding users, modifying attributes, creating OUs, etc.).
# Typically: “cn=admin,dc=example,dc=com” # Typically: “cn=admin,dc=example,dc=com”
data: "cn={{ applications.openldap.users.administrator.username }},{{ _ldap_dn_base }}" data: "cn={{ applications['svc-db-openldap'].users.administrator.username }},{{ _ldap_dn_base }}"
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Config-Tree Administrator Bind DN # Config-Tree Administrator Bind DN
@ -33,7 +33,7 @@ ldap:
# need to load or modify schema, overlays, modules, or other server- # need to load or modify schema, overlays, modules, or other server-
# level settings. # level settings.
# Typically: “cn=admin,cn=config” # Typically: “cn=admin,cn=config”
configuration: "cn={{ applications.openldap.users.administrator.username }},cn=config" configuration: "cn={{ applications['svc-db-openldap'].users.administrator.username }},cn=config"
ou: ou:
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
@ -55,14 +55,14 @@ ldap:
# for ordinary user/group operations, and vice versa. # for ordinary user/group operations, and vice versa.
# Password to access dn.bind # Password to access dn.bind
bind_credential: "{{ applications.openldap.credentials.administrator_database_password }}" bind_credential: "{{ applications['svc-db-openldap'].credentials.administrator_database_password }}"
server: server:
domain: "{{applications.openldap.hostname if applications.openldap.network.docker | bool else domains.openldap}}" # Mapping for public or locale access domain: "{{applications['svc-db-openldap'].hostname if applications['svc-db-openldap'].network.docker | bool else domains['svc-db-openldap']}}" # Mapping for public or locale access
port: "{{_ldap_server_port}}" port: "{{_ldap_server_port}}"
uri: "{% if applications.openldap.network.docker | bool %}ldap://{{ applications.openldap.hostname }}{% else %}ldaps://{{ domains.openldap }}{% endif %}:{{ _ldap_server_port }}" uri: "{% if applications['svc-db-openldap'].network.docker | bool %}ldap://{{ applications['svc-db-openldap'].hostname }}{% else %}ldaps://{{ domains['svc-db-openldap'] }}{% endif %}:{{ _ldap_server_port }}"
security: "" #TLS, SSL - Leave empty for none security: "" #TLS, SSL - Leave empty for none
network: network:
local: "{{applications.openldap.network.docker}}" # Uses the application configuration to define if local network should be available or not local: "{{applications['svc-db-openldap'].network.docker}}" # Uses the application configuration to define if local network should be available or not
user: user:
objects: objects:
structural: structural:

View File

@ -1,8 +1,8 @@
- name: "load docker and db for {{application_id}}" - name: "For '{{ application_id }}': load docker and db"
include_role: include_role:
name: cmp-db-docker name: cmp-db-docker
- name: "include role srv-proxy-6-6-domain for {{application_id}}" - name: "For '{{ application_id }}': include role srv-proxy-6-6-domain"
include_role: include_role:
name: srv-proxy-6-6-domain name: srv-proxy-6-6-domain
vars: vars:

View File

@ -1,17 +1,17 @@
- name: "set database_application_id (Needed due to lazzy loading issue)" - name: "For '{{ application_id }}': Set database_application_id (Needed due to lazzy loading issue)"
set_fact: set_fact:
database_application_id: "{{ application_id }}" database_application_id: "{{ application_id }}"
- name: "Load database variables" - name: "For '{{ application_id }}': Load database variables"
include_vars: "{{ item }}" include_vars: "{{ item }}"
loop: loop:
- "{{ cmp_db_docker_vars_file_docker }}" # Important to load docker variables first so that database can use them - "{{ cmp_db_docker_vars_file_docker }}" # Important to load docker variables first so that database can use them
- "{{ cmp_db_docker_vars_file_db }}" # Important to load them before docker role so that backup can use them - "{{ cmp_db_docker_vars_file_db }}" # Important to load them before docker role so that backup can use them
- name: "Load docker-compose for {{ application_id }}" - name: "For '{{ application_id }}': Load docker-compose"
include_role: include_role:
name: docker-compose name: docker-compose
- name: "Load central rdbms for {{ application_id }}" - name: "For '{{ application_id }}': Load central RDBMS"
include_role: include_role:
name: cmp-rdbms name: cmp-rdbms

View File

@ -1,8 +1,8 @@
- name: "include docker-compose role" - name: "For '{{ application_id }}': include docker-compose role"
include_role: include_role:
name: docker-compose name: docker-compose
- name: "include role srv-proxy-6-6-domain for {{application_id}}" - name: "For '{{ application_id }}': include role srv-proxy-6-6-domain"
include_role: include_role:
name: srv-proxy-6-6-domain name: srv-proxy-6-6-domain
vars: vars:

View File

@ -1,20 +1,18 @@
# The following env file will just be used from the dedicated mariadb container # The following env file will just be used from the dedicated mariadb container
# and not the {{applications['mariadb'].hostname }}-database # and not the {{applications['svc-db-mariadb'].hostname }}
- name: "Create {{database_env}}" - name: "For '{{ application_id }}': Create {{database_env}}"
template: template:
src: "env/{{database_type}}.env.j2" src: "env/{{database_type}}.env.j2"
dest: "{{database_env}}" dest: "{{database_env}}"
notify: docker compose up notify: docker compose up
when: not applications | is_feature_enabled('central_database',application_id) when: not applications | is_feature_enabled('central_database',application_id)
- name: "Create central database" - name: "For '{{ application_id }}': Create central database"
# I don't know why this includes leads to that the application_id in vars/main.yml of the database role isn't used
# This is the behaviour which I want, but I'm still wondering why ;)
include_role: include_role:
name: "svc-{{database_type}}" name: "svc-db-{{database_type}}"
when: applications | is_feature_enabled('central_database',application_id) when: applications | is_feature_enabled('central_database',application_id)
#- name: "Create central database" - name: "For '{{ application_id }}': Add Entry for Backup Procedure"
# include_tasks: "{{ playbook_dir }}/roles/svc-{{database_type}}/tasks/main.yml"
# when: applications | is_feature_enabled('central_database',application_id)
- name: "Add database to backup"
include_tasks: "{{ playbook_dir }}/roles/sys-bkp-docker-to-local/tasks/seed-database-to-backup.yml" include_tasks: "{{ playbook_dir }}/roles/sys-bkp-docker-to-local/tasks/seed-database-to-backup.yml"

View File

@ -1,7 +1,7 @@
# This template needs to be included in docker-compose.yml, which depend on a postgres database # This template needs to be included in docker-compose.yml, which depend on a postgres database
{% if not applications | is_feature_enabled('central_database',application_id) %} {% if not applications | is_feature_enabled('central_database',application_id) %}
{{ database_host }}: {{ database_host }}:
image: postgres:{{applications['postgres'].version}}-alpine image: postgres:{{applications['svc-db-postgres'].version}}-alpine
container_name: {{application_id}}-database container_name: {{application_id}}-database
env_file: env_file:
- {{database_env}} - {{database_env}}

View File

@ -1,9 +1,9 @@
database_instance: "{{ 'central-' + database_type if applications | is_feature_enabled('central_database',database_application_id) else database_application_id }}" database_instance: "{{ applications[ 'svc-db-' ~ database_type ].hostname if applications | is_feature_enabled('central_database',database_application_id) else database_application_id }}"
database_host: "{{ 'central-' + database_type if applications | is_feature_enabled('central_database',database_application_id) else 'database' }}" database_host: "{{ applications[ 'svc-db-' ~ database_type ].hostname if applications | is_feature_enabled('central_database',database_application_id) else 'database' }}"
database_name: "{{ applications[ database_application_id ].database.name | default( database_application_id ) }}" # The overwritte configuration is needed by bigbluebutton database_name: "{{ applications[ database_application_id ].database.name | default( database_application_id ) }}" # The overwritte configuration is needed by bigbluebutton
database_username: "{{ applications[ database_application_id ].database.username | default( database_application_id )}}" # The overwritte configuration is needed by bigbluebutton database_username: "{{ applications[ database_application_id ].database.username | default( database_application_id )}}" # The overwritte configuration is needed by bigbluebutton
database_password: "{{ applications[ database_application_id ].credentials.database_password }}" database_password: "{{ applications[ database_application_id ].credentials.database_password }}"
database_port: "{{ 3306 if database_type == 'mariadb' else applications['postgres'].port }}" database_port: "{{ applications[ 'svc-db-' ~ database_type ].port }}"
database_env: "{{docker_compose.directories.env}}{{database_type}}.env" database_env: "{{docker_compose.directories.env}}{{database_type}}.env"
database_url_jdbc: "jdbc:{{ database_type if database_type == 'mariadb' else 'postgresql' }}://{{ database_host }}:{{ database_port }}/{{ database_name }}" database_url_jdbc: "jdbc:{{ database_type if database_type == 'mariadb' else 'postgresql' }}://{{ database_host }}:{{ database_port }}/{{ database_name }}"
database_url_full: "{{database_type}}://{{database_username}}:{{database_password}}@{{database_host}}:{{database_port}}/{{ database_name }}" database_url_full: "{{database_type}}://{{database_username}}:{{database_password}}@{{database_host}}:{{database_port}}/{{ database_name }}"

View File

@ -1,11 +1,11 @@
{# This template needs to be included in docker-compose.yml #} {# This template needs to be included in docker-compose.yml #}
networks: networks:
{% if applications | is_feature_enabled('central_database',application_id) and database_type is defined %} {% if applications | is_feature_enabled('central_database',application_id) and database_type is defined %}
central_{{ database_type }}: {{ applications[ 'svc-db-' ~ database_type ].network }}:
external: true external: true
{% endif %} {% endif %}
{% if applications[application_id].get('features', {}).get('ldap', false) and applications.openldap.network.docker | bool %} {% if applications[application_id].get('features', {}).get('ldap', false) and applications['svc-db-openldap'].network.docker | bool %}
central_ldap: svc-db-openldap:
external: true external: true
{% endif %} {% endif %}
default: default:

View File

@ -1,10 +1,10 @@
{# This template needs to be included in docker-compose.yml containers #} {# This template needs to be included in docker-compose.yml containers #}
networks: networks:
{% if applications | is_feature_enabled('central_database',application_id) | bool and database_type is defined %} {% if applications | is_feature_enabled('central_database',application_id) | bool and database_type is defined %}
central_{{ database_type }}: {{ applications[ 'svc-db-' ~ database_type ].network }}:
{% endif %} {% endif %}
{% if applications[application_id].get('features', {}).get('ldap', false) | bool and applications.openldap.network.docker|bool %} {% if applications[application_id].get('features', {}).get('ldap', false) | bool and applications['svc-db-openldap'].network.docker|bool %}
central_ldap: svc-db-openldap:
{% endif %} {% endif %}
default: default:
{{ "\n" }} {{ "\n" }}

View File

@ -0,0 +1,4 @@
version: "latest"
hostname: "svc-db-mariadb"
network: "svc-db-mariadb"
port: 5432

View File

@ -1,6 +1,6 @@
# defaults/ # defaults/
This directory contains default variable definition files for the `svc-mariadb` Ansible role. It centralizes all configurable values related to MariaDB deployment and can be adjusted without modifying task logic. This directory contains default variable definition files for the `svc-db-mariadb` Ansible role. It centralizes all configurable values related to MariaDB deployment and can be adjusted without modifying task logic.
--- ---
@ -34,7 +34,7 @@ Defines default values for how the MariaDB database should be created.
To customize any of these values without editing role defaults: To customize any of these values without editing role defaults:
1. Create or update a playbook-level vars file (e.g. `group_vars/all/svc-mariadb.yml`). 1. Create or update a playbook-level vars file (e.g. `group_vars/all/svc-db-mariadb.yml`).
2. Set the desired values, for example: 2. Set the desired values, for example:
```yaml ```yaml

View File

@ -1,29 +1,29 @@
- name: Create Docker network for MariaDB - name: Create Docker network for MariaDB
docker_network: docker_network:
name: central_mariadb name: "{{ applications['svc-db-mariadb'].network }}"
state: present state: present
ipam_config: ipam_config:
- subnet: "{{ networks.local.mariadb.subnet }}" - subnet: "{{ networks.local['svc-db-mariadb'].subnet }}"
when: run_once_docker_mariadb is not defined when: run_once_docker_mariadb is not defined
- name: install MariaDB - name: install MariaDB
docker_container: docker_container:
name: "{{applications['mariadb'].hostname }}" name: "{{ applications['svc-db-mariadb'].hostname }}"
image: "mariadb:{{applications['mariadb'].version}}" #could lead to problems with nextcloud image: "mariadb:{{applications['svc-db-mariadb'].version}}"
detach: yes detach: yes
env: env:
MARIADB_ROOT_PASSWORD: "{{applications['mariadb'].credentials.root_password}}" MARIADB_ROOT_PASSWORD: "{{applications['svc-db-mariadb'].credentials.root_password}}"
MARIADB_AUTO_UPGRADE: "1" MARIADB_AUTO_UPGRADE: "1"
networks: networks:
- name: central_mariadb - name: "{{ applications['svc-db-mariadb'].network }}"
volumes: volumes:
- central_mariadb_database:/var/lib/mysql - mariadb_database:/var/lib/mysql
published_ports: published_ports:
- "127.0.0.1:{{database_port}}:3306" # can be that this will be removed if all applications use sockets - "127.0.0.1:{{database_port}}:3306" # can be that this will be removed if all applications use sockets
command: "--transaction-isolation=READ-COMMITTED --binlog-format=ROW" #for nextcloud command: "--transaction-isolation=READ-COMMITTED --binlog-format=ROW" #for nextcloud
restart_policy: "{{docker_restart_policy}}" restart_policy: "{{docker_restart_policy}}"
healthcheck: healthcheck:
test: "/usr/bin/mariadb --user=root --password={{applications['mariadb'].credentials.root_password}} --execute \"SHOW DATABASES;\"" test: "/usr/bin/mariadb --user=root --password={{applications['svc-db-mariadb'].credentials.root_password}} --execute \"SHOW DATABASES;\""
interval: 3s interval: 3s
timeout: 1s timeout: 1s
retries: 5 retries: 5
@ -38,7 +38,7 @@
- name: Wait until the MariaDB container is healthy - name: Wait until the MariaDB container is healthy
community.docker.docker_container_info: community.docker.docker_container_info:
name: "{{ applications['mariadb'].hostname }}" name: "{{ applications['svc-db-mariadb'].hostname }}"
register: db_info register: db_info
until: until:
- db_info.containers is defined - db_info.containers is defined
@ -56,7 +56,7 @@
name: "{{ database_name }}" name: "{{ database_name }}"
state: present state: present
login_user: root login_user: root
login_password: "{{ applications['mariadb'].credentials.root_password }}" login_password: "{{ applications['svc-db-mariadb'].credentials.root_password }}"
login_host: 127.0.0.1 login_host: 127.0.0.1
login_port: "{{ database_port }}" login_port: "{{ database_port }}"
encoding: "{{ database_encoding }}" encoding: "{{ database_encoding }}"
@ -70,7 +70,7 @@
priv: '{{database_name}}.*:ALL' priv: '{{database_name}}.*:ALL'
state: present state: present
login_user: root login_user: root
login_password: "{{applications['mariadb'].credentials.root_password}}" login_password: "{{applications['svc-db-mariadb'].credentials.root_password}}"
login_host: 127.0.0.1 login_host: 127.0.0.1
login_port: "{{database_port}}" login_port: "{{database_port}}"
@ -78,7 +78,7 @@
# @todo Remove if this works fine in the future. # @todo Remove if this works fine in the future.
#- name: Grant database privileges #- name: Grant database privileges
# ansible.builtin.shell: # ansible.builtin.shell:
# cmd: "docker exec {{applications['mariadb'].hostname }} mariadb -u root -p{{ applications['mariadb'].credentials.root_password }} -e \"GRANT ALL PRIVILEGES ON `{{database_name}}`.* TO '{{database_username}}'@'%';\"" # cmd: "docker exec {{applications['svc-db-mariadb'].hostname }} mariadb -u root -p{{ applications['svc-db-mariadb'].credentials.root_password }} -e \"GRANT ALL PRIVILEGES ON `{{database_name}}`.* TO '{{database_username}}'@'%';\""
# args: # args:
# executable: /bin/bash # executable: /bin/bash

View File

@ -1,6 +1,6 @@
# vars/ # vars/
This directory contains variable definition files for the `svc-mariadb` Ansible role. It centralizes all configurable values related to MariaDB deployment and can be adjusted without modifying task logic. This directory contains variable definition files for the `svc-db-mariadb` Ansible role. It centralizes all configurable values related to MariaDB deployment and can be adjusted without modifying task logic.
--- ---

View File

@ -0,0 +1 @@
application_id: svc-db-mariadb

View File

@ -1,10 +1,11 @@
images: hostname: "svc-db-openldap" # Hostname of the LDAP Server in the ldap network
openldap: "bitnami/openldap:latest"
network: network:
name: "svc-db-openldap"
local: True # Activates local network. Necessary for LDIF import routines local: True # Activates local network. Necessary for LDIF import routines
docker: True # Activates docker network to allow other docker containers to connect docker: True # Activates docker network to allow other docker containers to connect
public: False # Set to true in inventory file if you want to expose the LDAP port to the internet public: False # Set to true in inventory file if you want to expose the LDAP port to the internet
hostname: "ldap" # Hostname of the LDAP Server in the central_ldap network images:
openldap: "bitnami/openldap:latest"
webinterface: "lam" # The webinterface which should be used. Possible: lam and phpldapadmin webinterface: "lam" # The webinterface which should be used. Possible: lam and phpldapadmin
features: features:
ldap: true ldap: true

View File

@ -19,17 +19,17 @@
- name: create docker network for LDAP, so that other applications can access it - name: create docker network for LDAP, so that other applications can access it
docker_network: docker_network:
name: central_ldap name: "{{ applications[application_id].network.name }}"
state: present state: present
ipam_config: ipam_config:
- subnet: "{{ networks.local.central_ldap.subnet }}" - subnet: "{{ networks.local['svc-db-openldap'].subnet }}"
- meta: flush_handlers - meta: flush_handlers
- name: "Wait for LDAP to be available" - name: "Wait for LDAP to be available"
wait_for: wait_for:
host: "127.0.0.1" host: "127.0.0.1"
port: "{{ ports.localhost.ldap.openldap }}" port: "{{ ports.localhost.ldap['svc-db-openldap'] }}"
delay: 5 delay: 5
timeout: 120 timeout: 120
state: started state: started

View File

@ -1,6 +1,5 @@
--- ---
# Reset both Database and Configuration Admin passwords in LDAP via LDAPI # Reset both Database and Configuration Admin passwords in LDAP via LDAPI
# roles/svc-openldap/tasks/reset_admin_passwords.yml
- name: "Query available LDAP databases" - name: "Query available LDAP databases"
shell: | shell: |

View File

@ -6,7 +6,7 @@
{% include 'roles/docker-container/templates/base.yml.j2' %} {% include 'roles/docker-container/templates/base.yml.j2' %}
{% if applications[application_id].network.public | bool or applications[application_id].network.local | bool %} {% if applications[application_id].network.public | bool or applications[application_id].network.local | bool %}
ports: ports:
- 127.0.0.1:{{ports.localhost.ldap.openldap}}:{{ldap_docker_port}} - 127.0.0.1:{{ports.localhost.ldap['svc-db-openldap']}}:{{ldap_docker_port}}
{% endif %} {% endif %}
volumes: volumes:
- 'data:/bitnami/openldap' - 'data:/bitnami/openldap'

View File

@ -0,0 +1,6 @@
server {
listen {{ ports.public.ldaps['svc-db-openldap'] }}ssl;
proxy_pass 127.0.0.1:{{ ports.localhost.ldap['svc-db-openldap'] }};
{% include 'roles/srv-web-7-7-letsencrypt/templates/ssl_credentials.j2' %}
}

View File

@ -1,9 +1,9 @@
application_id: "openldap" application_id: "svc-db-openldap"
# LDAP Variables # LDAP Variables
ldaps_docker_port: 636 ldaps_docker_port: 636
ldap_docker_port: 389 ldap_docker_port: 389
ldap_server_uri: "ldap://127.0.0.1:{{ ports.localhost.ldap.openldap }}" ldap_server_uri: "ldap://127.0.0.1:{{ ports.localhost.ldap['svc-db-openldap'] }}"
ldap_hostname: "{{ applications[application_id].hostname }}" ldap_hostname: "{{ applications[application_id].hostname }}"
ldap_bind_dn: "{{ ldap.dn.administrator.configuration }}" ldap_bind_dn: "{{ ldap.dn.administrator.configuration }}"
ldap_bind_pw: "{{ applications[application_id].credentials.administrator_password }}" ldap_bind_pw: "{{ applications[application_id].credentials.administrator_password }}"

View File

@ -1,5 +1,5 @@
hostname: "central-postgres" hostname: "svc-db-postgres"
network: "central_postgres" network: "svc-db-postgres"
port: 5432 port: 5432
docker: docker:
images: images:

View File

@ -3,7 +3,7 @@
name: "{{ applications[application_id].network }}" name: "{{ applications[application_id].network }}"
state: present state: present
ipam_config: ipam_config:
- subnet: "{{ networks.local.postgres.subnet }}" - subnet: "{{ networks.local['svc-db-postgres'].subnet }}"
when: run_once_docker_postgres is not defined when: run_once_docker_postgres is not defined
- name: Install PostgreSQL - name: Install PostgreSQL
@ -19,7 +19,7 @@
published_ports: published_ports:
- "127.0.0.1:{{ applications[application_id].port }}:5432" - "127.0.0.1:{{ applications[application_id].port }}:5432"
volumes: volumes:
- central_postgres_database:/var/lib/postgresql/data - postgres_database:/var/lib/postgresql/data
restart_policy: "{{ docker_restart_policy }}" restart_policy: "{{ docker_restart_policy }}"
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"] test: ["CMD-SHELL", "pg_isready -U postgres"]

View File

@ -0,0 +1 @@
application_id: svc-db-postgres

View File

@ -1,2 +0,0 @@
version: "latest"
hostname: "central-mariadb"

View File

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

View File

@ -1,6 +0,0 @@
server {
listen {{ports.public.ldaps.ldap}}ssl;
proxy_pass 127.0.0.1:{{ports.localhost.ldap.openldap}};
{% include 'roles/srv-web-7-7-letsencrypt/templates/ssl_credentials.j2' %}
}

View File

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

View File

@ -133,7 +133,7 @@ def update_discourse(directory):
update_procedure("docker stop {{applications.discourse.container}}") update_procedure("docker stop {{applications.discourse.container}}")
update_procedure("docker rm {{applications.discourse.container}}") update_procedure("docker rm {{applications.discourse.container}}")
try: try:
update_procedure("docker network connect {{applications.discourse.network}} {{ applications['postgres'].hostname }}") update_procedure("docker network connect {{applications.discourse.network}} {{ applications['bpostgres'].hostname }}")
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
error_message = e.output.decode() error_message = e.output.decode()
if "already exists" in error_message or "is already connected" in error_message: if "already exists" in error_message or "is already connected" in error_message:

View File

@ -1,5 +1,5 @@
--- ---
- name: "load docker, db and proxy for {{application_id}}" - name: "For '{{ application_id }}': load docker, db and proxy"
include_role: include_role:
name: cmp-db-docker-proxy name: cmp-db-docker-proxy
@ -9,7 +9,7 @@
detached_files: detached_files:
- "docker-compose.yml" - "docker-compose.yml"
- name: "create {{docker_compose.files.env}}" - name: "For '{{ application_id }}': create {{docker_compose.files.env}}"
template: template:
src: "env.j2" src: "env.j2"
dest: "{{docker_compose.files.env}}" dest: "{{docker_compose.files.env}}"

View File

@ -1,9 +1,9 @@
--- ---
- name: "load docker and db for {{application_id}}" - name: "For '{{ application_id }}': load docker and db"
include_role: include_role:
name: cmp-db-docker name: cmp-db-docker
- name: "include role for {{application_id}} to receive certs & do modification routines" - name: "For '{{ application_id }}': include role to receive certs & do modification routines"
include_role: include_role:
name: srv-web-7-6-composer name: srv-web-7-6-composer
vars: vars:
@ -13,13 +13,13 @@
- "{{ domains | get_domain('mailu') }}" - "{{ domains | get_domain('mailu') }}"
- "{{ domain }}" - "{{ domain }}"
- name: configure {{domains | get_domain(application_id)}}.conf - name: "For '{{ application_id }}': configure {{domains | get_domain(application_id)}}.conf"
template: template:
src: roles/srv-proxy-7-4-core/templates/vhost/basic.conf.j2 src: roles/srv-proxy-7-4-core/templates/vhost/basic.conf.j2
dest: "{{nginx.directories.http.servers}}{{domains | get_domain(application_id)}}.conf" dest: "{{nginx.directories.http.servers}}{{domains | get_domain(application_id)}}.conf"
notify: restart nginx notify: restart nginx
- name: "include tasks update-repository-with-files.yml" - name: "For '{{ application_id }}': include tasks update-repository-with-files.yml"
include_tasks: utils/update-repository-with-files.yml include_tasks: utils/update-repository-with-files.yml
vars: vars:
detached_files: detached_files:

View File

@ -1,4 +1,4 @@
--- ---
- name: "load docker, db and proxy for {{application_id}}" - name: "For '{{ application_id }}': load docker, db and proxy"
include_role: include_role:
name: cmp-db-docker-proxy name: cmp-db-docker-proxy

View File

@ -17,7 +17,7 @@
database_username: "postgres" database_username: "postgres"
database_name: "" # Multiple databases database_name: "" # Multiple databases
- name: "include role srv-proxy-6-6-domain for {{application_id}}" - name: "include role srv-proxy-6-6-domain"
include_role: include_role:
name: srv-proxy-6-6-domain name: srv-proxy-6-6-domain

View File

@ -10,7 +10,7 @@
- name: Create Docker network for Collabora - name: Create Docker network for Collabora
docker_network: docker_network:
name: central_mariadb name: svc-db-mariadb
state: present state: present
ipam_config: ipam_config:
- subnet: "{{ networks.local.collabora.subnet }}" - subnet: "{{ networks.local.collabora.subnet }}"

View File

@ -43,13 +43,13 @@
meta: flush_handlers meta: flush_handlers
when: run_once_docker_discourse is not defined when: run_once_docker_discourse is not defined
- name: "Connect {{ applications[application_id].container }} to network {{ applications['postgres'].network }}" - name: "Connect {{ applications[application_id].container }} to network {{ applications['svc-db-postgres'].network }}"
command: > command: >
docker network connect {{ applications['postgres'].network }} {{ applications[application_id].container }} docker network connect {{ applications['svc-db-postgres'].network }} {{ applications[application_id].container }}
register: network_connect register: network_connect
failed_when: > failed_when: >
network_connect.rc != 0 and network_connect.rc != 0 and
'Error response from daemon: endpoint with name {{ applications[application_id].container }} already exists in network {{ applications['postgres'].network }}' 'Error response from daemon: endpoint with name {{ applications[application_id].container }} already exists in network {{ applications["svc-db-postgres"].network }}'
not in network_connect.stderr not in network_connect.stderr
changed_when: network_connect.rc == 0 changed_when: network_connect.rc == 0
when: when:

View File

@ -6,7 +6,7 @@
# - database_password # - database_password
- name: "create {{database_name}} database" - name: "create {{database_name}} database"
include_role: include_role:
name: svc-postgres name: svc-db-postgres
when: applications | is_feature_enabled('central_database',application_id) when: applications | is_feature_enabled('central_database',application_id)
- name: "include seed-database-to-backup.yml" - name: "include seed-database-to-backup.yml"

View File

@ -27,7 +27,7 @@ plugin_configuration:
- -
appid: "user_ldap" appid: "user_ldap"
configkey: "s01ldap_backup_port" configkey: "s01ldap_backup_port"
configvalue: "{{ ports.localhost.ldap.openldap }}" # This is just optimized for local port @todo implement for external ports as well configvalue: "{{ ports.localhost.ldap['svc-db-openldap'] }}" # This is just optimized for local port @todo implement for external ports as well
- -
appid: "user_ldap" appid: "user_ldap"

View File

@ -9,6 +9,6 @@ pgadmin_servers:
port: "{{ database_port }}" port: "{{ database_port }}"
username: "postgres" username: "postgres"
maintenance_db: "postgres" maintenance_db: "postgres"
password: "{{ applications['postgres'].credentials.postgres_password }}" password: "{{ applications['svc-db-postgres'].credentials.postgres_password }}"
# Here you can add more databases # Here you can add more databases

View File

@ -1,5 +1,5 @@
application_id: "pgadmin" application_id: "pgadmin"
database_type: "postgres" database_type: "postgres"
database_host: "{{ 'central-' + database_type if applications | is_feature_enabled('central_database',application_id) }}" database_host: "{{ applications['svc-db-postgres'].hostname if applications | is_feature_enabled('central_database',application_id) }}"
pgadmin_user: 5050 pgadmin_user: 5050
pgadmin_group: "{{pgadmin_user}}" pgadmin_group: "{{pgadmin_user}}"

View File

@ -1,7 +1,7 @@
# Configuration @see https://hub.docker.com/_/phpmyadmin # Configuration @see https://hub.docker.com/_/phpmyadmin
PMA_HOST={{applications['mariadb'].hostname}} PMA_HOST={{applications['svc-db-mariadb'].hostname}}
{% if applications[application_id].autologin | bool %} {% if applications[application_id].autologin | bool %}
PMA_USER= root PMA_USER= root
PMA_PASSWORD= "{{applications['mariadb'].credentials.root_password}}" PMA_PASSWORD= "{{applications['svc-db-mariadb'].credentials.root_password}}"
{% endif %} {% endif %}

View File

@ -1,3 +1,3 @@
application_id: "phpmyadmin" application_id: "phpmyadmin"
database_type: "mariadb" database_type: "mariadb"
database_host: "{{ 'central-' + database_type if applications | is_feature_enabled('central_database',application_id) }}" database_host: "{{ applications['svc-db-mariadb'].hostname if applications | is_feature_enabled('central_database',application_id) }}"

View File

@ -0,0 +1,104 @@
import os
import unittest
import yaml
import glob
import ipaddress
class TestNetworksUniqueValidAndMapped(unittest.TestCase):
@classmethod
def setUpClass(cls):
# locate group_vars/all/10_networks.yml
base_dir = os.path.dirname(__file__)
cls.networks_file = os.path.abspath(
os.path.join(base_dir, '..', '..', 'group_vars', 'all', '10_networks.yml')
)
if os.path.isfile(cls.networks_file):
with open(cls.networks_file, 'r', encoding='utf-8') as f:
cls.networks_data = yaml.safe_load(f)
else:
cls.networks_data = None
def test_networks_file_exists(self):
"""Fail if the networks file is missing."""
self.assertTrue(
os.path.isfile(self.networks_file),
f"{self.networks_file} does not exist."
)
def test_unique_and_non_overlapping_subnets(self):
"""Ensure that all subnets are valid, unique and do not overlap."""
if self.networks_data is None:
self.skipTest("10_networks.yml not found, skipping subnet validation.")
# extract all named subnets under defaults_networks.local
local = self.networks_data.get('defaults_networks', {}).get('local', {})
name_to_net = {}
for name, cfg in local.items():
subnet = cfg.get('subnet')
if not subnet:
continue
try:
net = ipaddress.ip_network(subnet)
except ValueError as e:
self.fail(f"Invalid subnet for network '{name}': {subnet} ({e})")
name_to_net[name] = net
# check for duplicate subnets
nets = list(name_to_net.values())
if len(nets) != len(set(nets)):
seen = {}
dupes = []
for nm, net in name_to_net.items():
if net in seen:
dupes.append(f"{seen[net]} and {nm} both use {net}")
else:
seen[net] = nm
self.fail("Duplicate subnets detected:\n" + "\n".join(dupes))
# check for overlaps
items = list(name_to_net.items())
for i in range(len(items)):
name1, net1 = items[i]
for j in range(i+1, len(items)):
name2, net2 = items[j]
if net1.overlaps(net2):
self.fail(
f"Subnet overlap between '{name1}' ({net1}) and "
f"'{name2}' ({net2})."
)
def test_network_names_mapped_to_application_id(self):
"""
Ensure each network name with a subnet under defaults_networks.local
matches an application_id in some roles/*/vars/main.yml.
"""
if self.networks_data is None:
self.skipTest("10_networks.yml not found, skipping application_id mapping check.")
# collect network names
local = self.networks_data.get('defaults_networks', {}).get('local', {})
network_names = [name for name, cfg in local.items() if 'subnet' in cfg]
# gather all application_id values from roles/*/vars/main.yml
base_dir = os.path.dirname(__file__)
roles_dir = os.path.abspath(os.path.join(base_dir, '..', '..', 'roles'))
app_ids = set()
for role_path in glob.glob(os.path.join(roles_dir, '*')):
vars_file = os.path.join(role_path, 'vars', 'main.yml')
if not os.path.isfile(vars_file):
continue
with open(vars_file, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f) or {}
app_id = data.get('application_id')
if app_id:
app_ids.add(app_id)
missing = [nm for nm in network_names if nm not in app_ids]
if missing:
self.fail(
"The following networks have no matching application_id in any role:\n"
+ ", ".join(missing)
)
if __name__ == '__main__':
unittest.main()

View File

@ -5,7 +5,7 @@ import importlib.util
# Dynamisch den Filter-Plugin Pfad hinzufügen # Dynamisch den Filter-Plugin Pfad hinzufügen
current_dir = os.path.dirname(__file__) current_dir = os.path.dirname(__file__)
filter_plugin_path = os.path.abspath(os.path.join(current_dir, "../../../../roles/svc-openldap/filter_plugins")) filter_plugin_path = os.path.abspath(os.path.join(current_dir, "../../../../roles/svc-db-openldap/filter_plugins"))
# Modul dynamisch laden # Modul dynamisch laden
spec = importlib.util.spec_from_file_location("build_ldap_role_entries", os.path.join(filter_plugin_path, "build_ldap_role_entries.py")) spec = importlib.util.spec_from_file_location("build_ldap_role_entries", os.path.join(filter_plugin_path, "build_ldap_role_entries.py"))