Compare commits

...

9 Commits

23 changed files with 609 additions and 227 deletions

View File

@ -5,6 +5,13 @@ def get_oauth2_enabled(applications, application_id):
enabled = app.get('oauth2_proxy', {}).get('enabled', False)
return bool(enabled)
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, application_id):
# Retrieve the application dictionary based on the given application_id.
app = applications.get(application_id, {})
@ -16,5 +23,6 @@ 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
}

View File

@ -114,14 +114,17 @@ defaults_applications:
setup: false # Set true in inventory file to execute the setup and initializing procedures
mailu:
version: "2024.06" # Docker Image Version
setup: false # Set true in inventory file to execute the setup and initializing procedures
oidc:
enabled: true # Activate OIDC for Mailu
domain: "{{primary_domain}}" # The main domain from which mails will be send \ email suffix behind @
# I don't know why the database deactivation is necessary
enable_central_database: False # Deactivate central database for mailu
# secret_key: # Needs to be set in inventory file
# database_password: # Needs to be set in inventory file
# api_token: # Needs to be set in inventory file
credentials:
# secret_key: # Needs to be set in inventory file
# database_password: # Needs to be set in inventory file
# api_token: # Needs to be set in inventory file
## MariaDB
mariadb:
@ -143,21 +146,19 @@ defaults_applications:
single_user_mode: false # Set true for initial setup
setup: false # Set true in inventory file to execute the setup and initializing procedures
oidc:
enabled: true # Activate OIDC for Mailu
#
enabled: true # Activate OIDC for Mastodon
credentials:
# Check out the README.md of the docker-mastodon role to get detailled instructions about how to setup the credentials
#
# credentials:
# database_password:
# secret_key_base:
# otp_secret:
# vapid:
# private_key:
# public_key:
# active_record_encryption:
# deterministic_key:
# key_derivation_salt:
# primary_key:
# database_password:
# secret_key_base:
# otp_secret:
# vapid:
# private_key:
# public_key:
# active_record_encryption:
# deterministic_key:
# key_derivation_salt:
# primary_key:
## Matrix
matrix:
@ -171,12 +172,6 @@ defaults_applications:
version: "latest"
setup: false # Set true in inventory file to execute the setup and initializing procedures
## Mailu
mailu:
version: "2024.06"
domain: "{{primary_domain}}"
setup: false # Set true in inventory file to execute the setup and initializing procedures
## Moodle
moodle:
site_titel: "Global Learning Academy on {{primary_domain}}"

View File

@ -6,6 +6,8 @@ defaults_networks:
# The default docker subnetworking does lead to overlapping and to huge networks.
# Due to this reason networks with 16 ips are created.
# This should be sufficient for the most cases
# /28 Networks, 14 Usable Ip Addresses
akaunting:
subnet: 192.168.101.0/28
attendize:
@ -32,8 +34,8 @@ defaults_networks:
subnet: 192.168.101.176/28
listmonk:
subnet: 192.168.101.192/28
mariadb:
subnet: 192.168.101.208/28
# Free:
# subnet: 192.168.101.208/28
matomo:
subnet: 192.168.101.224/28
mastodon:
@ -58,8 +60,8 @@ defaults_networks:
subnet: 192.168.102.112/28
pixelfed:
subnet: 192.168.102.128/28
postgres:
subnet: 192.168.102.144/28
# Free :
# subnet: 192.168.102.144/28
snipe_it:
subnet: 192.168.102.160/28
taiga:
@ -68,7 +70,14 @@ defaults_networks:
subnet: 192.168.102.192/28
discourse:
subnet: 192.168.102.208/28
# /24 Networks / 254 Usable Clients
bigbluebutton:
subnet: 10.7.7.0/24 # This variable does not have an impact. It's just there for documentation reasons.
subnet: 10.7.7.0/24 # This variable does not have an impact. It's just there for documentation reasons, because this network is used in bbb
postgres:
subnet: 192.168.200.0/24
mariadb:
subnet: 192.168.201.0/24
central_ldap:
subnet: 192.168.202.0/24

View File

@ -16,14 +16,15 @@ defaults_service_provider:
logo: https://cloud.veen.world/s/logo_cymais_512x512/download
favicon: https://cloud.veen.world/s/veen_world_favicon/download
contact:
bluesky: "@{{administrator_username}}.{{domains.bluesky_api}}"
email: "contact@{{primary_domain}}"
mastodon: "@{{administrator_username}}@{{domains.mastodon}}"
matrix: "@{{administrator_username}}:{{domains.matrix_synapse}}"
peertube: "@{{administrator_username}}@{{domains.peertube}}"
pixelfed: "@{{administrator_username}}@{{domains.pixelfed}}"
phone: "+0 000 000 404"
wordpress: "@{{administrator_username}}@{{domains.wordpress[0]}}"
bluesky: "{{ '@' ~ administrator_username ~ '.' ~ domains.bluesky_api if 'bluesky' in group_names else '' }}"
email: "contact@{{ primary_domain }}"
mastodon: "{{ '@' ~ administrator_username ~ '@' ~ domains.mastodon if 'mastodon' in group_names else '' }}"
matrix: "{{ '@' ~ administrator_username ~ ':' ~ domains.matrix_synapse if 'matrix' in group_names else '' }}"
peertube: "{{ '@' ~ administrator_username ~ '@' ~ domains.peertube if 'peertube' in group_names else '' }}"
pixelfed: "{{ '@' ~ administrator_username ~ '@' ~ domains.pixelfed if 'pixelfed' in group_names else '' }}"
phone: "+0 000 000 404"
wordpress: "{{ '@' ~ administrator_username ~ '@' ~ domains.wordpress[0] if 'wordpress' in group_names else '' }}"
legal:
editorial_responsible: "Johannes Gutenberg"
source_code: "https://github.com/kevinveenbirkenbach/cymais"

View File

@ -18,5 +18,5 @@
- name: create central database
include_role:
name: docker-{{database_type}}
name: "docker-{{database_type}}"
when: enable_central_database | bool

View File

@ -834,21 +834,18 @@
"clientAuthenticatorType": "client-secret",
"secret": "{{oidc.client.secret}}",
"redirectUris": [
{%- set redirect_uris = [] -%}
{%- for application, domain in domains.items() -%}
{%- if applications[application_id] is defined and applications | get_oauth2_enabled(application_id) -%}
{%- if applications[application] is defined and ( applications | get_oauth2_enabled(application) or applications | get_oidc_enabled(application)) -%}
{%- if domain is string -%}
{%- set _ = redirect_uris.append("https://" ~ domain ~ "/*") -%}
"https://{{ domain }}/*"{% if not loop.last %},{% endif %}
{%- else -%}
{%- for d in domain -%}
{%- set _ = redirect_uris.append("https://" ~ domain ~ "/*") -%}
"https://{{ d }}/*"{% if not (loop.last and loop.parent.last) %},{% endif %}
{%- endfor -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{{ redirect_uris | map('tojson') | join(",\n") }}
],
"webOrigins": [
"https://*.{{primary_domain}}"
],

View File

@ -24,6 +24,8 @@
docker_network:
name: central_ldap
state: present
ipam_config:
- subnet: "{{ networks.local.central_ldap.subnet }}"
- name: "copy docker-compose.yml and env file"
include_tasks: copy-docker-compose-and-env.yml

View File

@ -12,7 +12,7 @@
LD_PRELOAD=/usr/lib/libhardened_malloc.so
# Set to a randomly generated 16 bytes string
SECRET_KEY={{applications.mailu.secret_key}}
SECRET_KEY={{applications.mailu.credentials.secret_key}}
# Subnet of the docker network. This should not conflict with any networks to which your system is connected. (Internal and external!)
SUBNET={{networks.local.mailu.subnet}}
@ -145,7 +145,7 @@ LOG_LEVEL=WARNING
SQLALCHEMY_DATABASE_URI_ROUNDCUBE=mysql://{{database_username}}:{{database_password}}@{{database_host}}/{{database_name}}?collation=utf8mb4_unicode_ci
SQLALCHEMY_DATABASE_URI=mysql+mysqlconnector://{{database_username}}:{{database_password}}@{{database_host}}/{{database_name}}?collation=utf8mb4_unicode_ci
API_TOKEN={{applications.mailu.api_token}}
API_TOKEN={{applications.mailu.credentials.api_token}}
# Activated https://mailu.io/master/configuration.html#advanced-settings
AUTH_REQUIRE_TOKENS=True

View File

@ -1,5 +1,5 @@
application_id: "mailu"
database_password: "{{applications.mailu.database_password}}"
database_password: "{{applications.mailu.credentials.database_password}}"
database_type: "mariadb"
cert_mount_directory: "{{docker_compose.directories.volumes}}certs/"
enable_wildcard_certificate: false

View File

@ -2,6 +2,8 @@
docker_network:
name: central_mariadb
state: present
ipam_config:
- subnet: "{{ networks.local.mariadb.subnet }}"
when: run_once_docker_mariadb is not defined
- name: install MariaDB

View File

@ -31,4 +31,6 @@ docker exec -it central-postgres psql -U postgres
## Notes
- The PostgreSQL server is bound to `127.0.0.1:5432` on the host machine, making it accessible only from localhost.
- Ensure that the provided passwords are secure and stored securely, preferably using Ansible Vault or another encryption method.
## Author
This role was created by [Kevin Veen-Birkenbach](https://www.veen.world).

View File

@ -2,6 +2,8 @@
docker_network:
name: central_postgres
state: present
ipam_config:
- subnet: "{{ networks.local.postgres.subnet }}"
when: run_once_docker_postgres is not defined
- name: Install PostgreSQL

View File

@ -5,7 +5,7 @@ This Ansible role sets up and manages your Docker repository. It ensures that th
## Features 🔧
- **Default Path Setup:**
Automatically sets a default `docker_repository_path` if not already defined.
Automatically sets a default `docker_repository_path`
- **Repository Management:**
Clones or updates your Docker repository from a specified Git repository.
@ -34,12 +34,6 @@ Ensure that you have set the following variables (either via your inventory, `gr
- `docker_compose.directories.services`: The base directory where your Docker services are stored.
The role will append `repository/` to this path to form `docker_repository_path`.
If `docker_repository_path` is not defined, the role will automatically set it to:
```yaml
"{{ docker_compose.directories.services }}repository/"
```
## Author
Kevin Veen-Birkenbach

View File

@ -1,7 +1,6 @@
- name: Set default docker_repository_path if not defined
- name: Set default docker_repository_path
set_fact:
docker_repository_path: "{{docker_compose.directories.services}}repository/"
when: docker_repository_path is not defined
- name: pull docker repository
git:

View File

@ -45,12 +45,38 @@ HINT:
/* Bootstrap Overrides (Color/Shadow Variables Only) */
:root {
--bs-primary: var(--color-50);
--bs-secondary: var(--color-65);
--bs-body-bg: var(--color-90);
--bs-body-color: var(--color-40);
--bs-link-color: var(--color-50);
--bs-btn-color: var(--color-40);
--bs-black: var(--color-01); /* Original tone: Black (#000) */
--bs-white: var(--color-99); /* Original tone: White (#fff) */
--bs-gray: var(--color-50); /* Original tone: Gray (#6c757d) */
--bs-gray-dark: var(--color-20); /* Original tone: Dark Gray (#343a40) */
--bs-gray-100: var(--color-95); /* Original tone: Very Light Gray (#f8f9fa) */
--bs-gray-200: var(--color-90); /* Original tone: Lighter Gray (#e9ecef) */
--bs-gray-300: var(--color-85); /* Original tone: Light Gray (#dee2e6) */
--bs-gray-400: var(--color-80); /* Original tone: Gray (#ced4da) */
--bs-gray-500: var(--color-70); /* Original tone: Medium Gray (#adb5bd) */
--bs-gray-600: var(--color-50); /* Original tone: Gray (#6c757d) */
--bs-gray-700: var(--color-40); /* Original tone: Darker Gray (#495057) */
--bs-gray-800: var(--color-20); /* Original tone: Dark Gray (#343a40) */
--bs-gray-900: var(--color-10); /* Original tone: Very Dark Gray (#212529) */
--bs-primary: var(--color-65); /* Original tone: Blue (#0d6efd) */
--bs-light: var(--color-95); /* Original tone: Light (#f8f9fa) */
--bs-dark: var(--color-10); /* Original tone: Dark (#212529) */
--bs-primary-rgb: var(--color-rgb-65); /* Original tone: Blue (13, 110, 253) */
--bs-secondary-rgb: var(--color-rgb-50); /* Original tone: Grayish (#6c757d / 108, 117, 125) */
--bs-light-rgb: var(--color-rgb-95); /* Original tone: Light (248, 249, 250) */
--bs-dark-rgb: var(--color-rgb-10); /* Original tone: Dark (33, 37, 41) */
--bs-white-rgb: var(--color-rgb-99); /* Original tone: White (255, 255, 255) */
--bs-black-rgb: var(--color-rgb-01); /* Original tone: Black (0, 0, 0) */
--bs-body-color-rgb: var(--color-rgb-10); /* Original tone: Dark (#212529 / 33, 37, 41) */
--bs-body-bg-rgb: var(--color-rgb-99); /* Original tone: White (#fff / 255, 255, 255) */
--bs-body-color: var(--color-10); /* Original tone: Dark (#212529) */
--bs-body-bg: var(--color-99); /* Original tone: White (#fff) */
--bs-border-color: var(--color-85); /* Original tone: Gray (#dee2e6) */
--bs-link-color: var(--color-65); /* Original tone: Blue (#0d6efd) */
--bs-link-hover-color: var(--color-60); /* Original tone: Darker Blue (#0a58ca) */
--bs-code-color: var(--color-55); /* Original tone: Pink (#d63384) */
--bs-highlight-bg: var(--color-93); /* Original tone: Light Yellow (#fff3cd) */
--bs-list-group-bg: var(--color-40);
}
/* Discourse */
@ -162,110 +188,6 @@ HINT:
--float-kit-arrow-fill-color: var(--secondary); /* already mapped above */
}
/* Keycloak */
:root{
/* --- Palette Black (Graustufen) --- */
--pf-v5-global--palette--black-100: var(--color-95); /* #fafafa */
--pf-v5-global--palette--black-150: var(--color-90); /* #f5f5f5 */
--pf-v5-global--palette--black-200: var(--color-85); /* #f0f0f0 */
--pf-v5-global--palette--black-300: var(--color-75); /* #d2d2d2 */
--pf-v5-global--palette--black-400: var(--color-65); /* #b8bbbe */
--pf-v5-global--palette--black-500: var(--color-50); /* #8a8d90 */
--pf-v5-global--palette--black-600: var(--color-40); /* #6a6e73 */
--pf-v5-global--palette--black-700: var(--color-30); /* #4f5255 */
--pf-v5-global--palette--black-800: var(--color-25); /* #3c3f42 */
--pf-v5-global--palette--black-850: var(--color-20); /* #212427 */
--pf-v5-global--palette--black-900: var(--color-10); /* #151515 */
--pf-v5-global--palette--black-1000: var(--color-05); /* #030303 */
/* --- White --- */
--pf-v5-global--palette--white: var(--color-99);
/* --- Background Colors --- */
--pf-v5-global--BackgroundColor--100: var(--color-99);
--pf-v5-global--BackgroundColor--150: var(--color-95);
--pf-v5-global--BackgroundColor--200: var(--color-85);
--pf-v5-global--BackgroundColor--300: var(--color-75);
--pf-v5-global--BackgroundColor--400: var(--color-65);
--pf-v5-global--BackgroundColor--light-100: var(--color-99);
--pf-v5-global--BackgroundColor--light-200: var(--color-95);
--pf-v5-global--BackgroundColor--light-300: var(--color-85);
--pf-v5-global--BackgroundColor--dark-100: var(--color-10);
--pf-v5-global--BackgroundColor--dark-200: var(--color-25);
--pf-v5-global--BackgroundColor--dark-300: var(--color-20);
--pf-v5-global--BackgroundColor--dark-400: var(--color-30);
--pf-v5-global--BackgroundColor--dark-transparent-100: var(--color-05);
--pf-v5-global--BackgroundColor--dark-transparent-200: var(--color-05);
/* --- Color Variables --- */
--pf-v5-global--Color--100: var(--color-10);
--pf-v5-global--Color--200: var(--color-40);
--pf-v5-global--Color--300: var(--color-25);
--pf-v5-global--Color--400: var(--color-50);
--pf-v5-global--Color--light-100: var(--color-99);
--pf-v5-global--Color--light-200: var(--color-85);
--pf-v5-global--Color--light-300: var(--color-75);
--pf-v5-global--Color--dark-100: var(--color-10);
--pf-v5-global--Color--dark-200: var(--color-40);
/* --- Active Colors --- */
--pf-v5-global--active-color--100: var(--color-65);
--pf-v5-global--active-color--200: var(--color-95);
--pf-v5-global--active-color--300: var(--color-75);
--pf-v5-global--active-color--400: var(--color-85);
/* --- Disabled Colors --- */
--pf-v5-global--disabled-color--100: var(--color-40);
--pf-v5-global--disabled-color--200: var(--color-75);
--pf-v5-global--disabled-color--300: var(--color-85);
/* --- Primary Colors --- */
--pf-v5-global--primary-color--100: var(--color-65);
--pf-v5-global--primary-color--200: var(--color-40);
--pf-v5-global--primary-color--light-100: var(--color-75);
--pf-v5-global--primary-color--dark-100: var(--color-65);
/* --- Secondary Colors --- */
--pf-v5-global--secondary-color--100: var(--color-40);
/* --- Custom Colors --- */
--pf-v5-global--custom-color--100: var(--color-65);
--pf-v5-global--custom-color--200: var(--color-65);
--pf-v5-global--custom-color--300: var(--color-30);
/* --- Link Colors --- */
--pf-v5-global--link--Color: var(--color-65);
--pf-v5-global--link--Color--hover: var(--color-40);
--pf-v5-global--link--Color--light: var(--color-75);
--pf-v5-global--link--Color--light--hover: var(--color-85);
--pf-v5-global--link--Color--dark: var(--color-65);
--pf-v5-global--link--Color--dark--hover: var(--color-40);
--pf-v5-global--link--Color--visited: var(--color-40);
/* --- Border Colors --- */
--pf-v5-global--BorderColor--100: var(--color-75);
--pf-v5-global--BorderColor--200: var(--color-50);
--pf-v5-global--BorderColor--300: var(--color-85);
--pf-v5-global--BorderColor--400: var(--color-65);
--pf-v5-global--BorderColor--dark-100: var(--color-75);
--pf-v5-global--BorderColor--light-100: var(--color-65);
/* --- Icon Colors --- */
--pf-v5-global--icon--Color--light: var(--color-40);
--pf-v5-global--icon--Color--dark: var(--color-10);
--pf-v5-global--icon--Color--light--light: var(--color-85);
--pf-v5-global--icon--Color--dark--light: var(--color-99);
--pf-v5-global--icon--Color--light--dark: var(--color-40);
--pf-v5-global--icon--Color--dark--dark: var(--color-10);
}
/* Additional Keykloak Configuration */
a.pf-v5-c-nav__link{
--pf-v5-c-nav__link--BackgroundColor: rgba(var(--color-rgb-56), 0.4);
}
/* gitea */
:root {
/* Base and derived colors are now referenced from the computed scale */
@ -417,6 +339,129 @@ a.pf-v5-c-nav__link{
--color-overlay-backdrop: var(--color-05);
}
/* Keycloak */
:root{
/* --- Palette Black (Graustufen) --- */
--pf-v5-global--palette--black-100: var(--color-95); /* #fafafa */
--pf-v5-global--palette--black-150: var(--color-90); /* #f5f5f5 */
--pf-v5-global--palette--black-200: var(--color-85); /* #f0f0f0 */
--pf-v5-global--palette--black-300: var(--color-75); /* #d2d2d2 */
--pf-v5-global--palette--black-400: var(--color-65); /* #b8bbbe */
--pf-v5-global--palette--black-500: var(--color-50); /* #8a8d90 */
--pf-v5-global--palette--black-600: var(--color-40); /* #6a6e73 */
--pf-v5-global--palette--black-700: var(--color-30); /* #4f5255 */
--pf-v5-global--palette--black-800: var(--color-25); /* #3c3f42 */
--pf-v5-global--palette--black-850: var(--color-20); /* #212427 */
--pf-v5-global--palette--black-900: var(--color-10); /* #151515 */
--pf-v5-global--palette--black-1000: var(--color-05); /* #030303 */
/* --- White --- */
--pf-v5-global--palette--white: var(--color-99);
/* --- Background Colors --- */
--pf-v5-global--BackgroundColor--100: var(--color-99);
--pf-v5-global--BackgroundColor--150: var(--color-95);
--pf-v5-global--BackgroundColor--200: var(--color-85);
--pf-v5-global--BackgroundColor--300: var(--color-75);
--pf-v5-global--BackgroundColor--400: var(--color-65);
--pf-v5-global--BackgroundColor--light-100: var(--color-99);
--pf-v5-global--BackgroundColor--light-200: var(--color-95);
--pf-v5-global--BackgroundColor--light-300: var(--color-85);
--pf-v5-global--BackgroundColor--dark-100: var(--color-10);
--pf-v5-global--BackgroundColor--dark-200: var(--color-25);
--pf-v5-global--BackgroundColor--dark-300: var(--color-20);
--pf-v5-global--BackgroundColor--dark-400: var(--color-30);
--pf-v5-global--BackgroundColor--dark-transparent-100: var(--color-05);
--pf-v5-global--BackgroundColor--dark-transparent-200: var(--color-05);
/* --- Color Variables --- */
--pf-v5-global--Color--100: var(--color-10);
--pf-v5-global--Color--200: var(--color-40);
--pf-v5-global--Color--300: var(--color-25);
--pf-v5-global--Color--400: var(--color-50);
--pf-v5-global--Color--light-100: var(--color-99);
--pf-v5-global--Color--light-200: var(--color-85);
--pf-v5-global--Color--light-300: var(--color-75);
--pf-v5-global--Color--dark-100: var(--color-10);
--pf-v5-global--Color--dark-200: var(--color-40);
/* --- Active Colors --- */
--pf-v5-global--active-color--100: var(--color-65);
--pf-v5-global--active-color--200: var(--color-95);
--pf-v5-global--active-color--300: var(--color-75);
--pf-v5-global--active-color--400: var(--color-85);
/* --- Disabled Colors --- */
--pf-v5-global--disabled-color--100: var(--color-40);
--pf-v5-global--disabled-color--200: var(--color-75);
--pf-v5-global--disabled-color--300: var(--color-85);
/* --- Primary Colors --- */
--pf-v5-global--primary-color--100: var(--color-65);
--pf-v5-global--primary-color--200: var(--color-40);
--pf-v5-global--primary-color--light-100: var(--color-75);
--pf-v5-global--primary-color--dark-100: var(--color-65);
/* --- Secondary Colors --- */
--pf-v5-global--secondary-color--100: var(--color-40);
/* --- Custom Colors --- */
--pf-v5-global--custom-color--100: var(--color-65);
--pf-v5-global--custom-color--200: var(--color-65);
--pf-v5-global--custom-color--300: var(--color-30);
/* --- Link Colors --- */
--pf-v5-global--link--Color: var(--color-65);
--pf-v5-global--link--Color--hover: var(--color-40);
--pf-v5-global--link--Color--light: var(--color-75);
--pf-v5-global--link--Color--light--hover: var(--color-85);
--pf-v5-global--link--Color--dark: var(--color-65);
--pf-v5-global--link--Color--dark--hover: var(--color-40);
--pf-v5-global--link--Color--visited: var(--color-40);
/* --- Border Colors --- */
--pf-v5-global--BorderColor--100: var(--color-75);
--pf-v5-global--BorderColor--200: var(--color-50);
--pf-v5-global--BorderColor--300: var(--color-85);
--pf-v5-global--BorderColor--400: var(--color-65);
--pf-v5-global--BorderColor--dark-100: var(--color-75);
--pf-v5-global--BorderColor--light-100: var(--color-65);
/* --- Icon Colors --- */
--pf-v5-global--icon--Color--light: var(--color-40);
--pf-v5-global--icon--Color--dark: var(--color-10);
--pf-v5-global--icon--Color--light--light: var(--color-85);
--pf-v5-global--icon--Color--dark--light: var(--color-99);
--pf-v5-global--icon--Color--light--dark: var(--color-40);
--pf-v5-global--icon--Color--dark--dark: var(--color-10);
}
/* Additional Keykloak Configuration */
a.pf-v5-c-nav__link{
--pf-v5-c-nav__link--BackgroundColor: rgba(var(--color-rgb-56), 0.4);
}
/* LAM */
:root {
--lam-background-color-default: var(--color-99); {# from #FFFFFF (very bright white) #}
--lam-input-bg-color: var(--color-98); {# from #fcfcfc (almost white) #}
--lam-text-color-default: var(--color-01); {# from #000000 (pure black) #}
--lam-border-color: var(--color-90); {# from #e8e8e8 (light grey) #}
--lam-border-color-primary: var(--color-15); {# from #01689e (dark blue) #}
--lam-border-color-secondary: var(--color-85); {# from #ffcb1d (bright yellow) #}
--lam-background-color-primary: var(--color-50); {# from #3daee9 (mid-tone blue) #}
--lam-background-color-secondary: var(--color-90); {# from #ffe233 (bright yellow) #}
--lam-text-color-primary: var(--color-99); {# from #ffffff (pure white) #}
--lam-text-color-secondary: var(--color-01); {# from #000000 (pure black) #}
--lam-text-color-ok: var(--color-10); {# from #237d0c (dark green) #}
--lam-table-background-color-bright: var(--color-98); {# from #fbfbfb (very light grey) #}
--lam-table-background-color-dark: var(--color-92); {# from #e8f3ff (light blue) #}
--lam-table-background-color-hover: var(--color-50); {# from #3daee9 (mid-tone blue) #}
--lam-table-text-color-hover: var(--color-99); {# from #ffffff (pure white) #}
--lam-table-border-color: var(--color-50); {# from #3daee9 (mid-tone blue) #}
}
/** Mastodon Overrides **/
div#mastodon, div#admin-wrapper {
/* Dropdown */
@ -516,21 +561,42 @@ div.modal div.modal-content {
/* Global Defaults (Colors Only) */
body, html[native-dark-active] {
background-color: var(--color-93);
background-image: none;
background: linear-gradient(45deg, var(--color-93), var(--color-91), var(--color-95), var(--color-93));
color: var(--color-40);
/* Use the corporate-design font family */
font-family: "Liberation Sans", Arial, sans-serif;
}
/* Links (Color Only) */
{# All links (applies to all anchor elements regardless of state) #}
a {
color: var(--color-50);
}
{# Unvisited links (applies only to links that have not been visited) #}
a:link {
color: var(--color-55);
}
{# Visited links (applies only to links that have been visited) #}
a:visited {
color: var(--color-45);
}
{# Hover state (applies when the mouse pointer is over the link) #}
a:hover {
color: var(--color-60);
}
{# Active state (applies during the time the link is being activated, e.g., on click) #}
a:active {
color: var(--color-65);
}
/* Buttons (Background, Text, Border, and Shadow)
Now using a button background that is only slightly darker than the overall background */
html[native-dark-active] button, html[native-dark-active] .btn, button, .btn {
background-color: var(--color-87);
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-70), var(--color-91), var(--color-95), var(--color-95));
color: var(--color-50);
border-color: var(--color-80);
cursor: pointer;
@ -540,100 +606,271 @@ button:hover, .btn:hover {
filter: brightness(0.9);
}
/* Inputs & Forms in Light Mode (Using a Light Tone from the Corporate Design) */
input, textarea, select {
background-color: var(--color-82); /* Instead of var(--color-90) */
/* {# Invalid state: when the input value fails validation criteria. Use danger color for error indication. #} */
input:invalid,
textarea:invalid,
select:invalid {
background-color: var(--color-01);
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-01), var(--color-10));
/* Use Bootstrap danger color for error messages */
color: var(--bs-danger);
border-color: var(--color-20);
}
/* {# Valid state: when the input value meets all validation criteria. Use success color for confirmation. #} */
input:valid,
textarea:valid,
select:valid {
background-color: var(--color-80);
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-80), var(--color-90));
/* Use Bootstrap success color for confirmation messages */
color: var(--bs-success);
border-color: var(--color-70);
}
/* {# Required field: applied to elements that must be filled out by the user. Use warning color for emphasis. #} */
input:required,
textarea:required,
select:required {
background-color: var(--color-50);
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-50), var(--color-60));
/* Use Bootstrap warning color to indicate a required field */
color: var(--bs-warning);
border-color: var(--color-70);
}
/* {# Optional field: applied to elements that are not mandatory. Use info color to denote additional information. #} */
input:optional,
textarea:optional,
select:optional {
background-color: var(--color-60);
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-60), var(--color-70));
/* Use Bootstrap info color to indicate optional information */
color: var(--bs-info);
border-color: var(--color-70);
}
/* {# Read-only state: when an element is not editable by the user. #} */
input:read-only,
textarea:read-only,
select:read-only {
background-color: var(--color-80);
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-90), var(--color-70));
color: var(--color-20);
border-color: var(--color-50);
}
/* {# Read-write state: when an element is editable by the user. #} */
input:read-write,
textarea:read-write,
select:read-write {
background-color: var(--color-70);
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-70), var(--color-80));
color: var(--color-40);
border-color: var(--color-70);
}
input:focus, textarea:focus, select:focus {
/* {# In-range: for inputs with a defined range, when the value is within the allowed limits. #} */
input:in-range,
textarea:in-range,
select:in-range {
background-color: var(--color-70);
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-70), var(--color-85));
color: var(--color-40);
border-color: var(--color-70);
}
/* {# Out-of-range: for inputs with a defined range, when the value falls outside the allowed limits. #} */
input:out-of-range,
textarea:out-of-range,
select:out-of-range {
background-color: var(--color-10);
background: linear-gradient(45deg, var(--color-10), var(--color-30));
color: var(--color-10);
border-color: var(--color-50);
}
/* {# Placeholder-shown: when the input field is displaying its placeholder text. #} */
input:placeholder-shown,
textarea:placeholder-shown,
select:placeholder-shown {
background-color: var(--color-82);
background: linear-gradient(45deg, var(--color-82), var(--color-90));
color: var(--color-40);
border-color: var(--color-70);
}
/* {# Focus state: when the element is focused by the user. #} */
input:focus,
textarea:focus,
select:focus {
background-color: var(--color-75);
background: linear-gradient(45deg, var(--color-75), var(--color-85));
color: var(--color-40);
border-color: var(--color-50);
}
/* {# Hover state: when the mouse pointer is over the element. #} */
input:hover,
textarea:hover,
select:hover {
background-color: var(--color-78);
background: linear-gradient(45deg, var(--color-78), var(--color-88));
color: var(--color-40);
border-color: var(--color-65);
}
/* {# Active state: when the element is being activated (e.g., clicked). #} */
input:active,
textarea:active,
select:active {
background-color: var(--color-68);
background: linear-gradient(45deg, var(--color-68), var(--color-78));
color: var(--color-40);
border-color: var(--color-60);
}
/* {# Checked state: specifically for radio buttons and checkboxes when selected. #} */
input:checked {
background-color: var(--color-90);
background: linear-gradient(45deg, var(--color-90), var(--color-99));
color: var(--color-40);
border-color: var(--color-70);
}
/* Tables (Borders and Header Colors) */
th, td {
border-color: var(--color-70) !important;
border-color: var(--color-70);
}
thead {
background-color: var(--color-80) !important;
color: var(--color-40) !important;
background-color: var(--color-80);
/* New Gradient based on original background (80 -5, 80, 80 +1, 80 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-75), var(--color-80), var(--color-81), var(--color-85));
color: var(--color-40);
}
/* Headings (Text Color) */
h1, h2, h3, h4, h5, h6, p{
color: var(--color-10) !important;
color: var(--color-10);
}
/* Navigation (Background and Text Colors) */
.navbar, .navbar-light, .navbar-dark {
background-color: var(--color-90) !important;
color: var(--color-50) !important;
border-color: var(--color-85) !important;
background-color: var(--color-90);
/* New Gradient based on original background (90 -5, 90, 90 +1, 90 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-85), var(--color-90), var(--color-91), var(--color-95));
color: var(--color-50);
border-color: var(--color-85);
}
.navbar a {
color: var(--color-40) !important;
color: var(--color-40);
}
.navbar a.dropdown-item {
color: var(--color-40) !important;
color: var(--color-43);
}
/* Cards / Containers (Background, Border, and Shadow)
Cards now use a slightly lighter background and a bold, clear shadow */
.card {
background-color: var(--color-90) !important;
border-color: var(--color-85) !important;
background-color: var(--color-90);
/* New Gradient based on original background (90 -5, 90, 90 +1, 90 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-85), var(--color-90), var(--color-91), var(--color-95));
border-color: var(--color-85);
}
.card-body {
color: var(--color-40) !important;
color: var(--color-40);
}
/* Dropdown Menu and Submenu (Background, Text, and Shadow) */
.navbar .dropdown-menu,
.nav-item .dropdown-menu {
background-color: var(--color-80) !important;
color: var(--color-40) !important;
background-color: var(--color-80);
/* New Gradient based on original background (80 -5, 80, 80 +1, 80 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-75), var(--color-80), var(--color-81), var(--color-85));
color: var(--color-40);
}
.dropdown-item {
color: var(--color-40) !important;
background-color: var(--color-80) !important;
color: var(--color-40);
background-color: var(--color-80);
/* New Gradient based on original background (80 -5, 80, 80 +1, 80 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-75), var(--color-80), var(--color-81), var(--color-85));
}
.dropdown-item:hover,
.dropdown-item:focus {
background-color: var(--color-65) !important;
color: var(--color-40) !important;
background-color: var(--color-65);
/* New Gradient based on original background (65 -5, 65, 65 +1, 65 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-60), var(--color-65), var(--color-66), var(--color-70));
color: var(--color-40);
}
/* Keycloak Header */
div#app header, div#app header *{
background-color: var(--color-60) !important;
background-color: var(--color-60);
/* New Gradient based on original background (60 -5, 60, 60 +1, 60 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-55), var(--color-60), var(--color-61), var(--color-65));
color: var(--color-98);
}
/** LAM Specific **/
.lam-vertical-tabs-navigation li, .lam-vertical-tabs-navigation{
background-color: transparent !important;
border-color: transparent !important;
background-color: transparent;
/* New Gradient with transparent values */
background: linear-gradient({{ range(0, 361) | random }}deg, transparent, transparent, transparent, transparent);
border-color: transparent;
}
/* Not changable due to inline css */
.roundedShadowBox {
color: #000000;
}
.titleBar {
background-image: linear-gradient(var(--color-83), var(--color-92));
/* New Gradient based on original background (83 -5, 83, 83 +1, 83 +5) */
background-image: linear-gradient({{ range(0, 361) | random }}deg, var(--color-78), var(--color-83), var(--color-84), var(--color-88));
border-top-color: var(--color-78);
border-left-color: var(--color-87);
border-right-color: var(--color-87);
}
div.statusInfo {
background-color: var(--color-81);
/* New Gradient based on original background (81 -5, 81, 81 +1, 81 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-76), var(--color-81), var(--color-82), var(--color-86));
color: var(--color-23);
}
/** Mailu **/
[class*=sidebar-dark-], .bg-mailu-logo {
background-color: var(--color-90) !important;
background-color: var(--color-90);
/* New Gradient based on original background (90 -5, 90, 90 +1, 90 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-85), var(--color-90), var(--color-91), var(--color-95));
}
div.statusError {
background-color: var(--color-60);
/* New Gradient based on original background (60 -5, 60, 60 +1, 60 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-55), var(--color-60), var(--color-61), var(--color-65));
}
/** Nextcloud specific **/
html.ng-csp header#header{
color: var(--color-90) !important;
background-color: var(--color-80) !important;
background-color: var(--color-80);
/* New Gradient based on original background (80 -5, 80, 80 +1, 80 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-75), var(--color-80), var(--color-81), var(--color-85));
color: var(--color-90);
}
html.ng-csp div#postsetupchecks ul.info{
background-color: transparent !important;
background-color: transparent;
/* New Gradient with transparent values */
background: linear-gradient({{ range(0, 361) | random }}deg, transparent, transparent, transparent, transparent);
}
div#mastodon .column-link{
@ -646,6 +883,8 @@ div#mastodon .column-back-button {
div#mastodon textarea, div#mastodon input, div#mastodon .compose-form__highlightable {
background-color: var(--color-89);
/* New Gradient based on original background (89 -5, 89, 89 +1, 89 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-84), var(--color-89), var(--color-90), var(--color-94));
color: var(--color-19);
}
@ -662,6 +901,8 @@ div#mastodon .dropdown-button{
div#mastodon .button, div#mastodon .button:active, div#mastodon .button:focus, div#mastodon .button:hover{
background-color: var(--color-71);
/* New Gradient based on original background (71 -5, 71, 71 +1, 71 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-66), var(--color-71), var(--color-72), var(--color-76));
}
.compose-form__actions .icon-button {
@ -670,37 +911,61 @@ div#mastodon .button, div#mastodon .button:active, div#mastodon .button:focus, d
/** OpenProject **/
header.op-app-header{
background-color: var(--color-40) !important;
color: var(--color-40) !important;
background-color: var(--color-40);
/* New Gradient based on original background (40 -5, 40, 40 +1, 40 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-35), var(--color-40), var(--color-41), var(--color-45));
color: var(--color-40);
}
/** Open Project **/
div#wrapper button, div#wrapper input, button.top-menu-search-button, div.menu-sidebar a{
background-color: transparent !important;
background-color: transparent;
/* New Gradient with transparent values */
background: linear-gradient({{ range(0, 361) | random }}deg, transparent, transparent, transparent, transparent);
}
/* Peertube specific configuration */
/* Peertube specific configuration */
.peertube-container button {
background-color: transparent !important;
background-color: transparent;
/* New Gradient with transparent values */
background: linear-gradient({{ range(0, 361) | random }}deg, transparent, transparent, transparent, transparent);
}
/* Pixelfed */
div.page-wrapper{
background: none !important;
background-color: none !important;
background: none;
background-color: none;
}
/** Taiga specific configuration **/
section.main.kanban{
background-color: transparent !important;
background-color: transparent;
/* New Gradient with transparent values */
background: linear-gradient({{ range(0, 361) | random }}deg, transparent, transparent, transparent, transparent);
}
div.master, div.kanban-header, div.kanban-table-inner, section.kanban button,a.dropdown-project-list-projects{
background-color: var(--color-92) !important;
color: var(--color-40) !important;
background-color: var(--color-92);
/* New Gradient based on original background (92 -5, 92, 92 +1, 92 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-87), var(--color-92), var(--color-93), var(--color-97));
color: var(--color-40);
}
section.kanban h1, section.kanban h2{
color: var(--color-40) !important;
color: var(--color-40);
}
.home-project {
background: var(--color-88);
/* New Gradient based on original background (88 -5, 88, 88 +1, 88 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-83), var(--color-88), var(--color-89), var(--color-93));
border-color: var(--color-60);
color: var(--color-12);
}
.home-wrapper .title-bar {
background: var(--color-75);
/* New Gradient based on original background (75 -5, 75, 75 +1, 75 +5) */
background: linear-gradient({{ range(0, 361) | random }}deg, var(--color-70), var(--color-75), var(--color-76), var(--color-80));
}

View File

@ -4,3 +4,6 @@ This user needs to type in his password before executing sudo.
For security reasons it's recommended to use this user instead of the standard root user.
This user should not be used to login to other systems. It's just there to let administration tasks run.
For this reason no ssh-keys are generated.
## Author
This role was created by [Kevin Veen-Birkenbach](https://www.veen.world/)

View File

@ -46,6 +46,13 @@
notify: sshd restart
when: run_once_user_administrator is not defined
- name: "embed user routines for {{ role_path | basename }}"
include_role:
name: user
vars:
user_name: "administrator"
when: run_once_user_administrator is not defined
- name: run the user_administrator tasks once
set_fact:
run_once_user_administrator: true

View File

@ -1,4 +1,3 @@
Certainly! Below is a README file in English for an Ansible role that includes the tasks you've provided:
# Root User
## Overview
@ -14,16 +13,9 @@ This Ansible role is designed to manage the generation and handling of an SSH ke
4. **Output the public SSH key**: Debug task to display the SSH public key in the Ansible output.
5. **Run the user_root tasks once**: Sets a fact to ensure that the tasks for generating and displaying the key are executed only once.
## Usage
To use this role, include it in your playbook and set any necessary variables in your playbook's `vars` section. Ensure you have the necessary permissions to execute tasks as the root user.
```yaml
- hosts: servers
become: yes
roles:
- ssh_key_generator_root
```
## Important Notes
- Running this role will affect the root user's SSH configuration on the target system. Ensure you understand the implications of modifying root SSH keys.
- Always test the role in a controlled environment before deploying to production.
## Author
This role was created by [Kevin Veen-Birkenbach](https://www.veen.world/)

View File

@ -20,6 +20,13 @@
msg: "{{ public_key.stdout }}"
when: not ssh_key.stat.exists and run_once_user_root is not defined
- name: "embed user routines for {{ role_path | basename }}"
include_role:
name: user
vars:
user_name: "root"
when: run_once_user_root is not defined
- name: run the user_root tasks once
set_fact:
run_once_user_root: true

1
roles/user/README.md Normal file
View File

@ -0,0 +1 @@
This role executes tasks which are relevant for all users

View File

@ -0,0 +1,6 @@
- name: create .bashrc
template:
src: "bashrc.j2"
dest: "{{ '/root/.bashrc' if user_name == 'root' else '/home/' ~ user_name ~ '/.bashrc' }}"
owner: "{{user_name}}"
group: "{{user_name}}"

View File

@ -0,0 +1,79 @@
#!/bin/bash
# Set color variables for the welcome text based on the current user
if [ "$USER" = "root" ]; then
HEADER_COLOR="\033[1;31m" # Bold red for root
elif [ "$USER" = "administrator" ]; then
HEADER_COLOR="\033[1;38;5;208m" # Bold orange for administrator
else
HEADER_COLOR="\033[1;33m" # Bold yellow for other users
fi
RESET_COLOR="\033[0m"
# Color code for the hostname (set to green, bold, underlined, and blinking)
# (Note: \[ and \] are used for PS1 only; for echo, use plain escapes)
HOSTNAME_COLOR="\033[1;4;5;32m"
clear
# Primary IP (determined via default route)
PRIMARY_IP=$(ip route get 8.8.8.8 2>/dev/null | awk '{print $7}' | head -n1)
# Print welcome message
echo -e "${HEADER_COLOR}Welcome, $USER on ${HOSTNAME_COLOR}$HOSTNAME!${RESET_COLOR}"
echo -e "Primary IP Address: ${PRIMARY_IP}"
echo -e "${HEADER_COLOR}Today is $(date +"%A, %d.%m.%Y %T")${RESET_COLOR}"
echo -e "\033[94mPowered by: CyMaIS - Cyber Master Infrastructure Solutions!"
echo -e "\033[1;31mWARNING: This software is not to be used for generating commercial profits.\033[94m"
echo -e "If you require a license for commercial use, please contact Kevin Veen-Birkenbach, the author and copyright holder.\n"
echo -e "More Information:"
echo -e "- About CyMaIS: \033[35mhttps://s.veen.world/cymais\033[94m"
echo -e "- About the author: \033[35mhttps://www.veen.world\033[94m"
echo ""
# System Load (shows load averages and uptime)
echo -e "${HEADER_COLOR}System Load:${RESET_COLOR}"
uptime
echo ""
# Memory Usage (RAM and swap)
echo -e "${HEADER_COLOR}Memory Usage:${RESET_COLOR}"
free -h
echo ""
# Disk Usage
echo -e "${HEADER_COLOR}Disk Usage:${RESET_COLOR}"
df -h
echo ""
# CPU Information (e.g., model name)
echo -e "${HEADER_COLOR}CPU Information:${RESET_COLOR}"
lscpu | grep "Model name"
echo ""
# Top 5 Processes by CPU Usage
echo -e "${HEADER_COLOR}Top 5 Processes by CPU Usage:${RESET_COLOR}"
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%cpu | head -n 6
echo ""
# Set aliases for colored output for ls and grep
alias ls='ls --color=auto'
alias grep='grep --color=auto'
# --- Prompt Configuration ---
# Define color codes for the username in the prompt based on the current user
if [ "$USER" = "root" ]; then
PROMPT_USER_COLOR="\[\033[4;5;1;31m\]" # Underlined, bold red for root
elif [ "$USER" = "administrator" ]; then
PROMPT_USER_COLOR="\[\033[4;38;5;208m\]" # Underlined, bold orange for administrator
else
PROMPT_USER_COLOR="\[\033[33m\]" # Yellow for other users
fi
# Reset code for the prompt (must be wrapped in \[ \])
PROMPT_RESET="\[\033[0m\]"
# Configure PS1: username, hostname in green, time and current directory
PS1="${PROMPT_USER_COLOR}\u${PROMPT_RESET}@\[\033[1;4;5;32m\]\h${PROMPT_RESET} \[\033[90m\]\$(date +%H:%M:%S)\[\033[0m\]:\[\033[38;5;13m\]\w ${PROMPT_RESET}\$ "

View File

@ -1,13 +1,24 @@
- name: "create {{docker_compose.files.docker_compose}}"
- name: "create {{ docker_compose.files.docker_compose }}"
template:
src: "docker-compose.yml.j2"
dest: "{{docker_compose.files.docker_compose}}"
src: "docker-compose.yml.j2"
dest: "{{ docker_compose.files.docker_compose }}"
notify: docker compose project setup
register: docker_compose_template
- name: "create {{docker_compose.files.env}}"
template:
src: "env.j2"
dest: "{{docker_compose.files.env}}"
- name: "create {{ docker_compose.files.env }}"
template:
src: "env.j2"
dest: "{{ docker_compose.files.env }}"
mode: '770'
force: yes
notify: docker compose project setup
notify: docker compose project setup
register: env_template
- name: Check if docker compose has any running container and trigger setup if needed
command: docker compose ps -q --filter status=running
args:
chdir: "{{ docker_compose.directories.instance }}"
register: docker_ps
changed_when: (docker_ps.stdout | trim) == ""
notify: docker compose project setup
when: not (docker_compose_template.changed or env_template.changed)