Merge pull request 'dev' (#4) from dev into main

Reviewed-on: #4
This commit is contained in:
kevinheyer 2025-08-13 15:35:44 +00:00
commit 45510e6b63
152 changed files with 656 additions and 50 deletions

27
.gitignore vendored
View file

@ -1,16 +1,17 @@
# Ignore inventory file. This are Submodules # General Files
inventory/ .vscode
# Ignore .secret files.... you know, there secret...
*.secret
.vault-*
# Ignore Caching
cache/ cache/
# Ignore Testplaybook # Ansible Files
playbooks/global/testserver.yml ansible/inventory/
*.secret
ansible/.vault-*
ansible/.ansible
# Ignore unneccessary Files # Packer Files
.vscode packer/credentials.pkr.hcl
.ansible
# OpenTofu Files
opentofu/.terraform/
opentofu/.terraform.lock.hcl
opentofu/terraform.tfstate

View file

@ -1,5 +1,5 @@
[defaults] [defaults]
inventory = ./inventory/ inventory = ./ansible/inventory/
host_key_checking = False host_key_checking = False
retry_files_enabled = False retry_files_enabled = False
private_key_file = ~/.ssh/ansible_key private_key_file = ~/.ssh/ansible_key
@ -11,7 +11,7 @@ fact_caching_connection = ./cache
fact_caching_timeout = 86400 fact_caching_timeout = 86400
# Rollen-Pfade # Rollen-Pfade
roles_path = ./roles/ roles_path = ./ansible/roles/
# Vault-Einstellungen # Vault-Einstellungen
vault_password_file = ./vault.secret vault_password_file = ./vault.secret

View file

@ -51,3 +51,23 @@
tags: tags:
- booklore - booklore
- docker-container - 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

View 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 (04)
# ---------------------
# 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'

View 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

View file

@ -0,0 +1,2 @@
AUTHELIA_VERSION={{ container_authelia_version }}
AUTHELIA_DOMAIN={{ container_authelia_domain }}

View file

@ -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") }}'

View file

@ -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

View file

@ -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 %}

View file

@ -0,0 +1 @@
container_base_dir: /opt/docker/authelia

View file

@ -1,6 +1,5 @@
container_booklore_version: latest container_booklore_version: latest
container_booklore_domain: booklore.example.com 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_root_password: super_duper_secret_root_password
container_booklore_db_user: db_user container_booklore_db_user: db_user
container_booklore_db_password: super_secret_password container_booklore_db_password: super_secret_password

View file

@ -1,7 +1,7 @@
--- ---
- name: Ensure data directories exist - name: Ensure data directories exist
ansible.builtin.file: ansible.builtin.file:
path: "{{ container_booklore_directory }}/data/{{ item }}" path: "{{ container_base_dir }}/data/{{ item }}"
state: directory state: directory
mode: '0755' mode: '0755'
loop: loop:
@ -13,7 +13,7 @@
- name: Deploy Docker Compose and .env files - name: Deploy Docker Compose and .env files
ansible.builtin.template: ansible.builtin.template:
src: "{{ item.src }}" src: "{{ item.src }}"
dest: "{{ container_booklore_directory }}/{{ item.dest }}" dest: "{{ container_base_dir }}/{{ item.dest }}"
mode: '0644' mode: '0644'
loop: loop:
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' } - { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
@ -22,7 +22,7 @@
- name: Start Container - name: Start Container
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: "{{ container_booklore_directory }}" project_src: "{{ container_base_dir }}"
pull: always pull: always
docker_host: "unix:///run/user/1000/docker.sock" docker_host: "unix:///run/user/1000/docker.sock"
become: false become: false

View file

@ -0,0 +1 @@
container_base_dir: /opt/docker/booklore

View file

@ -1,3 +1,2 @@
container_excalidraw_version: latest container_excalidraw_version: latest
container_excalidraw_domain: excalidraw.example.com container_excalidraw_domain: excalidraw.example.com
container_excalidraw_directory: /opt/docker/excalidraw

View file

@ -1,7 +1,7 @@
--- ---
- name: Ensure data directories exist - name: Ensure data directories exist
ansible.builtin.file: ansible.builtin.file:
path: "{{ container_excalidraw_directory }}/data/{{ item }}" path: "{{ container_base_dir }}/data/{{ item }}"
state: directory state: directory
mode: '0755' mode: '0755'
loop: loop:
@ -11,7 +11,7 @@
- name: Create neccessary Files - name: Create neccessary Files
ansible.builtin.file: ansible.builtin.file:
path: "{{ traefik_container_dir }}/data/{{ item }}" path: "{{ container_base_dir }}/data/{{ item }}"
state: touch state: touch
mode: '0644' mode: '0644'
loop: loop:
@ -22,7 +22,7 @@
- name: Deploy Docker Compose and .env files - name: Deploy Docker Compose and .env files
ansible.builtin.template: ansible.builtin.template:
src: "{{ item.src }}" src: "{{ item.src }}"
dest: "{{ container_excalidraw_directory }}/{{ item.dest }}" dest: "{{ container_base_dir }}/{{ item.dest }}"
mode: '0644' mode: '0644'
loop: loop:
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' } - { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
@ -31,7 +31,7 @@
- name: Start Container - name: Start Container
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: "{{ container_excalidraw_directory }}" project_src: "{{ container_base_dir }}"
pull: always pull: always
docker_host: "unix:///run/user/1000/docker.sock" docker_host: "unix:///run/user/1000/docker.sock"
become: false become: false

View file

@ -0,0 +1 @@
container_base_dir: /opt/docker/excalidraw

View file

@ -0,0 +1,3 @@
---
container_grafana_version: latest
container_grafana_domain: grafana.example.com

View file

@ -1,7 +1,7 @@
--- ---
- name: Ensure data directories exist - name: Ensure data directories exist
ansible.builtin.file: ansible.builtin.file:
path: "{{ container_wishlist_directory }}/data" path: "{{ container_base_dir }}/"
state: directory state: directory
mode: '0755' mode: '0755'
become: false become: false
@ -9,7 +9,7 @@
- name: Deploy Docker Compose and .env files - name: Deploy Docker Compose and .env files
ansible.builtin.template: ansible.builtin.template:
src: "{{ item.src }}" src: "{{ item.src }}"
dest: "{{ container_wishlist_directory }}/{{ item.dest }}" dest: "{{ container_base_dir }}/{{ item.dest }}"
mode: '0644' mode: '0644'
loop: loop:
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' } - { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
@ -18,7 +18,7 @@
- name: Start Container - name: Start Container
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: "{{ container_wishlist_directory }}" project_src: "{{ container_base_dir }}"
pull: always pull: always
docker_host: "unix:///run/user/1000/docker.sock" docker_host: "unix:///run/user/1000/docker.sock"
become: false become: false

View file

@ -0,0 +1,2 @@
GRAFANA_VERSION={{ container_grafana_version }}
GRAFANA_DOMAIN={{ container_grafana_domain }}

View file

@ -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

View file

@ -0,0 +1 @@
container_base_dir: /opt/docker/grafana

View file

@ -1,6 +1,5 @@
container_homepage_version: latest container_homepage_version: latest
container_homepage_domain: dashboard.example.com container_homepage_domain: dashboard.example.com
container_homepage_directory: /opt/docker/homepage
container_homepage_config_files: container_homepage_config_files:
- src: "{{ inventory_dir }}/host_files/{{ inventory_hostname }}/container_homepage_config_files/bookmarks.yaml" - src: "{{ inventory_dir }}/host_files/{{ inventory_hostname }}/container_homepage_config_files/bookmarks.yaml"
dest: "bookmarks.yaml" dest: "bookmarks.yaml"

View file

@ -1,7 +1,7 @@
--- ---
- name: Ensure data directories exist - name: Ensure data directories exist
ansible.builtin.file: ansible.builtin.file:
path: "{{ container_homepage_directory }}/data/{{ item }}" path: "{{ container_base_dir }}/data/{{ item }}"
state: directory state: directory
mode: '0755' mode: '0755'
loop: loop:
@ -11,7 +11,7 @@
- name: Deploy Docker Compose and .env files - name: Deploy Docker Compose and .env files
ansible.builtin.template: ansible.builtin.template:
src: "{{ item.src }}" src: "{{ item.src }}"
dest: "{{ container_homepage_directory }}/{{ item.dest }}" dest: "{{ container_base_dir }}/{{ item.dest }}"
mode: '0644' mode: '0644'
loop: loop:
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' } - { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
@ -21,14 +21,14 @@
- name: Deploy tenant-specific config files - name: Deploy tenant-specific config files
ansible.builtin.copy: ansible.builtin.copy:
src: "{{ item.src }}" src: "{{ item.src }}"
dest: "{{ container_homepage_directory }}/data/config/{{ item.dest }}" dest: "{{ container_base_dir }}/data/config/{{ item.dest }}"
mode: '0644' mode: '0644'
loop: "{{ container_homepage_config_files }}" loop: "{{ container_homepage_config_files }}"
become: false become: false
- name: Start Container - name: Start Container
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: "{{ container_homepage_directory }}" project_src: "{{ container_base_dir }}"
pull: always pull: always
docker_host: "unix:///run/user/1000/docker.sock" docker_host: "unix:///run/user/1000/docker.sock"
become: false become: false

View file

@ -0,0 +1 @@
container_base_dir: /opt/docker/homepage

View file

@ -1,4 +1,3 @@
container_koito_version: latest container_koito_version: latest
container_koito_domain: music.heyer.systems container_koito_domain: music.heyer.systems
container_koito_directory: /opt/docker/koito
container_koito_db_password: "super_secret_db_password" container_koito_db_password: "super_secret_db_password"

View file

@ -1,7 +1,7 @@
--- ---
- name: Ensure data directories exist - name: Ensure data directories exist
ansible.builtin.file: ansible.builtin.file:
path: "{{ container_koito_directory }}/data/{{ item }}" path: "{{ container_base_dir }}/data/{{ item }}"
state: directory state: directory
mode: '0755' mode: '0755'
loop: loop:
@ -12,7 +12,7 @@
- name: Deploy Docker Compose and .env files - name: Deploy Docker Compose and .env files
ansible.builtin.template: ansible.builtin.template:
src: "{{ item.src }}" src: "{{ item.src }}"
dest: "{{ container_koito_directory }}/{{ item.dest }}" dest: "{{ container_base_dir }}/{{ item.dest }}"
mode: '0644' mode: '0644'
loop: loop:
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' } - { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
@ -21,7 +21,7 @@
- name: Start Container - name: Start Container
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: "{{ container_koito_directory }}" project_src: "{{ container_base_dir }}"
pull: always pull: always
docker_host: "unix:///run/user/1000/docker.sock" docker_host: "unix:///run/user/1000/docker.sock"
become: false become: false

View file

@ -0,0 +1 @@
container_base_dir: /opt/docker/koito

View file

@ -10,6 +10,3 @@ container_lldap_domain: "ldap.example.com" # Fully qualified domain na
# LDAP admin user password # LDAP admin user password
container_lldap_ldap_user_pass: "adminPas$word" # Admin password (can be replaced by secret file) 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

View file

@ -1,6 +1,6 @@
- name: Ensure data directories exist - name: Ensure data directories exist
ansible.builtin.file: ansible.builtin.file:
path: "{{ container_lldap_directory }}/{{ item }}" path: "{{ container_base_dir }}/{{ item }}"
state: directory state: directory
mode: '0755' mode: '0755'
loop: loop:
@ -10,12 +10,12 @@
- name: Check if jwt_secret file exists - name: Check if jwt_secret file exists
ansible.builtin.stat: ansible.builtin.stat:
path: "{{ container_lldap_directory }}/secrets/jwt_secret" path: "{{ container_base_dir }}/secrets/jwt_secret"
register: jwt_secret_stat register: jwt_secret_stat
- name: Check if key_seed file exists - name: Check if key_seed file exists
ansible.builtin.stat: ansible.builtin.stat:
path: "{{ container_lldap_directory }}/secrets/key_seed" path: "{{ container_base_dir }}/secrets/key_seed"
register: key_seed_stat register: key_seed_stat
- name: Generate JWT secret if not exists - name: Generate JWT secret if not exists
@ -33,7 +33,7 @@
- name: Copy JWT secret to host if generated - name: Copy JWT secret to host if generated
ansible.builtin.copy: ansible.builtin.copy:
content: "{{ jwt_secret }}" content: "{{ jwt_secret }}"
dest: "{{ container_lldap_directory }}/secrets/jwt_secret" dest: "{{ container_base_dir }}/secrets/jwt_secret"
mode: '0644' mode: '0644'
when: jwt_secret is defined when: jwt_secret is defined
become: false become: false
@ -41,7 +41,7 @@
- name: Copy Key Seed to host if generated - name: Copy Key Seed to host if generated
ansible.builtin.copy: ansible.builtin.copy:
content: "{{ key_seed }}" content: "{{ key_seed }}"
dest: "{{ container_lldap_directory }}/secrets/key_seed" dest: "{{ container_base_dir }}/secrets/key_seed"
mode: '0644' mode: '0644'
when: key_seed is defined when: key_seed is defined
become: false become: false
@ -49,14 +49,14 @@
- name: Write LDAP admin user password to file if not exists - name: Write LDAP admin user password to file if not exists
ansible.builtin.copy: ansible.builtin.copy:
content: "{{ container_lldap_ldap_user_pass }}" content: "{{ container_lldap_ldap_user_pass }}"
dest: "{{ container_lldap_directory }}/secrets/ldap_user_pass" dest: "{{ container_base_dir }}/secrets/ldap_user_pass"
mode: '0644' mode: '0644'
become: false become: false
- name: Deploy Docker Compose and .env files - name: Deploy Docker Compose and .env files
ansible.builtin.template: ansible.builtin.template:
src: "{{ item.src }}" src: "{{ item.src }}"
dest: "{{ container_lldap_directory }}/{{ item.dest }}" dest: "{{ container_base_dir }}/{{ item.dest }}"
mode: '0644' mode: '0644'
loop: loop:
- { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' } - { src: 'docker-compose.yml.j2', dest: 'docker-compose.yml' }
@ -65,7 +65,7 @@
- name: Start Container - name: Start Container
community.docker.docker_compose_v2: community.docker.docker_compose_v2:
project_src: "{{ container_lldap_directory }}" project_src: "{{ container_base_dir }}"
pull: always pull: always
docker_host: "unix:///run/user/1000/docker.sock" docker_host: "unix:///run/user/1000/docker.sock"
become: false become: false

View file

@ -0,0 +1 @@
container_base_dir: /opt/docker/lldap

View file

@ -0,0 +1,3 @@
---
container_loki_version: latest
container_loki_domain: loki.example.com

View 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

View file

@ -0,0 +1,2 @@
LOKI_VERSION={{ container_loki_version }}
LOKI_DOMAIN={{ container_loki_domain }}

View file

@ -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

View file

@ -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

View file

@ -0,0 +1 @@
container_base_dir: /opt/docker/loki

View 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"

View 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

View 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

View 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