mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-05-09 23:05:43 +02:00
Solved certreap bugs, implemented caching for pictures, optimized CSP policies (stricter), optimized recaptcha implementation for keycloak, solved mariadb wait bug, solved nextcloud plugin bugs, optimized ignore handling of tasks
This commit is contained in:
parent
f71c9e4b31
commit
d5f194b2c0
@ -14,5 +14,6 @@ nginx:
|
|||||||
html: "/var/www/public_html/" # Path where the static homepage files are stored
|
html: "/var/www/public_html/" # Path where the static homepage files are stored
|
||||||
files: "/var/www/public_files/" # Path where the web accessable files are stored
|
files: "/var/www/public_files/" # Path where the web accessable files are stored
|
||||||
global: "/var/www/global/" # Directory containing files which will be globaly accessable
|
global: "/var/www/global/" # Directory containing files which will be globaly accessable
|
||||||
|
cache: "/tmp/nginx_cache/" # Directory which nginx uses to cache data
|
||||||
user: "http" # Default nginx user in ArchLinux
|
user: "http" # Default nginx user in ArchLinux
|
||||||
iframe: true # Allows applications to be loaded in iframe
|
iframe: true # Allows applications to be loaded in iframe
|
@ -24,5 +24,4 @@ galaxy_info:
|
|||||||
documentation: "https://github.com/kevinveenbirkenbach/certreap#readme"
|
documentation: "https://github.com/kevinveenbirkenbach/certreap#readme"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- systemd-timer
|
|
||||||
- systemd-notifier
|
- systemd-notifier
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
include_role:
|
include_role:
|
||||||
name: pkgmgr-install
|
name: pkgmgr-install
|
||||||
vars:
|
vars:
|
||||||
package_name: cleanup-certs
|
package_name: certreap
|
||||||
when: run_once_cleanup_certs is not defined
|
when: run_once_cleanup_certs is not defined
|
||||||
|
|
||||||
- name: configure cleanup-certs.cymais.service
|
- name: configure cleanup-certs.cymais.service
|
||||||
|
@ -4,4 +4,4 @@ OnFailure=systemd-notifier.cymais@%n.service
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
ExecStartPre=/bin/sh -c '/usr/bin/python certreap --force'
|
ExecStart=/bin/sh -c 'certreap --force'
|
@ -1,4 +1,4 @@
|
|||||||
# nginx-domains-cleanup
|
# cleanup-domains
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
@ -2666,6 +2666,17 @@
|
|||||||
"autheticatorFlow": false,
|
"autheticatorFlow": false,
|
||||||
"userSetupAllowed": false
|
"userSetupAllowed": false
|
||||||
},
|
},
|
||||||
|
{%- if applications | is_feature_enabled('recaptcha', application_id) %}
|
||||||
|
{
|
||||||
|
"authenticatorConfig": "Google reCaptcha",
|
||||||
|
"authenticator": "registration-recaptcha-action",
|
||||||
|
"authenticatorFlow": false,
|
||||||
|
"requirement": "REQUIRED",
|
||||||
|
"priority": 60,
|
||||||
|
"autheticatorFlow": false,
|
||||||
|
"userSetupAllowed": false
|
||||||
|
},
|
||||||
|
{%- else %}
|
||||||
{
|
{
|
||||||
"authenticator": "registration-recaptcha-action",
|
"authenticator": "registration-recaptcha-action",
|
||||||
"authenticatorFlow": false,
|
"authenticatorFlow": false,
|
||||||
@ -2674,6 +2685,7 @@
|
|||||||
"autheticatorFlow": false,
|
"autheticatorFlow": false,
|
||||||
"userSetupAllowed": false
|
"userSetupAllowed": false
|
||||||
},
|
},
|
||||||
|
{%- endif %}
|
||||||
{
|
{
|
||||||
"authenticator": "registration-terms-and-conditions",
|
"authenticator": "registration-terms-and-conditions",
|
||||||
"authenticatorFlow": false,
|
"authenticatorFlow": false,
|
||||||
@ -2746,6 +2758,19 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"authenticatorConfig": [
|
"authenticatorConfig": [
|
||||||
|
{%- if applications | is_feature_enabled('recaptcha',application_id) %}
|
||||||
|
{
|
||||||
|
"id": "c6dcf381-7e39-4f7f-8d1f-631faec31b56",
|
||||||
|
"alias": "Google reCaptcha",
|
||||||
|
"config": {
|
||||||
|
"action": "register",
|
||||||
|
"useRecaptchaNet": "false",
|
||||||
|
"recaptcha.v3": "true",
|
||||||
|
"secret.key": "{{ applications[application_id].credentials.recaptcha.secret_key }}",
|
||||||
|
"site.key": "{{ applications[application_id].credentials.recaptcha.website_key }}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{%- endif %}
|
||||||
{
|
{
|
||||||
"id": "3e40f95e-d9a7-405d-b393-398bfc54c2e8",
|
"id": "3e40f95e-d9a7-405d-b393-398bfc54c2e8",
|
||||||
"alias": "create unique user config",
|
"alias": "create unique user config",
|
||||||
|
@ -36,10 +36,11 @@
|
|||||||
state: present
|
state: present
|
||||||
when: run_once_docker_mariadb is not defined
|
when: run_once_docker_mariadb is not defined
|
||||||
|
|
||||||
- name: Wait for MariaDB inside the container to respond
|
- name: Wait until the MariaDB container is healthy
|
||||||
shell: docker exec central-mariadb mysqladmin ping -h localhost --silent
|
community.docker.docker_container_info:
|
||||||
register: mysql_ping
|
name: central-mariadb
|
||||||
until: mysql_ping.rc == 0
|
register: db_info
|
||||||
|
until: db_info.containers[0].State.Health.Status == "healthy"
|
||||||
retries: 30
|
retries: 30
|
||||||
delay: 5
|
delay: 5
|
||||||
when:
|
when:
|
||||||
|
@ -16,46 +16,59 @@
|
|||||||
when: not (plugin_value.enabled | bool)
|
when: not (plugin_value.enabled | bool)
|
||||||
|
|
||||||
- name: install {{ plugin_key }} nextcloud plugin
|
- name: install {{ plugin_key }} nextcloud plugin
|
||||||
command: "{{nextcloud_docker_exec_occ}} app:install {{ plugin_key }}"
|
command: "{{ nextcloud_docker_exec_occ }} app:install {{ plugin_key }}"
|
||||||
register: install_result
|
register: install_result
|
||||||
failed_when: install_result.rc != 0 and ("already installed" not in install_result.stdout)
|
failed_when: >
|
||||||
changed_when: install_result.rc == 0 and ("already installed" not in install_result.stdout)
|
install_result.rc != 0
|
||||||
|
and
|
||||||
|
("already installed" not in install_result.stdout)
|
||||||
|
and
|
||||||
|
("not compatible with this version of the server" not in install_result.stdout)
|
||||||
|
changed_when: >
|
||||||
|
install_result.rc == 0
|
||||||
|
and
|
||||||
|
("already installed" not in install_result.stdout)
|
||||||
when: plugin_value.enabled | bool
|
when: plugin_value.enabled | bool
|
||||||
|
|
||||||
- name: enable {{plugin_key}} nextcloud plugin
|
- block:
|
||||||
command: "{{nextcloud_docker_exec_occ}} app:enable {{plugin_key}}"
|
- name: enable {{plugin_key}} nextcloud plugin
|
||||||
register: enable_result
|
command: "{{nextcloud_docker_exec_occ}} app:enable {{plugin_key}}"
|
||||||
changed_when: enable_result.rc == 0 and ("already enabled" not in enable_result.stdout)
|
register: enable_result
|
||||||
when: plugin_value.enabled | bool
|
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 {{nextcloud_control_node_plugin_vars_directory}}{{ plugin_key }}.yml exists
|
||||||
stat:
|
stat:
|
||||||
path: "{{nextcloud_control_node_plugin_vars_directory}}{{ plugin_key }}.yml"
|
path: "{{nextcloud_control_node_plugin_vars_directory}}{{ plugin_key }}.yml"
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
become: false
|
become: false
|
||||||
register: plugin_vars_file
|
register: plugin_vars_file
|
||||||
|
|
||||||
|
- name: "Load {{ plugin_key }} configuration variables"
|
||||||
|
include_vars:
|
||||||
|
file: "{{nextcloud_control_node_plugin_vars_directory}}{{ plugin_key }}.yml"
|
||||||
|
when: plugin_vars_file.stat.exists
|
||||||
|
|
||||||
- name: "Load {{ plugin_key }} configuration variables"
|
- name: "Set {{ item.configkey }} for {{ item.appid }}"
|
||||||
include_vars:
|
loop: "{{ plugin_configuration }}"
|
||||||
file: "{{nextcloud_control_node_plugin_vars_directory}}{{ plugin_key }}.yml"
|
command: >
|
||||||
when: plugin_vars_file.stat.exists
|
{{ nextcloud_docker_exec_occ }} config:app:set {{ item.appid }} {{ item.configkey }} --value '{{ item.configvalue | to_json if item.configvalue is mapping else item.configvalue }}'
|
||||||
|
register: config_set_result
|
||||||
|
changed_when: (config_set_result.stdout is defined) and ("Config value were not updated" not in config_set_result.stdout)
|
||||||
|
when: plugin_vars_file.stat.exists
|
||||||
|
|
||||||
- name: "Set {{ item.configkey }} for {{ item.appid }}"
|
- name: Check if {{nextcloud_control_node_plugin_tasks_directory}}{{ plugin_key }}.yml exists
|
||||||
loop: "{{ plugin_configuration }}"
|
stat:
|
||||||
command: >
|
path: "{{nextcloud_control_node_plugin_tasks_directory}}{{ plugin_key }}.yml"
|
||||||
{{ nextcloud_docker_exec_occ }} config:app:set {{ item.appid }} {{ item.configkey }} --value '{{ item.configvalue | to_json if item.configvalue is mapping else item.configvalue }}'
|
delegate_to: localhost
|
||||||
register: config_set_result
|
become: false
|
||||||
changed_when: (config_set_result.stdout is defined) and ("Config value were not updated" not in config_set_result.stdout)
|
register: plugin_tasks_file
|
||||||
when: plugin_vars_file.stat.exists
|
|
||||||
|
|
||||||
- name: Check if {{nextcloud_control_node_plugin_tasks_directory}}{{ plugin_key }}.yml exists
|
- name: "include {{nextcloud_control_node_plugin_tasks_directory}}{{ plugin_key }}.yml"
|
||||||
stat:
|
include_tasks: "{{nextcloud_control_node_plugin_tasks_directory}}{{ plugin_key }}.yml"
|
||||||
path: "{{nextcloud_control_node_plugin_tasks_directory}}{{ plugin_key }}.yml"
|
when: plugin_tasks_file.stat.exists
|
||||||
delegate_to: localhost
|
when:
|
||||||
become: false
|
- plugin_value.enabled | bool
|
||||||
register: plugin_tasks_file
|
- install_result is defined
|
||||||
|
- >
|
||||||
- name: "include {{nextcloud_control_node_plugin_tasks_directory}}{{ plugin_key }}.yml"
|
install_result.rc == 0
|
||||||
include_tasks: "{{nextcloud_control_node_plugin_tasks_directory}}{{ plugin_key }}.yml"
|
or "already installed" in install_result.stdout
|
||||||
when: plugin_tasks_file.stat.exists
|
|
23
roles/nginx-docker-reverse-proxy/tasks/main.yml
Normal file
23
roles/nginx-docker-reverse-proxy/tasks/main.yml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
- name: Remove (Cleanup) NGINX cache directory contents
|
||||||
|
become: true
|
||||||
|
file:
|
||||||
|
path: "{{ nginx.directories.cache }}"
|
||||||
|
state: absent
|
||||||
|
when:
|
||||||
|
- mode_cleanup | bool
|
||||||
|
- run_once_nginx_reverse_proxy is not defined
|
||||||
|
|
||||||
|
- name: Ensure NGINX cache directory exists
|
||||||
|
become: true
|
||||||
|
file:
|
||||||
|
path: "{{ nginx.directories.cache }}"
|
||||||
|
state: directory
|
||||||
|
owner: http
|
||||||
|
group: http
|
||||||
|
mode: '0755'
|
||||||
|
when: run_once_nginx_reverse_proxy is not defined
|
||||||
|
|
||||||
|
- name: run the nginx_reverse_proxy tasks once
|
||||||
|
set_fact:
|
||||||
|
run_once_nginx_reverse_proxy: true
|
||||||
|
when: run_once_nginx_reverse_proxy is not defined
|
@ -3,6 +3,13 @@
|
|||||||
{# default-src: Fallback for all other directives if not explicitly defined #}
|
{# default-src: Fallback for all other directives if not explicitly defined #}
|
||||||
{%- set csp_parts = csp_parts + ["default-src 'self';"] %}
|
{%- set csp_parts = csp_parts + ["default-src 'self';"] %}
|
||||||
|
|
||||||
|
{# connect-src: Controls where fetch(), XHR, WebSocket etc. can connect to #}
|
||||||
|
{%- set connect_src = "connect-src 'self' https://ka-f.fontawesome.com" %}
|
||||||
|
{%- if applications | is_feature_enabled('matomo', application_id) | bool %}
|
||||||
|
{%- set connect_src = connect_src + " " + web_protocol + "://" + domains.matomo %}
|
||||||
|
{%- endif %}
|
||||||
|
{%- set csp_parts = csp_parts + [connect_src + ";"] %}
|
||||||
|
|
||||||
{# frame-ancestors: Restricts which origins can embed this site in a frame or iframe #}
|
{# frame-ancestors: Restricts which origins can embed this site in a frame or iframe #}
|
||||||
{%- set frame_ancestors = "frame-ancestors 'self'" %}
|
{%- set frame_ancestors = "frame-ancestors 'self'" %}
|
||||||
{%- if applications | is_feature_enabled('iframe', application_id) | bool %}
|
{%- if applications | is_feature_enabled('iframe', application_id) | bool %}
|
||||||
@ -13,21 +20,22 @@
|
|||||||
{# frame-src: Controls which URLs can be embedded as iframes #}
|
{# frame-src: Controls which URLs can be embedded as iframes #}
|
||||||
{%- set frame_src = "frame-src 'self'" %}
|
{%- set frame_src = "frame-src 'self'" %}
|
||||||
{%- if applications | is_feature_enabled('recaptcha', application_id) | bool %}
|
{%- if applications | is_feature_enabled('recaptcha', application_id) | bool %}
|
||||||
{%- set frame_src = frame_src + " https://www.google.com https://www.recaptcha.net" %}
|
{%- set frame_src = frame_src + " https://www.google.com" %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- set csp_parts = csp_parts + [frame_src + ";"] %}
|
{%- set csp_parts = csp_parts + [frame_src + ";"] %}
|
||||||
|
|
||||||
{# img-src: Allow images from own domain and files deliverer. Also from Matomo if enabled. #}
|
{# img-src: Allow images. Prevent tracking by caching on server and client side. #}
|
||||||
{%- set img_src = "img-src 'self' " + web_protocol + "://" + domains.file_server %}
|
{%- set img_src = "img-src * data: blob:"%}
|
||||||
{%- if applications | is_feature_enabled('matomo', application_id) | bool %}
|
|
||||||
{%- set img_src = img_src + " " + web_protocol + "://" + domains.matomo %}
|
|
||||||
{%- endif %}
|
|
||||||
{%- set csp_parts = csp_parts + [img_src + ";"] %}
|
{%- set csp_parts = csp_parts + [img_src + ";"] %}
|
||||||
|
|
||||||
{# script-src: Allow JavaScript from self, FontAwesome, jsDelivr, and Matomo if enabled #}
|
{# script-src: Allow JavaScript from self, FontAwesome, jsDelivr, and Matomo if enabled #}
|
||||||
{%- set script_src = "script-src 'self' 'unsafe-inline'" %}
|
{# unsafe eval is set for sphinx #}
|
||||||
|
{%- set script_src = "script-src 'self' 'unsafe-eval' 'unsafe-inline'" %}
|
||||||
{%- if applications | is_feature_enabled('matomo', application_id) | bool %}
|
{%- if applications | is_feature_enabled('matomo', application_id) | bool %}
|
||||||
{%- set script_src = script_src + " " + domains.matomo %}
|
{%- set script_src = script_src + " " + web_protocol + "://" + domains.matomo %}
|
||||||
|
{%- endif %}
|
||||||
|
{%- if applications | is_feature_enabled('recaptcha', application_id) | bool %}
|
||||||
|
{%- set script_src = script_src + " https://www.google.com" %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- set script_src = script_src + " https://kit.fontawesome.com https://cdn.jsdelivr.net" %}
|
{%- set script_src = script_src + " https://kit.fontawesome.com https://cdn.jsdelivr.net" %}
|
||||||
{%- set csp_parts = csp_parts + [script_src + ";"] %}
|
{%- set csp_parts = csp_parts + [script_src + ";"] %}
|
||||||
@ -36,4 +44,10 @@
|
|||||||
{%- set style_src = "style-src 'self' 'unsafe-inline' https://kit.fontawesome.com https://cdn.jsdelivr.net" %}
|
{%- set style_src = "style-src 'self' 'unsafe-inline' https://kit.fontawesome.com https://cdn.jsdelivr.net" %}
|
||||||
{%- set csp_parts = csp_parts + [style_src + ";"] %}
|
{%- set csp_parts = csp_parts + [style_src + ";"] %}
|
||||||
|
|
||||||
|
{# font-src: Allow font-src from self, FontAwesome, jsDelivr and inline styles #}
|
||||||
|
{%- set font_src = "font-src 'self' https://kit.fontawesome.com https://cdn.jsdelivr.net" %}
|
||||||
|
{%- set csp_parts = csp_parts + [font_src + ";"] %}
|
||||||
|
|
||||||
add_header Content-Security-Policy "{{ csp_parts | join(' ') }}" always;
|
add_header Content-Security-Policy "{{ csp_parts | join(' ') }}" always;
|
||||||
|
# Oppress header send by proxied application
|
||||||
|
proxy_hide_header Content-Security-Policy;
|
@ -31,3 +31,6 @@ location {{location | default("/")}}
|
|||||||
proxy_read_timeout 900s;
|
proxy_read_timeout 900s;
|
||||||
send_timeout 900s;
|
send_timeout 900s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Load caching
|
||||||
|
{% include 'roles/nginx-docker-reverse-proxy/templates/location/proxy_cache.conf.j2' %}
|
@ -0,0 +1,18 @@
|
|||||||
|
proxy_cache_path {{ nginx.directories.cache }} levels=1:2 keys_zone=imgcache:10m inactive=60m use_temp_path=off;
|
||||||
|
|
||||||
|
{%- if location is defined %}
|
||||||
|
location ~* ^{{ location }}.*\.(jpg|jpeg|png|gif|webp|ico|svg)$ {
|
||||||
|
{%- else %}
|
||||||
|
location ~* \.(jpg|jpeg|png|gif|webp|ico|svg)$ {
|
||||||
|
{%- endif %}
|
||||||
|
# Cache in browser
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, max-age=2592000, immutable";
|
||||||
|
|
||||||
|
# Cache on reverse proxy side
|
||||||
|
proxy_pass http://127.0.0.1:{{http_port}}{{location | default("/")}};
|
||||||
|
proxy_cache imgcache;
|
||||||
|
proxy_cache_valid 200 302 60m;
|
||||||
|
proxy_cache_valid 404 1m;
|
||||||
|
add_header X-Proxy-Cache $upstream_cache_status;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- nginx
|
- nginx
|
||||||
- nginx-domains-cleanup
|
- cleanup-domains
|
||||||
- letsencrypt
|
- letsencrypt
|
@ -21,9 +21,9 @@
|
|||||||
|
|
||||||
- name: "Check if yay is installed"
|
- name: "Check if yay is installed"
|
||||||
command: which yay
|
command: which yay
|
||||||
ignore_errors: yes
|
|
||||||
register: yay_installed
|
register: yay_installed
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
- name: "Update with yay"
|
- name: "Update with yay"
|
||||||
include_role:
|
include_role:
|
||||||
@ -32,9 +32,9 @@
|
|||||||
|
|
||||||
- name: "Check if pip is installed"
|
- name: "Check if pip is installed"
|
||||||
command: which pip
|
command: which pip
|
||||||
ignore_errors: yes
|
|
||||||
register: pip_installed
|
register: pip_installed
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
- name: "Update with pip"
|
- name: "Update with pip"
|
||||||
include_role:
|
include_role:
|
||||||
@ -43,7 +43,7 @@
|
|||||||
- name: "Check if pkgmgr command is available"
|
- name: "Check if pkgmgr command is available"
|
||||||
command: "which pkgmgr"
|
command: "which pkgmgr"
|
||||||
register: pkgmgr_available
|
register: pkgmgr_available
|
||||||
ignore_errors: yes
|
failed_when: false
|
||||||
|
|
||||||
- name: "Update all repositories using pkgmgr"
|
- name: "Update all repositories using pkgmgr"
|
||||||
include_role:
|
include_role:
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
{% macro render_features(options) %}
|
{% macro render_features(options) %}
|
||||||
features:
|
features:
|
||||||
{%- set feature_map = {
|
{%- set feature_map = {
|
||||||
'matomo': 'Enables Matomo tracking',
|
'matomo': 'Enables Matomo tracking',
|
||||||
'css': 'Enables custom CSS styling',
|
'css': 'Enables custom CSS styling',
|
||||||
'iframe': 'Allows embedding via iframe on landing page',
|
'iframe': 'Allows embedding via iframe on landing page',
|
||||||
'ldap': 'Enables LDAP integration and networking',
|
'ldap': 'Enables LDAP integration and networking',
|
||||||
'oidc': 'Enables OpenID Connect (OIDC) authentication',
|
'oidc': 'Enables OpenID Connect (OIDC) authentication',
|
||||||
'oauth2': 'Enables OAuth2 proxy integration',
|
'oauth2': 'Enables OAuth2 proxy integration',
|
||||||
'database': 'Enables use of central database'
|
'database': 'Enables use of central database',
|
||||||
|
'recaptcha': 'Enables recaptcha functionality'
|
||||||
} %}
|
} %}
|
||||||
{%- for key, comment in feature_map.items() %}
|
{%- for key, comment in feature_map.items() %}
|
||||||
{%- if key in options %}
|
{%- if key in options %}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user