Compare commits

...

8 Commits

Author SHA1 Message Date
ce3fe1cd51 Nextcloud: integrate Talk & Whiteboard; adjust ports & healthchecks
- Enable Spreed (Talk); signaling via /standalone-signaling/
- STUN/TURN: move STUN to 3480 (3479 occupied by BBB), keep TURN 5350 reserved
- docker-compose: expose internal WS ports; explicit TURN port mapping
- Healthchecks: add nc-based TCP checks (roles/docker-container/templates/healthcheck/nc.yml.j2)
- Nginx: location proxy to talk:8081
- Schema: add talk_* secrets (turn/signaling/internal)
- Plugins: configure spreed/whiteboard via vars/*; remove old task files
- Ports matrix (group_vars/all/09_ports.yml) updated/commented

Conversation: https://chatgpt.com/share/68b61a6a-e1dc-800f-b793-4aa600bc0166
2025-09-02 00:13:23 +02:00
7ca8b7c71d feat(nextcloud): integrate Talk & Whiteboard; refactor to NEXTCLOUD_* vars; full-stack setup
config(ports): add Nextcloud websocket port (4003); canonical domains (nextcloud/talk/whiteboard)

refactor: unify get_app_conf usage & Jinja spacing; migrate paths/handlers to new NEXTCLOUD_* vars

feat(plugins): split plugin routines; configure Whiteboard via occ (URL + JWT)

fix(oidc): use NEXTCLOUD_URL for logout; correct LDAP attribute mappings; add OIDC flavor switch

feat: Whiteboard container & reverse-proxy location; Talk STUN/WS ports; Redis URL for Whiteboard

chore: drop obsolete TODO; minor cleanups in oauth2-proxy, matrix, peertube, pgadmin, phpldapadmin, pixelfed, phpmyadmin

security(schema): Bluesky jwt_secret now base64_prefixed_32; add Nextcloud whiteboard_jwt_secret

db: normalize postgres image tag templating; central DB host checks spacing fixes

ops: add full-stack bootstrap (certs, proxy, volumes); internal nginx config reload handler update

refs: https://chatgpt.com/share/68b5f5b7-8d64-800f-b001-1241f818dc0e
2025-09-01 21:37:02 +02:00
110381e80c Refactored peertube role and implemented config volume 2025-09-01 18:19:50 +02:00
b02d88adc0 Refactored server roles for better readability 2025-09-01 18:08:35 +02:00
b7065837df MediaWiki: switch feature.css to false and add custom Vector 2022 override stylesheet
See: https://chatgpt.com/share/68b5b925-f418-800f-8f84-de744dd2d093
2025-09-01 17:18:12 +02:00
c98a2378c4 Added is defined condition 2025-09-01 17:05:30 +02:00
4ae3cee36c web-svc-logout: merge logout domains into CSP connect-src and refactor task flow
• Add tasks/01_core.yml to set applications[application_id].server.csp.whitelist['connect-src'] = LOGOUT_CONNECT_SRC_NEW.

• Switch tasks/main.yml to include 01_core.yml (run-once guard preserved).

• Update templates/env.j2 to emit LOGOUT_DOMAINS as a comma-separated list.

• Rework vars/main.yml: compute LOGOUT_DOMAINS, derive LOGOUT_ORIGINS with WEB_PROTOCOL, read connect-src via the get_app_conf filter, and merge/dedupe (unique).

Rationale: ensure CSP allows cross-domain logout requests for all configured services.

Conversation: https://chatgpt.com/share/68b5b07d-b208-800f-b6b2-f26934607c8a
2025-09-01 16:41:33 +02:00
b834f0c95c Implemented config image for pretix 2025-09-01 16:20:04 +02:00
142 changed files with 795 additions and 389 deletions

View File

@@ -2,12 +2,12 @@ ports:
# Ports which are exposed to localhost # Ports which are exposed to localhost
localhost: localhost:
database: database:
svc-db-postgres: 5432 svc-db-postgres: 5432
svc-db-mariadb: 3306 svc-db-mariadb: 3306
# https://developer.mozilla.org/de/docs/Web/API/WebSockets_API # https://developer.mozilla.org/de/docs/Web/API/WebSockets_API
websocket: websocket:
web-app-mastodon: 4001 web-app-mastodon: 4001
web-app-espocrm: 4002 web-app-espocrm: 4002
oauth2_proxy: oauth2_proxy:
web-app-phpmyadmin: 4181 web-app-phpmyadmin: 4181
web-app-lam: 4182 web-app-lam: 4182
@@ -26,7 +26,7 @@ ports:
web-app-gitea: 8002 web-app-gitea: 8002
web-app-wordpress: 8003 web-app-wordpress: 8003
web-app-mediawiki: 8004 web-app-mediawiki: 8004
# Free: 8005 # Free : 8005
web-app-yourls: 8006 web-app-yourls: 8006
web-app-mailu: 8007 web-app-mailu: 8007
web-app-elk: 8008 web-app-elk: 8008
@@ -80,9 +80,10 @@ ports:
svc-db-openldap: 636 svc-db-openldap: 636
stun: stun:
web-app-bigbluebutton: 3478 # Not sure if it's right placed here or if it should be moved to localhost section web-app-bigbluebutton: 3478 # Not sure if it's right placed here or if it should be moved to localhost section
web-app-nextcloud: 3479 # Occupied by BBB: 3479
web-app-nextcloud: 3480
turn: turn:
web-app-bigbluebutton: 5349 # Not sure if it's right placed here or if it should be moved to localhost section web-app-bigbluebutton: 5349 # Not sure if it's right placed here or if it should be moved to localhost section
web-app-nextcloud: 5350 # Not used yet web-app-nextcloud: 5350 # Not used yet
federation: federation:
web-app-matrix_synapse: 8448 web-app-matrix_synapse: 8448

View File

@@ -111,16 +111,6 @@ roles:
description: "Developer-centric server utilities and admin toolkits." description: "Developer-centric server utilities and admin toolkits."
icon: "fas fa-code" icon: "fas fa-code"
invokable: false invokable: false
srv:
title: "Server"
description: "General server roles for provisioning and managing server infrastructure—covering web servers, proxy servers, network services, and other backend components."
icon: "fas fa-server"
invokable: false
proxy:
title: "Proxy Server"
description: "Proxy-server roles for virtual-host orchestration and reverse-proxy setups."
icon: "fas fa-project-diagram"
invokable: false
web: web:
title: "Web Infrastructure" title: "Web Infrastructure"
description: "Roles for managing web infrastructure—covering static content services and deployable web applications." description: "Roles for managing web infrastructure—covering static content services and deployable web applications."

View File

@@ -20,7 +20,7 @@ To offer a centralized, extensible system for managing containerized application
- **Reset Logic:** Cleans previous Compose project files and data when `MODE_RESET` is enabled. - **Reset Logic:** Cleans previous Compose project files and data when `MODE_RESET` is enabled.
- **Handlers for Runtime Control:** Automatically builds, sets up, or restarts containers based on handlers. - **Handlers for Runtime Control:** Automatically builds, sets up, or restarts containers based on handlers.
- **Template-ready Service Files:** Predefined service base and health check templates. - **Template-ready Service Files:** Predefined service base and health check templates.
- **Integration Support:** Compatible with `srv-proxy-core` and other Infinito.Nexus service roles. - **Integration Support:** Compatible with `sys-svc-proxy` and other Infinito.Nexus service roles.
## Administration Tips ## Administration Tips

View File

@@ -3,7 +3,7 @@
- "CMD" - "CMD"
- "curl" - "curl"
- "-f" - "-f"
{% if container_hostname %} {% if container_hostname is defined %}
- "-H" - "-H"
- "Host: {{ container_hostname }}" - "Host: {{ container_hostname }}"
{% endif %} {% endif %}

View File

@@ -0,0 +1,7 @@
healthcheck:
test: ["CMD-SHELL", "nc -z localhost {{ container_port }} || exit 1"]
interval: 30s
timeout: 3s
retries: 3
start_period: 10s
{{ "\n" }}

View File

@@ -1,4 +0,0 @@
- block:
- include_tasks: 01_core.yml
- include_tasks: utils/run_once.yml
when: run_once_srv_letsencrypt is not defined

View File

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

View File

@@ -43,7 +43,7 @@ for filename in os.listdir(config_path):
url = f"{{ WEB_PROTOCOL }}://{domain}" url = f"{{ WEB_PROTOCOL }}://{domain}"
redirected_domains = [domain['source'] for domain in {{ redirect_domain_mappings }}] redirected_domains = [domain['source'] for domain in {{ redirect_domain_mappings }}]
redirected_domains.append("{{domains | get_domain('web-app-mailu')}}") redirected_domains.append("{{domains | get_domain('web-app-mailu') }}")
expected_statuses = get_expected_statuses(domain, parts, redirected_domains) expected_statuses = get_expected_statuses(domain, parts, redirected_domains)

View File

@@ -3,7 +3,7 @@
name: '{{ item }}' name: '{{ item }}'
loop: loop:
- sys-svc-certbot - sys-svc-certbot
- srv-core - sys-svc-webserver
- sys-ctl-alm-compose - sys-ctl-alm-compose
- name: install certbot - name: install certbot

View File

@@ -41,9 +41,9 @@
when: inj_enabled.logout when: inj_enabled.logout
- block: - block:
- name: Include dependency 'srv-core' - name: Include dependency 'sys-svc-webserver'
include_role: include_role:
name: srv-core name: sys-svc-webserver
when: run_once_srv_core is not defined when: run_once_sys_svc_webserver is not defined
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
when: run_once_sys_front_inj_all is not defined when: run_once_sys_front_inj_all is not defined

View File

@@ -1,7 +1,7 @@
- name: Include dependency 'srv-core' - name: Include dependency 'sys-svc-webserver'
include_role: include_role:
name: srv-core name: sys-svc-webserver
when: run_once_srv_core is not defined when: run_once_sys_svc_webserver is not defined
- name: Generate color palette with colorscheme-generator - name: Generate color palette with colorscheme-generator
set_fact: set_fact:

View File

@@ -1,8 +1,8 @@
- block: - block:
- name: Include dependency 'srv-core' - name: Include dependency 'sys-svc-webserver'
include_role: include_role:
name: srv-core name: sys-svc-webserver
when: run_once_srv_core is not defined when: run_once_sys_svc_webserver is not defined
- include_tasks: 01_deploy.yml - include_tasks: 01_deploy.yml
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
when: run_once_sys_front_inj_desktop is not defined when: run_once_sys_front_inj_desktop is not defined

View File

@@ -1,9 +1,9 @@
- block: - block:
- name: Include dependency 'srv-core' - name: Include dependency 'sys-svc-webserver'
include_role: include_role:
name: srv-core name: sys-svc-webserver
when: run_once_srv_core is not defined when: run_once_sys_svc_webserver is not defined
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
when: run_once_sys_front_inj_javascript is not defined when: run_once_sys_front_inj_javascript is not defined

View File

@@ -1,8 +1,8 @@
- name: Include dependency 'srv-core' - name: Include dependency 'sys-svc-webserver'
include_role: include_role:
name: srv-core name: sys-svc-webserver
when: when:
- run_once_srv_core is not defined - run_once_sys_svc_webserver is not defined
- name: "deploy the logout.js" - name: "deploy the logout.js"
include_tasks: "02_deploy.yml" include_tasks: "02_deploy.yml"

View File

@@ -1,8 +1,8 @@
- block: - block:
- name: Include dependency 'srv-core' - name: Include dependency 'sys-svc-webserver'
include_role: include_role:
name: srv-core name: sys-svc-webserver
when: run_once_srv_core is not defined when: run_once_sys_svc_webserver is not defined
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
when: run_once_sys_front_inj_matomo is not defined when: run_once_sys_front_inj_matomo is not defined

View File

@@ -10,7 +10,7 @@ A higher-level orchestration wrapper, *sys-stk-front-proxy* ties together severa
1. **`sys-front-inj-all`** applies global tweaks and includes. 1. **`sys-front-inj-all`** applies global tweaks and includes.
2. **`sys-svc-certs`** obtains Lets Encrypt certificates. 2. **`sys-svc-certs`** obtains Lets Encrypt certificates.
3. **Domain template deployment** copies a Jinja2 vHost from *srv-proxy-core*. 3. **Domain template deployment** copies a Jinja2 vHost from *sys-svc-proxy*.
4. **`web-app-oauth2-proxy`** *(optional)* protects the site with OAuth2. 4. **`web-app-oauth2-proxy`** *(optional)* protects the site with OAuth2.
The result is a complete, reproducible domain rollout in a single playbook task. The result is a complete, reproducible domain rollout in a single playbook task.

View File

@@ -2,4 +2,4 @@
vhost_flavour: "basic" # valid: basic, ws_generic vhost_flavour: "basic" # valid: basic, ws_generic
# build the full template path from the flavour # build the full template path from the flavour
vhost_template_src: "roles/srv-proxy-core/templates/vhost/{{ vhost_flavour }}.conf.j2" vhost_template_src: "roles/sys-svc-proxy/templates/vhost/{{ vhost_flavour }}.conf.j2"

View File

@@ -1,8 +1,8 @@
- block: - block:
- name: Include dependency 'srv-proxy-core' - name: Include dependency 'sys-svc-proxy'
include_role: include_role:
name: srv-proxy-core name: sys-svc-proxy
when: run_once_srv_proxy_core is not defined when: run_once_sys_svc_proxy is not defined
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
when: run_once_sys_stk_front_proxy is not defined when: run_once_sys_stk_front_proxy is not defined
@@ -15,7 +15,7 @@
- name: "include role for {{ domain }} to receive certificates and do the modification routines" - name: "include role for {{ domain }} to receive certificates and do the modification routines"
include_role: include_role:
name: srv-composer name: sys-util-csp-cert
- name: "Copy nginx config to {{ configuration_destination }}" - name: "Copy nginx config to {{ configuration_destination }}"
template: template:

View File

@@ -1 +1 @@
configuration_destination: "{{ NGINX.DIRECTORIES.HTTP.SERVERS }}{{ domain }}.conf" configuration_destination: "{{ [ NGINX.DIRECTORIES.HTTP.SERVERS, domain ~ '.conf'] | path_join }}"

View File

@@ -7,7 +7,7 @@ The **sys-stk-front-pure** role extends a basic Nginx installation by wiring in
2. Pulls in Lets Encrypt ACME challenge handling. 2. Pulls in Lets Encrypt ACME challenge handling.
3. Applies global cleanup of unused domain configs. 3. Applies global cleanup of unused domain configs.
This role is built on top of your existing `srv-core` role, and it automates the end-to-end process of turning HTTP sites into secure HTTPS sites. This role is built on top of your existing `sys-svc-webserver` role, and it automates the end-to-end process of turning HTTP sites into secure HTTPS sites.
--- ---
@@ -15,9 +15,9 @@ This role is built on top of your existing `srv-core` role, and it automates the
When you apply **sys-stk-front-pure**, it will: When you apply **sys-stk-front-pure**, it will:
1. **Include** the `srv-core` role to install and configure Nginx. 1. **Include** the `sys-svc-webserver` role to install and configure Nginx.
2. **Clean up** any stale vHost files under `sys-svc-cln-domains`. 2. **Clean up** any stale vHost files under `sys-svc-cln-domains`.
3. **Deploy** the Lets Encrypt challenge-and-redirect snippet from `srv-letsencrypt`. 3. **Deploy** the Lets Encrypt challenge-and-redirect snippet from `sys-svc-letsencrypt`.
4. **Reload** Nginx automatically when any template changes. 4. **Reload** Nginx automatically when any template changes.
All tasks are idempotent—once your certificates are in place and your configuration is set, Ansible will skip unchanged steps on subsequent runs. All tasks are idempotent—once your certificates are in place and your configuration is set, Ansible will skip unchanged steps on subsequent runs.
@@ -42,7 +42,7 @@ All tasks are idempotent—once your certificates are in place and your configur
## Requirements ## Requirements
- A working `srv-core` setup. - A working `sys-svc-webserver` setup.
- DNS managed via Cloudflare (for CAA record tasks) or equivalent ACME DNS flow. - DNS managed via Cloudflare (for CAA record tasks) or equivalent ACME DNS flow.
- Variables: - Variables:
- `LETSENCRYPT_WEBROOT_PATH` - `LETSENCRYPT_WEBROOT_PATH`

View File

@@ -3,8 +3,8 @@
include_role: include_role:
name: '{{ item }}' name: '{{ item }}'
loop: loop:
- srv-core - sys-svc-webserver
- sys-svc-cln-domains - sys-svc-cln-domains
- srv-letsencrypt - sys-svc-letsencrypt
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
when: run_once_sys_stk_front_pure is not defined when: run_once_sys_stk_front_pure is not defined

View File

@@ -3,7 +3,7 @@
include_role: include_role:
name: '{{ item }}' name: '{{ item }}'
loop: loop:
- srv-core - sys-svc-webserver
- name: Include task to remove deprecated nginx configs - name: Include task to remove deprecated nginx configs
include_tasks: remove_deprecated_nginx_configs.yml include_tasks: remove_deprecated_nginx_configs.yml

View File

@@ -15,6 +15,6 @@
- name: Remove exact nginx config for {{ domain }} - name: Remove exact nginx config for {{ domain }}
ansible.builtin.file: ansible.builtin.file:
path: "{{ NGINX.DIRECTORIES.HTTP.SERVERS }}{{ domain }}.conf" path: "{{ [ NGINX.DIRECTORIES.HTTP.SERVERS, domain ~ '.conf'] | path_join }}"
state: absent state: absent
notify: restart openresty notify: restart openresty

View File

@@ -1,5 +1,4 @@
---
- block: - block:
- include_tasks: 01_core.yml - include_tasks: 01_core.yml
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
when: run_once_srv_core is not defined when: run_once_sys_svc_letsencrypt is not defined

View File

@@ -12,4 +12,4 @@ ssl_session_tickets on;
add_header Strict-Transport-Security max-age=15768000; add_header Strict-Transport-Security max-age=15768000;
ssl_stapling on; ssl_stapling on;
ssl_stapling_verify on; ssl_stapling_verify on;
{% include 'roles/srv-letsencrypt/templates/ssl_credentials.j2' %} {% include 'roles/sys-svc-letsencrypt/templates/ssl_credentials.j2' %}

View File

@@ -4,6 +4,6 @@
name: '{{ item }}' name: '{{ item }}'
loop: loop:
- sys-stk-front-pure - sys-stk-front-pure
- srv-core - sys-svc-webserver
- include_tasks: utils/run_once.yml - include_tasks: utils/run_once.yml
when: run_once_srv_proxy_core is not defined when: run_once_sys_svc_proxy is not defined

View File

@@ -1,6 +1,6 @@
# Nginx Location Templates # Nginx Location Templates
This directory contains Jinja2 templates for different Nginx `location` blocks, each designed to proxy and optimize different types of web traffic. These templates are used by the `srv-proxy-core` role to modularize and standardize reverse proxy configuration across a wide variety of applications. This directory contains Jinja2 templates for different Nginx `location` blocks, each designed to proxy and optimize different types of web traffic. These templates are used by the `sys-svc-proxy` role to modularize and standardize reverse proxy configuration across a wide variety of applications.
--- ---

View File

@@ -15,7 +15,7 @@ location {{location}}
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port {{ WEB_PORT }}; proxy_set_header X-Forwarded-Port {{ WEB_PORT }};
{% include 'roles/srv-proxy-core/templates/headers/content_security_policy.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/headers/content_security_policy.conf.j2' %}
# WebSocket specific header # WebSocket specific header
proxy_http_version 1.1; proxy_http_version 1.1;

View File

@@ -1,7 +1,7 @@
server server
{ {
server_name {{ domain }}; server_name {{ domain }};
{% include 'roles/srv-proxy-core/templates/headers/buffers.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/headers/buffers.conf.j2' %}
{% if applications | get_app_conf(application_id, 'features.oauth2', False) %} {% if applications | get_app_conf(application_id, 'features.oauth2', False) %}
{% include 'roles/web-app-oauth2-proxy/templates/endpoint.conf.j2'%} {% include 'roles/web-app-oauth2-proxy/templates/endpoint.conf.j2'%}
@@ -14,7 +14,7 @@ server
{{ proxy_extra_configuration }} {{ proxy_extra_configuration }}
{% endif %} {% endif %}
{% include 'roles/srv-letsencrypt/templates/ssl_header.j2' %} {% include 'roles/sys-svc-letsencrypt/templates/ssl_header.j2' %}
{% if applications | get_app_conf(application_id, 'features.oauth2', False) %} {% if applications | get_app_conf(application_id, 'features.oauth2', False) %}
{% set acl = applications | get_app_conf(application_id, 'oauth2_proxy.acl', False, {}) %} {% set acl = applications | get_app_conf(application_id, 'oauth2_proxy.acl', False, {}) %}
@@ -23,38 +23,38 @@ server
{# 1. Expose everything by default, then protect blacklisted paths #} {# 1. Expose everything by default, then protect blacklisted paths #}
{% set oauth2_proxy_enabled = false %} {% set oauth2_proxy_enabled = false %}
{% set location = "/" %} {% set location = "/" %}
{% include 'roles/srv-proxy-core/templates/location/html.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/location/html.conf.j2' %}
{% for loc in acl.blacklist %} {% for loc in acl.blacklist %}
{% set oauth2_proxy_enabled = true %} {% set oauth2_proxy_enabled = true %}
{% set location = loc %} {% set location = loc %}
{% include 'roles/srv-proxy-core/templates/location/html.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/location/html.conf.j2' %}
{% endfor %} {% endfor %}
{% elif acl.whitelist is defined %} {% elif acl.whitelist is defined %}
{# 2. Protect everything by default, then expose whitelisted paths #} {# 2. Protect everything by default, then expose whitelisted paths #}
{% set oauth2_proxy_enabled = true %} {% set oauth2_proxy_enabled = true %}
{% set location = "/" %} {% set location = "/" %}
{% include 'roles/srv-proxy-core/templates/location/html.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/location/html.conf.j2' %}
{% for loc in acl.whitelist %} {% for loc in acl.whitelist %}
{% set oauth2_proxy_enabled = false %} {% set oauth2_proxy_enabled = false %}
{% set location = loc %} {% set location = loc %}
{% include 'roles/srv-proxy-core/templates/location/html.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/location/html.conf.j2' %}
{% endfor %} {% endfor %}
{% else %} {% else %}
{# 3. OAuth2 enabled but no (or empty) ACL — protect all #} {# 3. OAuth2 enabled but no (or empty) ACL — protect all #}
{% set oauth2_proxy_enabled = true %} {% set oauth2_proxy_enabled = true %}
{% set location = "/" %} {% set location = "/" %}
{% include 'roles/srv-proxy-core/templates/location/html.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/location/html.conf.j2' %}
{% endif %} {% endif %}
{% else %} {% else %}
{# 4. OAuth2 completely disabled — expose all #} {# 4. OAuth2 completely disabled — expose all #}
{% set oauth2_proxy_enabled = false %} {% set oauth2_proxy_enabled = false %}
{% set location = "/" %} {% set location = "/" %}
{% include 'roles/srv-proxy-core/templates/location/html.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/location/html.conf.j2' %}
{% endif %} {% endif %}
} }

View File

@@ -6,7 +6,7 @@ map $http_upgrade $connection_upgrade {
server { server {
server_name {{ domain }}; server_name {{ domain }};
{% include 'roles/srv-letsencrypt/templates/ssl_header.j2' %} {% include 'roles/sys-svc-letsencrypt/templates/ssl_header.j2' %}
{% include 'roles/sys-front-inj-all/templates/server.conf.j2' %} {% include 'roles/sys-front-inj-all/templates/server.conf.j2' %}
@@ -25,10 +25,10 @@ server {
add_header Strict-Transport-Security "max-age=31536000"; add_header Strict-Transport-Security "max-age=31536000";
{% include 'roles/srv-proxy-core/templates/location/html.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/location/html.conf.j2' %}
{% if location_ws is defined %} {% if location_ws is defined %}
{% include 'roles/srv-proxy-core/templates/location/ws.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/location/ws.conf.j2' %}
{% endif %} {% endif %}
error_page 500 501 502 503 504 /500.html; error_page 500 501 502 503 504 /500.html;

View File

@@ -2,7 +2,7 @@
{% if not applications | get_app_conf(application_id, 'features.central_database', False) %} {% if not applications | get_app_conf(application_id, 'features.central_database', False) %}
{{ database_host }}: {{ database_host }}:
image: postgres:{{applications['svc-db-postgres'].version}}-alpine image: postgres:{{ applications['svc-db-postgres'].version}}-alpine
container_name: {{ application_id | get_entity_name }}-database container_name: {{ application_id | get_entity_name }}-database
env_file: env_file:
- {{database_env}} - {{database_env}}

View File

@@ -18,4 +18,4 @@ galaxy_info:
- performance - performance
repository: "https://s.infinito.nexus/code" repository: "https://s.infinito.nexus/code"
issue_tracker_url: "https://s.infinito.nexus/issues" issue_tracker_url: "https://s.infinito.nexus/issues"
documentation: "https://s.infinito.nexus/code/roles/srv-core" documentation: "https://s.infinito.nexus/code/roles/sys-svc-webserver"

View File

@@ -49,3 +49,5 @@
- sys-ctl-hlth-csp - sys-ctl-hlth-csp
vars: vars:
flush_handlers: false flush_handlers: false
- include_tasks: utils/run_once.yml

View File

@@ -0,0 +1,4 @@
---
- block:
- include_tasks: 01_core.yml
when: run_once_sys_svc_webserver is not defined

View File

@@ -1,4 +1,4 @@
# Role: srv-composer # Role: sys-util-csp-cert
This Ansible role composes and orchestrates all necessary HTTPS-layer tasks and HTML-content injections for your webserver domains. It integrates two key sub-roles into a unified workflow: This Ansible role composes and orchestrates all necessary HTTPS-layer tasks and HTML-content injections for your webserver domains. It integrates two key sub-roles into a unified workflow:

View File

@@ -27,4 +27,4 @@ galaxy_info:
- orchestration - orchestration
repository: "https://s.infinito.nexus/code" repository: "https://s.infinito.nexus/code"
issue_tracker_url: "https://s.infinito.nexus/issues" issue_tracker_url: "https://s.infinito.nexus/issues"
documentation: "https://s.infinito.nexus/code/roles/srv-composer" documentation: "https://s.infinito.nexus/code/roles/sys-util-csp-cert"

View File

@@ -1,4 +1,4 @@
# run_once_srv_composer: deactivated # run_once_sys_util_csp_cert: deactivated
- name: "include role sys-front-inj-all for '{{ domain }}'" - name: "include role sys-front-inj-all for '{{ domain }}'"
include_role: include_role:

View File

@@ -35,7 +35,7 @@ By default, BigBlueButton is deployed with best-practice hardening, modular secr
## System Requirements ## System Requirements
- Arch Linux with Docker, Compose, and Nginx roles pre-installed - Arch Linux with Docker, Compose, and Nginx roles pre-installed
- DNS and reverse proxy configuration using `srv-proxy-core` - DNS and reverse proxy configuration using `sys-svc-proxy`
- Functional email system for Greenlight SMTP - Functional email system for Greenlight SMTP
## Important Resources ## Important Resources

View File

@@ -3,7 +3,7 @@
set_fact: set_fact:
proxy_extra_configuration: >- proxy_extra_configuration: >-
{{ lookup('ansible.builtin.template', {{ lookup('ansible.builtin.template',
playbook_dir ~ '/roles/srv-proxy-core/templates/location/html.conf.j2') | trim }} playbook_dir ~ '/roles/sys-svc-proxy/templates/location/html.conf.j2') | trim }}
vars: vars:
location: '^~ /html5client' location: '^~ /html5client'
oauth2_proxy_enabled: false oauth2_proxy_enabled: false

View File

@@ -1,8 +1,8 @@
credentials: credentials:
jwt_secret: jwt_secret:
description: "Secret used for JWT signing (base64, 64 bytes)" description: "Secret used for JWT signing"
algorithm: "plain" algorithm: "base64_prefixed_32"
validation: "^[A-Za-z0-9+/=]{86,}$" # 64 bytes base64 = ~86 characters without newline validation: "^base64:[A-Za-z0-9+/]{43}=$"
plc_rotation_key_k256_private_key_hex: plc_rotation_key_k256_private_key_hex:
description: "PLC rotation key in hex format (32 bytes)" description: "PLC rotation key in hex format (32 bytes)"
algorithm: "sha256" algorithm: "sha256"

View File

@@ -1,5 +1,5 @@
PDS_HOSTNAME="{{domains[application_id].api}}" PDS_HOSTNAME="{{domains[application_id].api}}"
PDS_ADMIN_EMAIL="{{applications.bluesky.users.administrator.email}}" PDS_ADMIN_EMAIL="{{ applications.bluesky.users.administrator.email}}"
PDS_SERVICE_DID="did:web:{{domains[application_id].api}}" PDS_SERVICE_DID="did:web:{{domains[application_id].api}}"
# See https://mattdyson.org/blog/2024/11/self-hosting-bluesky-pds/ # See https://mattdyson.org/blog/2024/11/self-hosting-bluesky-pds/

View File

@@ -97,7 +97,7 @@ STATIC_ROOT={{funkwhale_static_root}}
DJANGO_SETTINGS_MODULE=config.settings.production DJANGO_SETTINGS_MODULE=config.settings.production
# Generate one using `openssl rand -base64 45`, for example # Generate one using `openssl rand -base64 45`, for example
DJANGO_SECRET_KEY={{applications | get_app_conf(application_id, 'credentials.django_secret', True)}} DJANGO_SECRET_KEY={{ applications | get_app_conf(application_id, 'credentials.django_secret', True)}}
{% if applications | get_app_conf(application_id, 'features.ldap', False) %} {% if applications | get_app_conf(application_id, 'features.ldap', False) %}
# LDAP settings # LDAP settings

View File

@@ -41,7 +41,7 @@
"id.token.claim": "true", "id.token.claim": "true",
"lightweight.claim": "false", "lightweight.claim": "false",
"access.token.claim": "true", "access.token.claim": "true",
"claim.name": "{{LDAP.USER.ATTRIBUTES.ID}}", "claim.name": "{{ LDAP.USER.ATTRIBUTES.ID }}",
"jsonType.label": "String" "jsonType.label": "String"
} }
} }

View File

@@ -112,7 +112,7 @@
- name: create chatgpt bot - name: create chatgpt bot
command: command:
cmd: docker compose exec -it synapse register_new_matrix_user -u chatgptbot -p {{applications | get_app_conf(application_id, 'credentials.chatgpt_bridge_user_password', True)}} -a -c {{ MATRIX_SYNAPSE_CONFIG_PATH_CONTAINER }} http://localhost:8008 cmd: docker compose exec -it synapse register_new_matrix_user -u chatgptbot -p {{ applications | get_app_conf(application_id, 'credentials.chatgpt_bridge_user_password', True)}} -a -c {{ MATRIX_SYNAPSE_CONFIG_PATH_CONTAINER }} http://localhost:8008
chdir: "{{ docker_compose.directories.instance }}" chdir: "{{ docker_compose.directories.instance }}"
ignore_errors: true ignore_errors: true
when: applications | get_app_conf(application_id, 'setup', True) | bool when: applications | get_app_conf(application_id, 'setup', True) | bool

View File

@@ -18,7 +18,7 @@
- name: "include role for {{ application_id }} to receive certs & do modification routines for {{ MATRIX_SYNAPSE_DOMAIN }}" - name: "include role for {{ application_id }} to receive certs & do modification routines for {{ MATRIX_SYNAPSE_DOMAIN }}"
include_role: include_role:
name: srv-composer name: sys-util-csp-cert
vars: vars:
domain: "{{ MATRIX_SYNAPSE_DOMAIN }}" domain: "{{ MATRIX_SYNAPSE_DOMAIN }}"
http_port: "{{ MATRIX_SYNAPSE_PORT }}" http_port: "{{ MATRIX_SYNAPSE_PORT }}"

View File

@@ -62,7 +62,7 @@
volumes: volumes:
- chatgpt_data:/storage - chatgpt_data:/storage
environment: environment:
OPENAI_API_KEY: '{{applications | get_app_conf(application_id, 'credentials.chatgpt_bridge_openai_api_key', True)}}' OPENAI_API_KEY: '{{ applications | get_app_conf(application_id, 'credentials.chatgpt_bridge_openai_api_key', True)}}'
# 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'

View File

@@ -39,7 +39,7 @@ appservice:
# Format examples: # Format examples:
# SQLite: sqlite:filename.db # SQLite: sqlite:filename.db
# Postgres: postgres://username:password@hostname/dbname # Postgres: postgres://username:password@hostname/dbname
database: postgres://mautrix_facebook_bridge:{{applications | get_app_conf(application_id, 'credentials.mautrix_facebook_bridge_database_password', True)}}@{{ database_host }}/mautrix_facebook_bridge database: postgres://mautrix_facebook_bridge:{{ applications | get_app_conf(application_id, 'credentials.mautrix_facebook_bridge_database_password', True)}}@{{ database_host }}/mautrix_facebook_bridge
# Additional arguments for asyncpg.create_pool() or sqlite3.connect() # Additional arguments for asyncpg.create_pool() or sqlite3.connect()
# https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.pool.create_pool # https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.pool.create_pool
# https://docs.python.org/3/library/sqlite3.html#sqlite3.connect # https://docs.python.org/3/library/sqlite3.html#sqlite3.connect

View File

@@ -42,7 +42,7 @@ appservice:
# Format examples: # Format examples:
# SQLite: sqlite:filename.db # SQLite: sqlite:filename.db
# Postgres: postgres://username:password@hostname/dbname # Postgres: postgres://username:password@hostname/dbname
database: postgres://mautrix_instagram_bridge:{{applications | get_app_conf(application_id, 'credentials.mautrix_instagram_bridge_database_password', True)}}@{{ database_host }}/mautrix_instagram_bridge database: postgres://mautrix_instagram_bridge:{{ applications | get_app_conf(application_id, 'credentials.mautrix_instagram_bridge_database_password', True)}}@{{ database_host }}/mautrix_instagram_bridge
# Additional arguments for asyncpg.create_pool() or sqlite3.connect() # Additional arguments for asyncpg.create_pool() or sqlite3.connect()
# https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.pool.create_pool # https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.pool.create_pool
# https://docs.python.org/3/library/sqlite3.html#sqlite3.connect # https://docs.python.org/3/library/sqlite3.html#sqlite3.connect

View File

@@ -43,7 +43,7 @@ appservice:
# https://github.com/mattn/go-sqlite3#connection-string # https://github.com/mattn/go-sqlite3#connection-string
# Postgres: Connection string. For example, postgres://user:password@host/database?sslmode=disable # Postgres: Connection string. For example, postgres://user:password@host/database?sslmode=disable
# To connect via Unix socket, use something like postgres:///dbname?host=/var/run/postgresql # To connect via Unix socket, use something like postgres:///dbname?host=/var/run/postgresql
uri: postgres://mautrix_signal_bridge:{{applications | get_app_conf(application_id, 'credentials.mautrix_signal_bridge_database_password', True)}}@{{ database_host }}/mautrix_signal_bridge?sslmode=disable uri: postgres://mautrix_signal_bridge:{{ applications | get_app_conf(application_id, 'credentials.mautrix_signal_bridge_database_password', True)}}@{{ database_host }}/mautrix_signal_bridge?sslmode=disable
# Maximum number of connections. Mostly relevant for Postgres. # Maximum number of connections. Mostly relevant for Postgres.
max_open_conns: 20 max_open_conns: 20
max_idle_conns: 2 max_idle_conns: 2

View File

@@ -43,7 +43,7 @@ appservice:
# https://github.com/mattn/go-sqlite3#connection-string # https://github.com/mattn/go-sqlite3#connection-string
# Postgres: Connection string. For example, postgres://user:password@host/database?sslmode=disable # Postgres: Connection string. For example, postgres://user:password@host/database?sslmode=disable
# To connect via Unix socket, use something like postgres:///dbname?host=/var/run/postgresql # To connect via Unix socket, use something like postgres:///dbname?host=/var/run/postgresql
uri: postgres://mautrix_slack_bridge:{{applications | get_app_conf(application_id, 'credentials.mautrix_slack_bridge_database_password', True)}}@{{ database_host }}/mautrix_slack_bridge?sslmode=disable uri: postgres://mautrix_slack_bridge:{{ applications | get_app_conf(application_id, 'credentials.mautrix_slack_bridge_database_password', True)}}@{{ database_host }}/mautrix_slack_bridge?sslmode=disable
# Maximum number of connections. Mostly relevant for Postgres. # Maximum number of connections. Mostly relevant for Postgres.
max_open_conns: 20 max_open_conns: 20
max_idle_conns: 2 max_idle_conns: 2

View File

@@ -42,7 +42,7 @@ appservice:
# Format examples: # Format examples:
# SQLite: sqlite:filename.db # SQLite: sqlite:filename.db
# Postgres: postgres://username:password@hostname/dbname # Postgres: postgres://username:password@hostname/dbname
database: postgres://mautrix_telegram_bridge:{{applications | get_app_conf(application_id, 'credentials.mautrix_telegram_bridge_database_password', True)}}@{{ database_host }}/mautrix_telegram_bridge database: postgres://mautrix_telegram_bridge:{{ applications | get_app_conf(application_id, 'credentials.mautrix_telegram_bridge_database_password', True)}}@{{ database_host }}/mautrix_telegram_bridge
# Additional arguments for asyncpg.create_pool() or sqlite3.connect() # Additional arguments for asyncpg.create_pool() or sqlite3.connect()
# https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.pool.create_pool # https://magicstack.github.io/asyncpg/current/api/index.html#asyncpg.pool.create_pool
# https://docs.python.org/3/library/sqlite3.html#sqlite3.connect # https://docs.python.org/3/library/sqlite3.html#sqlite3.connect
@@ -564,8 +564,8 @@ bridge:
# Telegram config # Telegram config
telegram: telegram:
# Get your own API keys at https://my.telegram.org/apps # Get your own API keys at https://my.telegram.org/apps
api_id: {{applications | get_app_conf(application_id, 'credentials.mautrix_telgegram_bridge_api_id', True)}} api_id: {{ applications | get_app_conf(application_id, 'credentials.mautrix_telgegram_bridge_api_id', True)}}
api_hash: {{applications | get_app_conf(application_id, 'credentials.mautrix_telgegram_bridge_api_pin', True)}} api_hash: {{ applications | get_app_conf(application_id, 'credentials.mautrix_telgegram_bridge_api_pin', True)}}
# (Optional) Create your own bot at https://t.me/BotFather # (Optional) Create your own bot at https://t.me/BotFather
bot_token: disabled bot_token: disabled

View File

@@ -42,7 +42,7 @@ appservice:
# https://github.com/mattn/go-sqlite3#connection-string # https://github.com/mattn/go-sqlite3#connection-string
# Postgres: Connection string. For example, postgres://user:password@host/database?sslmode=disable # Postgres: Connection string. For example, postgres://user:password@host/database?sslmode=disable
# To connect via Unix socket, use something like postgres:///dbname?host=/var/run/postgresql # To connect via Unix socket, use something like postgres:///dbname?host=/var/run/postgresql
uri: postgres://mautrix_whatsapp_bridge:{{applications | get_app_conf(application_id, 'credentials.mautrix_whatsapp_bridge_database_password', True)}}@{{ database_host }}/mautrix_whatsapp_bridge?sslmode=disable uri: postgres://mautrix_whatsapp_bridge:{{ applications | get_app_conf(application_id, 'credentials.mautrix_whatsapp_bridge_database_password', True)}}@{{ database_host }}/mautrix_whatsapp_bridge?sslmode=disable
# Maximum number of connections. Mostly relevant for Postgres. # Maximum number of connections. Mostly relevant for Postgres.
max_open_conns: 20 max_open_conns: 20
max_idle_conns: 2 max_idle_conns: 2

View File

@@ -1,6 +1,6 @@
server { server {
server_name {{ domain }}; server_name {{ domain }};
{% include 'roles/srv-letsencrypt/templates/ssl_header.j2' %} {% include 'roles/sys-svc-letsencrypt/templates/ssl_header.j2' %}
# For the federation port # For the federation port
listen {{ MATRIX_FEDERATION_PORT }} ssl default_server; listen {{ MATRIX_FEDERATION_PORT }} ssl default_server;
@@ -8,7 +8,7 @@ server {
{% include 'roles/sys-front-inj-all/templates/server.conf.j2'%} {% include 'roles/sys-front-inj-all/templates/server.conf.j2'%}
{% include 'roles/srv-proxy-core/templates/location/html.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/location/html.conf.j2' %}
{% include 'roles/srv-proxy-core/templates/location/upload.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/location/upload.conf.j2' %}
} }

View File

@@ -18,6 +18,6 @@ docker:
features: features:
logout: true logout: true
central_database: true central_database: true
css: true css: false
desktop: true desktop: true
oidc: true oidc: true

View File

@@ -0,0 +1,256 @@
/* MediaWiki (Vector 2022 + OOUI) color remap via Infinito.Nexus palette
- Keep changes scoped and variable-driven
- Prefer variables over hard values
- Avoid !important unless an inline style or strong OOUI rule requires it
*/
/* ---------- App-scoped variables (derived from global color scale) ---------- */
:root {
/* Brand & accents */
--mw-primary: var(--color-01-60);
--mw-primary-contrast: var(--color-01-99);
--mw-secondary: var(--color-01-85);
--mw-accent: var(--color-01-50);
/* Surfaces */
--mw-surface: var(--color-01-92);
--mw-surface-variant: var(--color-01-90);
--mw-surface-muted: var(--color-01-95);
/* Text */
--mw-text: var(--color-01-20);
--mw-text-muted: var(--color-01-45);
--mw-heading: var(--color-01-15);
--mw-link: var(--color-01-55);
--mw-link-hover: var(--color-01-60);
--mw-link-visited: var(--color-01-45);
/* Lines / borders / focus */
--mw-border: var(--color-01-85);
--mw-divider: var(--color-01-87);
--mw-focus: rgba(var(--color-01-rgb-65), .35);
/* Status */
--mw-success: var(--bs-success);
--mw-warning: var(--bs-warning);
--mw-danger: var(--bs-danger);
}
/* ---------- Global shell ---------- */
body.skin-vector,
.skin-vector .mw-page-container {
background-color: var(--mw-surface);
background-image: linear-gradient({{ range(0, 361) | random }}deg,
var(--mw-surface),
var(--mw-surface-variant),
var(--mw-surface-muted),
var(--mw-surface)
);
color: var(--mw-text);
}
/* ---------- Header / site chrome ---------- */
.skin-vector .vector-header,
.skin-vector .vector-header-container,
.skin-vector .mw-header {
background-color: var(--color-01-80);
background-image: linear-gradient({{ range(0, 361) | random }}deg,
var(--color-01-75), var(--color-01-80), var(--color-01-81), var(--color-01-85)
);
color: var(--color-01-17);
border-bottom: 1px solid var(--mw-divider);
}
/* Logo & title area often inherits link styles—keep readable */
.skin-vector .mw-logo a,
.skin-vector .mw-logo svg,
.skin-vector .vector-header a {
color: var(--mw-heading);
fill: currentColor;
}
/* ---------- Sidebar / menus ---------- */
.skin-vector .vector-sidebar,
.skin-vector .mw-portlet,
.skin-vector .vector-menu-content {
background-color: var(--mw-surface-variant);
border-color: var(--mw-border);
}
.skin-vector .vector-sidebar .vector-menu-heading,
.skin-vector .vector-menu-heading {
color: var(--mw-heading);
border-bottom: 1px solid var(--mw-divider);
}
/* ---------- Table of Contents ---------- */
.skin-vector .vector-toc,
.skin-vector .vector-toc .vector-toc-contents {
background-color: var(--mw-surface-muted);
border: 1px solid var(--mw-border);
}
.skin-vector .vector-toc .vector-toc-text {
color: var(--mw-text);
}
/* ---------- Content area ---------- */
.skin-vector .mw-content-container,
.skin-vector .mw-content-ltr,
.skin-vector .mw-body,
.skin-vector .mw-parser-output {
color: var(--mw-text);
}
.skin-vector .mw-parser-output h1,
.skin-vector .mw-parser-output h2,
.skin-vector .mw-parser-output h3,
.skin-vector .mw-parser-output h4,
.skin-vector .mw-parser-output h5,
.skin-vector .mw-parser-output h6 {
color: var(--mw-heading);
}
/* Links */
.skin-vector .mw-parser-output a { color: var(--mw-link); }
.skin-vector .mw-parser-output a:visited { color: var(--mw-link-visited); }
.skin-vector .mw-parser-output a:hover,
.skin-vector .mw-parser-output a:focus { color: var(--mw-link-hover); }
/* ---------- Search ---------- */
.skin-vector .vector-search-box input,
.skin-vector .vector-search-box .vector-search-input {
background-color: var(--mw-surface);
border: 1px solid var(--mw-border);
color: var(--mw-text);
}
.skin-vector .vector-search-box input:focus {
outline: 0;
box-shadow: 0 0 0 3px var(--mw-focus);
border-color: var(--mw-link);
}
/* ---------- Buttons (MediaWiki UI + OOUI) ---------- */
/* MediaWiki UI */
.mw-ui-button,
.mw-ui-button:visited {
background-color: var(--mw-surface-muted);
color: var(--mw-text);
border: 1px solid var(--mw-border);
}
.mw-ui-button:hover,
.mw-ui-button:focus {
background-color: var(--mw-surface-variant);
color: var(--mw-text);
border-color: var(--mw-link);
box-shadow: 0 0 0 3px var(--mw-focus);
}
.mw-ui-progressive,
.mw-ui-primary {
background-color: var(--mw-primary);
color: var(--mw-primary-contrast);
border-color: var(--mw-primary);
}
.mw-ui-progressive:hover,
.mw-ui-primary:hover {
filter: brightness(0.95);
}
/* OOUI (covers most modern UI widgets) */
.oo-ui-buttonElement-button {
background-color: var(--mw-surface-muted);
color: var(--mw-text);
border: 1px solid var(--mw-border);
}
.oo-ui-buttonElement-button:focus-visible {
outline: 0;
box-shadow: 0 0 0 3px var(--mw-focus);
border-color: var(--mw-link);
}
.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button,
.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button {
background-color: var(--mw-primary);
color: var(--mw-primary-contrast);
border-color: var(--mw-primary);
}
/* Inputs */
.mw-ui-input,
.oo-ui-inputWidget-input {
background-color: var(--mw-surface);
color: var(--mw-text);
border: 1px solid var(--mw-border);
}
.oo-ui-inputWidget-input:focus,
.mw-ui-input:focus {
outline: 0;
box-shadow: 0 0 0 3px var(--mw-focus);
border-color: var(--mw-link);
}
/* ---------- Tables / infoboxes ---------- */
table.wikitable,
.mw-parser-output table.infobox,
.mw-parser-output table.prettytable {
background-color: var(--color-01-99);
border: 1px solid var(--mw-border);
color: var(--mw-text);
}
table.wikitable > * > tr > th,
table.wikitable > * > tr > td {
border: 1px solid var(--mw-border);
}
table.wikitable > * > tr > th {
background-color: var(--color-01-80);
background-image: linear-gradient({{ range(0, 361) | random }}deg,
var(--color-01-75), var(--color-01-80), var(--color-01-81), var(--color-01-85)
);
color: var(--mw-heading);
}
/* ---------- Notices / boxes ---------- */
.mw-notification,
.mw-message-box,
.mw-message-box-notice {
background-color: var(--mw-surface-muted);
border-color: var(--mw-border);
color: var(--mw-text);
}
.mw-message-box-warning {
border-left: 4px solid var(--mw-warning);
}
.mw-message-box-error {
border-left: 4px solid var(--mw-danger);
}
.mw-message-box-success {
border-left: 4px solid var(--mw-success);
}
/* ---------- Footer ---------- */
.skin-vector .mw-footer {
background-color: var(--mw-surface-variant);
border-top: 1px solid var(--mw-divider);
color: var(--mw-text-muted);
}
/* ---------- Dark-mode helpers (for browser extensions honoring vars) ---------- */
@media (prefers-color-scheme: dark) {
:root {
/* Nudge contrast a bit in dark environments */
--mw-text: var(--color-01-90);
--mw-text-muted: var(--color-01-80);
--mw-heading: var(--color-01-95);
}
}

View File

@@ -1,12 +1,12 @@
# General # General
MOODLE_SITE_NAME="{{applications | get_app_conf(application_id, 'site_titel', True)}}" MOODLE_SITE_NAME="{{ applications | get_app_conf(application_id, 'site_titel', True) }}"
MOODLE_HOST="{{ domains | get_domain(application_id) }}" MOODLE_HOST="{{ domains | get_domain(application_id) }}"
MOODLE_SSLPROXY=yes MOODLE_SSLPROXY=yes
MOODLE_REVERSE_PROXY=yes MOODLE_REVERSE_PROXY=yes
MOODLE_USERNAME={{ applications | get_app_conf(application_id, 'users.administrator.username') }} MOODLE_USERNAME={{ applications | get_app_conf(application_id, 'users.administrator.username') }}
MOODLE_PASSWORD={{applications | get_app_conf(application_id, 'credentials.user_password', True)}} MOODLE_PASSWORD={{ applications | get_app_conf(application_id, 'credentials.user_password', True)}}
MOODLE_EMAIL={{applications | get_app_conf(application_id, 'users.administrator.email', True)}} MOODLE_EMAIL={{ applications | get_app_conf(application_id, 'users.administrator.email', True)}}
BITNAMI_DEBUG={% if MODE_DEBUG | bool %}true{% else %}false{% endif %} BITNAMI_DEBUG={% if MODE_DEBUG | bool %}true{% else %}false{% endif %}
# Database # Database

View File

@@ -1,2 +0,0 @@
# Todo
- Implement Collabora and Talk Supper . [See](https://www.youtube.com/watch?v=7cRmvTyt1ik)

View File

@@ -18,7 +18,6 @@ server:
domains: domains:
canonical: canonical:
- "cloud.{{ PRIMARY_DOMAIN }}" - "cloud.{{ PRIMARY_DOMAIN }}"
# talk: "talk.{{ PRIMARY_DOMAIN }}" @todo needs to be activated
docker: docker:
volumes: volumes:
data: nextcloud_data data: nextcloud_data
@@ -45,8 +44,14 @@ docker:
name: "nextcloud-talk" name: "nextcloud-talk"
image: "nextcloud/aio-talk" image: "nextcloud/aio-talk"
version: "latest" version: "latest"
enabled: false # Not enabled yet, because just implemented during refactoring and not tested yet. if tested activate backup:
oidc: no_stop_required: false
whiteboard:
name: "nextcloud-whiteboard"
image: "ghcr.io/nextcloud-releases/whiteboard"
version: "latest"
backup:
no_stop_required: true
enabled: "{{ applications | get_app_conf('web-app-nextcloud', 'features.oidc', False, True) }}" # Activate OIDC for Nextcloud enabled: "{{ applications | get_app_conf('web-app-nextcloud', 'features.oidc', False, True) }}" # Activate OIDC for Nextcloud
# floavor decides which OICD plugin should be used. # floavor decides which OICD plugin should be used.
# Available options: oidc_login, sociallogin # Available options: oidc_login, sociallogin
@@ -72,7 +77,8 @@ performance:
opcache_memory_consumption: "{{ ((ansible_memtotal_mb | int) / 30)|int }}M" # Dynamic set memory consumption opcache_memory_consumption: "{{ ((ansible_memtotal_mb | int) / 30)|int }}M" # Dynamic set memory consumption
plugins_enabled: true # Implemented for speeding up testing and debugging process. For productive environments keep it true and steer the apps via the plugins config plugins_enabled: true # Implemented for speeding up testing and debugging process. For productive environments keep it true and steer the apps via the plugins config
oidc:
flavor: "{{ _applications_nextcloud_oidc_flavor }}"
plugins: plugins:
# List for Nextcloud Plugin Routine # List for Nextcloud Plugin Routine
# Decides if plugins should be activated or deactivated # Decides if plugins should be activated or deactivated
@@ -234,7 +240,7 @@ plugins:
- oidc_login # Will be disabled - oidc_login # Will be disabled
spreed: spreed:
# Nextcloud Spreed: offers video conferencing and chat functionalities (https://apps.nextcloud.com/apps/spreed) # Nextcloud Spreed: offers video conferencing and chat functionalities (https://apps.nextcloud.com/apps/spreed)
enabled: false # @todo to activate it first implement web-svc-coturn and activate it enabled: true
tables: tables:
# Nextcloud tables: allows creation and editing of tables within the interface (https://apps.nextcloud.com/apps/tables) # Nextcloud tables: allows creation and editing of tables within the interface (https://apps.nextcloud.com/apps/tables)
enabled: true enabled: true

View File

@@ -1,6 +1,6 @@
--- ---
- name: restart nextcloud nginx service - name: restart nextcloud nginx service
command: command:
cmd: "docker exec {{ nextcloud_proxy_name }} nginx -s reload" cmd: "docker exec {{ NEXTCLOUD_PROXY_CONTAINER }} nginx -s reload"
listen: restart nextcloud nginx service listen: restart nextcloud nginx service
ignore_errors: true # Ignoring if container is restarting ignore_errors: true # Ignoring if container is restarting

View File

@@ -1,6 +1,21 @@
credentials: credentials:
whiteboard_jwt_secret:
description: "Secret used for JWT signing"
algorithm: "base64_prefixed_32"
validation: "^base64:[A-Za-z0-9+/]{43}=$"
administrator_password: administrator_password:
description: "Initial password for the Nextcloud administrator (change immediately and enable 2FA)" description: "Initial password for the Nextcloud administrator (change immediately and enable 2FA)"
algorithm: "sha256" algorithm: "sha256"
validation: "^[a-f0-9]{64}$" validation: "^[a-f0-9]{64}$"
talk_turn_secret:
description: "TURN REST secret for coturn"
algorithm: "base64_prefixed_32"
validation: "^base64:[A-Za-z0-9+/]{43}=$"
talk_signaling_secret:
description: "Secret for Talk signaling"
algorithm: "base64_prefixed_32"
validation: "^base64:[A-Za-z0-9+/]{43}=$"
talk_internal_secret:
description: "Internal secret for AIO Talk"
algorithm: "base64_prefixed_32"
validation: "^base64:[A-Za-z0-9+/]{43}=$"

View File

@@ -0,0 +1,37 @@
- name: "include role for {{ application_id }} to receive certs & do modification routines for '{{ domain }}:{{ port }}'"
include_role:
name: sys-util-csp-cert
- name: create nextcloud proxy configuration file
template:
src: "nginx/host.conf.j2"
dest: "{{ NEXTCLOUD_HOST_NGINX_PATH }}"
notify: restart openresty
- name: "load docker and db for {{ application_id }}"
include_role:
name: sys-stk-back-stateful
vars:
docker_compose_flush_handlers: false
- name: "create {{ NEXTCLOUD_HOST_CONF_ADD_PATH }}"
file:
path: "{{ NEXTCLOUD_HOST_CONF_ADD_PATH }}"
state: directory
mode: "0755"
- name: "Create config files at {{ NEXTCLOUD_HOST_CONF_ADD_PATH }}"
template:
src: "{{ item }}"
dest: "{{ NEXTCLOUD_HOST_CONF_ADD_PATH }}/{{ item | basename | regex_replace('\\.j2$', '') }}"
owner: "{{ NEXTCLOUD_DOCKER_USER_id }}"
group: "{{ NEXTCLOUD_DOCKER_USER_id }}"
loop: "{{ lookup('fileglob', role_path ~ '/templates/config/*.j2', wantlist=True) }}"
# Not all type of changes take instantly place. Due to this reason a rebuild is required.
notify: docker compose up
- name: create internal nextcloud nginx configuration
template:
src: "nginx/docker.conf.j2"
dest: "{{ [docker_compose.directories.volumes, 'nginx.conf'] | path_join }}"
notify: restart nextcloud nginx service

View File

@@ -3,7 +3,7 @@
- name: Add dynamic config merging from Jinja template - name: Add dynamic config merging from Jinja template
template: template:
src: include.php.j2 src: include.php.j2
dest: "{{ nextcloud_host_include_instructions_file }}" dest: "{{ NEXTCLOUD_HOST_INCL_PATH }}"
notify: docker compose restart notify: docker compose restart
- name: Flush handlers so Nextcloud container is restarted and ready - name: Flush handlers so Nextcloud container is restarted and ready
@@ -19,11 +19,11 @@
- name: Copy include instructions to the container - name: Copy include instructions to the container
command: > command: >
docker cp {{ nextcloud_host_include_instructions_file }} {{ NEXTCLOUD_CONTAINER }}:{{ nextcloud_docker_include_instructions_file }} docker cp {{ NEXTCLOUD_HOST_INCL_PATH }} {{ NEXTCLOUD_CONTAINER }}:{{ NEXTCLOUD_DOCKER_INCL_PATH }}
- name: Append generated config to config.php only if not present - name: Append generated config to config.php only if not present
command: > command: >
docker exec -u {{ NEXTCLOUD_DOCKER_USER }} {{ NEXTCLOUD_CONTAINER }} sh -c " docker exec -u {{ NEXTCLOUD_DOCKER_USER }} {{ NEXTCLOUD_CONTAINER }} sh -c "
grep -q '{{ nextcloud_docker_config_additives_directory }}' {{ nextcloud_docker_config_file }} || grep -q '{{ NEXTCLOUD_DOCKER_CONF_ADD_PATH }}' {{ NEXTCLOUD_DOCKER_CONFIG_FILE }} ||
cat {{ nextcloud_docker_include_instructions_file }} >> {{ nextcloud_docker_config_file }}" cat {{ NEXTCLOUD_DOCKER_INCL_PATH }} >> {{ NEXTCLOUD_DOCKER_CONFIG_FILE }}"
notify: docker compose restart notify: docker compose restart

View File

@@ -1,7 +1,7 @@
- name: Ensure Nextcloud administrator is in the 'admin' group - name: Ensure Nextcloud administrator is in the 'admin' group
command: > command: >
docker exec -u {{ NEXTCLOUD_DOCKER_USER }} {{ NEXTCLOUD_CONTAINER }} docker exec -u {{ NEXTCLOUD_DOCKER_USER }} {{ NEXTCLOUD_CONTAINER }}
php occ group:adduser admin {{ nextcloud_administrator_username }} php occ group:adduser admin {{ NEXTCLOUD_ADMINISTRATOR_USERNAME }}
register: add_admin_to_group register: add_admin_to_group
changed_when: "not ASYNC_ENABLED and 'Added user' in (add_admin_to_group.stdout | default(''))" changed_when: "not ASYNC_ENABLED and 'Added user' in (add_admin_to_group.stdout | default(''))"
failed_when: > failed_when: >

View File

@@ -1,5 +1,5 @@
- block: - block:
- include_tasks: 06_plugin_routines.yml - include_tasks: _plugin_a_routines.yml
when: plugin_value.enabled | bool when: plugin_value.enabled | bool
- name: disable {{ plugin_key }} nextcloud plugin - name: disable {{ plugin_key }} nextcloud plugin

View File

@@ -35,9 +35,12 @@
and and
("already installed" not in install_result.stdout) ("already installed" not in install_result.stdout)
- include_tasks: 07_plugin_enable_and_configure.yml - include_tasks: _plugin_b_enable_and_configure.yml
when: when:
- install_result is defined - install_result is defined
- > - >
install_result.rc == 0 install_result.rc == 0
or "already installed" in install_result.stdout or "already installed" in install_result.stdout
vars:
plugin_task_path: "{{ NEXTCLOUD_CNODE_PLUGIN_TASKS_PATH }}{{ plugin_key }}.yml"
plugin_vars_path: "{{ NEXTCLOUD_CNODE_PLUGIN_VARS_PATH }}{{ plugin_key }}.yml"

View File

@@ -3,16 +3,16 @@
register: enable_result register: enable_result
changed_when: enable_result.rc == 0 and ("already enabled" not in enable_result.stdout) changed_when: enable_result.rc == 0 and ("already enabled" not in enable_result.stdout)
- name: Check if {{ nextcloud_control_node_plugin_vars_directory }}{{ plugin_key }}.yml exists - name: Check if {{ plugin_vars_path }} exists
stat: stat:
path: "{{ nextcloud_control_node_plugin_vars_directory }}{{ plugin_key }}.yml" path: "{{ plugin_vars_path }}"
delegate_to: localhost delegate_to: localhost
become: false become: false
register: plugin_vars_file register: plugin_vars_file
- name: "Load {{ plugin_key }} configuration variables" - name: "Load {{ plugin_key }} configuration variables"
include_vars: include_vars:
file: "{{ nextcloud_control_node_plugin_vars_directory }}{{ plugin_key }}.yml" file: "{{ plugin_vars_path }}"
when: plugin_vars_file.stat.exists when: plugin_vars_file.stat.exists
- name: "Set plugin configuration (batched shell, no async)" - name: "Set plugin configuration (batched shell, no async)"
@@ -34,14 +34,15 @@
failed_when: not ASYNC_ENABLED and config_set_shell.rc != 0 failed_when: not ASYNC_ENABLED and config_set_shell.rc != 0
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}" async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}" poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | default(true) | bool }}"
- name: Check if {{ nextcloud_control_node_plugin_tasks_directory }}{{ plugin_key }}.yml exists - name: Check if {{ plugin_task_path }} exists
stat: stat:
path: "{{ nextcloud_control_node_plugin_tasks_directory }}{{ plugin_key }}.yml" path: "{{ plugin_task_path }}"
delegate_to: localhost delegate_to: localhost
become: false become: false
register: plugin_tasks_file register: plugin_tasks_file
- name: "include {{ nextcloud_control_node_plugin_tasks_directory }}{{ plugin_key }}.yml" - name: "include {{ plugin_task_path }}"
include_tasks: "{{ nextcloud_control_node_plugin_tasks_directory }}{{ plugin_key }}.yml" include_tasks: "{{ plugin_task_path }}"
when: plugin_tasks_file.stat.exists when: plugin_tasks_file.stat.exists

View File

@@ -1,76 +1,39 @@
--- ---
- name: "Install Collabora Dependency" - name: "load docker, db and proxy for {{ application_id }}"
include_role: include_role:
name: web-svc-collabora name: sys-stk-full-stateful
vars: vars:
flush_handlers: true
when:
- run_once_web_svc_collabora is not defined
- NEXTCLOUD_COLLABORA_ENABLED | bool
- name: Setup the full docker stack
- name: "include role for {{ application_id }} to receive certs & do modification routines" include_tasks: 01_fullstack.yml
include_role:
name: srv-composer
- name: create nextcloud proxy configuration file
template:
src: "nginx/host.conf.j2"
dest: "{{ nextcloud_host_nginx_path }}"
notify: restart openresty
- name: "load docker and db for {{ application_id }}"
include_role:
name: sys-stk-back-stateful
vars: vars:
docker_compose_flush_handlers: false domain: "{{ NEXTCLOUD_DOMAIN }}"
http_port: "{{ NEXTCLOUD_PORT }}"
- name: "create {{ nextcloud_host_config_additives_directory }}"
file:
path: "{{ nextcloud_host_config_additives_directory }}"
state: directory
mode: "0755"
- name: "Create config files at {{ nextcloud_host_config_additives_directory }}"
template:
src: "{{ item }}"
dest: "{{ nextcloud_host_config_additives_directory }}/{{ item | basename | regex_replace('\\.j2$', '') }}"
owner: "{{ NEXTCLOUD_DOCKER_USER_id }}"
group: "{{ NEXTCLOUD_DOCKER_USER_id }}"
loop: "{{ lookup('fileglob', role_path ~ '/templates/config/*.j2', wantlist=True) }}"
# Not all type of changes take instantly place. Due to this reason a rebuild is required.
notify: docker compose up
- name: create internal nextcloud nginx configuration
template:
src: "nginx/docker.conf.j2"
dest: "{{ docker_compose.directories.volumes }}nginx.conf"
notify: restart nextcloud nginx service
- name: Setup config.php - name: Setup config.php
include_tasks: 01_config.yml include_tasks: 02_config.yml
- name: Flush all handlers immediately so that occ can be used - name: Flush all handlers immediately so that occ can be used
meta: flush_handlers meta: flush_handlers
- name: Update\Upgrade Nextcloud - name: Update\Upgrade Nextcloud
include_tasks: 02_upgrade.yml include_tasks: 03_upgrade.yml
when: MODE_UPDATE | bool when: MODE_UPDATE | bool
- name: Load system configuration steps - name: Load system configuration steps
include_tasks: "{{ item }}" include_tasks: "{{ item }}"
loop: loop:
- 03_admin.yml - 04_admin.yml
- 04_system_config.yml - 05_system_config.yml
- name: Setup Nextcloud Plugins - name: Setup Nextcloud Plugins
include_tasks: 05_plugin.yml include_tasks: 06_setup_plugin.yml
loop: "{{ applications | get_app_conf(application_id, 'plugins', True) | dict2items }}" loop: "{{ NEXTCLOUD_PLUGIN_ITEMS }}"
loop_control: loop_control:
loop_var: plugin_item loop_var: plugin_item
vars: vars:
plugin_key: "{{ plugin_item.key }}" plugin_key: "{{ plugin_item.key }}"
plugin_value: "{{ plugin_item.value }}" plugin_value: "{{ plugin_item.value }}"
when: nextcloud_plugins_enabled when: NEXTCLOUD_PLUGINS_ENABLED

View File

@@ -0,0 +1,7 @@
- name: "Install Collabora Dependency"
include_role:
name: web-svc-collabora
vars:
flush_handlers: true
when:
- run_once_web_svc_collabora is not defined

View File

@@ -1,7 +1,7 @@
<?php <?php
# Implementing OICD configuration # Implementing OICD configuration
{% if applications | get_app_conf(application_id, 'oidc.flavor', True) == "oidc_login" %} {% if applications | get_app_conf(application_id, 'oidc.flavor') == "oidc_login" %}
# Check out: https://github.com/pulsejet/nextcloud-oidc-login # Check out: https://github.com/pulsejet/nextcloud-oidc-login
@@ -21,7 +21,7 @@ return array (
'oidc_login_auto_redirect' => true, 'oidc_login_auto_redirect' => true,
// Redirect to this page after logging out the user // Redirect to this page after logging out the user
'oidc_login_logout_url' => 'https://{{ domains | get_domain(application_id) }}', 'oidc_login_logout_url' => '{{ NEXTCLOUD_URL }}',
// If set to true the user will be redirected to the // If set to true the user will be redirected to the
// logout endpoint of the OIDC provider after logout // logout endpoint of the OIDC provider after logout
@@ -33,7 +33,7 @@ return array (
// //
// NOTE: If you want to allow NextCloud to manage quotas, omit this option. Do not set it to // NOTE: If you want to allow NextCloud to manage quotas, omit this option. Do not set it to
// zero or -1 or ''. // zero or -1 or ''.
'oidc_login_default_quota' => '{{applications | get_app_conf(application_id, 'default_quota', True)}}', 'oidc_login_default_quota' => '{{ applications | get_app_conf(application_id, 'default_quota', True)}}',
// Login button text // Login button text
'oidc_login_button_text' => '{{ OIDC.BUTTON_TEXT }}', 'oidc_login_button_text' => '{{ OIDC.BUTTON_TEXT }}',
@@ -97,7 +97,7 @@ return array (
// note: on Keycloak, OIDC name claim = "${given_name} ${family_name}" or one of them if any is missing // note: on Keycloak, OIDC name claim = "${given_name} ${family_name}" or one of them if any is missing
// //
'oidc_login_attributes' => array ( 'oidc_login_attributes' => array (
'id' => '{{LDAP.USER.ATTRIBUTES.ID}}', 'id' => '{{ LDAP.USER.ATTRIBUTES.ID }}',
'name' => 'name', 'name' => 'name',
'mail' => 'email', 'mail' => 'email',
'quota' => '{{ LDAP.USER.ATTRIBUTES.NEXTCLOUD_QUOTA }}', 'quota' => '{{ LDAP.USER.ATTRIBUTES.NEXTCLOUD_QUOTA }}',

View File

@@ -1,40 +1,8 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %} {% include 'roles/docker-compose/templates/base.yml.j2' %}
application:
image: "{{ nextcloud_image }}:{{ nextcloud_version }}"
container_name: {{ NEXTCLOUD_CONTAINER }}
volumes:
- data:{{ NEXTCLOUD_DOCKER_WORK_DIRECTORY }}
- {{ nextcloud_host_config_additives_directory }}:{{ nextcloud_docker_config_additives_directory }}:ro
healthcheck:
test: ["CMD", "su", "www-data", "-s", "/bin/sh", "-c", "php {{ NEXTCLOUD_DOCKER_WORK_DIRECTORY }}occ status"]
interval: 1m
timeout: 10s
retries: 3
{% include 'roles/docker-container/templates/base.yml.j2' %}
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
{% include 'roles/docker-container/templates/networks.yml.j2' %}
ipv4_address: 192.168.102.69
{% if nextcloud_talk_enabled %}
talk:
{% include 'roles/docker-container/templates/base.yml.j2' %}
image: "{{ nextcloud_talk_image }}:{{ nextcloud_talk_version }}"
container_name: {{ nextcloud_talk_name }}
hostname: hpb_yt
init: true
ports:
- {{ networks.internet.ip4 }}:{{ nextcloud_talk_stun_port }}:3478/tcp #TURN TCP
- {{ networks.internet.ip4 }}:{{ nextcloud_talk_stun_port }}:3478/udp #TURN UDP
- {{ networks.internet.ip4 }}:8181:8081/tcp #Signaling @todo needs to be optimized
networks:
default:
ipv4_address: 192.168.102.68
{% endif %}
proxy: proxy:
image: "{{ nextcloud_proxy_image }}:{{ nextcloud_proxy_version }}" image: "{{ NEXTCLOUD_PROXY_IMAGE }}:{{ NEXTCLOUD_PROXY_VERSION }}"
container_name: "{{ nextcloud_proxy_name }}" container_name: "{{ NEXTCLOUD_PROXY_CONTAINER }}"
logging: logging:
driver: journald driver: journald
restart: {{ DOCKER_RESTART_POLICY }} restart: {{ DOCKER_RESTART_POLICY }}
@@ -50,9 +18,57 @@
default: default:
ipv4_address: 192.168.102.67 ipv4_address: 192.168.102.67
application:
image: "{{ NEXTCLOUD_IMAGE }}:{{ NEXTCLOUD_VERSION }}"
container_name: {{ NEXTCLOUD_CONTAINER }}
volumes:
- data:{{ NEXTCLOUD_DOCKER_WORK_DIRECTORY }}
- {{ NEXTCLOUD_HOST_CONF_ADD_PATH }}:{{ NEXTCLOUD_DOCKER_CONF_ADD_PATH }}:ro
healthcheck:
test: ["CMD", "su", "www-data", "-s", "/bin/sh", "-c", "php {{ NEXTCLOUD_DOCKER_WORK_DIRECTORY }}occ status"]
interval: 1m
timeout: 10s
retries: 3
{% include 'roles/docker-container/templates/base.yml.j2' %}
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
{% include 'roles/docker-container/templates/networks.yml.j2' %}
ipv4_address: 192.168.102.69
{% if NEXTCLOUD_TALK_ENABLED %}
talk:
{% set container_port = NEXTCLOUD_TALK_INTERNAL_PORT %}
{% include 'roles/docker-container/templates/base.yml.j2' %}
{% include 'roles/docker-container/templates/healthcheck/tcp.yml.j2' %}
image: "{{ NEXTCLOUD_TALK_IMAGE }}:{{ NEXTCLOUD_TALK_VERSION }}"
container_name: {{ NEXTCLOUD_TALK_CONTAINER }}
init: true
ports:
- {{ networks.internet.ip4 }}:{{ NEXTCLOUD_TALK_STUN_PORT }}:{{ NEXTCLOUD_TALK_INT_TURN_PORT }}/tcp #TURN TCP
- {{ networks.internet.ip4 }}:{{ NEXTCLOUD_TALK_STUN_PORT }}:{{ NEXTCLOUD_TALK_INT_TURN_PORT }}/udp #TURN UDP
expose:
- "{{ container_port }}"
networks:
default:
ipv4_address: 192.168.102.68
{% endif %}
{% if NEXTCLOUD_WHITEBOARD_ENABLED %}
whiteboard:
{% set container_port = NEXTCLOUD_WHITEBOARD_INTERNAL_PORT %}
{% include 'roles/docker-container/templates/base.yml.j2' %}
{% include 'roles/docker-container/templates/healthcheck/nc.yml.j2' %}
image: "{{ NEXTCLOUD_WHITEBOARD_IMAGE }}:{{ NEXTCLOUD_WHITEBOARD_VERSION }}"
container_name: {{ NEXTCLOUD_WHITEBOARD_CONTAINER }}
expose:
- "{{ container_port }}"
networks:
default:
ipv4_address: 192.168.102.71
{% endif %}
cron: cron:
container_name: "{{ nextcloud_cron_name }}" container_name: "{{ NEXTCLOUD_CRON_CONTAINER }}"
image: "{{ nextcloud_image }}:{{ nextcloud_version }}" image: "{{ NEXTCLOUD_IMAGE }}:{{ NEXTCLOUD_VERSION }}"
restart: {{ DOCKER_RESTART_POLICY }} restart: {{ DOCKER_RESTART_POLICY }}
logging: logging:
driver: journald driver: journald
@@ -70,6 +86,6 @@
{% include 'roles/docker-compose/templates/volumes.yml.j2' %} {% include 'roles/docker-compose/templates/volumes.yml.j2' %}
data: data:
name: {{ nextcloud_volume }} name: {{ NEXTCLOUD_VOLUME }}
{% include 'roles/docker-compose/templates/networks.yml.j2' %} {% include 'roles/docker-compose/templates/networks.yml.j2' %}

View File

@@ -8,9 +8,9 @@ MYSQL_PASSWORD= "{{ database_password }}"
MYSQL_HOST= "{{ database_host }}:{{ database_port }}" MYSQL_HOST= "{{ database_host }}:{{ database_port }}"
# PHP # PHP
PHP_MEMORY_LIMIT= "{{applications | get_app_conf(application_id, 'performance.php.memory_limit')}}" PHP_MEMORY_LIMIT= "{{ applications | get_app_conf(application_id, 'performance.php.memory_limit') }}"
PHP_UPLOAD_LIMIT= "{{applications | get_app_conf(application_id, 'performance.php.upload_limit')}}" PHP_UPLOAD_LIMIT= "{{ applications | get_app_conf(application_id, 'performance.php.upload_limit') }}"
PHP_OPCACHE_MEMORY_CONSUMPTION= "{{applications | get_app_conf(application_id, 'performance.php.opcache_memory_consumption')}}" PHP_OPCACHE_MEMORY_CONSUMPTION= "{{ applications | get_app_conf(application_id, 'performance.php.opcache_memory_consumption') }}"
# Email Configuration # Email Configuration
SMTP_HOST= {{ SYSTEM_EMAIL.HOST }} SMTP_HOST= {{ SYSTEM_EMAIL.HOST }}
@@ -24,30 +24,37 @@ MAIL_FROM_ADDRESS= "{{ users['no-reply'].username }}"
MAIL_DOMAIN= "{{ SYSTEM_EMAIL.DOMAIN }}" MAIL_DOMAIN= "{{ SYSTEM_EMAIL.DOMAIN }}"
# Initial Admin Data # Initial Admin Data
NEXTCLOUD_ADMIN_USER= "{{applications | get_app_conf(application_id, 'users.administrator.username')}}" NEXTCLOUD_ADMIN_USER= "{{ NEXTCLOUD_ADMINISTRATOR_USER }}"
NEXTCLOUD_ADMIN_PASSWORD= "{{applications | get_app_conf(application_id, 'credentials.administrator_password')}}" NEXTCLOUD_ADMIN_PASSWORD= "{{ NEXTCLOUD_ADMINISTRATOR_PASSWORD }}"
# Security # Security
NEXTCLOUD_TRUSTED_DOMAINS= "{{ domains[application_id] | select | join(',') }}" NEXTCLOUD_TRUSTED_DOMAINS= "{{ NEXTCLOUD_DOMAIN }}"
# Whitelist local docker gateway in Nextcloud to prevent brute-force throtteling # Whitelist local docker gateway in Nextcloud to prevent brute-force throtteling
TRUSTED_PROXIES= "{{ networks.internet.values() | select | join(',') }}" TRUSTED_PROXIES= "{{ networks.internet.values() | select | join(',') }}"
OVERWRITECLIURL= "{{ domains | get_url(application_id, WEB_PROTOCOL) }}" OVERWRITECLIURL= "{{ NEXTCLOUD_URL }}"
OVERWRITEPROTOCOL= "https" OVERWRITEPROTOCOL= "{{ WEB_PROTOCOL }}"
# Redis Configuration # Redis Configuration
REDIS_HOST= redis REDIS_HOST= redis
REDIS_PORT= 6379 REDIS_PORT= 6379
{% if nextcloud_talk_enabled %} {% if NEXTCLOUD_TALK_ENABLED %}
# Talk Configuration # Talk Configuration
# This code was just moved here during refactoring and isn't tested yet.
# @todo move it to an own env file for encapsulation reasons # @todo move it to an own env file for encapsulation reasons
NC_DOMAIN=cloud.yourdomain.tld NC_DOMAIN={{ NEXTCLOUD_DOMAIN }}
TALK_HOST=signaling.yourdomain.tld TALK_HOST={{ NEXTCLOUD_TALK_DOMAIN }}
TURN_SECRET=${TURN_SECRET} TURN_SECRET={{ applications | get_app_conf(application_id, 'credentials.talk_turn_secret') }}
SIGNALING_SECRET=${SIGNALING_SECRET} SIGNALING_SECRET={{ applications | get_app_conf(application_id, 'credentials.talk_signaling_secret') }}
TZ=Europe/Berlin INTERNAL_SECRET={{ applications | get_app_conf(application_id, 'credentials.talk_internal_secret') }}
TZ={{ HOST_TIMEZONE }}
TALK_PORT=3478 TALK_PORT=3478
INTERNAL_SECRET=${INTERNAL_SECRET} {% endif %}
{% if NEXTCLOUD_WHITEBOARD_ENABLED %}
# @todo move it to an own env file for encapsuling reasons
NEXTCLOUD_URL= "{{ NEXTCLOUD_URL }}"
JWT_SECRET_KEY= "{{ NEXTCLOUD_WHITEBOARD_JWT }}"
STORAGE_STRATEGY=redis
REDIS_URL=redis://redis:6379/0
{% endif %} {% endif %}

View File

@@ -3,7 +3,7 @@
$CONFIG_EXTRA = []; $CONFIG_EXTRA = [];
foreach (glob("{% endraw %}{{ nextcloud_docker_config_additives_directory }}{% raw %}*.php") as $file) { foreach (glob("{% endraw %}{{ NEXTCLOUD_DOCKER_CONF_ADD_PATH }}{% raw %}*.php") as $file) {
$CONFIG_EXTRA = array_merge($CONFIG_EXTRA, include $file); $CONFIG_EXTRA = array_merge($CONFIG_EXTRA, include $file);
} }

View File

@@ -179,5 +179,24 @@ http {
location / { location / {
try_files $uri $uri/ /index.php$request_uri; try_files $uri $uri/ /index.php$request_uri;
} }
location {{ NEXTCLOUD_WHITEBOARD_LOCATION }} {
proxy_pass http://whiteboard:{{ NEXTCLOUD_WHITEBOARD_INTERNAL_PORT }}/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600;
}
location {{ NEXTCLOUD_TALK_LOCATION }} {
proxy_pass http://talk:{{ NEXTCLOUD_TALK_INTERNAL_PORT }}/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600;
}
} }
} }

View File

@@ -2,7 +2,7 @@ server
{ {
server_name {{ domain }}; server_name {{ domain }};
{% include 'roles/srv-letsencrypt/templates/ssl_header.j2' %} {% include 'roles/sys-svc-letsencrypt/templates/ssl_header.j2' %}
{% include 'roles/sys-front-inj-all/templates/server.conf.j2'%} {% include 'roles/sys-front-inj-all/templates/server.conf.j2'%}
@@ -17,7 +17,7 @@ server
client_body_buffer_size 400M; client_body_buffer_size 400M;
fastcgi_buffers 64 4K; fastcgi_buffers 64 4K;
{% include 'roles/srv-proxy-core/templates/location/html.conf.j2' %} {% include 'roles/sys-svc-proxy/templates/location/html.conf.j2' %}
location ^~ /.well-known { location ^~ /.well-known {
rewrite ^/\.well-known/host-meta\.json /public.php?service=host-meta-json last; rewrite ^/\.well-known/host-meta\.json /public.php?service=host-meta-json last;

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