Compare commits

...

3 Commits

Author SHA1 Message Date
0611ddda11
Changed iframe options 2025-03-20 04:31:02 +01:00
87ca1ccc11
Implemented assets server 2025-03-20 03:47:12 +01:00
836a3e0238
Big cleanup 2025-03-20 02:20:00 +01:00
41 changed files with 141 additions and 95 deletions

View File

@ -4,7 +4,7 @@ Welcome to CyMaIS (Cyber Master Infrastructure Solution), a transformative tool
At its core, CyMaIS leverages the power of Docker, Linux, and Ansible to offer a streamlined, automated solution for deploying and managing IT systems.
<img src="https://cybermaster.space/wp-content/uploads/sites/7/2023/12/logo_cymais.png" width="300" style="float: right; margin-left: 10px;">
<img src="assets/img/logo.png" width="300" style="float: right; margin-left: 10px;">
Whether you're a small startup, a growing enterprise, or an individual seeking efficient IT management, CyMaIS provides a comprehensive suite of tools that cater to a wide range of needs. From simple system setups to complex server configurations and end-user PC management, CyMaIS simplifies the entire process.

BIN
assets/img/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

View File

Before

Width:  |  Height:  |  Size: 286 KiB

After

Width:  |  Height:  |  Size: 286 KiB

View File

@ -1,35 +1,23 @@
import yaml
def get_oauth2_enabled(applications:yaml, application_id:string):
def get_oauth22_enabled(applications, application_id):
# Retrieve the application dictionary based on the ID
app = applications.get(application_id, {})
# Retrieve the value for oauth2_proxy.enabled, default is False
enabled = app.get('oauth2_proxy', {}).get('enabled', False)
return bool(enabled)
def get_oidc_enabled(applications:yaml, application_id:string):
def get_oidc_enabled(applications, application_id):
# Retrieve the application dictionary based on the ID
app = applications.get(application_id, {})
# Retrieve the value for oidc.enabled, default is False
enabled = app.get('oidc', {}).get('enabled', False)
return bool(enabled)
def get_css_enabled(applications:yaml, application_id:string):
app = applications.get(application_id)
enabled = app.get('css_enabled')
return bool(enabled)
def get_landingpage_iframe_enabled(applications:yaml, application_id:string):
def get_landingpage_iframe_enabled(applications, application_id):
app = applications.get(application_id)
enabled = app.get('landingpage_iframe_enabled')
return bool(enabled)
def get_matomo_tracking_enabled(applications:yaml, application_id:string):
app = applications.get(application_id)
enabled = app.get('matomo_tracking_enabled')
return bool(enabled)
def get_database_central_storage(applications:yaml, application_id:string):
def get_database_central_storage(applications, application_id):
"""
Retrieve the type of the database from the application dictionary.
The expected key structure is: applications[application_id]['database']['central_storage'].
@ -42,10 +30,8 @@ def get_database_central_storage(applications:yaml, application_id:string):
class FilterModule(object):
def filters(self):
return {
'get_css_enabled': get_css_enabled,
'get_oidc_enabled': get_oidc_enabled,
'get_oauth2_enabled': get_oauth2_enabled,
'get_oauth2_enabled': get_oauth22_enabled,
'get_database_central_storage': get_database_central_storage,
'get_landingpage_iframe_enabled': get_landingpage_iframe_enabled,
'get_matomo_tracking_enabled': get_matomo_tracking_enabled,
}

View File

@ -68,4 +68,6 @@ matomo_tracking_enabled_default: true # Enables\Disables Matomo track
css_enabled_default: true # Enables\Disables Global CSS on all html pages by default.
## iframe for primary domain
landingpage_iframe_enabled_default: false # Enables\Disables the possibility to be embedded via iframe by default.
# Enables\Disables the possibility to be embedded via iframe by default.
# Enable conciously on every app in which it makes sense, due to that this a potential security risk
landingpage_iframe_enabled_default: false

View File

@ -20,19 +20,24 @@ defaults_applications:
## Akaunting
akaunting:
version: "latest"
company_name: "{{primary_domain}}"
company_email: "{{users.administrator.email}}"
setup_admin_email: "{{users.administrator.email}}"
version: "latest"
company_name: "{{primary_domain}}"
company_email: "{{users.administrator.email}}"
setup_admin_email: "{{users.administrator.email}}"
database:
central_storage: True
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe
## Assets Server
assets_server:
source_directory: "{{ playbook_dir }}/assets" # Directory from which the assets will be copied
url: "https://{{domains.file_server}}/assets}}" # Public address of the assets directory
## Attendize
attendize:
version: "latest"
version: "latest"
database:
central_storage: True
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
@ -98,6 +103,12 @@ defaults_applications:
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe
## File Server
file_server:
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "true" # Landingpage should be embeded in portfolio
## Friendica
friendica:
version: "latest"
@ -122,21 +133,21 @@ defaults_applications:
## Gitea
gitea:
version: "latest" # Use latest docker image
version: "latest" # Use latest docker image
database:
central_storage: True # Activate Central Database Storage
central_storage: True # Activate Central Database Storage
configuration:
repository:
enable_push_create_user: True # Allow users to push local repositories to Gitea and have them automatically created for a user.
default_private: last # Default private when creating a new repository: last, private, public
default_push_create_private: True # Default private when creating a new repository with push-to-create.
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe
enable_push_create_user: True # Allow users to push local repositories to Gitea and have them automatically created for a user.
default_private: last # Default private when creating a new repository: last, private, public
default_push_create_private: True # Default private when creating a new repository with push-to-create.
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe
## Gitlab
gitlab:
version: "latest"
version: "latest"
database:
central_storage: True # Activate Central Database Storage
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
@ -145,11 +156,17 @@ defaults_applications:
## Joomla
joomla:
version: "latest"
version: "latest"
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe
## HTML Server
html_server:
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "true" # Landingpage should be embeded in portfolio
## Keycloak
keycloak:
version: "latest"
@ -165,7 +182,7 @@ defaults_applications:
# administrator_password: # Needs to be defined in inventory file
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe
landingpage_iframe_enabled: false # Disabled by default, because it leads to authentification problems
## LDAP
ldap:
@ -186,7 +203,6 @@ defaults_applications:
username: "{{users.administrator.username}}"
ldap:
enabled: True # Should have the same value as applications.ldap.openldap.network.local.
force_import: false # Forces the import of the LDIF files when set to true
oauth2_proxy:
enabled: true # Activate the OAuth2 Proxy for the LDAP Webinterface
application: lam # Needs to be the same as webinterface
@ -196,6 +212,7 @@ defaults_applications:
central_storage: false # LDAP doesn't use an database in the current configuration. Propably a good idea to implement one later.
# administrator_password: # CHANGE for security reasons in inventory file
# administrator_database_password: # CHANGE for security reasons in inventory file
force_import: False # Forces the import of the LDIF files
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe
@ -230,7 +247,7 @@ defaults_applications:
# initial_administrator_password: # Initial administrator password for setup
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe
landingpage_iframe_enabled: true # Default enabled because working well in iframe
## MariaDB
mariadb:
@ -298,12 +315,12 @@ defaults_applications:
## Moodle
moodle:
site_titel: "Global Learning Academy on {{primary_domain}}"
site_titel: "Global Learning Academy on {{primary_domain}}"
users:
administrator:
username: "{{users.administrator.username}}"
email: "{{users.administrator.email}}"
version: "latest"
username: "{{users.administrator.username}}"
email: "{{users.administrator.email}}"
version: "latest"
database:
central_storage: True # Activate Central Database Storage
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
@ -331,7 +348,9 @@ defaults_applications:
# @see https://apps.nextcloud.com/apps/oidc_login
# @see https://apps.nextcloud.com/apps/sociallogin
flavor: "oidc_login" # Keeping on sociallogin because the other option is not implemented yet
force_import: False # Forces the import of the LDIF files
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "true" # Enables\Disables the possibility to embed this on landing page via iframe
database:
central_storage: True # Activate Central Database Storage
credentials:
@ -540,9 +559,6 @@ defaults_applications:
whiteboard:
# Nextcloud Whiteboard: provides a collaborative drawing and brainstorming tool (https://apps.nextcloud.com/apps/whiteboard)
enabled: true
matomo_tracking_enabled: "{{matomo_tracking_enabled_default}}" # Enables\Disables Matomo Tracking
css_enabled: "{{css_enabled_default}}" # Enables\Disables Global CSS Style
landingpage_iframe_enabled: "{{landingpage_iframe_enabled_default}}" # Enables\Disables the possibility to embed this on landing page via iframe
## OAuth2 Proxy
oauth2_proxy:

View File

@ -9,12 +9,12 @@ defaults_service_provider:
city: "Cybertown"
postal_code: "00001"
country: "Nexusland"
logo: https://cloud.veen.world/s/logo_cymais_512x512/download
logo: "{{applications.assets_server.url}}/logo.png"
platform:
titel: "CyMaIS Plattform Demo"
subtitel: "Demo of the Cyber Master Infrastructur Solution Plattform"
logo: https://cloud.veen.world/s/logo_cymais_512x512/download
favicon: https://cloud.veen.world/s/veen_world_favicon/download
logo: "{{applications.assets_server.url}}/logo.png"
favicon: "{{applications.assets_server.url}}/favicon.ico"
contact:
bluesky: "{{ '@' ~ users.administrator.username ~ '.' ~ domains.bluesky_api if 'bluesky' in group_names else '' }}"
email: "contact@{{ primary_domain }}"

View File

@ -1,3 +1,4 @@
dependencies:
- nginx-serve-html-legal
- nginx-serve-legal
- nginx-serve-assets
- docker-portfolio

View File

@ -71,10 +71,11 @@ http {
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "noindex, nofollow" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Frame-Options "SAMEORIGIN" always;
{% include 'roles/nginx-docker-reverse-proxy/templates/iframe.conf.j2' %}
# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;

View File

@ -12,4 +12,10 @@ nextcloud_system_config:
value: "{{ on_calendar_nextcloud }}"
- parameter: "default_phone_region"
value: "{{ locale | upper }}"
value: "{{ locale | upper }}"
- parameter: "trusted_domains 0"
value: "{{domains[application_id]}}"
- parameter: "overwrite.cli.url"
value: "https://{{domains[application_id]}}"

View File

@ -4,6 +4,9 @@ server {
{% include 'roles/letsencrypt/templates/ssl_header.j2' %}
{% include 'roles/nginx-modifier-all/templates/global.includes.conf.j2'%}
{% include 'roles/nginx-docker-reverse-proxy/templates/iframe.conf.j2' %}
##
# Application
##

View File

@ -36,5 +36,7 @@
when: not config_file.stat.exists
- name: add docker-compose.yml
template: src=docker-compose.yml.j2 dest={{docker_compose.directories.instance}}docker-compose.yml
template:
src: docker-compose.yml.j2
dest: "{docker_compose.directories.instance}}docker-compose.yml"
notify: docker compose project setup

View File

@ -10,6 +10,9 @@ accounts:
description: Platforms where I share content.
icon:
class: fas fa-newspaper
{% if ["mastodon", "bluesky"] | any_in(group_names) %}
children:
- name: Microblogs
description: Stay updated with {{ 'our' if service_provider.type == 'legal' else 'my' }} microblogs.
@ -39,6 +42,7 @@ accounts:
- link: accounts.publishingchannels.microblogs.mastodon
identifier: "{{service_provider.contact.bluesky}}"
{% endif %}
{% endif %}
{% if service_provider.contact.pixelfed is defined and service_provider.contact.pixelfed != "" %}

View File

@ -1,4 +1,4 @@
{% if landingpage_iframe_enabled | bool %}
add_header X-Frame-Options "SAMEORIGIN" always; # Allow iframe embedding only from the same origin
add_header Content-Security-Policy "frame-ancestors {{primary_domain}};" always; # Restrict embedding to the specified primary domain
{% if landingpage_iframe_enabled | default(applications.get(application_id).get('landingpage_iframe_enabled')) | bool %}
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Content-Security-Policy "frame-ancestors 'self' {{primary_domain}};" always;
{% endif %}

View File

@ -14,7 +14,7 @@ location {{location | default("/")}}
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Accept-Encoding "";
{% include 'iframe.conf.j2' %}
{% include 'roles/nginx-docker-reverse-proxy/templates/iframe.conf.j2' %}
# WebSocket specific header
proxy_http_version 1.1;

View File

@ -11,4 +11,4 @@
- name: "include the docker-oauth2-proxy role {{domain}}"
include_role:
name: docker-oauth2-proxy
when: applications | get_oauth2_enabled(application_id)
when: final_oauth2_enabled | bool

View File

@ -1 +1,2 @@
configuration_destination: "{{nginx.directories.http.servers}}{{domain}}.conf"
configuration_destination: "{{nginx.directories.http.servers}}{{domain}}.conf"
final_oauth2_enabled: "{{applications[application_id].get('oauth2_proxy', {}).get('enabled', False)}}"

View File

@ -1,9 +1,9 @@
- name: "Activate Global CSS for {{domain}}"
include_role:
name: nginx-modifier-css
when: applications | get_css_enabled(application_id)
when: applications.get(application_id).get('css_enabled') | bool
- name: "Activate Global Matomo Tracking for {{domain}}"
include_role:
name: nginx-modifier-matomo
when: matomo_tracking_enabled | bool
when: applications.get(application_id).get('matomo_tracking_enabled') | bool

View File

@ -2,16 +2,20 @@
sub_filter_once off;
sub_filter_types text/html;
{% if matomo_tracking_enabled | bool %}
{% set css_enabled_final = applications.get(application_id).get('css_enabled') | bool %}
{% set matomo_tracking_enabled_final = applications.get(application_id).get('matomo_tracking_enabled') | bool %}
{% if matomo_tracking_enabled_final | bool %}
{# Include Global Matomo Tracking #}
{% include 'roles/nginx-modifier-matomo/templates/matomo-tracking.conf.j2' %}
{% endif %}
{% if css_enabled | bool or matomo_tracking_enabled | bool %}
sub_filter '</head>' '{% if matomo_tracking_enabled | bool %}{% include 'roles/nginx-modifier-matomo/templates/script.j2' %}{% endif %}{% if css_enabled | bool %}{% include 'roles/nginx-modifier-css/templates/link.j2' %}{% endif %}</head>';
{% if css_enabled_final | bool or matomo_tracking_enabled_final | bool %}
sub_filter '</head>' '{% if matomo_tracking_enabled_final | bool %}{% include 'roles/nginx-modifier-matomo/templates/script.j2' %}{% endif %}{% if css_enabled_final | bool %}{% include 'roles/nginx-modifier-css/templates/link.j2' %}{% endif %}</head>';
{% endif %}
{% if css_enabled | bool %}
{% if css_enabled_final | bool %}
{# Include Global CSS Location #}
{% include 'roles/nginx-modifier-css/templates/location.conf.j2' %}
{% endif %}

View File

@ -1,3 +0,0 @@
matomo_tracking_enabled: "{{ matomo_tracking_enabled | default(applications | get_matomo_tracking_enabled(application_id)) }}"
css_enabled: "{{ css_enabled | default (applications | get_css_enabled(application_id)) }}"
landingpage_iframe_enabled: "{{ landingpage_iframe_enabled | default (applications | get_landingpage_iframe_enabled(application_id)) }}"

View File

@ -0,0 +1,2 @@
# Assets Server
This role provides assets

View File

@ -0,0 +1,2 @@
dependencies:
- nginx-serve-files

View File

@ -0,0 +1,7 @@
---
- name: "Recursively copy files from local '{{ source_directory }}' to '{{ target_directory }}'"
ansible.builtin.copy:
src: "{{ source_directory }}"
dest: "{{ target_directory }}"
owner: "{{ nginx.user }}"
group: "{{ nginx.user }}"

View File

@ -0,0 +1,3 @@
application_id: "assets_server" # Application identifier
source_directory: "{{ applications[application_id].source_directory }}/" # Source directory from which the files are coming from
target_directory: "{{ nginx.directories.data.files }}assets" # Directory to which the files will be copied

View File

@ -1,6 +1,3 @@
# Nginx Homepage Role
# Nginx File Server
This Ansible role configures an Nginx server to serve files. It handles domain configuration, SSL certificate retrieval with Let's Encrypt.
## Author Information
This role was created in 2023 by [Kevin Veen Birkenbach](https://www.veen.world/).
This Ansible role configures an Nginx server to serve files.

View File

@ -5,6 +5,8 @@ server
{% include 'roles/letsencrypt/templates/ssl_header.j2' %}
{% include 'roles/nginx-modifier-all/templates/global.includes.conf.j2'%}
{% include 'roles/nginx-docker-reverse-proxy/templates/iframe.conf.j2' %}
charset utf-8;
location /

View File

@ -1,5 +0,0 @@
---
- name: copy imprint.html
template:
src: "imprint.html.j2"
dest: "{{nginx.directories.data.html}}imprint.html"

View File

@ -5,6 +5,8 @@ server
{% include 'roles/letsencrypt/templates/ssl_header.j2' %}
{% include 'roles/nginx-modifier-all/templates/global.includes.conf.j2'%}
{% include 'roles/nginx-docker-reverse-proxy/templates/iframe.conf.j2' %}
charset utf-8;
location /

View File

@ -0,0 +1,7 @@
---
- name: copy imprint.html
template:
src: "imprint.html.j2"
dest: "{{nginx.directories.data.html}}imprint.html"
owner: "{{nginx.user}}"
group: "{{nginx.user}}"

View File

@ -0,0 +1 @@
application_id: "legal" # Application identifier

1
sphinx/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
assets/img/*

View File

@ -1,20 +1,24 @@
# Minimal makefile for Sphinx documentation
# Minimal Makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment
SPHINXOPTS ?= -c .
SPHINXBUILD ?= sphinx-build
SPHINX_SOURCE_DIR ?= ../
SPHINX_BUILD_DIR ?= ../docs
SPHINXOPTS ?= -c .
SPHINXBUILD ?= sphinx-build
SPHINX_SOURCE_DIR ?= ../
SPHINX_BUILD_DIR ?= ../docs
# Put it first so that "make" without argument is like "make help".
.PHONY: help install copy-images Makefile
# Copy images before running any Sphinx command (except for help)
copy-images:
@echo "Copying images from ../images/ to ./assets/img/..."
cp -r ../assets/img/* ./assets/img/
# "help" target does not copy images
help:
@$(SPHINXBUILD) -M help "$(SPHINX_SOURCE_DIR)" "$(SPHINX_BUILD_DIR)" $(SPHINXOPTS) $(O)
.PHONY: help install Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SPHINX_SOURCE_DIR)" "$(SPHINX_BUILD_DIR)" $(SPHINXOPTS) $(O)

View File

@ -22,7 +22,7 @@ exclude_patterns = ['docs', 'venv', 'venv/**']
# -- Options for HTML output -------------------------------------------------
html_theme = 'sphinxawesome_theme'
html_static_path = ['_static']
html_static_path = ['assets']
html_sidebars = {
'**': [
@ -31,8 +31,8 @@ html_sidebars = {
]
}
cymais_logo = "_static/img/logo_cymais.png"
html_favicon = cymais_logo
cymais_logo = "assets/img/logo.png"
html_favicon = "assets/img/favicon.ico"
html_theme_options = {
"show_prev_next": False,

View File

@ -1,5 +1,5 @@
<div class="sidebar-logo" style="text-align: center; margin-bottom: 1em;">
<img src="{{ pathto("_static/img/logo_cymais.png", 1) }}" alt="Logo" style="max-width: 100%;">
<img src="{{ pathto("assets/img/logo_cymais.png", 1) }}" alt="Logo" style="max-width: 100%;">
</div>

View File

@ -61,5 +61,5 @@
{% endif %}
</div>
{% endif %}
<script src="{{ pathto('_static/js/current-nav.js', 1) }}"></script>
<script src="{{ pathto('assets/js/current-nav.js', 1) }}"></script>

View File

@ -4,7 +4,7 @@
- name: "Merge detached_files with applications.oauth2_proxy.configuration_file"
ansible.builtin.set_fact:
merged_detached_files: "{{ detached_files + [applications.oauth2_proxy.configuration_file] }}"
when: applications | get_oauth2_enabled(application_id)
when: applications[application_id].get('oauth2_proxy', {}).get('enabled', False) | bool
- name: "backup detached files"
command: >