mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-06-25 11:45:32 +02:00
Compare commits
7 Commits
c492c824b7
...
f06ad0af18
Author | SHA1 | Date | |
---|---|---|---|
f06ad0af18 | |||
76aef5949b | |||
9c65c320f9 | |||
2302cbfeb4 | |||
9c45d070b4 | |||
2478e4013f | |||
2aac8b5f80 |
27
Makefile
27
Makefile
@ -1,17 +1,26 @@
|
|||||||
ROLES_DIR=./roles
|
ROLES_DIR := ./roles
|
||||||
OUTPUT=./group_vars/all/11_applications.yml
|
APPLICATIONS_OUT := ./group_vars/all/11_applications.yml
|
||||||
SCRIPT=./cli/generate_defaults_applications.py
|
APPLICATIONS_SCRIPT := ./cli/generate_defaults_applications.py
|
||||||
|
INCLUDES_OUT := ./tasks/include-docker-roles.yml
|
||||||
|
INCLUDES_SCRIPT := ./cli/generate_role_includes.py
|
||||||
|
|
||||||
|
.PHONY: build install test
|
||||||
|
|
||||||
build:
|
build:
|
||||||
@echo "🔧 Generating $(OUTPUT) from roles in $(ROLES_DIR)..."
|
@echo "🔧 Generating applications defaults → $(APPLICATIONS_OUT) from roles in $(ROLES_DIR)…"
|
||||||
@mkdir -p $(dir $(OUTPUT))
|
@mkdir -p $(dir $(APPLICATIONS_OUT))
|
||||||
python3 $(SCRIPT) --roles-dir $(ROLES_DIR) --output-file $(OUTPUT)
|
python3 $(APPLICATIONS_SCRIPT) --roles-dir $(ROLES_DIR) --output-file $(APPLICATIONS_OUT)
|
||||||
@echo "✅ Output written to $(OUTPUT)"
|
@echo "✅ Applications defaults written to $(APPLICATIONS_OUT)\n"
|
||||||
|
@echo "🔧 Generating Docker role includes → $(INCLUDES_OUT)…"
|
||||||
|
@mkdir -p $(dir $(INCLUDES_OUT))
|
||||||
|
python3 $(INCLUDES_SCRIPT) $(ROLES_DIR) -o $(INCLUDES_OUT) -p docker-
|
||||||
|
@echo "✅ Docker role includes written to $(INCLUDES_OUT)"
|
||||||
|
|
||||||
install: build
|
install: build
|
||||||
|
@echo "⚙️ Install complete."
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@echo "Executing Unit Tests:"
|
@echo "🧪 Running Unit Tests..."
|
||||||
python -m unittest discover -s tests/unit
|
python -m unittest discover -s tests/unit
|
||||||
@echo "Executing Integration Tests:"
|
@echo "🔬 Running Integration Tests..."
|
||||||
python -m unittest discover -s tests/integration
|
python -m unittest discover -s tests/integration
|
79
cli/generate_role_includes.py
Normal file
79
cli/generate_role_includes.py
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
def find_roles(roles_dir, prefix=None):
|
||||||
|
"""
|
||||||
|
Yield absolute paths of role directories under roles_dir.
|
||||||
|
Only include roles whose directory name starts with prefix (if given) and contain vars/main.yml.
|
||||||
|
"""
|
||||||
|
for entry in os.listdir(roles_dir):
|
||||||
|
if prefix and not entry.startswith(prefix):
|
||||||
|
continue
|
||||||
|
path = os.path.join(roles_dir, entry)
|
||||||
|
vars_file = os.path.join(path, 'vars', 'main.yml')
|
||||||
|
if os.path.isdir(path) and os.path.isfile(vars_file):
|
||||||
|
yield path, vars_file
|
||||||
|
|
||||||
|
|
||||||
|
def load_application_id(vars_file):
|
||||||
|
"""
|
||||||
|
Load the vars/main.yml and return the value of application_id key.
|
||||||
|
Returns None if not found.
|
||||||
|
"""
|
||||||
|
with open(vars_file, 'r') as f:
|
||||||
|
data = yaml.safe_load(f) or {}
|
||||||
|
return data.get('application_id')
|
||||||
|
|
||||||
|
|
||||||
|
def generate_playbook_entries(roles_dir, prefix=None):
|
||||||
|
entries = []
|
||||||
|
for role_path, vars_file in find_roles(roles_dir, prefix):
|
||||||
|
app_id = load_application_id(vars_file)
|
||||||
|
if not app_id:
|
||||||
|
continue
|
||||||
|
# Derive role name from directory name
|
||||||
|
role_name = os.path.basename(role_path)
|
||||||
|
# entry text
|
||||||
|
entry = (
|
||||||
|
f"- name: setup {app_id}\n"
|
||||||
|
f" when: (\"{app_id}\" in group_names)\n"
|
||||||
|
f" include_role:\n"
|
||||||
|
f" name: {role_name}\n"
|
||||||
|
)
|
||||||
|
entries.append(entry)
|
||||||
|
return entries
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description='Generate an Ansible playbook include file from Docker roles and application_ids.'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'roles_dir',
|
||||||
|
help='Path to directory containing role folders'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-p', '--prefix',
|
||||||
|
help='Only include roles whose names start with this prefix (e.g. docker-, client-)',
|
||||||
|
default=None
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-o', '--output',
|
||||||
|
help='Output file path (default: stdout)',
|
||||||
|
default=None
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
entries = generate_playbook_entries(args.roles_dir, args.prefix)
|
||||||
|
output = ''.join(entries)
|
||||||
|
|
||||||
|
if args.output:
|
||||||
|
with open(args.output, 'w') as f:
|
||||||
|
f.write(output)
|
||||||
|
print(f"Playbook entries written to {args.output}")
|
||||||
|
else:
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -21,7 +21,7 @@ defaults_applications:
|
|||||||
features: # Version of the service
|
features: # Version of the service
|
||||||
matomo: true # Enable Matomo tracking for analytics
|
matomo: true # Enable Matomo tracking for analytics
|
||||||
css: true # Enable or disable global CSS styling
|
css: true # Enable or disable global CSS styling
|
||||||
iframe: false # Allow embedding the landing page in an iframe (if true)
|
portfolio_iframe: false # Allow embedding the landing page in an iframe (if true)
|
||||||
database: true # Enable central database integration
|
database: true # Enable central database integration
|
||||||
ldap: true # Enable ldap integration
|
ldap: true # Enable ldap integration
|
||||||
oauth2: true # Enable oauth2 proxy
|
oauth2: true # Enable oauth2 proxy
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
from pkgutil import extend_path
|
||||||
|
__path__ = extend_path(__path__, __name__)
|
@ -113,6 +113,13 @@ class FilterModule(object):
|
|||||||
if matomo_domain:
|
if matomo_domain:
|
||||||
tokens.append(f"{web_protocol}://{matomo_domain}")
|
tokens.append(f"{web_protocol}://{matomo_domain}")
|
||||||
|
|
||||||
|
# ReCaptcha integration: allow loading scripts from Google if feature enabled
|
||||||
|
if (
|
||||||
|
self.is_feature_enabled(applications, 'recaptcha', application_id)
|
||||||
|
and directive == 'script-src'
|
||||||
|
):
|
||||||
|
tokens.append('https://www.google.com')
|
||||||
|
|
||||||
# whitelist
|
# whitelist
|
||||||
tokens += self.get_csp_whitelist(applications, application_id, directive)
|
tokens += self.get_csp_whitelist(applications, application_id, directive)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
CYMAIS_ENVIRONMENT: "production"
|
||||||
|
|
||||||
HOST_CURRENCY: "EUR"
|
HOST_CURRENCY: "EUR"
|
||||||
HOST_TIMEZONE: "UTC"
|
HOST_TIMEZONE: "UTC"
|
||||||
|
5
main.py
5
main.py
@ -3,6 +3,7 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
|
import datetime
|
||||||
|
|
||||||
def run_ansible_vault(action, filename, password_file):
|
def run_ansible_vault(action, filename, password_file):
|
||||||
"""Execute an ansible-vault command with the specified action on a file."""
|
"""Execute an ansible-vault command with the specified action on a file."""
|
||||||
@ -10,6 +11,8 @@ def run_ansible_vault(action, filename, password_file):
|
|||||||
subprocess.run(cmd, check=True)
|
subprocess.run(cmd, check=True)
|
||||||
|
|
||||||
def run_ansible_playbook(inventory: str, playbook: str, modes: dict, limit: str = None, password_file: str = None, verbose: int = 0, skip_tests: bool = False):
|
def run_ansible_playbook(inventory: str, playbook: str, modes: dict, limit: str = None, password_file: str = None, verbose: int = 0, skip_tests: bool = False):
|
||||||
|
start_time = datetime.datetime.now().isoformat()
|
||||||
|
print(f"\n▶️ Script started at: {start_time}\n")
|
||||||
print("\n🛠️ Building project (make build)...\n")
|
print("\n🛠️ Building project (make build)...\n")
|
||||||
subprocess.run(["make", "build"], check=True)
|
subprocess.run(["make", "build"], check=True)
|
||||||
|
|
||||||
@ -39,6 +42,8 @@ def run_ansible_playbook(inventory: str, playbook: str, modes: dict, limit: str
|
|||||||
print("\n🚀 Launching Ansible Playbook...\n")
|
print("\n🚀 Launching Ansible Playbook...\n")
|
||||||
subprocess.run(cmd, check=True)
|
subprocess.run(cmd, check=True)
|
||||||
|
|
||||||
|
end_time = datetime.datetime.now().isoformat()
|
||||||
|
print(f"\n✅ Script ended at: {end_time}\n")
|
||||||
def main():
|
def main():
|
||||||
# Change to script dir to execute all folders relative to their
|
# Change to script dir to execute all folders relative to their
|
||||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
@ -5,7 +5,7 @@ setup_admin_email: "{{users.administrator.email}}"
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
central_database: true
|
central_database: true
|
||||||
credentials:
|
credentials:
|
||||||
# database_password: Needs to be defined in inventory file
|
# database_password: Needs to be defined in inventory file
|
||||||
|
@ -5,5 +5,5 @@ credentials:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
central_database: true
|
central_database: true
|
||||||
|
@ -2,5 +2,5 @@ version: "latest"
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
||||||
central_database: true
|
central_database: true
|
@ -15,7 +15,7 @@ urls:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
ldap: false
|
ldap: false
|
||||||
oidc: true
|
oidc: true
|
||||||
central_database: false
|
central_database: false
|
@ -10,5 +10,5 @@ credentials:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
||||||
central_database: true
|
central_database: true
|
@ -5,7 +5,7 @@ credentials:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
oidc: true
|
oidc: true
|
||||||
central_database: true
|
central_database: true
|
||||||
csp:
|
csp:
|
||||||
|
@ -8,7 +8,7 @@ credentials:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: false
|
css: false
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
ldap: false
|
ldap: false
|
||||||
oidc: true
|
oidc: true
|
||||||
central_database: true
|
central_database: true
|
||||||
|
@ -2,6 +2,6 @@ version: "latest"
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
||||||
oidc: true
|
oidc: true
|
||||||
central_database: true
|
central_database: true
|
@ -2,7 +2,7 @@ version: "1.4.0"
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
||||||
ldap: true
|
ldap: true
|
||||||
central_database: true
|
central_database: true
|
||||||
credentials:
|
credentials:
|
||||||
|
@ -12,7 +12,7 @@ SSH_PORT={{ports.public.ssh[application_id]}}
|
|||||||
SSH_LISTEN_PORT=22
|
SSH_LISTEN_PORT=22
|
||||||
DOMAIN={{domains[application_id]}}
|
DOMAIN={{domains[application_id]}}
|
||||||
SSH_DOMAIN={{domains[application_id]}}
|
SSH_DOMAIN={{domains[application_id]}}
|
||||||
RUN_MODE="{{run_mode}}"
|
RUN_MODE="{{ 'dev' if (CYMAIS_ENVIRONMENT | lower) == 'development' else 'prod' }}"
|
||||||
ROOT_URL="{{ web_protocol }}://{{domains[application_id]}}/"
|
ROOT_URL="{{ web_protocol }}://{{domains[application_id]}}/"
|
||||||
|
|
||||||
# Mail Configuration
|
# Mail Configuration
|
||||||
|
@ -7,7 +7,7 @@ configuration:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
||||||
central_database: true
|
central_database: true
|
||||||
csp:
|
csp:
|
||||||
flags:
|
flags:
|
||||||
|
@ -2,5 +2,5 @@ version: "latest"
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
||||||
central_database: true
|
central_database: true
|
@ -2,4 +2,4 @@ version: "latest"
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
@ -4,12 +4,16 @@ users:
|
|||||||
username: "{{users.administrator.username}}" # Administrator Username for Keycloak
|
username: "{{users.administrator.username}}" # Administrator Username for Keycloak
|
||||||
import_realm: True # If True realm will be imported. If false skip.
|
import_realm: True # If True realm will be imported. If false skip.
|
||||||
credentials:
|
credentials:
|
||||||
# database_password: # Needs to be defined in inventory file
|
|
||||||
# administrator_password: # Needs to be defined in inventory file
|
|
||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
||||||
ldap: true
|
ldap: true
|
||||||
central_database: true
|
central_database: true
|
||||||
recaptcha: true
|
recaptcha: true
|
||||||
|
csp:
|
||||||
|
flags:
|
||||||
|
script-src:
|
||||||
|
unsafe-inline: true
|
||||||
|
style-src:
|
||||||
|
unsafe-inline: true
|
@ -8,7 +8,7 @@ credentials:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
||||||
ldap: true
|
ldap: true
|
||||||
central_database: false
|
central_database: false
|
||||||
oauth2: false
|
oauth2: false
|
||||||
|
@ -6,6 +6,6 @@ version: "latest" # Docker Image
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
||||||
central_database: true
|
central_database: true
|
||||||
oidc: true
|
oidc: true
|
@ -15,6 +15,6 @@ credentials:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false # Deactivated mailu iframe loading until keycloak supports it
|
portfolio_iframe: false # Deactivated mailu iframe loading until keycloak supports it
|
||||||
oidc: true
|
oidc: true
|
||||||
central_database: false # Deactivate central database for mailu, I don't know why the database deactivation is necessary
|
central_database: false # Deactivate central database for mailu, I don't know why the database deactivation is necessary
|
@ -14,6 +14,6 @@ credentials:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
oidc: true
|
oidc: true
|
||||||
central_database: true
|
central_database: true
|
||||||
|
@ -2,7 +2,7 @@ version: "latest"
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: false
|
css: false
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
central_database: true
|
central_database: true
|
||||||
oauth2: false
|
oauth2: false
|
||||||
csp:
|
csp:
|
||||||
|
5
roles/docker-matrix/Todo.md
Normal file
5
roles/docker-matrix/Todo.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Todo
|
||||||
|
- Enable Whatsapp by default
|
||||||
|
- Enable Telegram by default
|
||||||
|
- Enable Slack by default
|
||||||
|
- Enable ChatGPT by default
|
2
roles/docker-matrix/filter_plugins/__init__.py
Normal file
2
roles/docker-matrix/filter_plugins/__init__.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
from pkgutil import extend_path
|
||||||
|
__path__ = extend_path(__path__, __name__)
|
13
roles/docker-matrix/filter_plugins/bridge_filters.py
Normal file
13
roles/docker-matrix/filter_plugins/bridge_filters.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
def filter_enabled_bridges(bridges, plugins):
|
||||||
|
"""
|
||||||
|
Return only those bridge definitions whose 'bridge_name' is set to True in plugins.
|
||||||
|
:param bridges: list of dicts, each with a 'bridge_name' key
|
||||||
|
:param plugins: dict mapping bridge_name to a boolean
|
||||||
|
"""
|
||||||
|
return [b for b in bridges if plugins.get(b['bridge_name'], False)]
|
||||||
|
|
||||||
|
class FilterModule(object):
|
||||||
|
def filters(self):
|
||||||
|
return {
|
||||||
|
'filter_enabled_bridges': filter_enabled_bridges,
|
||||||
|
}
|
@ -1,4 +1,13 @@
|
|||||||
---
|
---
|
||||||
|
- name: Load bridges configuration
|
||||||
|
include_vars:
|
||||||
|
file: "bridges.yml"
|
||||||
|
|
||||||
|
- name: Filter enabled bridges and register as fact
|
||||||
|
set_fact:
|
||||||
|
bridges: "{{ bridges_configuration | filter_enabled_bridges(applications[application_id].plugins) }}"
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
- name: "include docker-central-database"
|
- name: "include docker-central-database"
|
||||||
include_role:
|
include_role:
|
||||||
name: docker-central-database
|
name: docker-central-database
|
||||||
|
@ -25,7 +25,11 @@ services:
|
|||||||
interval: 1m
|
interval: 1m
|
||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 3
|
retries: 3
|
||||||
|
{% if bridges | bool %}
|
||||||
{% include 'templates/docker/container/depends-on-also-database.yml.j2' %}
|
{% include 'templates/docker/container/depends-on-also-database.yml.j2' %}
|
||||||
|
{% else %}
|
||||||
|
{% include 'templates/docker/container/depends-on-just-database.yml.j2' %}
|
||||||
|
{% endif %}
|
||||||
{% for item in bridges %}
|
{% for item in bridges %}
|
||||||
mautrix-{{item.bridge_name}}:
|
mautrix-{{item.bridge_name}}:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@ -61,47 +65,47 @@ services:
|
|||||||
retries: 3
|
retries: 3
|
||||||
{% include 'templates/docker/container/networks.yml.j2' %}
|
{% include 'templates/docker/container/networks.yml.j2' %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
# Deactivated chatgpt.
|
{% if applications[application_id] | bool %}
|
||||||
# @todo needs to be reactivated as soon as bug is found
|
matrix-chatgpt-bot:
|
||||||
# matrix-chatgpt-bot:
|
restart: {{docker_restart_policy}}
|
||||||
# restart: {{docker_restart_policy}}
|
container_name: matrix-chatgpt
|
||||||
# container_name: matrix-chatgpt
|
image: ghcr.io/matrixgpt/matrix-chatgpt-bot:latest
|
||||||
# image: ghcr.io/matrixgpt/matrix-chatgpt-bot:latest
|
volumes:
|
||||||
# volumes:
|
- chatgpt_data:/storage
|
||||||
# - chatgpt_data:/storage
|
environment:
|
||||||
# environment:
|
OPENAI_API_KEY: '{{applications[application_id].credentials.chatgpt_bridge_openai_api_key}}'
|
||||||
# OPENAI_API_KEY: '{{applications[application_id].credentials.chatgpt_bridge_openai_api_key}}'
|
# Uncomment the next two lines if you are using Azure OpenAI API
|
||||||
# # Uncomment the next two lines if you are using Azure OpenAI API
|
# OPENAI_AZURE: 'false'
|
||||||
# # OPENAI_AZURE: 'false'
|
# CHATGPT_REVERSE_PROXY: 'your-completion-endpoint-here'
|
||||||
# # CHATGPT_REVERSE_PROXY: 'your-completion-endpoint-here'
|
CHATGPT_CONTEXT: 'thread'
|
||||||
# CHATGPT_CONTEXT: 'thread'
|
CHATGPT_API_MODEL: 'gpt-3.5-turbo'
|
||||||
# CHATGPT_API_MODEL: 'gpt-3.5-turbo'
|
# Uncomment and edit the next line if needed
|
||||||
# # Uncomment and edit the next line if needed
|
# CHATGPT_PROMPT_PREFIX: 'Instructions:\nYou are ChatGPT, a large language model trained by OpenAI.'
|
||||||
# # CHATGPT_PROMPT_PREFIX: 'Instructions:\nYou are ChatGPT, a large language model trained by OpenAI.'
|
# CHATGPT_IGNORE_MEDIA: 'false'
|
||||||
# # CHATGPT_IGNORE_MEDIA: 'false'
|
CHATGPT_REVERSE_PROXY: 'https://api.openai.com/v1/chat/completions'
|
||||||
# CHATGPT_REVERSE_PROXY: 'https://api.openai.com/v1/chat/completions'
|
# Uncomment and edit the next line if needed
|
||||||
# # Uncomment and edit the next line if needed
|
# CHATGPT_TEMPERATURE: '0.8'
|
||||||
# # CHATGPT_TEMPERATURE: '0.8'
|
# Uncomment and edit the next line if needed
|
||||||
# # Uncomment and edit the next line if needed
|
#CHATGPT_MAX_CONTEXT_TOKENS: '4097'
|
||||||
# #CHATGPT_MAX_CONTEXT_TOKENS: '4097'
|
CHATGPT_MAX_PROMPT_TOKENS: '3000'
|
||||||
# CHATGPT_MAX_PROMPT_TOKENS: '3000'
|
KEYV_BACKEND: 'file'
|
||||||
# KEYV_BACKEND: 'file'
|
KEYV_URL: ''
|
||||||
# KEYV_URL: ''
|
KEYV_BOT_ENCRYPTION: 'false'
|
||||||
# KEYV_BOT_ENCRYPTION: 'false'
|
KEYV_BOT_STORAGE: 'true'
|
||||||
# KEYV_BOT_STORAGE: 'true'
|
MATRIX_HOMESERVER_URL: 'https://{{domains.synapse}}'
|
||||||
# MATRIX_HOMESERVER_URL: 'https://{{domains.synapse}}'
|
MATRIX_BOT_USERNAME: '@chatgptbot:{{applications.matrix.server_name}}'
|
||||||
# MATRIX_BOT_USERNAME: '@chatgptbot:{{applications.matrix.server_name}}'
|
MATRIX_ACCESS_TOKEN: '{{ applications[application_id].credentials.chatgpt_bridge_access_token | default('') }}'
|
||||||
# MATRIX_ACCESS_TOKEN: '{{ applications[application_id].credentials.chatgpt_bridge_access_token | default('') }}'
|
MATRIX_BOT_PASSWORD: '{{applications[application_id].credentials.chatgpt_bridge_user_password}}'
|
||||||
# MATRIX_BOT_PASSWORD: '{{applications[application_id].credentials.chatgpt_bridge_user_password}}'
|
MATRIX_DEFAULT_PREFIX: '!chatgpt'
|
||||||
# MATRIX_DEFAULT_PREFIX: '!chatgpt'
|
MATRIX_DEFAULT_PREFIX_REPLY: 'false'
|
||||||
# MATRIX_DEFAULT_PREFIX_REPLY: 'false'
|
#MATRIX_BLACKLIST: ''
|
||||||
# #MATRIX_BLACKLIST: ''
|
MATRIX_WHITELIST: ':{{applications.matrix.server_name}}'
|
||||||
# MATRIX_WHITELIST: ':{{applications.matrix.server_name}}'
|
MATRIX_AUTOJOIN: 'true'
|
||||||
# MATRIX_AUTOJOIN: 'true'
|
MATRIX_ENCRYPTION: 'true'
|
||||||
# MATRIX_ENCRYPTION: 'true'
|
MATRIX_THREADS: 'true'
|
||||||
# MATRIX_THREADS: 'true'
|
MATRIX_PREFIX_DM: 'false'
|
||||||
# MATRIX_PREFIX_DM: 'false'
|
MATRIX_RICH_TEXT: 'true'
|
||||||
# MATRIX_RICH_TEXT: 'true'
|
{% endif %}
|
||||||
|
|
||||||
{% include 'templates/docker/compose/volumes.yml.j2' %}
|
{% include 'templates/docker/compose/volumes.yml.j2' %}
|
||||||
synapse_data:
|
synapse_data:
|
||||||
|
@ -45,7 +45,7 @@ email:
|
|||||||
client_base_url: "{{domains.synapse}}"
|
client_base_url: "{{domains.synapse}}"
|
||||||
validation_token_lifetime: 15m
|
validation_token_lifetime: 15m
|
||||||
|
|
||||||
{% if applications[application_id].features.oidc | bool %}
|
{% if applications | is_feature_enabled('oidc',application_id) %}
|
||||||
# @See https://matrix-org.github.io/synapse/latest/openid.html
|
# @See https://matrix-org.github.io/synapse/latest/openid.html
|
||||||
oidc_providers:
|
oidc_providers:
|
||||||
- idp_id: keycloak
|
- idp_id: keycloak
|
||||||
@ -61,7 +61,9 @@ oidc_providers:
|
|||||||
backchannel_logout_enabled: true
|
backchannel_logout_enabled: true
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if bridges | bool %}
|
||||||
app_service_config_files:
|
app_service_config_files:
|
||||||
{% for item in bridges %}
|
{% for item in bridges %}
|
||||||
- {{registration_file_folder}}{{item.bridge_name}}.registration.yaml
|
- {{registration_file_folder}}{{item.bridge_name}}.registration.yaml
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% endif %}
|
30
roles/docker-matrix/vars/bridges.yml
Normal file
30
roles/docker-matrix/vars/bridges.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
bridges_configuration:
|
||||||
|
- database_password: "{{ applications[application_id].credentials.mautrix_whatsapp_bridge_database_password }}"
|
||||||
|
database_username: "mautrix_whatsapp_bridge"
|
||||||
|
database_name: "mautrix_whatsapp_bridge"
|
||||||
|
bridge_name: "whatsapp"
|
||||||
|
|
||||||
|
- database_password: "{{ applications[application_id].credentials.mautrix_telegram_bridge_database_password }}"
|
||||||
|
database_username: "mautrix_telegram_bridge"
|
||||||
|
database_name: "mautrix_telegram_bridge"
|
||||||
|
bridge_name: "telegram"
|
||||||
|
|
||||||
|
- database_password: "{{ applications[application_id].credentials.mautrix_signal_bridge_database_password }}"
|
||||||
|
database_username: "mautrix_signal_bridge"
|
||||||
|
database_name: "mautrix_signal_bridge"
|
||||||
|
bridge_name: "signal"
|
||||||
|
|
||||||
|
- database_password: "{{ applications[application_id].credentials.mautrix_slack_bridge_database_password }}"
|
||||||
|
database_username: "mautrix_slack_bridge"
|
||||||
|
database_name: "mautrix_slack_bridge"
|
||||||
|
bridge_name: "slack"
|
||||||
|
|
||||||
|
- database_password: "{{ applications[application_id].credentials.mautrix_facebook_bridge_database_password }}"
|
||||||
|
database_username: "mautrix_facebook_bridge"
|
||||||
|
database_name: "mautrix_facebook_bridge"
|
||||||
|
bridge_name: "facebook"
|
||||||
|
|
||||||
|
- database_password: "{{ applications[application_id].credentials.mautrix_instagram_bridge_database_password }}"
|
||||||
|
database_username: "mautrix_instagram_bridge"
|
||||||
|
database_name: "mautrix_instagram_bridge"
|
||||||
|
bridge_name: "instagram"
|
@ -3,7 +3,6 @@ users:
|
|||||||
administrator:
|
administrator:
|
||||||
username: "{{users.administrator.username}}" # Accountname of the matrix admin
|
username: "{{users.administrator.username}}" # Accountname of the matrix admin
|
||||||
playbook_tags: "setup-all,start" # For the initial update use: install-all,ensure-matrix-users-created,start
|
playbook_tags: "setup-all,start" # For the initial update use: install-all,ensure-matrix-users-created,start
|
||||||
role: "compose" # Role to setup Matrix. Valid values: ansible, compose
|
|
||||||
server_name: "{{primary_domain}}" # Adress for the account names etc.
|
server_name: "{{primary_domain}}" # Adress for the account names etc.
|
||||||
synapse:
|
synapse:
|
||||||
version: "latest"
|
version: "latest"
|
||||||
@ -13,8 +12,8 @@ setup: false # Set true in inventory
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
oidc: false # Deactivated OIDC due to this issue https://github.com/matrix-org/synapse/issues/10492
|
oidc: true # Deactivated OIDC due to this issue https://github.com/matrix-org/synapse/issues/10492
|
||||||
central_database: true
|
central_database: true
|
||||||
csp:
|
csp:
|
||||||
flags:
|
flags:
|
||||||
@ -30,3 +29,14 @@ csp:
|
|||||||
script-src:
|
script-src:
|
||||||
- "{{ domains.synapse }}"
|
- "{{ domains.synapse }}"
|
||||||
- "https://cdn.jsdelivr.net"
|
- "https://cdn.jsdelivr.net"
|
||||||
|
plugins:
|
||||||
|
# You need to enable them in the inventory file
|
||||||
|
chatgpt: false
|
||||||
|
facebook: false
|
||||||
|
immesage: false
|
||||||
|
instagram: false
|
||||||
|
signal: false
|
||||||
|
slack: false
|
||||||
|
telegram: false
|
||||||
|
whatsapp: false
|
||||||
|
|
||||||
|
@ -3,36 +3,3 @@ application_id: "matrix"
|
|||||||
database_type: "postgres"
|
database_type: "postgres"
|
||||||
registration_file_folder: "/data/"
|
registration_file_folder: "/data/"
|
||||||
well_known_directory: "{{nginx.directories.data.well_known}}/matrix/"
|
well_known_directory: "{{nginx.directories.data.well_known}}/matrix/"
|
||||||
|
|
||||||
bridges:
|
|
||||||
- database_password: "{{ applications[application_id].credentials.mautrix_whatsapp_bridge_database_password }}"
|
|
||||||
database_username: "mautrix_whatsapp_bridge"
|
|
||||||
database_name: "mautrix_whatsapp_bridge"
|
|
||||||
bridge_name: "whatsapp"
|
|
||||||
|
|
||||||
- database_password: "{{ applications[application_id].credentials.mautrix_telegram_bridge_database_password }}"
|
|
||||||
database_username: "mautrix_telegram_bridge"
|
|
||||||
database_name: "mautrix_telegram_bridge"
|
|
||||||
bridge_name: "telegram"
|
|
||||||
|
|
||||||
- database_password: "{{ applications[application_id].credentials.mautrix_signal_bridge_database_password }}"
|
|
||||||
database_username: "mautrix_signal_bridge"
|
|
||||||
database_name: "mautrix_signal_bridge"
|
|
||||||
bridge_name: "signal"
|
|
||||||
|
|
||||||
# Deactivated temporary, due to bug which is hard to find
|
|
||||||
# @todo Reactivate
|
|
||||||
# - database_password: "{{ applications[application_id].credentials.mautrix_slack_bridge_database_password }}"
|
|
||||||
# database_username: "mautrix_slack_bridge"
|
|
||||||
# database_name: "mautrix_slack_bridge"
|
|
||||||
# bridge_name: "slack"
|
|
||||||
|
|
||||||
- database_password: "{{ applications[application_id].credentials.mautrix_facebook_bridge_database_password }}"
|
|
||||||
database_username: "mautrix_facebook_bridge"
|
|
||||||
database_name: "mautrix_facebook_bridge"
|
|
||||||
bridge_name: "facebook"
|
|
||||||
|
|
||||||
- database_password: "{{ applications[application_id].credentials.mautrix_instagram_bridge_database_password }}"
|
|
||||||
database_username: "mautrix_instagram_bridge"
|
|
||||||
database_name: "mautrix_instagram_bridge"
|
|
||||||
bridge_name: "instagram"
|
|
@ -6,8 +6,8 @@ users:
|
|||||||
version: "latest"
|
version: "latest"
|
||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: false
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
central_database: true
|
central_database: true
|
||||||
csp:
|
csp:
|
||||||
flags:
|
flags:
|
||||||
@ -20,4 +20,5 @@ csp:
|
|||||||
font-src:
|
font-src:
|
||||||
- "data:"
|
- "data:"
|
||||||
- "blob:"
|
- "blob:"
|
||||||
|
script-src:
|
||||||
- "https://cdn.jsdelivr.net"
|
- "https://cdn.jsdelivr.net"
|
@ -3,5 +3,5 @@ version: "latest"
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
central_database: true
|
central_database: true
|
||||||
|
@ -23,7 +23,7 @@ credentials:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
ldap: true
|
ldap: true
|
||||||
oidc: true
|
oidc: true
|
||||||
central_database: true
|
central_database: true
|
||||||
|
@ -5,4 +5,4 @@ allowed_roles: admin
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
@ -96,7 +96,7 @@
|
|||||||
shell: >
|
shell: >
|
||||||
docker compose exec web bash -c "
|
docker compose exec web bash -c "
|
||||||
cd /app &&
|
cd /app &&
|
||||||
RAILS_ENV=production bundle exec rails runner \"
|
RAILS_ENV={{ CYMAIS_ENVIRONMENT | lower }} bundle exec rails runner \"
|
||||||
user = User.find_by(mail: '{{ users.administrator.email }}');
|
user = User.find_by(mail: '{{ users.administrator.email }}');
|
||||||
if user.nil?;
|
if user.nil?;
|
||||||
puts 'User with email {{ users.administrator.email }} not found.';
|
puts 'User with email {{ users.administrator.email }} not found.';
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
- name: Set settings in OpenProject
|
- name: Set settings in OpenProject
|
||||||
shell: >
|
shell: >
|
||||||
docker compose exec web bash -c "cd /app &&
|
docker compose exec web bash -c "cd /app &&
|
||||||
RAILS_ENV=production bundle exec rails runner \"Setting[:{{ item.key }}] = '{{ item.value }}'\""
|
RAILS_ENV={{ CYMAIS_ENVIRONMENT | lower }} bundle exec rails runner \"Setting[:{{ item.key }}] = '{{ item.value }}'\""
|
||||||
args:
|
args:
|
||||||
chdir: "{{ docker_compose.directories.instance }}"
|
chdir: "{{ docker_compose.directories.instance }}"
|
||||||
loop: "{{ openproject_rails_settings | dict2items }}"
|
loop: "{{ openproject_rails_settings | dict2items }}"
|
||||||
|
@ -9,7 +9,7 @@ ldap:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
ldap: true
|
ldap: true
|
||||||
central_database: true
|
central_database: true
|
||||||
oauth2: true
|
oauth2: true
|
||||||
|
@ -2,7 +2,7 @@ version: "bookworm"
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
central_database: true
|
central_database: true
|
||||||
csp:
|
csp:
|
||||||
flags:
|
flags:
|
||||||
|
@ -10,6 +10,6 @@ oauth2_proxy:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
central_database: true
|
central_database: true
|
||||||
oauth2: true
|
oauth2: true
|
@ -5,6 +5,6 @@ oauth2_proxy:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
ldap: true
|
ldap: true
|
||||||
oauth2: true
|
oauth2: true
|
@ -6,7 +6,7 @@ oauth2_proxy:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: false
|
css: false
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
central_database: true
|
central_database: true
|
||||||
oauth2: true
|
oauth2: true
|
||||||
hostname: central-mariadb
|
hostname: central-mariadb
|
@ -3,7 +3,7 @@ version: "latest"
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
central_database: true
|
central_database: true
|
||||||
csp:
|
csp:
|
||||||
flags:
|
flags:
|
||||||
|
@ -28,7 +28,7 @@ accounts:
|
|||||||
class: fa-brands fa-mastodon
|
class: fa-brands fa-mastodon
|
||||||
url: "{{ web_protocol }}://{{ service_provider.contact.mastodon.split('@')[2] }}/@{{ service_provider.contact.mastodon.split('@')[1] }}"
|
url: "{{ web_protocol }}://{{ service_provider.contact.mastodon.split('@')[2] }}/@{{ service_provider.contact.mastodon.split('@')[1] }}"
|
||||||
identifier: "{{service_provider.contact.mastodon}}"
|
identifier: "{{service_provider.contact.mastodon}}"
|
||||||
iframe: {{ applications | is_feature_enabled('landing_page_iframe','mastodon') }}
|
iframe: {{ applications | is_feature_enabled('portfolio_iframe','mastodon') }}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if service_provider.contact.bluesky is defined and service_provider.contact.bluesky != "" %}
|
{% if service_provider.contact.bluesky is defined and service_provider.contact.bluesky != "" %}
|
||||||
@ -52,7 +52,7 @@ accounts:
|
|||||||
class: fa-solid fa-camera
|
class: fa-solid fa-camera
|
||||||
identifier: "{{service_provider.contact.pixelfed}}"
|
identifier: "{{service_provider.contact.pixelfed}}"
|
||||||
url: "{{ web_protocol }}://{{ service_provider.contact.pixelfed.split('@')[2] }}/@{{ service_provider.contact.pixelfed.split('@')[1] }}"
|
url: "{{ web_protocol }}://{{ service_provider.contact.pixelfed.split('@')[2] }}/@{{ service_provider.contact.pixelfed.split('@')[1] }}"
|
||||||
iframe: {{ applications | is_feature_enabled('landing_page_iframe','pixelfed') }}
|
iframe: {{ applications | is_feature_enabled('portfolio_iframe','pixelfed') }}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if service_provider.contact.peertube is defined and service_provider.contact.peertube != "" %}
|
{% if service_provider.contact.peertube is defined and service_provider.contact.peertube != "" %}
|
||||||
@ -64,7 +64,7 @@ accounts:
|
|||||||
class: fa-solid fa-video
|
class: fa-solid fa-video
|
||||||
identifier: "{{service_provider.contact.peertube}}"
|
identifier: "{{service_provider.contact.peertube}}"
|
||||||
url: "{{ web_protocol }}://{{ service_provider.contact.peertube.split('@')[2] }}/@{{ service_provider.contact.peertube.split('@')[1] }}"
|
url: "{{ web_protocol }}://{{ service_provider.contact.peertube.split('@')[2] }}/@{{ service_provider.contact.peertube.split('@')[1] }}"
|
||||||
iframe: {{ applications | is_feature_enabled('landing_page_iframe','peertube') }}
|
iframe: {{ applications | is_feature_enabled('portfolio_iframe','peertube') }}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if service_provider.contact.wordpress is defined and service_provider.contact.wordpress != "" %}
|
{% if service_provider.contact.wordpress is defined and service_provider.contact.wordpress != "" %}
|
||||||
@ -76,7 +76,7 @@ accounts:
|
|||||||
class: fa-solid fa-blog
|
class: fa-solid fa-blog
|
||||||
identifier: "{{service_provider.contact.wordpress}}"
|
identifier: "{{service_provider.contact.wordpress}}"
|
||||||
url: "{{ web_protocol }}://{{ service_provider.contact.wordpress.split('@')[2] }}/@{{ service_provider.contact.wordpress.split('@')[1] }}"
|
url: "{{ web_protocol }}://{{ service_provider.contact.wordpress.split('@')[2] }}/@{{ service_provider.contact.wordpress.split('@')[1] }}"
|
||||||
iframe: {{ applications | is_feature_enabled('landing_page_iframe','wordpress') }}
|
iframe: {{ applications | is_feature_enabled('portfolio_iframe','wordpress') }}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if service_provider.contact.source_code is defined and service_provider.contact.source_code != "" %}
|
{% if service_provider.contact.source_code is defined and service_provider.contact.source_code != "" %}
|
||||||
@ -98,7 +98,7 @@ accounts:
|
|||||||
class: fas fa-network-wired
|
class: fas fa-network-wired
|
||||||
identifier: "{{service_provider.contact.friendica}}"
|
identifier: "{{service_provider.contact.friendica}}"
|
||||||
url: "{{ web_protocol }}://{{ service_provider.contact.friendica.split('@')[2] }}/@{{ service_provider.contact.friendica.split('@')[1] }}"
|
url: "{{ web_protocol }}://{{ service_provider.contact.friendica.split('@')[2] }}/@{{ service_provider.contact.friendica.split('@')[1] }}"
|
||||||
iframe: {{ applications | is_feature_enabled('landing_page_iframe','friendica') }}
|
iframe: {{ applications | is_feature_enabled('portfolio_iframe','friendica') }}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -37,13 +37,13 @@
|
|||||||
icon:
|
icon:
|
||||||
class: fa-solid fa-shield-halved
|
class: fa-solid fa-shield-halved
|
||||||
url: https://{{domains.keycloak}}/admin
|
url: https://{{domains.keycloak}}/admin
|
||||||
iframe: {{ applications | is_feature_enabled('landing_page_iframe','keycloak') }}
|
iframe: {{ applications | is_feature_enabled('portfolio_iframe','keycloak') }}
|
||||||
- name: Profile
|
- name: Profile
|
||||||
description: Update your personal admin settings
|
description: Update your personal admin settings
|
||||||
icon:
|
icon:
|
||||||
class: fa-solid fa-user-gear
|
class: fa-solid fa-user-gear
|
||||||
url: https://{{ domains.keycloak }}/realms/{{oidc.client.id}}/account
|
url: https://{{ domains.keycloak }}/realms/{{oidc.client.id}}/account
|
||||||
iframe: {{ applications | is_feature_enabled('landing_page_iframe','keycloak') }}
|
iframe: {{ applications | is_feature_enabled('portfolio_iframe','keycloak') }}
|
||||||
- name: Logout
|
- name: Logout
|
||||||
description: End your admin session securely
|
description: End your admin session securely
|
||||||
icon:
|
icon:
|
||||||
@ -113,7 +113,7 @@
|
|||||||
icon:
|
icon:
|
||||||
class: fas fa-book
|
class: fas fa-book
|
||||||
url: https://{{domains.sphinx}}
|
url: https://{{domains.sphinx}}
|
||||||
iframe: {{ applications | is_feature_enabled('landing_page_iframe','sphinx') }}
|
iframe: {{ applications | is_feature_enabled('portfolio_iframe','sphinx') }}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@
|
|||||||
icon:
|
icon:
|
||||||
class: "fas fa-chalkboard-teacher"
|
class: "fas fa-chalkboard-teacher"
|
||||||
url: https://{{domains.presentation}}
|
url: https://{{domains.presentation}}
|
||||||
iframe: {{ applications | is_feature_enabled('landing_page_iframe','presentation') }}
|
iframe: {{ applications | is_feature_enabled('portfolio_iframe','presentation') }}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
csp:
|
csp:
|
||||||
whitelist:
|
whitelist:
|
||||||
script-src:
|
script-src:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
||||||
|
|
||||||
csp:
|
csp:
|
||||||
whitelist:
|
whitelist:
|
||||||
|
@ -2,5 +2,5 @@ version: "latest"
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
central_database: true
|
central_database: true
|
@ -1,7 +1,7 @@
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
csp:
|
csp:
|
||||||
flags:
|
flags:
|
||||||
script-src:
|
script-src:
|
||||||
|
@ -9,7 +9,7 @@ flavor: 'taigaio' # Potential flavors: robrotheram, taigaio
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
oidc: false
|
oidc: false
|
||||||
central_database: true
|
central_database: true
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ plugins:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: false
|
css: false
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
oidc: true
|
oidc: true
|
||||||
central_database: true
|
central_database: true
|
||||||
csp:
|
csp:
|
||||||
@ -28,10 +28,9 @@ csp:
|
|||||||
- "blob:"
|
- "blob:"
|
||||||
font-src:
|
font-src:
|
||||||
- "data:"
|
- "data:"
|
||||||
|
- "https://fonts.bunny.net"
|
||||||
script-src:
|
script-src:
|
||||||
- "https://cdn.gtranslate.net"
|
- "https://cdn.gtranslate.net"
|
||||||
- "{{ domains.wordpress[0] }}"
|
- "{{ domains.wordpress[0] }}"
|
||||||
frame-src:
|
|
||||||
- "{{ domains.peertube }}"
|
|
||||||
style-src:
|
style-src:
|
||||||
- "https://fonts.bunny.net"
|
- "https://fonts.bunny.net"
|
@ -9,6 +9,6 @@ oauth2_proxy:
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
||||||
central_database: true
|
central_database: true
|
||||||
oauth2: true
|
oauth2: true
|
@ -1,4 +1,4 @@
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: true
|
portfolio_iframe: true
|
@ -1,4 +1,4 @@
|
|||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
landingpage_iframe: false
|
portfolio_iframe: false
|
@ -149,7 +149,7 @@ def update_mastodon():
|
|||||||
Runs the database migration for Mastodon to ensure all required tables are up to date.
|
Runs the database migration for Mastodon to ensure all required tables are up to date.
|
||||||
"""
|
"""
|
||||||
print("Starting Mastodon database migration.")
|
print("Starting Mastodon database migration.")
|
||||||
run_command("docker compose exec -T web bash -c 'RAILS_ENV=production bin/rails db:migrate'")
|
run_command("docker compose exec -T web bash -c 'RAILS_ENV={{ CYMAIS_ENVIRONMENT | lower }} bin/rails db:migrate'")
|
||||||
print("Mastodon database migration complete.")
|
print("Mastodon database migration complete.")
|
||||||
|
|
||||||
def upgrade_listmonk():
|
def upgrade_listmonk():
|
||||||
|
1
tasks/.gitignore
vendored
Normal file
1
tasks/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
include-docker-roles.yml
|
211
tasks/server.yml
211
tasks/server.yml
@ -11,215 +11,8 @@
|
|||||||
- health-btrfs
|
- health-btrfs
|
||||||
- system-btrfs-auto-balancer
|
- system-btrfs-auto-balancer
|
||||||
|
|
||||||
#########################################################################
|
- name: "Integrate Docker Role includes"
|
||||||
### Docker Roles ###
|
include_tasks: "include-docker-roles.yml"
|
||||||
#########################################################################
|
|
||||||
|
|
||||||
- name: "setup matomo"
|
|
||||||
when: ("matomo" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-matomo
|
|
||||||
|
|
||||||
- name: setup ldap
|
|
||||||
when: ("ldap" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-ldap
|
|
||||||
|
|
||||||
- name: setup keycloak
|
|
||||||
when: ("keycloak" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-keycloak
|
|
||||||
|
|
||||||
- name: setup lam
|
|
||||||
when: ("lam" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-lam
|
|
||||||
|
|
||||||
- name: setup phpldapadmin
|
|
||||||
when: ("phpldapadmin" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-phpldapadmin
|
|
||||||
|
|
||||||
- name: setup nextcloud hosts
|
|
||||||
when: ("nextcloud" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-nextcloud
|
|
||||||
|
|
||||||
- name: setup gitea hosts
|
|
||||||
when: ("gitea" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-gitea
|
|
||||||
vars:
|
|
||||||
run_mode: prod
|
|
||||||
|
|
||||||
- name: setup wordpress hosts
|
|
||||||
when: ("wordpress" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-wordpress
|
|
||||||
|
|
||||||
- name: setup mediawiki hosts
|
|
||||||
when: ("mediawiki" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-mediawiki
|
|
||||||
|
|
||||||
- name: setup mybb hosts
|
|
||||||
when: ("mybb" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-mybb
|
|
||||||
vars:
|
|
||||||
mybb_domains: "{{domains.mybb}}"
|
|
||||||
|
|
||||||
- name: setup yourls hosts
|
|
||||||
when: ("yourls" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-yourls
|
|
||||||
|
|
||||||
- name: setup mailu hosts
|
|
||||||
when: ("mailu" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-mailu
|
|
||||||
|
|
||||||
- name: setup elk hosts
|
|
||||||
when: ("elk" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-elk
|
|
||||||
|
|
||||||
- name: setup mastodon hosts
|
|
||||||
when: ("mastodon" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-mastodon
|
|
||||||
|
|
||||||
- name: setup pixelfed hosts
|
|
||||||
when: ("pixelfed" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-pixelfed
|
|
||||||
|
|
||||||
- name: setup peertube hosts
|
|
||||||
when: ("peertube" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-peertube
|
|
||||||
|
|
||||||
- name: setup bigbluebutton hosts
|
|
||||||
when: ("bigbluebutton" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-bigbluebutton
|
|
||||||
vars:
|
|
||||||
domain: "{{domains.bigbluebutton}}"
|
|
||||||
|
|
||||||
- name: setup funkwhale hosts
|
|
||||||
when: ("funkwhale" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-funkwhale
|
|
||||||
|
|
||||||
- name: setup roulette-wheel hosts
|
|
||||||
when: ("roulette-wheel" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-roulette-wheel
|
|
||||||
|
|
||||||
- name: setup joomla hosts
|
|
||||||
when: ("joomla" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-joomla
|
|
||||||
|
|
||||||
- name: setup attendize
|
|
||||||
when: ("attendize" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-attendize
|
|
||||||
|
|
||||||
- name: setup baserow hosts
|
|
||||||
when: ("baserow" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-baserow
|
|
||||||
|
|
||||||
- name: setup listmonk
|
|
||||||
when: ("listmonk" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-listmonk
|
|
||||||
|
|
||||||
- name: setup discourse
|
|
||||||
when: ("discourse" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-discourse
|
|
||||||
|
|
||||||
- name: setup matrix with flavor 'ansible'
|
|
||||||
include_role:
|
|
||||||
name: docker-matrix-ansible
|
|
||||||
when: applications.matrix.role == 'ansible' and ("matrix" in group_names)
|
|
||||||
|
|
||||||
- name: setup matrix with flavor 'compose'
|
|
||||||
include_role:
|
|
||||||
name: docker-matrix
|
|
||||||
when: applications.matrix.role == 'compose' and ("matrix" in group_names)
|
|
||||||
|
|
||||||
- name: setup open project instances
|
|
||||||
when: ("openproject" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-openproject
|
|
||||||
|
|
||||||
- name: setup gitlab hosts
|
|
||||||
when: ("gitlab" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-gitlab
|
|
||||||
|
|
||||||
- name: setup akaunting hosts
|
|
||||||
when: ("akaunting" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-akaunting
|
|
||||||
|
|
||||||
- name: setup moodle instance
|
|
||||||
when: ("moodle" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-moodle
|
|
||||||
|
|
||||||
- name: setup taiga instance
|
|
||||||
when: ("taiga" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-taiga
|
|
||||||
|
|
||||||
- name: setup friendica hosts
|
|
||||||
when: ("friendica" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-friendica
|
|
||||||
|
|
||||||
- name: setup portfolio
|
|
||||||
when: ("portfolio" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-portfolio
|
|
||||||
|
|
||||||
- name: setup bluesky
|
|
||||||
when: ("bluesky" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-bluesky
|
|
||||||
|
|
||||||
- name: setup PHPMyAdmin
|
|
||||||
when: ("phpmyadmin" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-phpmyadmin
|
|
||||||
|
|
||||||
- name: setup SNIPE-IT
|
|
||||||
when: ("snipe_it" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-snipe_it
|
|
||||||
|
|
||||||
- name: setup sphinx
|
|
||||||
when: ("sphinx" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-sphinx
|
|
||||||
|
|
||||||
- name: setup pgadmin
|
|
||||||
when: ("pgadmin" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-pgadmin
|
|
||||||
|
|
||||||
- name: setup presentation
|
|
||||||
when: ("presentation" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-presentation
|
|
||||||
|
|
||||||
- name: setup espocrm hosts
|
|
||||||
when: ("espocrm" in group_names)
|
|
||||||
include_role:
|
|
||||||
name: docker-espocrm
|
|
||||||
|
|
||||||
# Native Webserver Roles
|
# Native Webserver Roles
|
||||||
- name: setup nginx-serve-htmls
|
- name: setup nginx-serve-htmls
|
||||||
|
64
tests/unit/test_bridge_filters.py
Normal file
64
tests/unit/test_bridge_filters.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
# Add the filter_plugins directory from the docker-matrix role to the import path
|
||||||
|
sys.path.insert(
|
||||||
|
0,
|
||||||
|
os.path.abspath(
|
||||||
|
os.path.join(os.path.dirname(__file__), "../../roles/docker-matrix")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
from filter_plugins.bridge_filters import filter_enabled_bridges
|
||||||
|
|
||||||
|
|
||||||
|
class TestBridgeFilters(unittest.TestCase):
|
||||||
|
def test_no_bridges_returns_empty_list(self):
|
||||||
|
# When there are no bridges defined, result should be an empty list
|
||||||
|
self.assertEqual(filter_enabled_bridges([], {}), [])
|
||||||
|
|
||||||
|
def test_all_bridges_disabled(self):
|
||||||
|
# Define two bridges, but plugins dict has them disabled or missing
|
||||||
|
bridges = [
|
||||||
|
{'bridge_name': 'whatsapp', 'config': {}},
|
||||||
|
{'bridge_name': 'telegram', 'config': {}},
|
||||||
|
]
|
||||||
|
plugins = {
|
||||||
|
'whatsapp': False,
|
||||||
|
'telegram': False,
|
||||||
|
}
|
||||||
|
result = filter_enabled_bridges(bridges, plugins)
|
||||||
|
self.assertEqual(result, [])
|
||||||
|
|
||||||
|
def test_some_bridges_enabled(self):
|
||||||
|
# Only bridges with True in plugins should be returned
|
||||||
|
bridges = [
|
||||||
|
{'bridge_name': 'whatsapp', 'version': '1.0'},
|
||||||
|
{'bridge_name': 'telegram', 'version': '1.0'},
|
||||||
|
{'bridge_name': 'signal', 'version': '1.0'},
|
||||||
|
]
|
||||||
|
plugins = {
|
||||||
|
'whatsapp': True,
|
||||||
|
'telegram': False,
|
||||||
|
'signal': True,
|
||||||
|
}
|
||||||
|
result = filter_enabled_bridges(bridges, plugins)
|
||||||
|
expected = [
|
||||||
|
{'bridge_name': 'whatsapp', 'version': '1.0'},
|
||||||
|
{'bridge_name': 'signal', 'version': '1.0'},
|
||||||
|
]
|
||||||
|
self.assertEqual(result, expected)
|
||||||
|
|
||||||
|
def test_bridge_without_plugin_entry_defaults_to_disabled(self):
|
||||||
|
# If a bridge_name is not present in plugins, it should be treated as disabled
|
||||||
|
bridges = [
|
||||||
|
{'bridge_name': 'facebook', 'enabled': True},
|
||||||
|
]
|
||||||
|
plugins = {} # no entries
|
||||||
|
result = filter_enabled_bridges(bridges, plugins)
|
||||||
|
self.assertEqual(result, [])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
@ -1,6 +1,16 @@
|
|||||||
# tests/unit/test_configuration_filters.py
|
# tests/unit/test_configuration_filters.py
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
sys.path.insert(
|
||||||
|
0,
|
||||||
|
os.path.abspath(
|
||||||
|
os.path.join(os.path.dirname(__file__), "../../")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
from filter_plugins.configuration_filters import (
|
from filter_plugins.configuration_filters import (
|
||||||
is_feature_enabled,
|
is_feature_enabled,
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,16 @@
|
|||||||
import unittest
|
import unittest
|
||||||
import hashlib
|
import hashlib
|
||||||
import base64
|
import base64
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
sys.path.insert(
|
||||||
|
0,
|
||||||
|
os.path.abspath(
|
||||||
|
os.path.join(os.path.dirname(__file__), "../../")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
from filter_plugins.csp_filters import FilterModule, AnsibleFilterError
|
from filter_plugins.csp_filters import FilterModule, AnsibleFilterError
|
||||||
|
|
||||||
class TestCspFilters(unittest.TestCase):
|
class TestCspFilters(unittest.TestCase):
|
||||||
@ -137,5 +147,25 @@ class TestCspFilters(unittest.TestCase):
|
|||||||
style_hash = self.filter.get_csp_hash("body { background: #fff; }")
|
style_hash = self.filter.get_csp_hash("body { background: #fff; }")
|
||||||
self.assertNotIn(style_hash, header)
|
self.assertNotIn(style_hash, header)
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_csp_header_recaptcha_toggle(self):
|
||||||
|
"""
|
||||||
|
When the 'recaptcha' feature is enabled, 'https://www.google.com'
|
||||||
|
must be included in script-src; when disabled, it must not be.
|
||||||
|
"""
|
||||||
|
# enabled case
|
||||||
|
self.apps['app1']['features']['recaptcha'] = True
|
||||||
|
header_enabled = self.filter.build_csp_header(
|
||||||
|
self.apps, 'app1', self.domains, web_protocol='https'
|
||||||
|
)
|
||||||
|
self.assertIn("https://www.google.com", header_enabled)
|
||||||
|
|
||||||
|
# disabled case
|
||||||
|
self.apps['app1']['features']['recaptcha'] = False
|
||||||
|
header_disabled = self.filter.build_csp_header(
|
||||||
|
self.apps, 'app1', self.domains, web_protocol='https'
|
||||||
|
)
|
||||||
|
self.assertNotIn("https://www.google.com", header_disabled)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
@ -2,8 +2,12 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../.."))
|
sys.path.insert(
|
||||||
sys.path.insert(0, PROJECT_ROOT)
|
0,
|
||||||
|
os.path.abspath(
|
||||||
|
os.path.join(os.path.dirname(__file__), "../../")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
from filter_plugins.redirect_filters import FilterModule
|
from filter_plugins.redirect_filters import FilterModule
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user