mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-09-08 03:07:14 +02:00
Compare commits
16 Commits
fd637c58e3
...
9469452275
Author | SHA1 | Date | |
---|---|---|---|
9469452275 | |||
fd8ef26b53 | |||
8cda54c46e | |||
90bc52632e | |||
0b8d2e0b40 | |||
40491dbc2e | |||
fac8971982 | |||
c791e86b8b | |||
d222b55f30 | |||
a04a1710d3 | |||
4f06f94023 | |||
2529c7cdb3 | |||
ab12a933f6 | |||
529efc0bd7 | |||
725fea1169 | |||
84322f81ef |
@@ -1,50 +0,0 @@
|
||||
# filter_plugins/get_cymais_path.py
|
||||
|
||||
"""
|
||||
This plugin provides filters to extract the CyMaIS directory and file identifiers
|
||||
from a given role name. It assumes the role name is structured as 'dir_file'.
|
||||
If the structure is invalid (e.g., missing or too many underscores), it raises an error.
|
||||
These filters are used to support internal processing within CyMaIS.
|
||||
"""
|
||||
|
||||
from ansible.errors import AnsibleFilterError
|
||||
|
||||
|
||||
class CymaisPathExtractor:
|
||||
"""Extracts directory and file parts from role names in the format 'dir_file'."""
|
||||
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
self._parts = self._split_value()
|
||||
|
||||
def _split_value(self):
|
||||
parts = self.value.split("_")
|
||||
if len(parts) != 2:
|
||||
raise AnsibleFilterError(
|
||||
f"Invalid format: '{self.value}' must contain exactly one underscore (_)"
|
||||
)
|
||||
return parts
|
||||
|
||||
def get_dir(self):
|
||||
return self._parts[0]
|
||||
|
||||
def get_file(self):
|
||||
return self._parts[1]
|
||||
|
||||
|
||||
def get_cymais_dir(value):
|
||||
return CymaisPathExtractor(value).get_dir()
|
||||
|
||||
|
||||
def get_cymais_file(value):
|
||||
return CymaisPathExtractor(value).get_file()
|
||||
|
||||
|
||||
class FilterModule(object):
|
||||
"""Ansible filter plugin for CyMaIS path parsing."""
|
||||
|
||||
def filters(self):
|
||||
return {
|
||||
"get_cymais_dir": get_cymais_dir,
|
||||
"get_cymais_file": get_cymais_file,
|
||||
}
|
17
filter_plugins/get_public_id.py
Normal file
17
filter_plugins/get_public_id.py
Normal file
@@ -0,0 +1,17 @@
|
||||
class FilterModule(object):
|
||||
def filters(self):
|
||||
return {
|
||||
'get_public_id': self.get_public_id
|
||||
}
|
||||
|
||||
def get_public_id(self, value):
|
||||
"""
|
||||
Extract the substring after the last hyphen in the input string.
|
||||
Example:
|
||||
'service-user-abc123' => 'abc123'
|
||||
"""
|
||||
if not isinstance(value, str):
|
||||
raise ValueError("Expected a string")
|
||||
if '-' not in value:
|
||||
raise ValueError("No hyphen found in input string")
|
||||
return value.rsplit('-', 1)[-1]
|
@@ -7,9 +7,9 @@ ports:
|
||||
# https://developer.mozilla.org/de/docs/Web/API/WebSockets_API
|
||||
websocket:
|
||||
web-app-mastodon: 4001
|
||||
espocrm: 4002
|
||||
web-app-espocrm: 4002
|
||||
oauth2_proxy:
|
||||
phpmyadmin: 4181
|
||||
web-app-phpmyadmin: 4181
|
||||
lam: 4182
|
||||
web-app-openproject: 4183
|
||||
yourls: 4184
|
||||
@@ -46,21 +46,21 @@ ports:
|
||||
web-app-openproject: 8023
|
||||
gitlab: 8024
|
||||
web-app-akaunting: 8025
|
||||
moodle: 8026
|
||||
web-app-moodle: 8026
|
||||
taiga: 8027
|
||||
friendica: 8028
|
||||
web-app-port-ui: 8029
|
||||
bluesky_api: 8030
|
||||
bluesky_web: 8031
|
||||
keycloak: 8032
|
||||
web-app-keycloak: 8032
|
||||
lam: 8033
|
||||
phpmyadmin: 8034
|
||||
web-app-phpmyadmin: 8034
|
||||
snipe-it: 8035
|
||||
sphinx: 8036
|
||||
phpldapadmin: 8037
|
||||
fusiondirectory: 8038
|
||||
presentation: 8039
|
||||
espocrm: 8040
|
||||
web-app-espocrm: 8040
|
||||
syncope: 8041
|
||||
collabora: 8042
|
||||
mobilizon: 8043
|
||||
|
@@ -28,7 +28,7 @@ defaults_networks:
|
||||
subnet: 192.168.101.128/28
|
||||
web-app-joomla:
|
||||
subnet: 192.168.101.144/28
|
||||
keycloak:
|
||||
web-app-keycloak:
|
||||
subnet: 192.168.101.160/28
|
||||
web-app-wordpress:
|
||||
subnet: 192.168.101.176/28
|
||||
@@ -46,7 +46,7 @@ defaults_networks:
|
||||
# Use one of the last container ips for dns resolving so that it isn't used
|
||||
dns: 192.168.102.29
|
||||
subnet: 192.168.102.16/28
|
||||
moodle:
|
||||
web-app-moodle:
|
||||
subnet: 192.168.102.32/28
|
||||
web-app-mybb:
|
||||
subnet: 192.168.102.48/28
|
||||
@@ -56,7 +56,7 @@ defaults_networks:
|
||||
subnet: 192.168.102.80/28
|
||||
web-app-peertube:
|
||||
subnet: 192.168.102.96/28
|
||||
phpmyadmin:
|
||||
web-app-phpmyadmin:
|
||||
subnet: 192.168.102.112/28
|
||||
web-app-pixelfed:
|
||||
subnet: 192.168.102.128/28
|
||||
@@ -80,7 +80,7 @@ defaults_networks:
|
||||
subnet: 192.168.103.32/28
|
||||
presentation:
|
||||
subnet: 192.168.103.48/28
|
||||
espocrm:
|
||||
web-app-espocrm:
|
||||
subnet: 192.168.103.64/28
|
||||
syncope:
|
||||
subnet: 192.168.103.80/28
|
||||
|
@@ -12,7 +12,7 @@ _oidc_client_realm: "{{ oidc.client.realm if oidc.client is defined and
|
||||
_oidc_url: "{{
|
||||
(oidc.url
|
||||
if (oidc is defined and oidc.url is defined)
|
||||
else web_protocol ~ '://' ~ (domains | get_domain('keycloak'))
|
||||
else web_protocol ~ '://' ~ (domains | get_domain('web-app-keycloak'))
|
||||
)
|
||||
}}"
|
||||
_oidc_client_issuer_url: "{{ _oidc_url }}/realms/{{_oidc_client_realm}}"
|
||||
|
@@ -1,13 +1,12 @@
|
||||
# Helper variables
|
||||
_database_id: "svc-db-{{ database_type }}"
|
||||
_database_central_name: "{{ applications | get_app_conf( _database_id, 'docker.services.' ~ database_type ~ '.name') }}"
|
||||
_database_central_user: "{{ database_type }}"
|
||||
|
||||
# Definition
|
||||
database_name: "{{ applications | get_app_conf( database_application_id, 'database.name', false, _database_central_name ) }}" # The overwritte configuration is needed by bigbluebutton
|
||||
database_name: "{{ applications | get_app_conf( database_application_id, 'database.name', false, database_application_id | get_public_id ) }}" # The overwritte configuration is needed by bigbluebutton
|
||||
database_instance: "{{ _database_central_name if applications | get_app_conf(database_application_id, 'features.central_database', False) else database_name }}" # This could lead to bugs at dedicated database @todo cleanup
|
||||
database_host: "{{ _database_central_name if applications | get_app_conf(database_application_id, 'features.central_database', False) else 'database' }}" # This could lead to bugs at dedicated database @todo cleanup
|
||||
database_username: "{{ applications | get_app_conf(database_application_id, 'database.username', false, _database_central_user )}}" # The overwritte configuration is needed by bigbluebutton
|
||||
database_username: "{{ applications | get_app_conf(database_application_id, 'database.username', false, database_application_id | get_public_id)}}" # The overwritte configuration is needed by bigbluebutton
|
||||
database_password: "{{ applications | get_app_conf(database_application_id, 'credentials.database_password', true) }}"
|
||||
database_port: "{{ ports.localhost.database[ _database_id ] }}"
|
||||
database_env: "{{docker_compose.directories.env}}{{database_type}}.env"
|
||||
|
@@ -6,7 +6,7 @@ docker:
|
||||
services:
|
||||
openldap:
|
||||
image: "bitnami/openldap"
|
||||
name: "optenldap"
|
||||
name: "openldap"
|
||||
version: "latest"
|
||||
network: "openldap"
|
||||
volumes:
|
||||
|
@@ -1,5 +1,3 @@
|
||||
images:
|
||||
espocrm: "espocrm/espocrm:latest"
|
||||
features:
|
||||
matomo: true
|
||||
css: false
|
||||
@@ -31,3 +29,9 @@ docker:
|
||||
services:
|
||||
database:
|
||||
enabled: true
|
||||
espocrm:
|
||||
image: "espocrm/espocrm"
|
||||
version: "latest"
|
||||
name: "espocrm"
|
||||
volumes:
|
||||
data: espocrm_data
|
@@ -1,6 +1,7 @@
|
||||
{% include 'roles/docker-compose/templates/base.yml.j2' %}
|
||||
web:
|
||||
image: "{{ applications | get_app_conf(application_id, 'images.espocrm', True) }}"
|
||||
container_name: {{ espocrm_name }}
|
||||
image: "{{ espocrm_image }}:{{ espocrm_version }}"
|
||||
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||
{% include 'roles/docker-container/templates/healthcheck/curl.yml.j2' %}
|
||||
ports:
|
||||
@@ -11,7 +12,7 @@
|
||||
- data:/var/www/html
|
||||
|
||||
daemon:
|
||||
image: "{{ applications | get_app_conf(application_id, 'images.espocrm', True) }}"
|
||||
image: "{{ espocrm_image }}:{{ espocrm_version }}"
|
||||
restart: {{docker_restart_policy}}
|
||||
logging:
|
||||
driver: journald
|
||||
@@ -21,7 +22,7 @@
|
||||
- data:/var/www/html
|
||||
|
||||
websocket:
|
||||
image: "{{ applications | get_app_conf(application_id, 'images.espocrm', True) }}"
|
||||
image: "{{ espocrm_image }}:{{ espocrm_version }}"
|
||||
restart: {{docker_restart_policy}}
|
||||
logging:
|
||||
driver: journald
|
||||
@@ -40,5 +41,6 @@
|
||||
|
||||
{% include 'roles/docker-compose/templates/volumes.yml.j2' %}
|
||||
data:
|
||||
name: {{ espocrm_volume }}
|
||||
|
||||
{% include 'roles/docker-compose/templates/networks.yml.j2' %}
|
@@ -1,7 +1,11 @@
|
||||
application_id: "espocrm"
|
||||
application_id: "web-app-espocrm"
|
||||
database_type: "mariadb"
|
||||
ws_path: "/ws"
|
||||
ws_port: "{{ ports.localhost.websocket[application_id] }}"
|
||||
client_max_body_size: "100m"
|
||||
vhost_flavour: "ws_generic"
|
||||
docker_compose_flush_handlers: true
|
||||
espocrm_version: "{{ applications | get_app_conf(application_id, 'docker.services.espocrm.version', True) }}"
|
||||
espocrm_image: "{{ applications | get_app_conf(application_id, 'docker.services.espocrm.image', True) }}"
|
||||
espocrm_name: "{{ applications | get_app_conf(application_id, 'docker.services.espocrm.name', True) }}"
|
||||
espocrm_volume: "{{ applications | get_app_conf(application_id, 'docker.volumes.data', True) }}"
|
@@ -27,6 +27,7 @@ docker:
|
||||
keycloak:
|
||||
image: "quay.io/keycloak/keycloak"
|
||||
version: "latest"
|
||||
name: "keycloak"
|
||||
database:
|
||||
enabled: true
|
||||
|
||||
|
@@ -78,5 +78,5 @@
|
||||
|
||||
- name: Apply SSH Public Key to user-profile via kcadm
|
||||
shell: |
|
||||
docker exec -i {{ container_name }} \
|
||||
docker exec -i {{ keycloak_container }} \
|
||||
/opt/keycloak/bin/kcadm.sh update realms/{{ keycloak_realm }} -f {{ keycloak_docker_import_directory }}user-profile.json
|
||||
|
@@ -517,7 +517,7 @@
|
||||
"/realms/{{ keycloak_realm }}/account/*"
|
||||
],
|
||||
"webOrigins": [
|
||||
"{{ domains | get_url('keycloak', web_protocol) }}"
|
||||
"{{ domains | get_url('web-app-keycloak', web_protocol) }}"
|
||||
],
|
||||
"notBefore": 0,
|
||||
"bearerOnly": false,
|
||||
@@ -1697,7 +1697,7 @@
|
||||
"replyTo": "",
|
||||
"host": "{{system_email.host}}",
|
||||
"from": "{{ users['no-reply'].email }}",
|
||||
"fromDisplayName": "Keycloak Authentification System - {{domains | get_domain('keycloak')}}",
|
||||
"fromDisplayName": "Keycloak Authentification System - {{domains | get_domain('web-app-keycloak')}}",
|
||||
"envelopeFrom": "",
|
||||
"ssl": "true",
|
||||
"user": "{{ users['no-reply'].email }}"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
application_id: "keycloak" # Internal CyMaIS application id
|
||||
application_id: "web-app-keycloak" # Internal CyMaIS application id
|
||||
database_type: "postgres" # Database which will be used
|
||||
keycloak_container: "{{ application_id }}_application" # Name of the keycloack docker container
|
||||
keycloak_container: "{{ applications | get_app_conf(application_id, 'docker.services.keycloak.name', True) }}" # Name of the keycloack docker container
|
||||
keycloak_host_import_directory: "{{ docker_compose.directories.volumes }}import/" # Directory in which keycloack import files are placed on the host
|
||||
keycloak_docker_import_directory: "/opt/keycloak/data/import/" # Directory in which keycloack import files are placed in the running docker container
|
||||
keycloak_realm: "{{ primary_domain}}" # This is the name of the default realm which is used by the applications
|
||||
|
@@ -28,5 +28,6 @@ docker:
|
||||
streaming:
|
||||
image: "ghcr.io/mastodon/mastodon-streaming"
|
||||
version: latest
|
||||
name: "mastodon-streaming"
|
||||
volumes:
|
||||
data: "mastodon_data"
|
@@ -6,7 +6,7 @@
|
||||
- name: "Include setup for domain '{{ domain }}'"
|
||||
include_role:
|
||||
name: srv-proxy-6-6-domain
|
||||
loop: "{{ domains.mastodon }}"
|
||||
loop: "{{ domains['web-app-mastodon'] }}"
|
||||
loop_control:
|
||||
loop_var: domain
|
||||
vars:
|
||||
|
@@ -24,7 +24,7 @@
|
||||
command: node ./streaming
|
||||
{% include 'roles/docker-container/templates/healthcheck/wget.yml.j2' %}
|
||||
ports:
|
||||
- "127.0.0.1:{{ports.localhost.websocket[application_id]}}:{{ container_port }}"
|
||||
- "127.0.0.1:{{ ports.localhost.websocket[application_id] }}:{{ container_port }}"
|
||||
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
|
||||
{% include 'roles/docker-container/templates/networks.yml.j2' %}
|
||||
|
||||
@@ -37,7 +37,10 @@
|
||||
volumes:
|
||||
- data:/mastodon/public/system
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', "ps aux | grep '[s]idekiq\ 6' || false"]
|
||||
test: ["CMD-SHELL", "pgrep -f sidekiq || exit 1"]
|
||||
interval: 1m
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
{% include 'roles/docker-container/templates/networks.yml.j2' %}
|
||||
|
||||
{% include 'roles/docker-compose/templates/volumes.yml.j2' %}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
|
||||
LOCAL_DOMAIN={{domains | get_domain(application_id)}}
|
||||
ALTERNATE_DOMAINS="{{ domains.mastodon[1:] | join(',') }}"
|
||||
ALTERNATE_DOMAINS="{{ domains['web-app-mastodon'][1:] | join(',') }}"
|
||||
SINGLE_USER_MODE={{ applications | get_app_conf(application_id, 'single_user_mode', True) }}
|
||||
|
||||
# Credentials
|
||||
|
@@ -4,8 +4,8 @@ mastodon_version: "{{ applications | get_app_conf(application_id, 'd
|
||||
mastodon_image: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.image', True) }}"
|
||||
mastodon_name: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.name', True) }}"
|
||||
mastodon_volume: "{{ applications | get_app_conf(application_id, 'docker.volumes.data', True) }}"
|
||||
mastodon_streaming_version: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.version', True) }}"
|
||||
mastodon_streaming_image: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.image', True) }}"
|
||||
mastodon_streaming_name: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.name', True) }}_streaming"
|
||||
mastodon_streaming_version: "{{ applications | get_app_conf(application_id, 'docker.services.streaming.version', True) }}"
|
||||
mastodon_streaming_image: "{{ applications | get_app_conf(application_id, 'docker.services.streaming.image', True) }}"
|
||||
mastodon_streaming_name: "{{ applications | get_app_conf(application_id, 'docker.services.streaming.name', True) }}"
|
||||
mastodon_sidekiq_name: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.name', True) }}_sidekiq"
|
||||
mastodon_setup: "{{ applications | get_app_conf(application_id, 'setup', True) }}"
|
@@ -2,6 +2,9 @@
|
||||
include_role:
|
||||
name: cmp-db-docker-proxy
|
||||
|
||||
- name: "Update database credentials"
|
||||
include_tasks: database.yml
|
||||
|
||||
- name: flush docker service
|
||||
meta: flush_handlers
|
||||
|
||||
|
25
roles/web-app-matomo/tasks/database.yml
Normal file
25
roles/web-app-matomo/tasks/database.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
- name: Backup config.ini.php before patching
|
||||
command: >
|
||||
docker cp {{ matomo_name }}:{{ matomo_config }} {{ matomo_backup_file }}
|
||||
|
||||
- name: Patch Matomo config.ini.php with updated DB credentials
|
||||
block:
|
||||
- name: Update DB host
|
||||
command: >
|
||||
docker exec --user root {{ matomo_name }}
|
||||
sed -i "s/^host *=.*/host = {{ database_host }}/" {{ matomo_config }}
|
||||
|
||||
- name: Update DB name
|
||||
command: >
|
||||
docker exec --user root {{ matomo_name }}
|
||||
sed -i "s/^dbname *=.*/dbname = {{ database_name }}/" {{ matomo_config }}
|
||||
|
||||
- name: Update DB user
|
||||
command: >
|
||||
docker exec --user root {{ matomo_name }}
|
||||
sed -i "s/^username *=.*/username = {{ database_username }}/" {{ matomo_config }}
|
||||
|
||||
- name: Update DB password
|
||||
command: >
|
||||
docker exec --user root {{ matomo_name }}
|
||||
sed -i "s/^password *=.*/password = {{ database_password }}/" {{ matomo_config }}
|
@@ -1,5 +1,6 @@
|
||||
{% include 'roles/docker-compose/templates/base.yml.j2' %}
|
||||
application:
|
||||
container_name: {{ matomo_name }}
|
||||
{% set container_port = 80 %}
|
||||
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||
image: "{{ matomo_image }}:{{ matomo_version }}"
|
||||
|
@@ -6,7 +6,10 @@ matomo_index_php_url: "{{ domains | get_url(application_id, web_protocol) }}/ind
|
||||
matomo_auth_token: "{{ applications | get_app_conf(application_id, 'credentials.auth_token', True) }}"
|
||||
matomo_version: "{{ applications | get_app_conf(application_id, 'docker.services.matomo.version', True) }}"
|
||||
matomo_image: "{{ applications | get_app_conf(application_id, 'docker.services.matomo.image', True) }}"
|
||||
matomo_name: "{{ applications | get_app_conf(application_id, 'docker.services.matomo.name', True) }}"
|
||||
matomo_data: "{{ applications | get_app_conf(application_id, 'docker.volumes.data', True) }}"
|
||||
matomo_backup_file: "{{ docker_compose.directories.instance }}/config.ini.php.bak"
|
||||
matomo_config: "/var/www/html/config/config.ini.php"
|
||||
|
||||
# I don't know if this is still necessary
|
||||
domain: "{{ domains | get_domain(application_id) }}"
|
@@ -1,5 +1,4 @@
|
||||
site_titel: "Academy on {{primary_domain}}"
|
||||
version: "4.5" # Latest LTS - Necessary for OIDC
|
||||
features:
|
||||
matomo: true
|
||||
css: false
|
||||
@@ -29,3 +28,11 @@ docker:
|
||||
services:
|
||||
database:
|
||||
enabled: true
|
||||
moodle:
|
||||
version: "4.5" # Latest LTS - Necessary for OIDC
|
||||
image: bitnami/moodle
|
||||
name: moodle
|
||||
volumes:
|
||||
data: moodle_data
|
||||
code: moodle_code
|
||||
|
47
roles/web-app-moodle/tasks/database.yml
Normal file
47
roles/web-app-moodle/tasks/database.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
- name: Check if config.php exists
|
||||
command: docker exec --user root {{ moodle_container }} test -f {{ moodle_config }}
|
||||
register: config_file_exists
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Backup config.php to host
|
||||
when: config_file_exists.rc == 0
|
||||
block:
|
||||
- name: Create backup directory on host
|
||||
ansible.builtin.file:
|
||||
path: "/opt/docker/moodle/_backup"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Copy config.php from container to host
|
||||
command: >
|
||||
docker cp {{ moodle_container }}:{{ moodle_config }} {{ moodle_backup_file }}
|
||||
|
||||
- name: Check if config.php exists
|
||||
command: docker exec --user root {{ moodle_container }} test -f {{ moodle_config }}
|
||||
register: config_file_exists
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Patch Moodle config.php with updated DB credentials
|
||||
when: config_file_exists.rc == 0
|
||||
block:
|
||||
- name: Update DB host
|
||||
command: >
|
||||
docker exec --user root {{ moodle_container }}
|
||||
sed -i "s/^\$CFG->dbhost *= *.*/\$CFG->dbhost = '{{ database_host }}';/" {{ moodle_config }}
|
||||
|
||||
- name: Update DB name
|
||||
command: >
|
||||
docker exec --user root {{ moodle_container }}
|
||||
sed -i "s/^\$CFG->dbname *= *.*/\$CFG->dbname = '{{ database_name }}';/" {{ moodle_config }}
|
||||
|
||||
- name: Update DB user
|
||||
command: >
|
||||
docker exec --user root {{ moodle_container }}
|
||||
sed -i "s/^\$CFG->dbuser *= *.*/\$CFG->dbuser = '{{ database_username }}';/" {{ moodle_config }}
|
||||
|
||||
- name: Update DB password
|
||||
command: >
|
||||
docker exec --user root {{ moodle_container }}
|
||||
sed -i "s/^\$CFG->dbpass *= *.*/\$CFG->dbpass = '{{ database_password }}';/" {{ moodle_config }}
|
@@ -3,8 +3,14 @@
|
||||
include_role:
|
||||
name: cmp-db-docker-proxy
|
||||
|
||||
- name: "Update database credentials"
|
||||
include_tasks: database.yml
|
||||
|
||||
- name: flush docker service
|
||||
meta: flush_handlers
|
||||
|
||||
- name: Wait until the Moodle container is healthy
|
||||
shell: docker inspect --format '{% raw %}{{.State.Health.Status}}{% endraw %}' {{ container_name }}
|
||||
shell: docker inspect --format '{% raw %}{{.State.Health.Status}}{% endraw %}' {{ moodle_container }}
|
||||
register: health_check
|
||||
until: health_check.stdout.strip() == "healthy"
|
||||
retries: 120
|
||||
@@ -19,7 +25,7 @@
|
||||
|
||||
- name: Run Moodle system check
|
||||
command: >
|
||||
docker exec --user {{ bitnami_user }} {{ container_name }}
|
||||
docker exec --user {{ bitnami_user }} {{ moodle_container }}
|
||||
php /opt/bitnami/moodle/admin/cli/checks.php
|
||||
register: moodle_checks
|
||||
changed_when: false
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
- name: Check if OIDC plugin is present in container
|
||||
command: >
|
||||
docker exec --user root {{ container_name }} test -d {{ bitnami_oidc_plugin_dir }}
|
||||
docker exec --user root {{ moodle_container }} test -d {{ bitnami_oidc_plugin_dir }}
|
||||
register: oidc_plugin_check
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
@@ -13,11 +13,11 @@
|
||||
when: oidc_plugin_check.rc != 0
|
||||
|
||||
#- name: "Upgrade Moodle to apply OIDC plugin"
|
||||
# command: "docker exec --user {{ bitnami_user }} {{ container_name }} php /opt/bitnami/moodle/admin/cli/upgrade.php --non-interactive"
|
||||
# command: "docker exec --user {{ bitnami_user }} {{ moodle_container }} php /opt/bitnami/moodle/admin/cli/upgrade.php --non-interactive"
|
||||
#
|
||||
#- name: Clear Moodle cache
|
||||
# command: >
|
||||
# docker exec --user {{ bitnami_user }} {{ container_name }} php /opt/bitnami/moodle/admin/cli/purge_caches.php
|
||||
# docker exec --user {{ bitnami_user }} {{ moodle_container }} php /opt/bitnami/moodle/admin/cli/purge_caches.php
|
||||
|
||||
- name: "Set Moodle OIDC configuration via CLI"
|
||||
loop:
|
||||
@@ -43,11 +43,11 @@
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
command: >
|
||||
docker exec --user {{ bitnami_user }} {{ container_name }} php /opt/bitnami/moodle/admin/cli/cfg.php --component=auth_oidc
|
||||
docker exec --user {{ bitnami_user }} {{ moodle_container }} php /opt/bitnami/moodle/admin/cli/cfg.php --component=auth_oidc
|
||||
--name={{ item.name }} --set="{{ item.value }}"
|
||||
|
||||
- name: "Enable OIDC login"
|
||||
command: "docker exec --user {{ bitnami_user }} {{ container_name }} php /opt/bitnami/moodle/admin/cli/cfg.php --name=auth --set=oidc"
|
||||
command: "docker exec --user {{ bitnami_user }} {{ moodle_container }} php /opt/bitnami/moodle/admin/cli/cfg.php --name=auth --set=oidc"
|
||||
|
||||
- name: Set auth = 'oidc' for all users except guest
|
||||
shell: >
|
||||
@@ -57,4 +57,4 @@
|
||||
executable: /bin/bash
|
||||
|
||||
#- name: Prevent Account Creation
|
||||
# command: docker exec --user {{ bitnami_user }} {{ container_name }} php /opt/bitnami/moodle/admin/cli/cfg.php --name=authpreventaccountcreation --set=1
|
||||
# command: docker exec --user {{ bitnami_user }} {{ moodle_container }} php /opt/bitnami/moodle/admin/cli/cfg.php --name=authpreventaccountcreation --set=1
|
@@ -7,13 +7,13 @@
|
||||
- "{{ bitnami_data_dir }}"
|
||||
block:
|
||||
- name: Ensure ownership is correct
|
||||
command: "docker exec --user root {{ container_name }} chown -R {{ bitnami_user_group }} {{ item }}"
|
||||
command: "docker exec --user root {{ moodle_container }} chown -R {{ bitnami_user_group }} {{ item }}"
|
||||
loop: "{{ moodle_dirs }}"
|
||||
|
||||
- name: Set directory permissions (770)
|
||||
command: "docker exec --user root {{ container_name }} find {{ item }} -type d -exec chmod 770 {} \\;"
|
||||
command: "docker exec --user root {{ moodle_container }} find {{ item }} -type d -exec chmod 770 {} \\;"
|
||||
loop: "{{ moodle_dirs }}"
|
||||
|
||||
- name: Set file permissions (660)
|
||||
command: "docker exec --user root {{ container_name }} find {{ item }} -type f -exec chmod 660 {} \\;"
|
||||
command: "docker exec --user root {{ moodle_container }} find {{ item }} -type f -exec chmod 660 {} \\;"
|
||||
loop: "{{ moodle_dirs }}"
|
||||
|
@@ -1,10 +1,10 @@
|
||||
FROM bitnami/moodle:{{ applications | get_app_conf(application_id, 'version', True) }}
|
||||
FROM {{ moodle_image }}:{{ moodle_version }}
|
||||
|
||||
{% if applications | get_app_conf(application_id, 'features.oidc', False) %}
|
||||
RUN install_packages unzip curl jq \
|
||||
&& VERSION=$(curl -s https://api.github.com/repos/microsoft/moodle-auth_oidc/tags \
|
||||
| jq -r '.[].name' \
|
||||
| grep v{{ applications | get_app_conf(application_id, 'version', True) }} \
|
||||
| grep v{{ moodle_version }} \
|
||||
| sort -Vr \
|
||||
| head -n1) \
|
||||
&& echo "Using version $VERSION" \
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
moodle:
|
||||
{% set container_port = 8080 %}
|
||||
container_name: {{ container_name }}
|
||||
container_name: {{ moodle_container }}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
@@ -19,7 +19,9 @@
|
||||
|
||||
{% include 'roles/docker-compose/templates/volumes.yml.j2' %}
|
||||
code:
|
||||
name: {{ moodle_volume_code }}
|
||||
data:
|
||||
name: {{ moodle_volume_data }}
|
||||
|
||||
{% include 'roles/docker-compose/templates/networks.yml.j2' %}
|
||||
|
@@ -1,11 +1,19 @@
|
||||
---
|
||||
application_id: "moodle"
|
||||
application_id: "web-app-moodle"
|
||||
database_type: "mariadb"
|
||||
container_name: "{{ application_id }}"
|
||||
bitnami_code_link: "/bitnami/moodle"
|
||||
bitnami_code_dir: "/opt{{bitnami_code_link}}"
|
||||
bitnami_data_dir: "/bitnami/moodledata"
|
||||
bitnami_oidc_plugin_dir: "{{ bitnami_code_dir }}/auth/oidc"
|
||||
bitnami_user: "daemon"
|
||||
bitnami_user_group: "{{ bitnami_user }}:{{ bitnami_user }}"
|
||||
docker_compose_flush_handlers: true
|
||||
|
||||
docker_compose_flush_handlers: false # Wait for env update
|
||||
|
||||
moodle_backup_file: "{{ docker_compose.directories.instance }}/config.ini.php.bak"
|
||||
moodle_config: "/bitnami/moodle/config.php"
|
||||
moodle_version: "{{ applications | get_app_conf(application_id, 'docker.services.moodle.version', True) }}"
|
||||
moodle_image: "{{ applications | get_app_conf(application_id, 'docker.services.moodle.image', True) }}"
|
||||
moodle_container: "{{ applications | get_app_conf(application_id, 'docker.services.moodle.name', True) }}"
|
||||
moodle_volume_data: "{{ applications | get_app_conf(application_id, 'docker.volumes.data', True) }}"
|
||||
moodle_volume_code: "{{ applications | get_app_conf(application_id, 'docker.volumes.code', True) }}"
|
@@ -25,7 +25,7 @@ plugin_configuration:
|
||||
configkey: "custom_providers"
|
||||
configvalue:
|
||||
custom_oidc:
|
||||
- name: "{{ domains | get_domain('keycloak') }}"
|
||||
- name: "{{ domains | get_domain('web-app-keycloak') }}"
|
||||
title: "keycloak"
|
||||
style: "keycloak"
|
||||
authorizeUrl: "{{ oidc.client.authorize_url }}"
|
||||
|
@@ -2,7 +2,7 @@ http_address = "0.0.0.0:4180"
|
||||
cookie_secret = "{{ applications | get_app_conf(oauth2_proxy_application_id, 'credentials.oauth2_proxy_cookie_secret', True) }}"
|
||||
cookie_secure = "true" # True is necessary to force the cookie set via https
|
||||
upstreams = "http://{{ applications | get_app_conf(oauth2_proxy_application_id, 'oauth2_proxy.application', True) }}:{{ applications | get_app_conf(oauth2_proxy_application_id, 'oauth2_proxy.port', True) }}"
|
||||
cookie_domains = ["{{ domains | get_domain(oauth2_proxy_application_id) }}", "{{ domains | get_domain('keycloak') }}"] # Required so cookie can be read on all subdomains.
|
||||
cookie_domains = ["{{ domains | get_domain(oauth2_proxy_application_id) }}", "{{ domains | get_domain('web-app-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
|
||||
|
@@ -1,4 +1,3 @@
|
||||
version: "latest" # Use the latest phpmyadmin version
|
||||
autologin: false # This is a high security risk. Just activate this option if you know what you're doing
|
||||
oauth2_proxy:
|
||||
port: "80"
|
||||
@@ -24,3 +23,7 @@ docker:
|
||||
services:
|
||||
database:
|
||||
enabled: true
|
||||
phpmyadmin:
|
||||
version: "latest" # Use the latest phpmyadmin version
|
||||
name: "phpmyadmin"
|
||||
image: phpmyadmin/phpmyadmin
|
||||
|
@@ -2,8 +2,8 @@
|
||||
|
||||
application:
|
||||
{% set container_port = 80 %}
|
||||
image: phpmyadmin/phpmyadmin:{{applications.phpmyadmin.version}}
|
||||
container_name: phpmyadmin
|
||||
image: "{{ phpmyadmin_image }}:{{ phpmyadmin_version }}"
|
||||
container_name: "{{ phpmyadmin_name }}"
|
||||
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||
ports:
|
||||
- "127.0.0.1:{{ports.localhost.http[application_id]}}:{{ container_port }}"
|
||||
|
@@ -1,3 +1,6 @@
|
||||
application_id: "phpmyadmin"
|
||||
application_id: "web-app-phpmyadmin"
|
||||
database_type: "mariadb"
|
||||
database_host: "{{ applications | get_app_conf('svc-db-mariadb', 'docker.services.mariadb.name', True) if applications | get_app_conf(application_id, 'features.central_database', False)}}"
|
||||
phpmyadmin_version: "{{ applications | get_app_conf(application_id, 'docker.services.phpmyadmin.version', True) }}"
|
||||
phpmyadmin_image: "{{ applications | get_app_conf(application_id, 'docker.services.phpmyadmin.image', True) }}"
|
||||
phpmyadmin_name: "{{ applications | get_app_conf(application_id, 'docker.services.phpmyadmin.name', True) }}"
|
@@ -32,19 +32,19 @@ applications:
|
||||
description: Access the central admin console
|
||||
icon:
|
||||
class: fa-solid fa-shield-halved
|
||||
url: https://{{domains | get_domain('keycloak')}}/admin
|
||||
iframe: {{ applications | get_app_conf( 'keycloak', 'features.port-ui-desktop', False) }}
|
||||
url: https://{{domains | get_domain('web-app-keycloak')}}/admin
|
||||
iframe: {{ applications | get_app_conf( 'web-app-keycloak', 'features.port-ui-desktop', False) }}
|
||||
- name: Profile
|
||||
description: Update your personal admin settings
|
||||
icon:
|
||||
class: fa-solid fa-user-gear
|
||||
url: https://{{ domains | get_domain('keycloak') }}/realms/{{oidc.client.id}}/account
|
||||
iframe: {{ applications | get_app_conf( 'keycloak', 'features.port-ui-desktop', False) }}
|
||||
url: https://{{ domains | get_domain('web-app-keycloak') }}/realms/{{oidc.client.id}}/account
|
||||
iframe: {{ applications | get_app_conf( 'web-app-keycloak', 'features.port-ui-desktop', False) }}
|
||||
- name: Logout
|
||||
description: End your admin session securely
|
||||
icon:
|
||||
class: fa-solid fa-right-from-bracket
|
||||
url: https://{{ domains | get_domain('keycloak') }}/realms/{{oidc.client.id}}/protocol/openid-connect/logout
|
||||
url: https://{{ domains | get_domain('web-app-keycloak') }}/realms/{{oidc.client.id}}/protocol/openid-connect/logout
|
||||
iframe: false
|
||||
|
||||
{% endif %}
|
||||
|
@@ -31,7 +31,7 @@ followus:
|
||||
class: fa-solid fa-camera
|
||||
identifier: "{{service_provider.contact.pixelfed}}"
|
||||
url: "{{ web_protocol }}://{{ service_provider.contact.pixelfed.split('@')[2] }}/@{{ service_provider.contact.pixelfed.split('@')[1] }}"
|
||||
iframe: {{ applications | get_app_conf(web-app-pixelfed,'features.port-ui-desktop',True) }}
|
||||
iframe: {{ applications | get_app_conf('web-app-pixelfed','features.port-ui-desktop',True) }}
|
||||
{% endif %}
|
||||
{% if service_provider.contact.peertube is defined and service_provider.contact.peertube != "" %}
|
||||
- name: Peertube
|
||||
|
@@ -1,46 +0,0 @@
|
||||
# tests/unit/filter_plugins/test_get_cymais_path.py
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ensure the filter_plugins directory is in the import path
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../filter_plugins')))
|
||||
|
||||
from get_cymais_path import get_cymais_dir, get_cymais_file
|
||||
from ansible.errors import AnsibleFilterError
|
||||
|
||||
|
||||
class TestGetCymaisPath(unittest.TestCase):
|
||||
def test_valid_input(self):
|
||||
"""Test valid input with exactly one underscore"""
|
||||
self.assertEqual(get_cymais_dir("web_app"), "web")
|
||||
self.assertEqual(get_cymais_file("web_app"), "app")
|
||||
|
||||
self.assertEqual(get_cymais_dir("sys_timer"), "sys")
|
||||
self.assertEqual(get_cymais_file("sys_timer"), "timer")
|
||||
|
||||
def test_invalid_no_underscore(self):
|
||||
"""Test input with no underscore raises error"""
|
||||
with self.assertRaises(AnsibleFilterError):
|
||||
get_cymais_dir("invalid")
|
||||
with self.assertRaises(AnsibleFilterError):
|
||||
get_cymais_file("invalid")
|
||||
|
||||
def test_invalid_multiple_underscores(self):
|
||||
"""Test input with more than one underscore raises error"""
|
||||
with self.assertRaises(AnsibleFilterError):
|
||||
get_cymais_dir("too_many_parts_here")
|
||||
with self.assertRaises(AnsibleFilterError):
|
||||
get_cymais_file("too_many_parts_here")
|
||||
|
||||
def test_empty_string(self):
|
||||
"""Test empty string input raises error"""
|
||||
with self.assertRaises(AnsibleFilterError):
|
||||
get_cymais_dir("")
|
||||
with self.assertRaises(AnsibleFilterError):
|
||||
get_cymais_file("")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
26
tests/unit/filter_plugins/test_get_public_id.py
Normal file
26
tests/unit/filter_plugins/test_get_public_id.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import unittest
|
||||
from filter_plugins.get_public_id import FilterModule
|
||||
|
||||
class TestGetPublicId(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.filter = FilterModule().filters()['get_public_id']
|
||||
|
||||
def test_extract_public_id(self):
|
||||
self.assertEqual(self.filter("svc-user-abc123"), "abc123")
|
||||
self.assertEqual(self.filter("something-simple-xyz"), "xyz")
|
||||
self.assertEqual(self.filter("a-b-c-d-e"), "e")
|
||||
|
||||
def test_no_hyphen(self):
|
||||
with self.assertRaises(ValueError):
|
||||
self.filter("nohyphenhere")
|
||||
|
||||
def test_non_string_input(self):
|
||||
with self.assertRaises(ValueError):
|
||||
self.filter(12345)
|
||||
|
||||
def test_empty_string(self):
|
||||
with self.assertRaises(ValueError):
|
||||
self.filter("")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Reference in New Issue
Block a user