commit
45510e6b63
152 changed files with 656 additions and 50 deletions
27
.gitignore
vendored
27
.gitignore
vendored
|
@ -1,16 +1,17 @@
|
|||
# Ignore inventory file. This are Submodules
|
||||
inventory/
|
||||
|
||||
# Ignore .secret files.... you know, there secret...
|
||||
*.secret
|
||||
.vault-*
|
||||
|
||||
# Ignore Caching
|
||||
# General Files
|
||||
.vscode
|
||||
cache/
|
||||
|
||||
# Ignore Testplaybook
|
||||
playbooks/global/testserver.yml
|
||||
# Ansible Files
|
||||
ansible/inventory/
|
||||
*.secret
|
||||
ansible/.vault-*
|
||||
ansible/.ansible
|
||||
|
||||
# Ignore unneccessary Files
|
||||
.vscode
|
||||
.ansible
|
||||
# Packer Files
|
||||
packer/credentials.pkr.hcl
|
||||
|
||||
# OpenTofu Files
|
||||
opentofu/.terraform/
|
||||
opentofu/.terraform.lock.hcl
|
||||
opentofu/terraform.tfstate
|
|
@ -1,5 +1,5 @@
|
|||
[defaults]
|
||||
inventory = ./inventory/
|
||||
inventory = ./ansible/inventory/
|
||||
host_key_checking = False
|
||||
retry_files_enabled = False
|
||||
private_key_file = ~/.ssh/ansible_key
|
||||
|
@ -11,7 +11,7 @@ fact_caching_connection = ./cache
|
|||
fact_caching_timeout = 86400
|
||||
|
||||
# Rollen-Pfade
|
||||
roles_path = ./roles/
|
||||
roles_path = ./ansible/roles/
|
||||
|
||||
# Vault-Einstellungen
|
||||
vault_password_file = ./vault.secret
|
||||
|
|
|
@ -51,3 +51,23 @@
|
|||
tags:
|
||||
- booklore
|
||||
- docker-container
|
||||
|
||||
- role: deploy_container_grafana
|
||||
tags:
|
||||
- grafana
|
||||
- docker-container
|
||||
|
||||
- role: deploy_container_loki
|
||||
tags:
|
||||
- loki
|
||||
- docker-container
|
||||
- role: deploy_container_n8n
|
||||
tags:
|
||||
- n8n
|
||||
- docker-container
|
||||
- role: deploy_container_authelia
|
||||
tags:
|
||||
- authelia
|
||||
- sso
|
||||
- auth
|
||||
- docker-container
|
114
ansible/roles/deploy_container_authelia/defaults/main.yml
Normal file
114
ansible/roles/deploy_container_authelia/defaults/main.yml
Normal file
|
@ -0,0 +1,114 @@
|
|||
############
|
||||
# Authelia #
|
||||
############
|
||||
|
||||
# ---------------------
|
||||
# General Configuration
|
||||
# ---------------------
|
||||
container_authelia_version: latest # Authelia container image tag/version
|
||||
container_authelia_domain: authelia.example.com # Fully Qualified Domain Name (FQDN) for Authelia
|
||||
container_authelia_theme: "dark" # dark, light or grey theme
|
||||
|
||||
# ---------------------
|
||||
# Server Settings
|
||||
# ---------------------
|
||||
container_authelia_server_port: 9091 # Port on which Authelia will listen
|
||||
|
||||
# ---------------------
|
||||
# Logging
|
||||
# ---------------------
|
||||
container_authelia_log_level: debug # Log level: trace, debug, info, warn, error
|
||||
container_authelia_log_file_path: /var/log/authelia/authelia.log # Path to log file
|
||||
container_authelia_log_keep_stdout: true # Also log to STDOUT (recommended for containers)
|
||||
|
||||
# ---------------------
|
||||
# Identity Validation / Password Reset
|
||||
# ---------------------
|
||||
container_authelia_elevated_session_2fa: true # Require 2FA for elevated sessions
|
||||
container_authelia_jwt_lifespan: "5 minutes" # Expiration time for password reset links
|
||||
container_authelia_jwt_secret: "nyt4JDvuhU6SGp7H0vaEs0rfGETjI26fRQPJZzwdWPuXsmHdAun2hryiJDyDPRuC" # docker run --rm authelia/authelia:latest authelia crypto rand --length 64 --charset alphanumeric
|
||||
|
||||
# ---------------------
|
||||
# TOTP (Two-Factor Authentication)
|
||||
# ---------------------
|
||||
container_authelia_totp_disable: false # Disable TOTP (false = enabled)
|
||||
container_authelia_totp_issuer: example.com # Issuer name shown in authenticator apps
|
||||
container_authelia_totp_period: 30 # Time interval in seconds
|
||||
container_authelia_totp_skew: 1 # Allowed time drift (in periods)
|
||||
|
||||
# ---------------------
|
||||
# Password Policy (Zxcvbn)
|
||||
# ---------------------
|
||||
container_authelia_zxcvbn_enabled: true # Enable password strength validation
|
||||
container_authelia_zxcvbn_min_score: 4 # Minimum strength score (0–4)
|
||||
|
||||
# ---------------------
|
||||
# Authentication Backend (File-based)
|
||||
# ---------------------
|
||||
container_authelia_auth_file_path: /config/users.yml # Path to user configuration file
|
||||
container_authelia_auth_algorithm: argon2 # Password hashing algorithm
|
||||
container_authelia_auth_argon2_variant: argon2id
|
||||
container_authelia_auth_argon2_iterations: 3
|
||||
container_authelia_auth_argon2_memory: 65535
|
||||
container_authelia_auth_argon2_parallelism: 4
|
||||
container_authelia_auth_argon2_key_length: 32
|
||||
container_authelia_auth_argon2_salt_length: 16
|
||||
|
||||
# ---------------------
|
||||
# Access Control
|
||||
# ---------------------
|
||||
container_authelia_access_default_policy: deny # Default access policy (deny/one_factor/two_factor)
|
||||
container_authelia_access_rules:
|
||||
- domain: "traefik.example.com"
|
||||
policy: "one_factor"
|
||||
- domain: "whoami-secure.example.com"
|
||||
policy: "two_factor"
|
||||
|
||||
# ---------------------
|
||||
# Session Configuration
|
||||
# ---------------------
|
||||
container_authelia_session_name: authelia_session # Name of the session cookie
|
||||
container_authelia_session_key: "zB3d7gTWVbhB5jFQVkjtxfhVZ4aEaFwKHWNa81jjqSL7JgV5HmqOAULDhlJA0muI" # docker run --rm authelia/authelia:latest authelia crypto rand --length 64 --charset alphanumeric
|
||||
container_authelia_session_cookies:
|
||||
- domain: "example.com"
|
||||
authelia_url: "https://auth.example.com"
|
||||
|
||||
# ---------------------
|
||||
# Security Regulation (Brute Force Protection)
|
||||
# ---------------------
|
||||
container_authelia_regulation_max_retries: 4 # Max failed login attempts before ban
|
||||
container_authelia_regulation_find_time: 120 # Time window to count failed attempts (in seconds)
|
||||
container_authelia_regulation_ban_time: 300 # Ban duration after reaching retry limit (in seconds)
|
||||
|
||||
# ---------------------
|
||||
# Storage
|
||||
# ---------------------
|
||||
|
||||
container_authelia_storage_encryption_key: "B4g3XlMfiBJPUXqrZmxfE1CccUASi1r2Cxpr8q9QbmQ3Rvx1RDJvZ1J3DTqkR2a5" # docker run --rm authelia/authelia:latest authelia crypto rand --length 64 --charset alphanumeric
|
||||
container_authelia_storage_path: /config/db.sqlite3 # Path to SQLite storage file
|
||||
|
||||
# ---------------------
|
||||
# Notifications
|
||||
# ---------------------
|
||||
container_authelia_notifier_disable_startup_check: false # Disable notifier startup check (recommended: false)
|
||||
container_authelia_notifier_file: /config/notification.txt # File path used for file-based notifications
|
||||
|
||||
# ---------------------
|
||||
# User Configuration (for file-based backend)
|
||||
# ---------------------
|
||||
# !! SECURITY WARNING !!:
|
||||
# Passwords must always be hashed (argon2, bcrypt, sha512, etc.).
|
||||
# Never store plain-text passwords in production.
|
||||
# Use this guide to generate secure hashes:
|
||||
# https://www.authelia.com/reference/guides/passwords/#passwords
|
||||
|
||||
container_authelia_users:
|
||||
- username: authelia
|
||||
displayname: 'Authelia User'
|
||||
# docker run --rm -it authelia/authelia:latest authelia crypto hash generate argon2
|
||||
# !! Replace the password with a secure hashed password
|
||||
password: '$6$rounds=50000$BpLnfgDsc2WD8F2q$Zis.ixdg9s/UOJYrs56b5QEZFiZECu0qZVNsIYxBaNJ7ucIL.nlxVCT5tqh8KHG8X4tlwCFm5r6NTOZZ5qRFN/'
|
||||
email: 'authelia@authelia.com'
|
||||
groups:
|
||||
- 'admin'
|
||||
- 'dev'
|
44
ansible/roles/deploy_container_authelia/tasks/main.yml
Normal file
44
ansible/roles/deploy_container_authelia/tasks/main.yml
Normal file
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
- name: Ensure data directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ container_base_dir }}/data/{{ item }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
loop:
|
||||
- "secrets"
|
||||
- "config"
|
||||
- "logs"
|
||||
become: false
|
||||
|
||||
- name: Ensure authelia.log file exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ container_base_dir }}/data/logs/authelia.log"
|
||||
state: touch
|
||||
mode: '0644'
|
||||
become: false
|
||||
|
||||
- name: Deploy Docker Compose and .env files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ container_base_dir }}/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
|
||||
- { src: '.env.j2', dest: '.env' }
|
||||
- { src: 'users.yml.j2', dest: 'data/config/users.yml' }
|
||||
- { src: 'configuration.yml.j2', dest: 'data/config/configuration.yml' }
|
||||
become: false
|
||||
|
||||
- name: Stop Container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ container_base_dir }}"
|
||||
state: absent
|
||||
docker_host: "unix:///run/user/1000/docker.sock"
|
||||
become: false
|
||||
|
||||
- name: Start Container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ container_base_dir }}"
|
||||
pull: always
|
||||
docker_host: "unix:///run/user/1000/docker.sock"
|
||||
become: false
|
|
@ -0,0 +1,2 @@
|
|||
AUTHELIA_VERSION={{ container_authelia_version }}
|
||||
AUTHELIA_DOMAIN={{ container_authelia_domain }}
|
|
@ -0,0 +1,74 @@
|
|||
server:
|
||||
address: 'tcp4://:{{ container_authelia_server_port | default(9091) }}'
|
||||
|
||||
theme: {{ container_authelia_theme }}
|
||||
|
||||
log:
|
||||
level: {{ container_authelia_log_level | default('debug') }}
|
||||
file_path: '{{ container_authelia_log_file_path | default("/var/log/authelia/authelia.log") }}'
|
||||
keep_stdout: {{ container_authelia_log_keep_stdout | default(true) }}
|
||||
|
||||
identity_validation:
|
||||
elevated_session:
|
||||
require_second_factor: {{ container_authelia_elevated_session_2fa | default(true) }}
|
||||
reset_password:
|
||||
jwt_lifespan: '{{ container_authelia_jwt_lifespan | default("5 minutes") }}'
|
||||
jwt_secret: {{ container_authelia_jwt_secret }}
|
||||
|
||||
totp:
|
||||
disable: {{ container_authelia_totp_disable | default(false) }}
|
||||
issuer: '{{ container_authelia_totp_issuer | default("example.com") }}'
|
||||
period: {{ container_authelia_totp_period | default(30) }}
|
||||
skew: {{ container_authelia_totp_skew | default(1) }}
|
||||
|
||||
password_policy:
|
||||
zxcvbn:
|
||||
enabled: {{ container_authelia_zxcvbn_enabled | default(true) }}
|
||||
min_score: {{ container_authelia_zxcvbn_min_score | default(4) }}
|
||||
|
||||
authentication_backend:
|
||||
file:
|
||||
path: '{{ container_authelia_auth_file_path | default("/config/users.yml") }}'
|
||||
password:
|
||||
algorithm: '{{ container_authelia_auth_algorithm | default("argon2") }}'
|
||||
argon2:
|
||||
variant: '{{ container_authelia_auth_argon2_variant | default("argon2id") }}'
|
||||
iterations: {{ container_authelia_auth_argon2_iterations | default(3) }}
|
||||
memory: {{ container_authelia_auth_argon2_memory | default(65535) }}
|
||||
parallelism: {{ container_authelia_auth_argon2_parallelism | default(4) }}
|
||||
key_length: {{ container_authelia_auth_argon2_key_length | default(32) }}
|
||||
salt_length: {{ container_authelia_auth_argon2_salt_length | default(16) }}
|
||||
|
||||
access_control:
|
||||
default_policy: '{{ container_authelia_access_default_policy | default("deny") }}'
|
||||
rules:
|
||||
{% for rule in container_authelia_access_rules %}
|
||||
- domain: '{{ rule.domain }}'
|
||||
policy: '{{ rule.policy }}'
|
||||
{% endfor %}
|
||||
|
||||
session:
|
||||
name: '{{ container_authelia_session_name | default("authelia_session") }}'
|
||||
secret: {{ container_authelia_session_key }}
|
||||
|
||||
cookies:
|
||||
{% for cookie in container_authelia_session_cookies %}
|
||||
- domain: '{{ cookie.domain }}'
|
||||
authelia_url: '{{ cookie.authelia_url }}'
|
||||
{% endfor %}
|
||||
|
||||
regulation:
|
||||
max_retries: {{ container_authelia_regulation_max_retries | default(4) }}
|
||||
find_time: {{ container_authelia_regulation_find_time | default(120) }}
|
||||
ban_time: {{ container_authelia_regulation_ban_time | default(300) }}
|
||||
|
||||
storage:
|
||||
encryption_key: {{ container_authelia_storage_encryption_key }}
|
||||
|
||||
local:
|
||||
path: '{{ container_authelia_storage_path | default("/config/db.sqlite3") }}'
|
||||
|
||||
notifier:
|
||||
disable_startup_check: {{ container_authelia_notifier_disable_startup_check | default(false) }}
|
||||
filesystem:
|
||||
filename: '{{ container_authelia_notifier_file | default("/config/notification.txt") }}'
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
services:
|
||||
authelia:
|
||||
image: authelia/authelia:${AUTHELIA_VERSION}
|
||||
container_name: authelia
|
||||
volumes:
|
||||
- './data/secrets:/secrets:ro'
|
||||
- './data/config:/config'
|
||||
- './data/logs/authelia.log:{{ container_authelia_log_file_path }}'
|
||||
networks:
|
||||
traefik:
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik"
|
||||
- "traefik.http.routers.authelia.entrypoints=http"
|
||||
- "traefik.http.routers.authelia.rule=Host(`${AUTHELIA_DOMAIN:?error}`)"
|
||||
- "traefik.http.middlewares.authelia-https-redirect.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.authelia.middlewares=authelia-https-redirect"
|
||||
- "traefik.http.routers.authelia-secure.entrypoints=https"
|
||||
- "traefik.http.routers.authelia-secure.rule=Host(`${AUTHELIA_DOMAIN:?error}`)"
|
||||
- "traefik.http.routers.authelia-secure.tls=true"
|
||||
- "traefik.http.routers.authelia-secure.service=authelia"
|
||||
- "traefik.http.services.authelia.loadbalancer.server.port=9091"
|
||||
# Authelia Middleware
|
||||
- "traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth"
|
||||
- "traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true"
|
||||
- "traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email"
|
||||
environment:
|
||||
TZ: 'EUROPE/BERLIN'
|
||||
X_AUTHELIA_CONFIG_FILTERS: 'template'
|
||||
|
||||
networks:
|
||||
traefik:
|
||||
external: true
|
|
@ -0,0 +1,11 @@
|
|||
users:
|
||||
{% for user in container_authelia_users %}
|
||||
{{ user.username }}:
|
||||
displayname: '{{ user.displayname }}'
|
||||
password: '{{ user.password }}'
|
||||
email: '{{ user.email }}'
|
||||
groups:
|
||||
{% for group in user.groups %}
|
||||
- '{{ group }}'
|
||||
{% endfor %}
|
||||
{% endfor %}
|
1
ansible/roles/deploy_container_authelia/vars/main.yml
Normal file
1
ansible/roles/deploy_container_authelia/vars/main.yml
Normal file
|
@ -0,0 +1 @@
|
|||
container_base_dir: /opt/docker/authelia
|
|
@ -1,6 +1,5 @@
|
|||
container_booklore_version: latest
|
||||
container_booklore_domain: booklore.example.com
|
||||
container_booklore_directory: /opt/docker/booklore
|
||||
container_booklore_db_root_password: super_duper_secret_root_password
|
||||
container_booklore_db_user: db_user
|
||||
container_booklore_db_password: super_secret_password
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
- name: Ensure data directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ container_booklore_directory }}/data/{{ item }}"
|
||||
path: "{{ container_base_dir }}/data/{{ item }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
loop:
|
||||
|
@ -13,7 +13,7 @@
|
|||
- name: Deploy Docker Compose and .env files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ container_booklore_directory }}/{{ item.dest }}"
|
||||
dest: "{{ container_base_dir }}/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
|
||||
|
@ -22,7 +22,7 @@
|
|||
|
||||
- name: Start Container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ container_booklore_directory }}"
|
||||
project_src: "{{ container_base_dir }}"
|
||||
pull: always
|
||||
docker_host: "unix:///run/user/1000/docker.sock"
|
||||
become: false
|
1
ansible/roles/deploy_container_booklore/vars/main.yml
Normal file
1
ansible/roles/deploy_container_booklore/vars/main.yml
Normal file
|
@ -0,0 +1 @@
|
|||
container_base_dir: /opt/docker/booklore
|
|
@ -1,3 +1,2 @@
|
|||
container_excalidraw_version: latest
|
||||
container_excalidraw_domain: excalidraw.example.com
|
||||
container_excalidraw_directory: /opt/docker/excalidraw
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
- name: Ensure data directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ container_excalidraw_directory }}/data/{{ item }}"
|
||||
path: "{{ container_base_dir }}/data/{{ item }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
loop:
|
||||
|
@ -11,7 +11,7 @@
|
|||
|
||||
- name: Create neccessary Files
|
||||
ansible.builtin.file:
|
||||
path: "{{ traefik_container_dir }}/data/{{ item }}"
|
||||
path: "{{ container_base_dir }}/data/{{ item }}"
|
||||
state: touch
|
||||
mode: '0644'
|
||||
loop:
|
||||
|
@ -22,7 +22,7 @@
|
|||
- name: Deploy Docker Compose and .env files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ container_excalidraw_directory }}/{{ item.dest }}"
|
||||
dest: "{{ container_base_dir }}/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
|
||||
|
@ -31,7 +31,7 @@
|
|||
|
||||
- name: Start Container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ container_excalidraw_directory }}"
|
||||
project_src: "{{ container_base_dir }}"
|
||||
pull: always
|
||||
docker_host: "unix:///run/user/1000/docker.sock"
|
||||
become: false
|
1
ansible/roles/deploy_container_excalidraw/vars/main.yml
Normal file
1
ansible/roles/deploy_container_excalidraw/vars/main.yml
Normal file
|
@ -0,0 +1 @@
|
|||
container_base_dir: /opt/docker/excalidraw
|
3
ansible/roles/deploy_container_grafana/defaults/main.yml
Normal file
3
ansible/roles/deploy_container_grafana/defaults/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
container_grafana_version: latest
|
||||
container_grafana_domain: grafana.example.com
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
- name: Ensure data directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ container_wishlist_directory }}/data"
|
||||
path: "{{ container_base_dir }}/"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
become: false
|
||||
|
@ -9,7 +9,7 @@
|
|||
- name: Deploy Docker Compose and .env files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ container_wishlist_directory }}/{{ item.dest }}"
|
||||
dest: "{{ container_base_dir }}/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
|
||||
|
@ -18,7 +18,7 @@
|
|||
|
||||
- name: Start Container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ container_wishlist_directory }}"
|
||||
project_src: "{{ container_base_dir }}"
|
||||
pull: always
|
||||
docker_host: "unix:///run/user/1000/docker.sock"
|
||||
become: false
|
2
ansible/roles/deploy_container_grafana/templates/.env.j2
Normal file
2
ansible/roles/deploy_container_grafana/templates/.env.j2
Normal file
|
@ -0,0 +1,2 @@
|
|||
GRAFANA_VERSION={{ container_grafana_version }}
|
||||
GRAFANA_DOMAIN={{ container_grafana_domain }}
|
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
services:
|
||||
grafana:
|
||||
image: grafana/grafana:${GRAFANA_VERSION}
|
||||
container_name: grafana
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
traefik:
|
||||
volumes:
|
||||
- 'grafana_storage:/var/lib/grafana'
|
||||
environment:
|
||||
- GF_SERVER_ROOT_URL=https://${GRAFANA_DOMAIN}/
|
||||
- GF_PLUGINS_PREINSTALL=grafana-clock-panel
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik"
|
||||
- "traefik.http.routers.grafana.entrypoints=http"
|
||||
- "traefik.http.routers.grafana.rule=Host(`${GRAFANA_DOMAIN}`)"
|
||||
- "traefik.http.middlewares.grafana-https-redirect.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.grafana.middlewares=grafana-https-redirect"
|
||||
- "traefik.http.routers.grafana-secure.entrypoints=https"
|
||||
- "traefik.http.routers.grafana-secure.rule=Host(`${GRAFANA_DOMAIN}`)"
|
||||
- "traefik.http.routers.grafana-secure.tls=true"
|
||||
- "traefik.http.routers.grafana-secure.service=grafana"
|
||||
- "traefik.http.services.grafana.loadbalancer.server.port=3000"
|
||||
|
||||
volumes:
|
||||
grafana_storage: {}
|
||||
|
||||
networks:
|
||||
traefik:
|
||||
external: true
|
1
ansible/roles/deploy_container_grafana/vars/main.yml
Normal file
1
ansible/roles/deploy_container_grafana/vars/main.yml
Normal file
|
@ -0,0 +1 @@
|
|||
container_base_dir: /opt/docker/grafana
|
|
@ -1,6 +1,5 @@
|
|||
container_homepage_version: latest
|
||||
container_homepage_domain: dashboard.example.com
|
||||
container_homepage_directory: /opt/docker/homepage
|
||||
container_homepage_config_files:
|
||||
- src: "{{ inventory_dir }}/host_files/{{ inventory_hostname }}/container_homepage_config_files/bookmarks.yaml"
|
||||
dest: "bookmarks.yaml"
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
- name: Ensure data directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ container_homepage_directory }}/data/{{ item }}"
|
||||
path: "{{ container_base_dir }}/data/{{ item }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
loop:
|
||||
|
@ -11,7 +11,7 @@
|
|||
- name: Deploy Docker Compose and .env files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ container_homepage_directory }}/{{ item.dest }}"
|
||||
dest: "{{ container_base_dir }}/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
|
||||
|
@ -21,14 +21,14 @@
|
|||
- name: Deploy tenant-specific config files
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ container_homepage_directory }}/data/config/{{ item.dest }}"
|
||||
dest: "{{ container_base_dir }}/data/config/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop: "{{ container_homepage_config_files }}"
|
||||
become: false
|
||||
|
||||
- name: Start Container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ container_homepage_directory }}"
|
||||
project_src: "{{ container_base_dir }}"
|
||||
pull: always
|
||||
docker_host: "unix:///run/user/1000/docker.sock"
|
||||
become: false
|
1
ansible/roles/deploy_container_homepage/vars/main.yml
Normal file
1
ansible/roles/deploy_container_homepage/vars/main.yml
Normal file
|
@ -0,0 +1 @@
|
|||
container_base_dir: /opt/docker/homepage
|
|
@ -1,4 +1,3 @@
|
|||
container_koito_version: latest
|
||||
container_koito_domain: music.heyer.systems
|
||||
container_koito_directory: /opt/docker/koito
|
||||
container_koito_db_password: "super_secret_db_password"
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
- name: Ensure data directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ container_koito_directory }}/data/{{ item }}"
|
||||
path: "{{ container_base_dir }}/data/{{ item }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
loop:
|
||||
|
@ -12,7 +12,7 @@
|
|||
- name: Deploy Docker Compose and .env files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ container_koito_directory }}/{{ item.dest }}"
|
||||
dest: "{{ container_base_dir }}/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
|
||||
|
@ -21,7 +21,7 @@
|
|||
|
||||
- name: Start Container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ container_koito_directory }}"
|
||||
project_src: "{{ container_base_dir }}"
|
||||
pull: always
|
||||
docker_host: "unix:///run/user/1000/docker.sock"
|
||||
become: false
|
1
ansible/roles/deploy_container_koito/vars/main.yml
Normal file
1
ansible/roles/deploy_container_koito/vars/main.yml
Normal file
|
@ -0,0 +1 @@
|
|||
container_base_dir: /opt/docker/koito
|
|
@ -10,6 +10,3 @@ container_lldap_domain: "ldap.example.com" # Fully qualified domain na
|
|||
|
||||
# LDAP admin user password
|
||||
container_lldap_ldap_user_pass: "adminPas$word" # Admin password (can be replaced by secret file)
|
||||
|
||||
# Base directory for container data (e.g., for volumes, secrets)
|
||||
container_lldap_directory: "/opt/docker/lldap" # Base directory on the host for LLDAP data
|
|
@ -1,6 +1,6 @@
|
|||
- name: Ensure data directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ container_lldap_directory }}/{{ item }}"
|
||||
path: "{{ container_base_dir }}/{{ item }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
loop:
|
||||
|
@ -10,12 +10,12 @@
|
|||
|
||||
- name: Check if jwt_secret file exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ container_lldap_directory }}/secrets/jwt_secret"
|
||||
path: "{{ container_base_dir }}/secrets/jwt_secret"
|
||||
register: jwt_secret_stat
|
||||
|
||||
- name: Check if key_seed file exists
|
||||
ansible.builtin.stat:
|
||||
path: "{{ container_lldap_directory }}/secrets/key_seed"
|
||||
path: "{{ container_base_dir }}/secrets/key_seed"
|
||||
register: key_seed_stat
|
||||
|
||||
- name: Generate JWT secret if not exists
|
||||
|
@ -33,7 +33,7 @@
|
|||
- name: Copy JWT secret to host if generated
|
||||
ansible.builtin.copy:
|
||||
content: "{{ jwt_secret }}"
|
||||
dest: "{{ container_lldap_directory }}/secrets/jwt_secret"
|
||||
dest: "{{ container_base_dir }}/secrets/jwt_secret"
|
||||
mode: '0644'
|
||||
when: jwt_secret is defined
|
||||
become: false
|
||||
|
@ -41,7 +41,7 @@
|
|||
- name: Copy Key Seed to host if generated
|
||||
ansible.builtin.copy:
|
||||
content: "{{ key_seed }}"
|
||||
dest: "{{ container_lldap_directory }}/secrets/key_seed"
|
||||
dest: "{{ container_base_dir }}/secrets/key_seed"
|
||||
mode: '0644'
|
||||
when: key_seed is defined
|
||||
become: false
|
||||
|
@ -49,14 +49,14 @@
|
|||
- name: Write LDAP admin user password to file if not exists
|
||||
ansible.builtin.copy:
|
||||
content: "{{ container_lldap_ldap_user_pass }}"
|
||||
dest: "{{ container_lldap_directory }}/secrets/ldap_user_pass"
|
||||
dest: "{{ container_base_dir }}/secrets/ldap_user_pass"
|
||||
mode: '0644'
|
||||
become: false
|
||||
|
||||
- name: Deploy Docker Compose and .env files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ container_lldap_directory }}/{{ item.dest }}"
|
||||
dest: "{{ container_base_dir }}/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
|
||||
|
@ -65,7 +65,7 @@
|
|||
|
||||
- name: Start Container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ container_lldap_directory }}"
|
||||
project_src: "{{ container_base_dir }}"
|
||||
pull: always
|
||||
docker_host: "unix:///run/user/1000/docker.sock"
|
||||
become: false
|
1
ansible/roles/deploy_container_lldap/vars/main.yml
Normal file
1
ansible/roles/deploy_container_lldap/vars/main.yml
Normal file
|
@ -0,0 +1 @@
|
|||
container_base_dir: /opt/docker/lldap
|
3
ansible/roles/deploy_container_loki/defaults/main.yml
Normal file
3
ansible/roles/deploy_container_loki/defaults/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
container_loki_version: latest
|
||||
container_loki_domain: loki.example.com
|
27
ansible/roles/deploy_container_loki/tasks/main.yml
Normal file
27
ansible/roles/deploy_container_loki/tasks/main.yml
Normal file
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
- name: Ensure data directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ container_base_dir }}/{{ item.dir }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
become: false
|
||||
loop:
|
||||
- {dir: "data"}
|
||||
|
||||
- name: Deploy Docker Compose and .env files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ container_base_dir }}/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
|
||||
- { src: '.env.j2', dest: '.env' }
|
||||
- { src: 'local-config.yaml.j2', dest: 'data/local-config.yaml' }
|
||||
become: false
|
||||
|
||||
- name: Start Container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ container_base_dir }}"
|
||||
pull: always
|
||||
docker_host: "unix:///run/user/1000/docker.sock"
|
||||
become: false
|
2
ansible/roles/deploy_container_loki/templates/.env.j2
Normal file
2
ansible/roles/deploy_container_loki/templates/.env.j2
Normal file
|
@ -0,0 +1,2 @@
|
|||
LOKI_VERSION={{ container_loki_version }}
|
||||
LOKI_DOMAIN={{ container_loki_domain }}
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
services:
|
||||
loki:
|
||||
image: grafana/loki:${LOKI_VERSION}
|
||||
container_name: loki
|
||||
networks:
|
||||
traefik:
|
||||
volumes:
|
||||
- ./data/local-config.yaml:/etc/loki/local-config.yaml
|
||||
command: -config.file=/etc/loki/local-config.yaml
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.docker.network=traefik"
|
||||
- "traefik.http.routers.loki.entrypoints=http"
|
||||
- "traefik.http.routers.loki.rule=Host(`${LOKI_DOMAIN}`)"
|
||||
- "traefik.http.middlewares.loki-https-redirect.redirectscheme.scheme=https"
|
||||
- "traefik.http.routers.loki.middlewares=loki-https-redirect"
|
||||
- "traefik.http.routers.loki-secure.entrypoints=https"
|
||||
- "traefik.http.routers.loki-secure.rule=Host(`${LOKI_DOMAIN}`)"
|
||||
- "traefik.http.routers.loki-secure.tls=true"
|
||||
- "traefik.http.routers.loki-secure.service=loki"
|
||||
- "traefik.http.services.loki.loadbalancer.server.port=3100"
|
||||
|
||||
networks:
|
||||
traefik:
|
||||
external: true
|
|
@ -0,0 +1,32 @@
|
|||
auth_enabled: false
|
||||
|
||||
server:
|
||||
http_listen_port: 3100
|
||||
|
||||
common:
|
||||
instance_addr: 0.0.0.0
|
||||
path_prefix: /loki
|
||||
storage:
|
||||
filesystem:
|
||||
chunks_directory: /loki/chunks
|
||||
rules_directory: /loki/rules
|
||||
replication_factor: 1
|
||||
ring:
|
||||
kvstore:
|
||||
store: inmemory
|
||||
|
||||
schema_config:
|
||||
configs:
|
||||
- from: 2020-10-24
|
||||
store: tsdb
|
||||
object_store: filesystem
|
||||
schema: v13
|
||||
index:
|
||||
prefix: index_
|
||||
period: 24h
|
||||
|
||||
ruler:
|
||||
alertmanager_url: http://localhost:9093
|
||||
|
||||
analytics:
|
||||
reporting_enabled: false
|
1
ansible/roles/deploy_container_loki/vars/main.yml
Normal file
1
ansible/roles/deploy_container_loki/vars/main.yml
Normal file
|
@ -0,0 +1 @@
|
|||
container_base_dir: /opt/docker/loki
|
11
ansible/roles/deploy_container_n8n/defaults/main.yml
Normal file
11
ansible/roles/deploy_container_n8n/defaults/main.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
#######
|
||||
# N8N #
|
||||
#######
|
||||
container_n8n_version: "latest"
|
||||
container_n8n_postgres_version: "16"
|
||||
container_n8n_domain: "n8n.example.com"
|
||||
container_n8n_postgres_user: "changeUser"
|
||||
container_n8n_postgres_password: "changePassword"
|
||||
container_n8n_postgres_db: "n8n"
|
||||
container_n8n_postgres_non_root_user: "changeUser"
|
||||
container_n8n_postgres_non_root_password: "changePassword"
|
13
ansible/roles/deploy_container_n8n/files/init-data.sh
Normal file
13
ansible/roles/deploy_container_n8n/files/init-data.sh
Normal file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
set -e;
|
||||
|
||||
|
||||
if [ -n "${POSTGRES_NON_ROOT_USER:-}" ] && [ -n "${POSTGRES_NON_ROOT_PASSWORD:-}" ]; then
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
CREATE USER ${POSTGRES_NON_ROOT_USER} WITH PASSWORD '${POSTGRES_NON_ROOT_PASSWORD}';
|
||||
GRANT ALL PRIVILEGES ON DATABASE ${POSTGRES_DB} TO ${POSTGRES_NON_ROOT_USER};
|
||||
GRANT CREATE ON SCHEMA public TO ${POSTGRES_NON_ROOT_USER};
|
||||
EOSQL
|
||||
else
|
||||
echo "SETUP INFO: No Environment variables given!"
|
||||
fi
|
33
ansible/roles/deploy_container_n8n/tasks/main.yml
Normal file
33
ansible/roles/deploy_container_n8n/tasks/main.yml
Normal file
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
- name: Ensure data directories exist
|
||||
ansible.builtin.file:
|
||||
path: "{{ container_base_dir }}/data"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
become: false
|
||||
|
||||
- name: Deploy Docker Compose and .env files
|
||||
ansible.builtin.template:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ container_base_dir }}/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
|
||||
- { src: '.env.j2', dest: '.env' }
|
||||
become: false
|
||||
|
||||
- name: Copy postgres init-data file
|
||||
ansible.builtin.copy:
|
||||
src: "{{ item.src }}"
|
||||
dest: "{{ container_base_dir }}/data/{{ item.dest }}"
|
||||
mode: '0644'
|
||||
loop:
|
||||
- { src: "init-data.sh", dest: "init-data.sh"}
|
||||
become: false
|
||||
|
||||
- name: Start Container
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ container_base_dir }}"
|
||||
pull: always
|
||||
docker_host: "unix:///run/user/1000/docker.sock"
|
||||
become: false
|
15
ansible/roles/deploy_container_n8n/templates/.env.j2
Normal file
15
ansible/roles/deploy_container_n8n/templates/.env.j2
Normal file
|
@ -0,0 +1,15 @@
|
|||
# N8N Version (Standard: latest)
|
||||
N8N_VERSION={{ container_n8n_version | default('latest') }}
|
||||
|
||||
# N8N PostgreSQL Version
|
||||
N8N_POSTGRES_VERSION={{ container_n8n_postgres_version | default('16') }}
|
||||
|
||||
# N8N Domain
|
||||
N8N_DOMAIN={{ container_n8n_domain }}
|
||||
|
||||
# N8N Database Config
|
||||
N8N_POSTGRES_USER={{ container_n8n_postgres_user }}
|
||||
N8N_POSTGRES_PASSWORD={{ container_n8n_postgres_password }}
|
||||
N8N_POSTGRES_DB={{ container_n8n_postgres_db }}
|
||||
N8N_POSTGRES_NON_ROOT_USER={{ container_n8n_postgres_non_root_user }}
|
||||
N8N_POSTGRES_NON_ROOT_PASSWORD={{ container_n8n_postgres_non_root_password }}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue