bk node and refactor

This commit is contained in:
il
2026-06-23 10:57:10 +09:00
parent 927b5b4934
commit fe146b25c7
131 changed files with 2310 additions and 920 deletions
+96 -19
View File
@@ -21,31 +21,62 @@ domain:
services: services:
crowdsec: crowdsec:
domain: "crowdsec" domain:
internal: "crowdsec"
ports: ports:
https: "8080" https: "8080"
dependency:
cert: true
bind: bind:
domain: "bind" domain:
internal: "bind"
ports: ports:
dns: "53" dns: "53"
blocky: blocky:
domain: "blocky" domain:
internal: "blocky"
ports: ports:
https: "443" https: "443"
dns: "53" dns: "53"
dot: "853"
dependency:
cert: true
kopia:
domain:
internal: "kopia"
ports:
https: "51515"
dependency:
cert: true
postgresql: postgresql:
domain: "postgresql" domain:
internal: "postgresql"
ports: ports:
tcp: "5432" # postgresql db connection port tcp: "5432" # postgresql db connection port
subuid: "100998" subuid: "100998"
dependency:
cert: true
ldap: ldap:
domain: "ldap" domain:
internal: "ldap"
ports: ports:
http: "17170" http: "17170"
ldaps: "6360" ldaps: "6360"
subuid: "100999" subuid: "100999"
dependency:
cert: true
web: "infra-internal"
db: "postgresql"
mail:
domain:
internal: "mail"
ports: ""
subuid: ""
dependency:
cert: true
ca: ca:
domain: "ca" domain:
internal: "ca"
ports: ports:
https: "9000" https: "9000"
subuid: "100999" subuid: "100999"
@@ -54,36 +85,43 @@ services:
http: "9793" http: "9793"
subuid: "165533" subuid: "165533"
prometheus: prometheus:
domain: "prometheus" domain:
internal: "prometheus"
ports: ports:
https: "9090" https: "9090"
subuid: "165533" subuid: "165533"
dependency:
cert: true
web: "infra-internal"
loki: loki:
domain: "loki" domain:
internal: "loki"
ports: ports:
https: "3100" https: "3100"
subuid: "110000" subuid: "110000"
dependency:
cert: true
grafana: grafana:
domain: "grafana" domain:
internal: "grafana"
ports: ports:
http: "3000" http: "3000"
subuid: "100471" subuid: "100471"
dependency:
web: "infra-internal"
db: "postgresql"
caddy: caddy:
ports: ports:
http: "2080" http: "2080"
https: "2443" https: "2443"
nas:
domain: "nas"
ports:
https: "5001"
kopia:
domain: "nas"
ports:
https: "51515"
authelia: authelia:
domain: "authelia" domain:
public: "authelia"
ports: ports:
http: "9091" http: "9091"
dependency:
web: "auth-public"
db: "postgresql"
redis: redis:
subuid: "100998" subuid: "100998"
vaultwarden: vaultwarden:
@@ -92,6 +130,9 @@ services:
internal: "vault.app" internal: "vault.app"
ports: ports:
http: "8000" http: "8000"
dependency:
web: "app-public"
db: "postgresql"
gitea: gitea:
domain: domain:
public: "gitea" public: "gitea"
@@ -99,6 +140,9 @@ services:
ports: ports:
http: "3001" http: "3001"
subuid: "100999" subuid: "100999"
dependency:
web: "app-public"
db: "postgresql"
immich: immich:
domain: domain:
public: "immich" public: "immich"
@@ -106,6 +150,9 @@ services:
ports: ports:
http: "2283" http: "2283"
redis: "6379" redis: "6379"
dependency:
web: "app-public"
db: "postgresql"
immich-ml: immich-ml:
ports: ports:
http: "3003" http: "3003"
@@ -117,6 +164,9 @@ services:
http: "8001" http: "8001"
redis: "6380" redis: "6380"
subuid: "100999" subuid: "100999"
dependency:
web: "app-public"
db: "postgresql"
nextcloud: nextcloud:
domain: domain:
public: "nextcloud" public: "nextcloud"
@@ -125,6 +175,9 @@ services:
http: "8002" http: "8002"
redis: "6382" redis: "6382"
subuid: "100032" subuid: "100032"
dependency:
web: "app-public"
db: "postgresql"
collabora: collabora:
domain: domain:
public: "collabora" public: "collabora"
@@ -132,6 +185,8 @@ services:
ports: ports:
http: "9980" http: "9980"
subuid: "101000" subuid: "101000"
dependency:
web: "app-public"
sure: sure:
domain: domain:
public: "sure" public: "sure"
@@ -140,6 +195,9 @@ services:
http: "3002" http: "3002"
redis: "6383" redis: "6383"
subuid: "100999" subuid: "100999"
dependency:
web: "app-public"
db: "postgresql"
outline: outline:
domain: domain:
public: "outline" public: "outline"
@@ -148,6 +206,9 @@ services:
http: "3004" http: "3004"
redis: "6384" redis: "6384"
subuid: "101000" subuid: "101000"
dependency:
web: "app-public"
db: "postgresql"
memos: memos:
domain: domain:
public: "memos" public: "memos"
@@ -155,6 +216,9 @@ services:
ports: ports:
http: "3005" http: "3005"
subuid: "110000" subuid: "110000"
dependency:
web: "app-public"
db: "postgresql"
mealie: mealie:
domain: domain:
public: "mealie" public: "mealie"
@@ -162,6 +226,18 @@ services:
ports: ports:
http: "9001" http: "9001"
subuid: "100910" subuid: "100910"
dependency:
web: "app-public"
db: "postgresql"
homebox:
domain:
public: "homebox"
internal: "homebox.app"
ports:
http: "7745"
dependency:
web: "app-public"
db: "postgresql"
version: version:
packages: packages:
@@ -194,8 +270,9 @@ version:
immich: "v2.7.5" immich: "v2.7.5"
paperless: "2.20.15" paperless: "2.20.15"
nextcloud: "33.0.5" nextcloud: "33.0.5"
collabora: "25.04.10.3.1" collabora: "26.04.1.4.1"
sure: "0.7.1" sure: "0.7.1"
outline: "1.8.1" outline: "1.8.1"
memos: "0.29.1" memos: "0.29.1"
mealie: "v3.19.2" mealie: "v3.19.2"
homebox: "0.26.2"
+36 -9
View File
@@ -21,13 +21,40 @@ hardware:
bus: "0x00" bus: "0x00"
slot: "0x02" slot: "0x02"
function: "0x0" function: "0x0"
hdd: disk:
data: data:
hdd0: "WMC6N0E617S8" serials:
hdd1: "P6HVTL0W" - "WMC6N0E617S8"
hdd2: "P2GH354H" - "P6HVTL0W"
hdd3: "P6GJKSMP" - "P2GH354H"
btrfs: - "P6GJKSMP"
label: "DATA" fs:
level: "raid10" type: "btrfs"
mount_point: "{{ node['libvirt_path'] }}/data" label: "DATA"
mount_point: "{{ node['libvirt_path'] }}/disk/data"
mount_opts:
- "defaults"
- "noatime"
- "nodatacow"
- "degraded"
- "nofail"
btrfs:
data_profile: "raid10"
metadata_profile: "raid10"
min_devices: 4
backup:
serials:
- "6261S5G4S75H"
fs:
type: "btrfs"
label: "BACKUP"
mount_point: "{{ node['libvirt_path'] }}/disk/backup"
mount_opts:
- "defaults"
- "noatime"
- "nodatacow"
- "nofail"
btrfs:
data_profile: "single"
metadata_profile: "dup"
min_devices: 1
+1 -10
View File
@@ -24,17 +24,8 @@ vm:
storage: 256 storage: 256
data_storage: data_storage:
name: "vdb" name: "vdb"
pool: "data"
size: 3.5 size: 3.5
lan_mac: "0a:49:6e:4d:03:00" lan_mac: "0a:49:6e:4d:03:00"
lan_net: "lan-net" lan_net: "lan-net"
lan_group: "vlan10-access" lan_group: "vlan10-access"
# PCIe passthrough address
# result of `lspci | grep -i -e "sata controller" -e "vga"` and parse it.
# Ex) 04:00.0 > domain: "0x0000", bus: "0x04", slot: "0x00", function: "0x0"
pass_through:
igpu:
address: "0000:00:02.0"
domain: "0x0000"
bus: "0x00"
slot: "0x02"
function: "0x0"
+4 -4
View File
@@ -12,12 +12,12 @@ vm:
name: "auth" name: "auth"
cpu: 2 cpu: 2
cpu_pin: | cpu_pin: |
<vcpupin vcpu='0' cpuset='8'/> <vcpupin vcpu='0' cpuset='6'/>
<vcpupin vcpu='1' cpuset='9'/> <vcpupin vcpu='1' cpuset='7'/>
<emulatorpin cpuset='8-9'/> <emulatorpin cpuset='6-7'/>
shares: 1024 shares: 1024
memory: 2 memory: 2
storage: 64 storage: 32
lan_mac: "0a:49:6e:4d:02:00" lan_mac: "0a:49:6e:4d:02:00"
lan_net: "lan-net" lan_net: "lan-net"
lan_group: "vlan10-access" lan_group: "vlan10-access"
+27
View File
@@ -0,0 +1,27 @@
---
# Node Factors
node:
name: "bk"
group: "svadmins"
uid: 2009
home_path: "/home/bk"
ssh_san: "{{ node['name'] }},{{ node['name'] }}.{{ domain['internal'] }}"
local_san: "localhost {{ node['name'] }}.{{ domain['internal'] }}"
# VM Factors
vm:
name: "bk"
cpu: 2
cpu_pin: |
<vcpupin vcpu='0' cpuset='6'/>
<vcpupin vcpu='1' cpuset='7'/>
<emulatorpin cpuset='6-7'/>
shares: 512
memory: 2
storage: 32
data_storage:
name: "vdb"
pool: "backup"
size: 3.5
lan_mac: "0a:49:6e:4d:09:00"
lan_net: "lan-net"
lan_group: "vlan10-access"
+1 -1
View File
@@ -21,6 +21,6 @@ node:
data_path: "{{ node['homelab_path'] }}/data" data_path: "{{ node['homelab_path'] }}/data"
config_path: "{{ node['homelab_path'] }}/config" config_path: "{{ node['homelab_path'] }}/config"
ssh_san: "{{ node['name'] }},{{ node['name'] }}.{{ domain['internal'] }}" ssh_san: "{{ node['name'] }},{{ node['name'] }}.{{ domain['internal'] }}"
ssh_users: "vmm,fw,infra,auth,app" ssh_users: "vmm,fw,bk,infra,auth,app"
# add the hostname of wsl, it is needed to improve the sudo problem # add the hostname of wsl, it is needed to improve the sudo problem
local_san: "localhost {{ node['name'] }} {{ node['name'] }}.{{ domain['internal'] }}" local_san: "localhost {{ node['name'] }} {{ node['name'] }}.{{ domain['internal'] }}"
+4 -8
View File
@@ -52,6 +52,8 @@ network4:
vmm: vmm:
client: "192.168.1.10" client: "192.168.1.10"
server: "192.168.10.10" server: "192.168.10.10"
bk:
server: "192.168.10.9"
infra: infra:
server: "192.168.10.11" server: "192.168.10.11"
auth: auth:
@@ -60,8 +62,6 @@ network4:
server: "192.168.10.13" server: "192.168.10.13"
switch: switch:
client: "192.168.1.2" client: "192.168.1.2"
nas:
client: "192.168.1.11"
printer: printer:
client: "192.168.1.101" client: "192.168.1.101"
@@ -85,18 +85,14 @@ network6:
vmm: vmm:
client: "fd00:1::10" client: "fd00:1::10"
server: "fd00:10::10" server: "fd00:10::10"
bk:
server: "fd00:10::9"
infra: infra:
server: "fd00:10::11" server: "fd00:10::11"
auth: auth:
server: "fd00:10::12" server: "fd00:10::12"
app: app:
server: "fd00:10::13" server: "fd00:10::13"
switch:
client: "fd00:1::2"
nas:
client: "fd00:1::11"
printer:
client: "fd00:1::101"
# Suricata Factors # Suricata Factors
# suricata_home_net: '[10.0.0.0/8,172.16.0.0/12,192.168.0.0/16]' # suricata_home_net: '[10.0.0.0/8,172.16.0.0/12,192.168.0.0/16]'
+4 -4
View File
@@ -15,11 +15,11 @@ vm:
cpu_pin: | cpu_pin: |
<vcpupin vcpu='0' cpuset='2'/> <vcpupin vcpu='0' cpuset='2'/>
<vcpupin vcpu='1' cpuset='3'/> <vcpupin vcpu='1' cpuset='3'/>
<vcpupin vcpu='2' cpuset='6'/> <vcpupin vcpu='2' cpuset='8'/>
<vcpupin vcpu='3' cpuset='7'/> <vcpupin vcpu='3' cpuset='9'/>
<emulatorpin cpuset='6-7'/> <emulatorpin cpuset='8-9'/>
shares: 2048 shares: 2048
memory: 6 memory: 4
storage: 256 storage: 256
lan_mac: "0a:49:6e:4d:01:00" lan_mac: "0a:49:6e:4d:01:00"
lan_net: "lan-net" lan_net: "lan-net"
+1
View File
@@ -9,6 +9,7 @@ vmm ansible_host=vmm.ilnmors.internal ansible_user=vmm
# --- Virtual Machines --- # --- Virtual Machines ---
[vms] [vms]
fw ansible_host=fw.ilnmors.internal ansible_user=fw fw ansible_host=fw.ilnmors.internal ansible_user=fw
bk ansible_host=bk.ilnmors.internal ansible_user=bk
infra ansible_host=infra.ilnmors.internal ansible_user=infra infra ansible_host=infra.ilnmors.internal ansible_user=infra
auth ansible_host=auth.ilnmors.internal ansible_user=auth auth ansible_host=auth.ilnmors.internal ansible_user=auth
app ansible_host=app.ilnmors.internal ansible_user=app app ansible_host=app.ilnmors.internal ansible_user=app
+17 -1
View File
@@ -78,6 +78,14 @@
tags: ["init", "resolved"] tags: ["init", "resolved"]
tags: ["init", "resolved"] tags: ["init", "resolved"]
- name: Set timesyncd
ansible.builtin.include_role:
name: "common"
tasks_from: "node/set_timesyncd"
apply:
tags: ["init", "timesyncd"]
tags: ["init", "timesyncd"]
- name: Update and upgrade apt - name: Update and upgrade apt
ansible.builtin.apt: ansible.builtin.apt:
upgrade: "dist" upgrade: "dist"
@@ -100,7 +108,7 @@
- name: Set data volume - name: Set data volume
ansible.builtin.include_role: ansible.builtin.include_role:
name: "app" name: "common"
tasks_from: "node/set_data_volume" tasks_from: "node/set_data_volume"
apply: apply:
tags: ["init", "raid"] tags: ["init", "raid"]
@@ -242,6 +250,14 @@
tags: ["site", "mealie"] tags: ["site", "mealie"]
tags: ["site", "mealie"] tags: ["site", "mealie"]
- name: Set homebox
ansible.builtin.include_role:
name: "app"
tasks_from: "services/set_homebox"
apply:
tags: ["site", "homebox"]
tags: ["site", "homebox"]
- name: Flush handlers right now - name: Flush handlers right now
ansible.builtin.meta: "flush_handlers" ansible.builtin.meta: "flush_handlers"
+8
View File
@@ -78,6 +78,14 @@
tags: ["init", "resolved"] tags: ["init", "resolved"]
tags: ["init", "resolved"] tags: ["init", "resolved"]
- name: Set timesyncd
ansible.builtin.include_role:
name: "common"
tasks_from: "node/set_timesyncd"
apply:
tags: ["init", "timesyncd"]
tags: ["init", "timesyncd"]
- name: Update and upgrade apt - name: Update and upgrade apt
ansible.builtin.apt: ansible.builtin.apt:
upgrade: "dist" upgrade: "dist"
+163
View File
@@ -0,0 +1,163 @@
---
- name: Load secret values
hosts: "console"
gather_facts: false
become: false
tasks:
- name: Load secret from secrets.yaml
ansible.builtin.include_role:
name: "console"
tasks_from: "node/load_secret_vars"
apply:
tags: ["always"]
tags: ["always"]
- name: Site bk
hosts: "bk"
gather_facts: false
become: false
pre_tasks:
- name: Set become password
ansible.builtin.set_fact:
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['bk'] }}"
no_log: true
tags: ["always"]
tasks:
- name: Set timezone
community.general.timezone:
name: "{{ timezone }}"
become: true
tags: ["init", "timezone"]
- name: Deploy root_ca certificate
ansible.builtin.include_role:
name: "common"
tasks_from: "node/deploy_root_ca"
apply:
tags: ["init", "root_crt"]
tags: ["init", "root_crt"]
- name: Deploy hosts file
ansible.builtin.include_role:
name: "common"
tasks_from: "node/deploy_hosts"
apply:
tags: ["init", "hosts"]
tags: ["init", "hosts"]
- name: Create default directory
ansible.builtin.include_role:
name: "common"
tasks_from: "node/create_default_dir"
apply:
tags: ["init", "default_dir"]
tags: ["init", "default_dir"]
- name: Set ssh host
ansible.builtin.include_role:
name: "common"
tasks_from: "node/set_ssh_host"
apply:
tags: ["init", "ssh_host"]
tags: ["init", "ssh_host"]
- name: Set networkd
ansible.builtin.include_role:
name: "common"
tasks_from: "node/set_networkd"
apply:
tags: ["init", "networkd"]
tags: ["init", "networkd"]
- name: Set resolved
ansible.builtin.include_role:
name: "common"
tasks_from: "node/set_resolved"
apply:
tags: ["init", "resolved"]
tags: ["init", "resolved"]
- name: Set timesyncd
ansible.builtin.include_role:
name: "common"
tasks_from: "node/set_timesyncd"
apply:
tags: ["init", "timesyncd"]
tags: ["init", "timesyncd"]
- name: Update and upgrade apt
ansible.builtin.apt:
upgrade: "dist"
update_cache: true
cache_valid_time: 3600
become: true
tags: ["init", "site", "upgrade-packages"]
- name: Install common packages
ansible.builtin.apt:
name:
- "acl"
- "curl"
- "jq"
- "netcat-openbsd"
- "dbus-user-session"
state: "present"
become: true
tags: ["init", "site", "install-packages"]
- name: Set data volume
ansible.builtin.include_role:
name: "common"
tasks_from: "node/set_data_volume"
apply:
tags: ["init", "raid"]
tags: ["init", "raid"]
- name: Set linger
ansible.builtin.include_role:
name: "common"
tasks_from: "node/set_linger"
apply:
tags: ["init", "linger"]
tags: ["init", "linger"]
- name: Set nftables
ansible.builtin.include_role:
name: "common"
tasks_from: "node/set_nftables"
apply:
tags: ["init", "nftables"]
tags: ["init", "nftables"]
- name: Set crowdsec
ansible.builtin.include_role:
name: "common"
tasks_from: "services/set_crowdsec"
apply:
tags: ["site", "crowdsec"]
tags: ["site", "crowdsec"]
- name: Set kopia
ansible.builtin.include_role:
name: "common"
tasks_from: "services/set_kopia"
apply:
tags: ["site", "kopia"]
tags: ["site", "kopia"]
- name: Set rclone
ansible.builtin.include_role:
name: "bk"
tasks_from: "services/set_rclone"
apply:
tags: ["site", "rclone"]
tags: ["site", "rclone"]
- name: Set alloy
ansible.builtin.include_role:
name: "common"
tasks_from: "services/set_alloy"
apply:
tags: ["site", "alloy"]
tags: ["site", "alloy"]
+223
View File
@@ -0,0 +1,223 @@
---
- name: Load secret values
hosts: "console"
gather_facts: false
become: false
tasks:
- name: Load secret from secrets.yaml
ansible.builtin.include_role:
name: "console"
tasks_from: "node/load_secret_vars"
apply:
tags: ["always"]
tags: ["always"]
- name: Site console
hosts: "console"
gather_facts: false
become: false
tasks:
- name: Create root CA
tags: ["never", "root"]
block:
- name: Clean previous CA temporary directory
ansible.builtin.file:
path: "/run/user/{{ node['uid'] }}/ca"
state: "absent"
no_log: true
- name: Create ca directory
ansible.builtin.file:
path: "/run/user/{{ node['uid'] }}/ca"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
state: "directory"
mode: "0700"
- name: Get root CA password
ansible.builtin.copy:
content: |
{{ hostvars['console']['ca']['root']['password'] }}
dest: "/run/user/{{ node['uid'] }}/ca/root_ca.password"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0400"
no_log: true
- name: Create root CA
ansible.builtin.command: |
step certificate create \
"{{ domain['internal'] }} Root CA" \
/run/user/{{ node['uid'] }}/ca/root_ca.crt \
/run/user/{{ node['uid'] }}/ca/root_ca.key \
--password-file /run/user/{{ node['uid'] }}/ca/root_ca.password \
--profile root-ca \
--not-after 87600h
changed_when: true
no_log: true
- name: Update root CA
environment:
SOPS_AGE_KEY: "{{ hostvars['console']['age_key'] }}"
ansible.builtin.shell: |
set -euo pipefail
jq -Rs . "/run/user/{{ node['uid'] }}/ca/root_ca.crt" \
| sops set --value-stdin "{{ hostvars['console']['node']['config_path'] }}/secrets/secrets.yaml" \
'["ca"]["root"]["crt"]'
jq -Rs . "/run/user/{{ node['uid'] }}/ca/root_ca.key" \
| sops set --value-stdin "{{ hostvars['console']['node']['config_path'] }}/secrets/secrets.yaml" \
'["ca"]["root"]["key"]'
changed_when: true
no_log: true
always:
- name: Clean temporary files
ansible.builtin.file:
path: "/run/user/{{ node['uid'] }}/ca"
state: "absent"
no_log: true
- name: Get root CA and create intermediate CA
tags: ["never", "intermediate"]
block:
- name: Clean previous CA temporary directory
ansible.builtin.file:
path: "/run/user/{{ node['uid'] }}/ca"
state: "absent"
no_log: true
- name: Create ca certificates directory
ansible.builtin.file:
path: "/run/user/{{ node['uid'] }}/ca"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
state: "directory"
mode: "0700"
- name: Get root key and cert and password
ansible.builtin.copy:
content: |
{{ hostvars['console']['ca']['root'][item] }}
dest: "/run/user/{{ node['uid'] }}/ca/root_ca.{{ item }}"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0400"
loop:
- "key"
- "crt"
- "password"
no_log: true
- name: Get intermediate CA password
ansible.builtin.copy:
content: |
{{ hostvars['console']['ca']['intermediate']['password'] }}
dest: "/run/user/{{ node['uid'] }}/ca/intermediate_ca.password"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0400"
no_log: true
- name: Create intermediate CA
ansible.builtin.command: |
step certificate create \
"{{ domain['internal'] }} intermediate CA" \
/run/user/{{ node['uid'] }}/ca/intermediate_ca.crt \
/run/user/{{ node['uid'] }}/ca/intermediate_ca.key \
--password-file /run/user/{{ node['uid'] }}/ca/intermediate_ca.password \
--profile intermediate-ca \
--ca /run/user/{{ node['uid'] }}/ca/root_ca.crt \
--ca-key /run/user/{{ node['uid'] }}/ca/root_ca.key \
--ca-password-file /run/user/{{ node['uid'] }}/ca/root_ca.password \
--not-after 43800h
changed_when: true
no_log: true
- name: Update intermediate CA
environment:
SOPS_AGE_KEY: "{{ hostvars['console']['age_key'] }}"
ansible.builtin.shell: |
set -euo pipefail
jq -Rs . "/run/user/{{ node['uid'] }}/ca/intermediate_ca.crt" \
| sops set --value-stdin "{{ hostvars['console']['node']['config_path'] }}/secrets/secrets.yaml" \
'["ca"]["intermediate"]["crt"]'
jq -Rs . "/run/user/{{ node['uid'] }}/ca/intermediate_ca.key" \
| sops set --value-stdin "{{ hostvars['console']['node']['config_path'] }}/secrets/secrets.yaml" \
'["ca"]["intermediate"]["key"]'
changed_when: true
no_log: true
always:
- name: Clean temporary files
ansible.builtin.file:
path: "/run/user/{{ node['uid'] }}/ca"
state: "absent"
no_log: true
- name: Get intermediate CA and create leaf cert
tags: ["never", "leaf"]
block:
- name: Initialize self-cert services list
ansible.builtin.set_fact:
cert_services: []
- name: Set self-cert services list
ansible.builtin.set_fact:
cert_services: >-
{{
services
| dict2items
| selectattr('value.dependency.cert', 'defined')
| selectattr('value.dependency.cert', 'equalto', true)
| map(attribute='key')
| list
}}
- name: Clean previous leaf temporary directory
ansible.builtin.file:
path: "/run/user/{{ node['uid'] }}/leaf"
state: "absent"
no_log: true
- name: Create leaf certificates directory
ansible.builtin.file:
path: "/run/user/{{ node['uid'] }}/leaf"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
state: "directory"
mode: "0700"
- name: Get intermediate key and cert and password
ansible.builtin.copy:
content: |
{{ hostvars['console']['ca']['intermediate'][item] }}
dest: "/run/user/{{ node['uid'] }}/leaf/intermediate_ca.{{ item }}"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0400"
loop:
- "key"
- "crt"
- "password"
no_log: true
- name: Create leaf certificates
ansible.builtin.command: |
step certificate create \
"{{ services[item]['domain']['internal'] }}.{{ domain['internal'] }}" \
/run/user/{{ node['uid'] }}/leaf/{{ item }}.crt \
/run/user/{{ node['uid'] }}/leaf/{{ item }}.key \
--profile leaf \
--san {{ services[item]['domain']['internal'] }}.{{ domain['internal'] }} \
--ca /run/user/{{ node['uid'] }}/leaf/intermediate_ca.crt \
--ca-key /run/user/{{ node['uid'] }}/leaf/intermediate_ca.key \
--ca-password-file /run/user/{{ node['uid'] }}/leaf/intermediate_ca.password \
--not-after 21900h \
--insecure --no-password
loop: "{{ cert_services }}"
changed_when: true
no_log: true
- name: Update leaf keys and certificates
environment:
SOPS_AGE_KEY: "{{ hostvars['console']['age_key'] }}"
ansible.builtin.shell: |
set -euo pipefail
jq -Rs . "/run/user/{{ node['uid'] }}/leaf/{{ item }}.crt" \
| sops set --value-stdin "{{ hostvars['console']['node']['config_path'] }}/secrets/secrets.yaml" \
'["{{ item }}"]["crt"]'
jq -Rs . "/run/user/{{ node['uid'] }}/leaf/{{ item }}.key" \
| sops set --value-stdin "{{ hostvars['console']['node']['config_path'] }}/secrets/secrets.yaml" \
'["{{ item }}"]["key"]'
loop: "{{ cert_services }}"
changed_when: true
no_log: true
always:
- name: Clean temporary files
ansible.builtin.file:
path: "/run/user/{{ node['uid'] }}/leaf"
state: "absent"
no_log: true
+2 -2
View File
@@ -108,8 +108,8 @@
ansible.builtin.get_url: ansible.builtin.get_url:
url: "https://cdimage.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2" url: "https://cdimage.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2"
dest: "{{ node['data_path'] }}/images/debian-13-generic-amd64.qcow2" dest: "{{ node['data_path'] }}/images/debian-13-generic-amd64.qcow2"
owner: "console" owner: "{{ ansible_user }}"
group: "svadmins" group: "{{ node['group'] }}"
mode: "0600" mode: "0600"
tags: ["init", "site", "cloud-init-image"] tags: ["init", "site", "cloud-init-image"]
+8
View File
@@ -78,6 +78,14 @@
tags: ["init", "resolved"] tags: ["init", "resolved"]
tags: ["init", "resolved"] tags: ["init", "resolved"]
- name: Set timesyncd
ansible.builtin.include_role:
name: "common"
tasks_from: "node/set_timesyncd"
apply:
tags: ["init", "timesyncd"]
tags: ["init", "timesyncd"]
- name: Update and upgrade apt - name: Update and upgrade apt
ansible.builtin.apt: ansible.builtin.apt:
upgrade: "dist" upgrade: "dist"
+1
View File
@@ -19,6 +19,7 @@
vars: vars:
valid_vm_names: valid_vm_names:
- "fw" - "fw"
- "bk"
- "infra" - "infra"
- "auth" - "auth"
- "app" - "app"
+1 -1
View File
@@ -104,7 +104,7 @@
- name: Set raid - name: Set raid
ansible.builtin.include_role: ansible.builtin.include_role:
name: "vmm" name: "vmm"
tasks_from: "node/set_raid" tasks_from: "node/set_disk"
apply: apply:
tags: ["init", "raid"] tags: ["init", "raid"]
tags: ["init", "raid"] tags: ["init", "raid"]
+11
View File
@@ -124,3 +124,14 @@
changed_when: false changed_when: false
listen: "notification_restart_mealie" listen: "notification_restart_mealie"
ignore_errors: true # noqa: ignore-errors ignore_errors: true # noqa: ignore-errors
- name: Restart homebox
ansible.builtin.systemd:
name: "homebox.service"
state: "restarted"
enabled: true
scope: "user"
daemon_reload: true
changed_when: false
listen: "notification_restart_homebox"
ignore_errors: true # noqa: ignore-errors
@@ -1,4 +1,11 @@
--- ---
- name: Pull image
containers.podman.podman_image:
name: "docker.io/collabora/code"
tag: "{{ version['containers']['collabora'] }}"
state: "present"
pull: true
- name: Deploy container file - name: Deploy container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/collabora/collabora.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/collabora/collabora.container.j2"
@@ -8,6 +8,7 @@
mode: "0770" mode: "0770"
loop: loop:
- "data/containers/gitea" - "data/containers/gitea"
- "data/containers/gitea/data"
- "containers/gitea" - "containers/gitea"
- "containers/gitea/ssl" - "containers/gitea/ssl"
become: true become: true
@@ -33,6 +34,13 @@
notify: "notification_restart_gitea" notify: "notification_restart_gitea"
no_log: true no_log: true
- name: Pull image
containers.podman.podman_image:
name: "docker.io/gitea/gitea"
tag: "{{ version['containers']['gitea'] }}"
state: "present"
pull: true
- name: Deploy container file - name: Deploy container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/gitea/gitea.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/gitea/gitea.container.j2"
@@ -0,0 +1,86 @@
---
- name: Create homebox directory
ansible.builtin.file:
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "data/containers/homebox"
- "data/containers/homebox/data"
- "containers/homebox"
- "containers/homebox/ssl"
become: true
- name: Deploy root certificate
ansible.builtin.copy:
content: |
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/homebox/ssl/{{ root_cert_filename }}"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0440"
become: true
notify: "notification_restart_homebox"
no_log: true
- name: Register secret value to podman secret
containers.podman.podman_secret:
name: "{{ item.name }}"
data: "{{ item.value }}"
state: "present"
force: true
loop:
- name: "HBOX_AUTH_API_KEY_PEPPER"
value: "{{ hostvars['console']['homebox']['api_secret'] }}"
- name: "HBOX_DATABASE_PASSWORD"
value: "{{ hostvars['console']['postgresql']['password']['homebox'] }}"
- name: "HBOX_OIDC_CLIENT_SECRET"
value: "{{ hostvars['console']['homebox']['oidc']['secret'] }}"
notify: "notification_restart_homebox"
no_log: true
- name: Pull image
containers.podman.podman_image:
name: "ghcr.io/sysadminsmedia/homebox"
tag: "{{ version['containers']['homebox'] }}"
state: "present"
pull: true
- name: Deploy homebox.container file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/homebox/homebox.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/homebox.container"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_homebox"
- name: Enable homebox.service
ansible.builtin.systemd:
name: "homebox.service"
state: "started"
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/ghcr.io_sysadminsmedia_homebox_{{ version['containers']['homebox'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "ghcr.io/sysadminsmedia/homebox:{{ version['containers']['homebox'] }}"
dest: "{{ node['home_path'] }}/archives/containers/ghcr.io_sysadminsmedia_homebox_{{ version['containers']['homebox'] }}.tar"
format: "oci-archive"
force: false
when: not container_archive_images.stat.exists
- name: Fetch container archive images
ansible.builtin.fetch:
src: "{{ node['home_path'] }}/archives/containers/ghcr.io_sysadminsmedia_homebox_{{ version['containers']['homebox'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -60,6 +60,7 @@
mode: "0770" mode: "0770"
loop: loop:
- "data/containers/immich" - "data/containers/immich"
- "data/containers/immich/data"
- "containers/immich" - "containers/immich"
- "containers/immich/ssl" - "containers/immich/ssl"
- "containers/immich/ml" - "containers/immich/ml"
@@ -85,6 +86,22 @@
notify: "notification_restart_immich" notify: "notification_restart_immich"
no_log: true no_log: true
- name: Pull image
containers.podman.podman_image:
name: "{{ item.image }}"
tag: "{{ item.tag }}"
state: "present"
pull: true
loop:
- name: "immich_ml"
image: "ghcr.io/immich-app/immich-machine-learning"
tag: "{{ version['containers']['immich'] }}-openvino"
- name: "immich"
image: "ghcr.io/immich-app/immich-server"
tag: "{{ version['containers']['immich'] }}"
loop_control:
label: "{{ item.name }}"
- name: Deploy immich.container file - name: Deploy immich.container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/immich/immich.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/immich/immich.container.j2"
@@ -123,14 +140,17 @@
ansible.builtin.stat: ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar" path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
loop: loop:
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}" - name: "redis"
image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
file: "docker.io_library_redis_{{ version['containers']['redis'] }}" file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
- image: "ghcr.io/immich-app/immich-machine-learning:{{ version['containers']['immich'] }}-openvino" - name: "immich_ml"
image: "ghcr.io/immich-app/immich-machine-learning:{{ version['containers']['immich'] }}-openvino"
file: "ghcr.io_immich-app_immich-machine-learning_{{ version['containers']['immich'] }}-openvino" file: "ghcr.io_immich-app_immich-machine-learning_{{ version['containers']['immich'] }}-openvino"
- image: "ghcr.io/immich-app/immich-server:{{ version['containers']['immich'] }}" - name: "immich"
image: "ghcr.io/immich-app/immich-server:{{ version['containers']['immich'] }}"
file: "ghcr.io_immich-app_immich-server_{{ version['containers']['immich'] }}" file: "ghcr.io_immich-app_immich-server_{{ version['containers']['immich'] }}"
loop_control: loop_control:
label: "{{ item.file }}" label: "{{ item.name }}"
register: container_archive_images register: container_archive_images
- name: Save container archive images - name: Save container archive images
@@ -39,6 +39,13 @@
notify: "notification_restart_mealie" notify: "notification_restart_mealie"
no_log: true no_log: true
- name: Pull image
containers.podman.podman_image:
name: "ghcr.io/mealie-recipes/mealie"
tag: "{{ version['containers']['mealie'] }}"
state: "present"
pull: true
- name: Deploy mealie.container file - name: Deploy mealie.container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/mealie/mealie.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/mealie/mealie.container.j2"
@@ -29,13 +29,20 @@
containers.podman.podman_secret: containers.podman.podman_secret:
name: "MEMOS_DSN" name: "MEMOS_DSN"
data: "postgresql://memos:{{ hostvars['console']['postgresql']['password']['memos'] | urlencode | replace('/', '%2F') }}\ data: "postgresql://memos:{{ hostvars['console']['postgresql']['password']['memos'] | urlencode | replace('/', '%2F') }}\
@{{ services['postgresql']['domain'] }}.{{ domain['internal'] }}/memos_db?sslmode=verify-full&\ @{{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}/memos_db?sslmode=verify-full&\
sslrootcert=/etc/ssl/memos/{{ root_cert_filename }}" sslrootcert=/etc/ssl/memos/{{ root_cert_filename }}"
state: "present" state: "present"
force: true force: true
no_log: true no_log: true
notify: "notification_restart_memos" notify: "notification_restart_memos"
- name: Pull image
containers.podman.podman_image:
name: "docker.io/neosmemo/memos"
tag: "{{ version['containers']['memos'] }}"
state: "present"
pull: true
- name: Deploy memos.container file - name: Deploy memos.container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/memos/memos.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/memos/memos.container.j2"
@@ -90,7 +90,7 @@
NEXTCLOUD_UPDATE: "1" NEXTCLOUD_UPDATE: "1"
NEXTCLOUD_ADMIN_USER: "{{ hostvars['console']['nextcloud']['admin']['id'] }}" NEXTCLOUD_ADMIN_USER: "{{ hostvars['console']['nextcloud']['admin']['id'] }}"
NEXTCLOUD_ADMIN_PASSWORD: "{{ hostvars['console']['nextcloud']['admin']['password'] }}" NEXTCLOUD_ADMIN_PASSWORD: "{{ hostvars['console']['nextcloud']['admin']['password'] }}"
POSTGRES_HOST: "{{ services['postgresql']['domain'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }}" POSTGRES_HOST: "{{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }}"
POSTGRES_DB: "nextcloud_db" POSTGRES_DB: "nextcloud_db"
POSTGRES_USER: "nextcloud" POSTGRES_USER: "nextcloud"
POSTGRES_PASSWORD: "{{ hostvars['console']['postgresql']['password']['nextcloud'] }}" POSTGRES_PASSWORD: "{{ hostvars['console']['postgresql']['password']['nextcloud'] }}"
@@ -139,6 +139,13 @@
- "upload.ini" - "upload.ini"
notify: "notification_restart_nextcloud" notify: "notification_restart_nextcloud"
- name: Pull image
containers.podman.podman_image:
name: "docker.io/library/nextcloud"
tag: "{{ version['containers']['nextcloud'] }}"
state: "present"
pull: true
- name: Deploy nextcloud.container file - name: Deploy nextcloud.container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/nextcloud/nextcloud.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/nextcloud/nextcloud.container.j2"
@@ -179,12 +186,14 @@
ansible.builtin.stat: ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar" path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
loop: loop:
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}" - name: "redis"
image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
file: "docker.io_library_redis_{{ version['containers']['redis'] }}" file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
- image: "docker.io/library/nextcloud:{{ version['containers']['nextcloud'] }}" - name: "nextcloud"
image: "docker.io/library/nextcloud:{{ version['containers']['nextcloud'] }}"
file: "docker.io_library_nextcloud_{{ version['containers']['nextcloud'] }}" file: "docker.io_library_nextcloud_{{ version['containers']['nextcloud'] }}"
loop_control: loop_control:
label: "{{ item.file }}" label: "{{ item.name }}"
register: container_archive_images register: container_archive_images
- name: Save container archive images - name: Save container archive images
@@ -101,6 +101,13 @@
notify: "notification_restart_outline" notify: "notification_restart_outline"
no_log: true no_log: true
- name: Pull image
containers.podman.podman_image:
name: "docker.io/outlinewiki/outline"
tag: "{{ version['containers']['outline'] }}"
state: "present"
pull: true
- name: Deploy outline.container file - name: Deploy outline.container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/outline/outline.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/outline/outline.container.j2"
@@ -122,12 +129,14 @@
ansible.builtin.stat: ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar" path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
loop: loop:
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}" - name: "redis"
image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
file: "docker.io_library_redis_{{ version['containers']['redis'] }}" file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
- image: "docker.io/outlinewiki/outline:{{ version['containers']['outline'] }}" - name: "outline"
image: "docker.io/outlinewiki/outline:{{ version['containers']['outline'] }}"
file: "docker.io_outlinewiki_outline_{{ version['containers']['outline'] }}" file: "docker.io_outlinewiki_outline_{{ version['containers']['outline'] }}"
loop_control: loop_control:
label: "{{ item.file }}" label: "{{ item.name }}"
register: container_archive_images register: container_archive_images
- name: Save container archive images - name: Save container archive images
@@ -67,6 +67,8 @@
owner: "{{ ansible_user }}" owner: "{{ ansible_user }}"
group: "{{ node['group'] }}" group: "{{ node['group'] }}"
mode: "0640" mode: "0640"
register: "is_paperless_containerfile"
notify: "notification_restart_paperless"
- name: Deploy root certificate - name: Deploy root certificate
ansible.builtin.copy: ansible.builtin.copy:
@@ -87,6 +89,7 @@
tag: "{{ version['containers']['paperless'] }}" tag: "{{ version['containers']['paperless'] }}"
state: "build" state: "build"
path: "{{ node['home_path'] }}/containers/paperless/build" path: "{{ node['home_path'] }}/containers/paperless/build"
force: "{{ is_paperless_containerfile.changed }}"
- name: Prune paperless dangling images - name: Prune paperless dangling images
containers.podman.podman_prune: containers.podman.podman_prune:
@@ -116,7 +119,7 @@
"client_id": "paperless", "client_id": "paperless",
"secret": "{{ hostvars['console']['paperless']['oidc']['secret'] }}", "secret": "{{ hostvars['console']['paperless']['oidc']['secret'] }}",
"settings": { "settings": {
"server_url": "https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}/.well-known/openid-configuration", "server_url": "https://{{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}/.well-known/openid-configuration",
"token_auth_method": "client_secret_post" "token_auth_method": "client_secret_post"
} }
} }
@@ -147,12 +150,14 @@
ansible.builtin.stat: ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar" path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
loop: loop:
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}" - name: "redis"
image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
file: "docker.io_library_redis_{{ version['containers']['redis'] }}" file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
- image: "{{ domain['internal'] }}/{{ node['name'] }}/paperless-ngx:{{ version['containers']['paperless'] }}" - name: "paperless"
image: "{{ domain['internal'] }}/{{ node['name'] }}/paperless-ngx:{{ version['containers']['paperless'] }}"
file: "{{ domain['internal'] }}_{{ node['name'] }}_paperless-ngx_{{ version['containers']['paperless'] }}" file: "{{ domain['internal'] }}_{{ node['name'] }}_paperless-ngx_{{ version['containers']['paperless'] }}"
loop_control: loop_control:
label: "{{ item.file }}" label: "{{ item.name }}"
register: container_archive_images register: container_archive_images
- name: Save container archive images - name: Save container archive images
@@ -161,11 +166,11 @@
- "{{ item.item.image }}" - "{{ item.item.image }}"
dest: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar" dest: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
format: "oci-archive" format: "oci-archive"
force: false force: "{{ is_paperless_containerfile.changed }}"
loop: "{{ container_archive_images.results }}" loop: "{{ container_archive_images.results }}"
loop_control: loop_control:
label: "{{ item.item.file }}" label: "{{ item.item.file }}"
when: not item.stat.exists when: not item.stat.exists or (item.item.name == 'paperless' and is_paperless_containerfile.changed)
- name: Fetch container archive images - name: Fetch container archive images
ansible.builtin.fetch: ansible.builtin.fetch:
+12 -3
View File
@@ -86,6 +86,13 @@
notify: "notification_restart_sure" notify: "notification_restart_sure"
no_log: true no_log: true
- name: Pull image
containers.podman.podman_image:
name: "ghcr.io/we-promise/sure"
tag: "{{ version['containers']['sure'] }}"
state: "present"
pull: true
- name: Deploy sure.container file - name: Deploy sure.container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/sure/{{ item }}.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/sure/{{ item }}.j2"
@@ -113,12 +120,14 @@
ansible.builtin.stat: ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar" path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
loop: loop:
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}" - name: "redis"
image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
file: "docker.io_library_redis_{{ version['containers']['redis'] }}" file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
- image: "ghcr.io/we-promise/sure:{{ version['containers']['sure'] }}" - name: "sure"
image: "ghcr.io/we-promise/sure:{{ version['containers']['sure'] }}"
file: "ghcr.io_we-promise_sure_{{ version['containers']['sure'] }}" file: "ghcr.io_we-promise_sure_{{ version['containers']['sure'] }}"
loop_control: loop_control:
label: "{{ item.file }}" label: "{{ item.name }}"
register: container_archive_images register: container_archive_images
- name: Save container archive images - name: Save container archive images
@@ -8,6 +8,7 @@
mode: "0770" mode: "0770"
loop: loop:
- "data/containers/vaultwarden" - "data/containers/vaultwarden"
- "data/containers/vaultwarden/data"
- "containers/vaultwarden" - "containers/vaultwarden"
- "containers/vaultwarden/ssl" - "containers/vaultwarden/ssl"
@@ -34,11 +35,18 @@
value: "{{ hostvars['console']['vaultwarden']['admin']['hash'] }}" value: "{{ hostvars['console']['vaultwarden']['admin']['hash'] }}"
- name: "VW_DATABASE_URL" - name: "VW_DATABASE_URL"
value: "postgresql://vaultwarden:{{ hostvars['console']['postgresql']['password']['vaultwarden'] | urlencode | replace('/', '%2F') }}\ value: "postgresql://vaultwarden:{{ hostvars['console']['postgresql']['password']['vaultwarden'] | urlencode | replace('/', '%2F') }}\
@{{ services['postgresql']['domain'] }}.{{ domain['internal'] }}/vaultwarden_db?sslmode=verify-full&\ @{{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}/vaultwarden_db?sslmode=verify-full&\
sslrootcert=/etc/ssl/vaultwarden/{{ root_cert_filename }}" sslrootcert=/etc/ssl/vaultwarden/{{ root_cert_filename }}"
notify: "notification_restart_vaultwarden" notify: "notification_restart_vaultwarden"
no_log: true no_log: true
- name: Pull image
containers.podman.podman_image:
name: "docker.io/vaultwarden/server"
tag: "{{ version['containers']['vaultwarden'] }}"
state: "present"
pull: true
- name: Deploy container file - name: Deploy container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/vaultwarden/vaultwarden.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/vaultwarden/vaultwarden.container.j2"
@@ -60,6 +60,13 @@
notify: "notification_restart_authelia" notify: "notification_restart_authelia"
no_log: true no_log: true
- name: Pull image
containers.podman.podman_image:
name: "docker.io/authelia/authelia"
tag: "{{ version['containers']['authelia'] }}"
state: "present"
pull: true
- name: Deploy container file - name: Deploy container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/auth/authelia/authelia.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/auth/authelia/authelia.container.j2"
@@ -0,0 +1,54 @@
---
- name: Check rclone installation
ansible.builtin.shell: |
command -v rclone
changed_when: false
failed_when: false
register: "is_rclone_installed"
ignore_errors: true
- name: Install rclone
ansible.builtin.apt:
name:
- "rclone"
state: "present"
become: true
when: is_rclone_installed.rc != 0
- name: Create rclone config directory
ansible.builtin.file:
path: "/etc/secrets/{{ node['uid'] }}/rclone"
state: "directory"
owner: "{{ ansible_user }}"
group: "root"
mode: "0700"
become: true
- name: Deploy rclone config
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/bk/rclone/config/rclone.config.j2"
dest: "/etc/secrets/{{ node['uid'] }}/rclone/rclone.config"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0600"
no_log: true
- name: Deploy rclone backup service files
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/bk/rclone/{{ item }}.j2"
dest: "{{ node['home_path'] }}/.config/systemd/user/{{ item }}"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
validate: "/usr/bin/systemd-analyze verify %s"
loop:
- "rclone.service"
- "rclone.timer"
- name: Enable rclone timer
ansible.builtin.systemd:
name: "rclone.timer"
state: "started"
enabled: true
scope: "user"
daemon_reload: true
+11
View File
@@ -99,3 +99,14 @@
changed_when: false changed_when: false
listen: "notification_restart_alloy" listen: "notification_restart_alloy"
ignore_errors: true # noqa: ignore-errors ignore_errors: true # noqa: ignore-errors
- name: Restart kopia server
ansible.builtin.systemd:
name: "kopia-server.service"
state: "restarted"
enabled: true
scope: "user"
daemon_reload: true
changed_when: false
listen: "notification_restart_kopia_server"
ignore_errors: true # noqa: ignore-errors
@@ -1,16 +1,16 @@
--- ---
- name: Check app data volume filesystem already exists - name: Check data volume filesystem already exists
ansible.builtin.command: ansible.builtin.command: |
cmd: "blkid /dev/{{ vm['data_storage']['name'] }}" blkid /dev/{{ vm['data_storage']['name'] }}
register: is_app_data register: is_volume
changed_when: false changed_when: false
failed_when: false failed_when: false
become: true become: true
- name: Create ext4 filesystem on app data raw - name: Create ext4 filesystem on data raw
ansible.builtin.command: ansible.builtin.command: |
cmd: "mkfs.ext4 -F /dev/{{ vm['data_storage']['name'] }}" mkfs.ext4 -F /dev/{{ vm['data_storage']['name'] }}
when: is_app_data.rc != 0 when: is_volume.rc != 0
changed_when: true changed_when: true
become: true become: true
@@ -22,7 +22,7 @@
group: "{{ node['group'] }}" group: "{{ node['group'] }}"
mode: "0770" mode: "0770"
- name: Mount app data volume - name: Mount data volume
ansible.posix.mount: ansible.posix.mount:
path: "{{ node['home_path'] }}/data" path: "{{ node['home_path'] }}/data"
src: "/dev/{{ vm['data_storage']['name'] }}" src: "/dev/{{ vm['data_storage']['name'] }}"
@@ -31,7 +31,7 @@
fstype: "ext4" fstype: "ext4"
become: true become: true
- name: Set app data volume path permissions - name: Set data volume path permissions
ansible.builtin.file: ansible.builtin.file:
path: "{{ node['home_path'] }}/data" path: "{{ node['home_path'] }}/data"
state: "directory" state: "directory"
@@ -9,8 +9,8 @@
become: true become: true
- name: Deploy timesyncd.conf.d/local-ntp.conf - name: Deploy timesyncd.conf.d/local-ntp.conf
ansible.builtin.copy: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/node/common/timesyncd/local-ntp.conf" src: "{{ hostvars['console']['node']['config_path'] }}/node/common/timesyncd/local-ntp.conf.j2"
dest: "/etc/systemd/timesyncd.conf.d/local-ntp.conf" dest: "/etc/systemd/timesyncd.conf.d/local-ntp.conf"
owner: "root" owner: "root"
group: "systemd-timesync" group: "systemd-timesync"
@@ -1,5 +1,5 @@
--- ---
- name: Gather ystem facts (hardware) - name: Gather system facts (hardware)
ansible.builtin.setup: ansible.builtin.setup:
gather_subset: gather_subset:
- hardware - hardware
@@ -78,7 +78,7 @@
- "{{ node['home_path'] }}" - "{{ node['home_path'] }}"
- "{{ node['home_path'] }}/data" - "{{ node['home_path'] }}/data"
become: true become: true
when: node['name'] == "app" when: node['name'] in ["bk", "app"]
- name: Enable alloy service - name: Enable alloy service
ansible.builtin.systemd: ansible.builtin.systemd:
@@ -88,9 +88,16 @@
daemon_reload: true daemon_reload: true
become: true become: true
- name: Check alloy.deb on console
delegate_to: "console"
ansible.builtin.stat:
path: "{{ hostvars['console']['node']['data_path'] }}/bin/alloy-{{ version['packages']['alloy'] }}.deb"
register: is_console_alloy_deb
- name: Fetch deb bin file - name: Fetch deb bin file
ansible.builtin.fetch: ansible.builtin.fetch:
src: "/var/cache/apt/archives/alloy-{{ version['packages']['alloy'] }}.deb" src: "/var/cache/apt/archives/alloy-{{ version['packages']['alloy'] }}.deb"
dest: "{{ hostvars['console']['node']['data_path'] }}/bin/" dest: "{{ hostvars['console']['node']['data_path'] }}/bin/"
flat: true flat: true
when: not is_console_alloy_deb.stat.exists
become: true become: true
@@ -1,5 +1,48 @@
--- ---
- name: Initialize Caddy services list
ansible.builtin.set_fact:
caddy_services: []
# infra, auth, app (vmm, fw has no podman in it) # infra, auth, app (vmm, fw has no podman in it)
- name: Set Caddy infra services list
ansible.builtin.set_fact:
caddy_services: >-
{{
services
| dict2items
| selectattr('value.dependency.web', 'defined')
| selectattr('value.dependency.web', 'in', ['infra-internal', 'infra-public'])
| map(attribute='key')
| list
}}
when: node['name'] == 'infra'
- name: Set Caddy auth services list
ansible.builtin.set_fact:
caddy_services: >-
{{
services
| dict2items
| selectattr('value.dependency.web', 'defined')
| selectattr('value.dependency.web', 'in', ['auth-public', 'infra-public', 'app-public'])
| map(attribute='key')
| list
}}
when: node['name'] == 'auth'
- name: Set Caddy app services list
ansible.builtin.set_fact:
caddy_services: >-
{{
services
| dict2items
| selectattr('value.dependency.web', 'defined')
| selectattr('value.dependency.web', 'in', ['app-internal', 'app-public'])
| map(attribute='key')
| list
}}
when: node['name'] == 'app'
- name: Create caddy directory - name: Create caddy directory
ansible.builtin.file: ansible.builtin.file:
path: "{{ node['home_path'] }}/containers/{{ item }}" path: "{{ node['home_path'] }}/containers/{{ item }}"
@@ -50,6 +93,8 @@
owner: "{{ ansible_user }}" owner: "{{ ansible_user }}"
group: "{{ node['group'] }}" group: "{{ node['group'] }}"
mode: "0640" mode: "0640"
register: "is_caddy_containerfile"
notify: "notification_restart_caddy"
- name: Deploy root crt for build - name: Deploy root crt for build
ansible.builtin.copy: ansible.builtin.copy:
@@ -58,6 +103,8 @@
owner: "{{ ansible_user }}" owner: "{{ ansible_user }}"
group: "{{ node['group'] }}" group: "{{ node['group'] }}"
mode: "0640" mode: "0640"
register: "is_caddy_root_crt"
notify: "notification_restart_caddy"
no_log: true no_log: true
- name: Build caddy container image - name: Build caddy container image
@@ -67,6 +114,7 @@
tag: "{{ version['containers']['caddy'] }}" tag: "{{ version['containers']['caddy'] }}"
state: "build" state: "build"
path: "{{ node['home_path'] }}/containers/caddy/build" path: "{{ node['home_path'] }}/containers/caddy/build"
force: "{{ is_caddy_root_crt.changed or is_caddy_containerfile.changed }}"
- name: Prune caddy dangling images - name: Prune caddy dangling images
containers.podman.podman_prune: containers.podman.podman_prune:
@@ -74,7 +122,7 @@
- name: Deploy caddyfile - name: Deploy caddyfile
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/common/caddy/etc/{{ node['name'] }}/Caddyfile.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/common/caddy/etc/Caddyfile.j2"
dest: "{{ node['home_path'] }}/containers/caddy/etc/Caddyfile" dest: "{{ node['home_path'] }}/containers/caddy/etc/Caddyfile"
owner: "{{ ansible_user }}" owner: "{{ ansible_user }}"
group: "{{ node['group'] }}" group: "{{ node['group'] }}"
@@ -109,8 +157,8 @@
- "{{ domain['internal'] }}/{{ node['name'] }}/caddy:{{ version['containers']['caddy'] }}" - "{{ domain['internal'] }}/{{ node['name'] }}/caddy:{{ version['containers']['caddy'] }}"
dest: "{{ node['home_path'] }}/archives/containers/{{ domain['internal'] }}_{{ node['name'] }}_caddy_{{ version['containers']['caddy'] }}.tar" dest: "{{ node['home_path'] }}/archives/containers/{{ domain['internal'] }}_{{ node['name'] }}_caddy_{{ version['containers']['caddy'] }}.tar"
format: "oci-archive" format: "oci-archive"
force: false force: "{{ is_caddy_root_crt.changed or is_caddy_containerfile.changed }}"
when: not container_archive_images.stat.exists when: not container_archive_images.stat.exists or is_caddy_root_crt.changed or is_caddy_containerfile.changed
- name: Fetch container archive images - name: Fetch container archive images
ansible.builtin.fetch: ansible.builtin.fetch:
@@ -120,8 +120,8 @@
no_log: true no_log: true
- name: Get existing machines list - name: Get existing machines list
ansible.builtin.command: ansible.builtin.command: |
cmd: "cscli machines list -o json" cscli machines list -o json
become: true become: true
changed_when: false changed_when: false
register: "existing_crowdsec_machines_list" register: "existing_crowdsec_machines_list"
@@ -132,27 +132,27 @@
- name: Set goal machines' name - name: Set goal machines' name
ansible.builtin.set_fact: ansible.builtin.set_fact:
machines_name: ["fw", "vmm", "infra", "auth", "app"] machines_name: ["fw", "vmm", "bk", "infra", "auth", "app"]
no_log: true no_log: true
- name: Prune unknown (random) machines - name: Prune unknown (random) machines
ansible.builtin.command: ansible.builtin.command: |
cmd: "cscli machines delete {{ item }}" cscli machines delete {{ item }}
loop: "{{ existing_machines_name | difference(machines_name) }}" loop: "{{ existing_machines_name | difference(machines_name) }}"
become: true become: true
changed_when: true changed_when: true
- name: Register crowdsec machines to LAPI server - name: Register crowdsec machines to LAPI server
ansible.builtin.command: ansible.builtin.command: |
cmd: "cscli machines add {{ item }} --password {{ hostvars['console']['crowdsec']['machine'][item] }} --force -f /dev/null" cscli machines add {{ item }} --password {{ hostvars['console']['crowdsec']['machine'][item] }} --force -f /dev/null
loop: "{{ machines_name }}" loop: "{{ machines_name }}"
become: true become: true
changed_when: false changed_when: false
no_log: true no_log: true
- name: Get existing bouncers list - name: Get existing bouncers list
ansible.builtin.command: ansible.builtin.command: |
cmd: "cscli bouncers list -o json" cscli bouncers list -o json
become: true become: true
register: "existing_crowdsec_bouncers_list" register: "existing_crowdsec_bouncers_list"
changed_when: false changed_when: false
@@ -162,8 +162,8 @@
existing_bouncers_name: "{{ existing_crowdsec_bouncers_list.stdout | from_json | map(attribute='name') | list }}" existing_bouncers_name: "{{ existing_crowdsec_bouncers_list.stdout | from_json | map(attribute='name') | list }}"
- name: Flush bouncers - name: Flush bouncers
ansible.builtin.command: ansible.builtin.command: |
cmd: "cscli bouncers delete {{ item }}" cscli bouncers delete {{ item }}
loop: "{{ existing_bouncers_name }}" loop: "{{ existing_bouncers_name }}"
become: true become: true
changed_when: true changed_when: true
@@ -173,8 +173,8 @@
bouncers_name: ["fw", "caddy"] bouncers_name: ["fw", "caddy"]
- name: Register Firewall Bouncer to LAPI - name: Register Firewall Bouncer to LAPI
ansible.builtin.command: ansible.builtin.command: |
cmd: "cscli bouncers add {{ item }}-bouncer -k {{ hostvars['console']['crowdsec']['bouncer'][item] }}" cscli bouncers add {{ item }}-bouncer -k {{ hostvars['console']['crowdsec']['bouncer'][item] }}
loop: "{{ bouncers_name }}" loop: "{{ bouncers_name }}"
become: true become: true
changed_when: true changed_when: true
@@ -185,8 +185,8 @@
when: node['name'] in acquisd_list when: node['name'] in acquisd_list
block: block:
- name: Install crowdsec collection - name: Install crowdsec collection
ansible.builtin.command: ansible.builtin.command: |
cmd: "cscli collections install {{ item }}" cscli collections install {{ item }}
loop: "{{ acquisd_list[node['name']]['collection'] }}" loop: "{{ acquisd_list[node['name']]['collection'] }}"
become: true become: true
changed_when: "'overwrite' not in is_collection_installed.stderr" changed_when: "'overwrite' not in is_collection_installed.stderr"
@@ -196,8 +196,8 @@
register: "is_collection_installed" register: "is_collection_installed"
- name: Install crowdsec parser - name: Install crowdsec parser
ansible.builtin.command: ansible.builtin.command: |
cmd: "cscli parsers install {{ item }}" cscli parsers install {{ item }}
loop: "{{ acquisd_list[node['name']]['parser'] }}" loop: "{{ acquisd_list[node['name']]['parser'] }}"
become: true become: true
changed_when: "'overwrite' not in is_parser_installed.stderr" changed_when: "'overwrite' not in is_parser_installed.stderr"
@@ -5,50 +5,288 @@
- hardware - hardware
become: true become: true
- name: Set console kopia - name: Set backup kopia repository server
when: node['name'] == 'console' when: node['name'] == "bk"
block: block:
- name: Download kopia - name: Download kopia deb file (x86_64)
ansible.builtin.get_url: ansible.builtin.get_url:
url: "https://github.com/kopia/kopia/releases/download/v{{ version['packages']['kopia'] }}/\ url: "https://github.com/kopia/kopia/releases/download/v{{ version['packages']['kopia'] }}/\
kopia_{{ version['packages']['kopia'] }}_linux_{{ item }}.deb" kopia_{{ version['packages']['kopia'] }}_linux_amd64.deb"
dest: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-{{ item }}.deb" dest: "/var/cache/apt/archives/kopia-{{ version['packages']['kopia'] }}.deb"
owner: "{{ ansible_user }}" owner: "root"
group: "{{ node['group'] }}" group: "root"
mode: "0600" mode: "0644"
loop:
- "amd64"
- "arm64"
- name: Install kopia (x86_64)
ansible.builtin.apt:
deb: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-amd64.deb"
state: "present"
become: true become: true
when: ansible_facts['architecture'] == "x86_64" when: ansible_facts['architecture'] == "x86_64"
- name: Install kopia (aarch64) - name: Download kopia deb file (aarch64)
ansible.builtin.apt: ansible.builtin.get_url:
deb: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-arm64.deb" url: "https://github.com/kopia/kopia/releases/download/v{{ version['packages']['kopia'] }}/\
state: "present" kopia_{{ version['packages']['kopia'] }}_linux_arm64.deb"
dest: "/var/cache/apt/archives/kopia-{{ version['packages']['kopia'] }}.deb"
owner: "root"
group: "root"
mode: "0644"
become: true become: true
when: ansible_facts['architecture'] == "aarch64" when: ansible_facts['architecture'] == "aarch64"
- name: Connect console kopia server - name: Create kopia directory
environment: ansible.builtin.file:
KOPIA_PASSWORD: "{{ hostvars['console']['kopia']['users']['console'] }}" path: "{{ item.name }}"
ansible.builtin.shell: | state: "directory"
/usr/bin/kopia repository connect server \ owner: "{{ ansible_user }}"
--url=https://{{ services['kopia']['domain'] }}.{{ domain['internal'] }}:{{ services['kopia']['ports']['https'] }} \ group: "root"
--override-username=console \ mode: "{{ item.mode }}"
--override-hostname=console.{{ domain['internal'] }} loop:
changed_when: false - name: "/etc/kopia"
failed_when: is_kopia_connected.rc != 0 mode: "0700"
register: "is_kopia_connected" - name: "/etc/kopia/ssl"
mode: "0700"
- name: "/var/cache/kopia"
mode: "0700"
become: true
no_log: true no_log: true
- name: Set infra/app kopia - name: Install kopia
when: node['name'] in ['infra', 'app'] ansible.builtin.apt:
deb: "/var/cache/apt/archives/kopia-{{ version['packages']['kopia'] }}.deb"
state: "present"
become: true
- name: Deploy kopia env
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/kopia/kopia.env.j2"
dest: "/etc/secrets/{{ node['uid'] }}/kopia.env"
owner: "{{ ansible_user }}"
group: "root"
mode: "0400"
become: true
notify: "notification_restart_kopia_server"
no_log: true
- name: Deploy kopia certificate and key
ansible.builtin.copy:
content: |
{{ item.value }}
dest: "/etc/kopia/ssl/{{ item.name }}"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "{{ item.mode }}"
loop:
- name: "kopia.crt"
value: |
{{ hostvars['console']['kopia']['crt'] | trim }}
{{ hostvars['console']['ca']['intermediate']['crt'] }}
mode: "0440"
- name: "kopia.key"
value: "{{ hostvars['console']['kopia']['key'] }}"
mode: "0400"
notify: "notification_restart_kopia_server"
no_log: true
- name: Check repository existance
ansible.builtin.stat:
path: "{{ node['home_path'] }}/data/kopia/repository"
register: "is_kopia_repository"
- name: Create repository directory
ansible.builtin.file:
path: "{{ node['home_path'] }}/data/kopia/repository"
state: "directory"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0770"
when: not is_kopia_repository.stat.exists
- name: Create kopia repository
ansible.builtin.shell: |
set -a
. /etc/secrets/{{ node['uid'] }}/kopia.env
set +a
/usr/bin/kopia repository create filesystem \
--path="{{ node['home_path'] }}/data/kopia/repository" \
--description="ilnmors.internal kopia repository" \
--create-only
when: not is_kopia_repository.stat.exists
changed_when: true
register: "is_repository_created"
no_log: true
- name: Connect to kopia repository
ansible.builtin.shell: |
set -a
. /etc/secrets/{{ node['uid'] }}/kopia.env
set +a
/usr/bin/kopia repository connect filesystem \
--path="{{ node['home_path'] }}/data/kopia/repository" \
--override-username="il" \
--override-hostname="{{ node['name'] }}.{{ domain['internal'] }}" \
when:
- not is_kopia_repository.stat.exists
- is_repository_created.rc == 0
changed_when: true
register: "is_repository_connected"
no_log: true
- name: Create kopia user
ansible.builtin.shell: |
set -a
. /etc/secrets/{{ node['uid'] }}/kopia.env
set +a
/usr/bin/kopia server users add \
--user-password {{ item.password | quote }} \
{{ item.name }}
loop:
- name: "console@console.ilnmors.internal"
password: "{{ hostvars['console']['kopia']['users']['console'] }}"
- name: "infra@infra.ilnmors.internal"
password: "{{ hostvars['console']['kopia']['users']['infra'] }}"
- name: "app@app.ilnmors.internal"
password: "{{ hostvars['console']['kopia']['users']['app'] }}"
when:
- not is_kopia_repository.stat.exists
- is_repository_connected.rc == 0
changed_when: true
register: "is_user_created"
no_log: true
- name: Set kopia console ACL
ansible.builtin.shell: |
set -a
. /etc/secrets/{{ node['uid'] }}/kopia.env
set +a
/usr/bin/kopia server acl add \
--user console@console.ilnmors.internal \
--target {{ item }} \
--access FULL
loop:
- "type=snapshot"
- "type=policy"
- "type=user"
- "type=acl"
- "type=content"
when:
- not is_kopia_repository.stat.exists
- is_repository_connected.rc == 0
changed_when: true
no_log: true
- name: Set kopia infra ACL
ansible.builtin.shell: |
set -a
. /etc/secrets/{{ node['uid'] }}/kopia.env
set +a
/usr/bin/kopia server acl add \
--user infra@infra.ilnmors.internal \
--target {{ item.target }} \
--access {{ item.access }}
loop:
- target: "type=snapshot"
access: "FULL"
- target: "type=policy"
access: "READ"
- target: "type=policy,username=infra,hostname=infra.ilnmors.internal"
access: "FULL"
- target: "type=content"
access: "APPEND"
when:
- not is_kopia_repository.stat.exists
- is_repository_connected.rc == 0
changed_when: true
no_log: true
- name: Set kopia app ACL
ansible.builtin.shell: |
set -a
. /etc/secrets/{{ node['uid'] }}/kopia.env
set +a
/usr/bin/kopia server acl add \
--user app@app.ilnmors.internal \
--target {{ item.target }} \
--access {{ item.access }}
loop:
- target: "type=snapshot"
access: "FULL"
- target: "type=policy"
access: "READ"
- target: "type=policy,username=app,hostname=app.ilnmors.internal"
access: "FULL"
- target: "type=content"
access: "APPEND"
when:
- not is_kopia_repository.stat.exists
- is_repository_connected.rc == 0
changed_when: true
no_log: true
- name: Set kopia policy
ansible.builtin.shell: |
set -a
. /etc/secrets/{{ node['uid'] }}/kopia.env
set +a
/usr/bin/kopia policy set \
{{ item.content }}
loop:
- content: |
--global \
--compression=zstd
- content: |
infra@infra.ilnmors.internal \
--compression=zstd \
--keep-latest=10 \
--keep-hourly=0 \
--keep-daily=14 \
--keep-weekly=4 \
--keep-monthly=6 \
--keep-annual=1
- content: |
app@app.ilnmors.internal \
--compression=none \
--keep-latest=10 \
--keep-hourly=0 \
--keep-daily=14 \
--keep-weekly=4 \
--keep-monthly=6 \
--keep-annual=1
when:
- not is_kopia_repository.stat.exists
- is_repository_connected.rc == 0
changed_when: true
no_log: true
- name: Set kopia parameters
ansible.builtin.shell: |
set -a
. /etc/secrets/{{ node['uid'] }}/kopia.env
set +a
/usr/bin/kopia repository set-parameters \
--max-pack-size-mb=100
when:
- not is_kopia_repository.stat.exists
- is_repository_connected.rc == 0
changed_when: true
no_log: true
- name: Deploy kopia servcer service file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/kopia/kopia-server.service.j2"
dest: "{{ node['home_path'] }}/.config/systemd/user/kopia-server.service"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
validate: "/usr/bin/systemd-analyze verify %s"
become: true
- name: Enable kopia server service
ansible.builtin.systemd:
name: "kopia-server.service"
state: "started"
enabled: true
scope: "user"
daemon_reload: true
- name: Set infra/app backup kopia
when: node['name'] in ["infra", "app"]
block: block:
- name: Set kopia uid - name: Set kopia uid
ansible.builtin.set_fact: ansible.builtin.set_fact:
@@ -127,7 +365,7 @@
become: true become: true
no_log: true no_log: true
- name: Deploy kopia service files - name: Deploy kopia backup service files
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/kopia/{{ item }}.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/kopia/{{ item }}.j2"
dest: "/etc/systemd/system/{{ item }}" dest: "/etc/systemd/system/{{ item }}"
@@ -140,10 +378,52 @@
- "kopia-backup.timer" - "kopia-backup.timer"
become: true become: true
- name: Enable auto kopia rules update - name: Enable Kopia backup timer
ansible.builtin.systemd: ansible.builtin.systemd:
name: "kopia-backup.timer" name: "kopia-backup.timer"
state: "started" state: "started"
enabled: true enabled: true
daemon_reload: true daemon_reload: true
become: true become: true
- name: Set console kopia
when: node['name'] == "console"
block:
- name: Download kopia
ansible.builtin.get_url:
url: "https://github.com/kopia/kopia/releases/download/v{{ version['packages']['kopia'] }}/\
kopia_{{ version['packages']['kopia'] }}_linux_{{ item }}.deb"
dest: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-{{ item }}.deb"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0600"
loop:
- "amd64"
- "arm64"
- name: Install kopia (x86_64)
ansible.builtin.apt:
deb: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-amd64.deb"
state: "present"
become: true
when: ansible_facts['architecture'] == "x86_64"
- name: Install kopia (aarch64)
ansible.builtin.apt:
deb: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-arm64.deb"
state: "present"
become: true
when: ansible_facts['architecture'] == "aarch64"
- name: Connect console kopia server
environment:
KOPIA_PASSWORD: "{{ hostvars['console']['kopia']['users']['console'] }}"
ansible.builtin.shell: |
/usr/bin/kopia repository connect server \
--url=https://{{ services['kopia']['domain']['internal'] }}.{{ domain['internal'] }}:443 \
--override-username=console \
--override-hostname=console.{{ domain['internal'] }}
changed_when: false
failed_when: is_kopia_connected.rc != 0
register: "is_kopia_connected"
no_log: true
@@ -16,7 +16,7 @@
environment: environment:
SOPS_AGE_KEY: "{{ hostvars['console']['age_key'] }}" SOPS_AGE_KEY: "{{ hostvars['console']['age_key'] }}"
ansible.builtin.command: | ansible.builtin.command: |
sops -d --output-type yaml {{ hostvars['console']['node']['config_path'] }}/secrets/secrets.yaml sops -d --output-type yaml "{{ hostvars['console']['node']['config_path'] }}/secrets/secrets.yaml"
changed_when: false changed_when: false
register: "decrypted_secrets" register: "decrypted_secrets"
run_once: true run_once: true
@@ -24,16 +24,20 @@
notify: "notification_restart_ca" notify: "notification_restart_ca"
no_log: true no_log: true
- name: Deploy ca config files - name: Pull image
containers.podman.podman_image:
name: "docker.io/smallstep/step-ca"
tag: "{{ version['containers']['step'] }}"
state: "present"
pull: true
- name: Deploy ca config file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ca/config/{{ item }}.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ca/config/ca.json.j2"
dest: "{{ node['home_path'] }}/containers/ca/config/{{ item }}" dest: "{{ node['home_path'] }}/containers/ca/config/ca.json"
owner: "{{ services['ca']['subuid'] }}" owner: "{{ services['ca']['subuid'] }}"
group: "{{ node['group'] }}" group: "{{ node['group'] }}"
mode: "0400" mode: "0400"
loop:
- "ca.json"
- "defaults.json"
become: true become: true
notify: "notification_restart_ca" notify: "notification_restart_ca"
@@ -68,6 +68,13 @@
become: true become: true
notify: "notification_restart_grafana" notify: "notification_restart_grafana"
- name: Pull image
containers.podman.podman_image:
name: "docker.io/grafana/grafana"
tag: "{{ version['containers']['grafana'] }}"
state: "present"
pull: true
- name: Deploy container file - name: Deploy container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/grafana/grafana.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/grafana/grafana.container.j2"
@@ -46,7 +46,8 @@
# urlencode doesn't fix `/` as `%2F`. It needs replace # urlencode doesn't fix `/` as `%2F`. It needs replace
- name: "LLDAP_DATABASE_URL" - name: "LLDAP_DATABASE_URL"
value: "postgres://ldap:{{ hostvars['console']['postgresql']['password']['ldap'] | urlencode | replace('/', '%2F') }}\ value: "postgres://ldap:{{ hostvars['console']['postgresql']['password']['ldap'] | urlencode | replace('/', '%2F') }}\
@{{ services['postgresql']['domain'] }}.{{ domain['internal'] }}/ldap_db?sslmode=verify-full&sslrootcert=/etc/ssl/ldap/{{ root_cert_filename }}" @{{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}/\
ldap_db?sslmode=verify-full&sslrootcert=/etc/ssl/ldap/{{ root_cert_filename }}"
- name: "LLDAP_KEY_SEED" - name: "LLDAP_KEY_SEED"
value: "{{ hostvars['console']['ldap']['seed_key'] }}" value: "{{ hostvars['console']['ldap']['seed_key'] }}"
- name: "LLDAP_JWT_SECRET" - name: "LLDAP_JWT_SECRET"
@@ -93,6 +94,13 @@
name: "LLDAP_LDAP_USER_PASSWORD" name: "LLDAP_LDAP_USER_PASSWORD"
state: "absent" state: "absent"
- name: Pull image
containers.podman.podman_image:
name: "docker.io/lldap/lldap"
tag: "{{ version['containers']['ldap'] }}"
state: "present"
pull: true
- name: Deploy container file - name: Deploy container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ldap/ldap.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ldap/ldap.container.j2"
@@ -48,6 +48,13 @@
notify: "notification_restart_loki" notify: "notification_restart_loki"
no_log: true no_log: true
- name: Pull image
containers.podman.podman_image:
name: "docker.io/grafana/loki"
tag: "{{ version['containers']['loki'] }}"
state: "present"
pull: true
- name: Deploy container file - name: Deploy container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/loki/loki.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/loki/loki.container.j2"
@@ -1,19 +1,19 @@
--- ---
- name: Initialize connected services list
ansible.builtin.set_fact:
connected_services: []
- name: Set connected services list - name: Set connected services list
ansible.builtin.set_fact: ansible.builtin.set_fact:
connected_services: connected_services: >-
- "ldap" {{
- "grafana" services
- "authelia" | dict2items
- "vaultwarden" | selectattr('value.dependency.db', 'defined')
- "gitea" | selectattr('value.dependency.db', 'equalto', 'postgresql')
- "immich" | map(attribute='key')
- "paperless" | list
- "nextcloud" }}
- "sure"
- "outline"
- "memos"
- "mealie"
- name: Create postgresql directory - name: Create postgresql directory
ansible.builtin.file: ansible.builtin.file:
@@ -39,6 +39,8 @@
owner: "{{ ansible_user }}" owner: "{{ ansible_user }}"
group: "{{ node['group'] }}" group: "{{ node['group'] }}"
mode: "0640" mode: "0640"
register: "is_postgresql_containerfile"
notify: "notification_restart_postgresql"
- name: Build postgresql container image - name: Build postgresql container image
containers.podman.podman_image: containers.podman.podman_image:
@@ -47,6 +49,7 @@
tag: "pg{{ version['containers']['postgresql'] }}-vectorchord{{ version['containers']['vectorchord'] }}" tag: "pg{{ version['containers']['postgresql'] }}-vectorchord{{ version['containers']['vectorchord'] }}"
state: "build" state: "build"
path: "{{ node['home_path'] }}/containers/postgresql/build" path: "{{ node['home_path'] }}/containers/postgresql/build"
force: "{{ is_postgresql_containerfile.changed }}"
- name: Prune postgresql dangling images - name: Prune postgresql dangling images
containers.podman.podman_prune: containers.podman.podman_prune:
@@ -96,16 +99,33 @@
become: true become: true
register: "is_postgresql_init" register: "is_postgresql_init"
- name: Check init directory empty
ansible.builtin.find:
path: "{{ node['home_path'] }}/containers/postgresql/init/"
file_type: "any"
patterns:
- "*.sql"
become: true
register: "is_init_dir_empty"
- name: Check pg_cluster.sql on console
delegate_to: "console"
ansible.builtin.stat:
path: "{{ hostvars['console']['node']['data_path'] }}/sql/postgresql/pg_cluster.sql"
register: is_console_pg_cluster_sql
- name: Prepare initiating DB - name: Prepare initiating DB
when: when:
- not is_postgresql_init.stat.exists - not is_postgresql_init.stat.exists
- is_init_dir_empty.matched == 0
- is_console_pg_cluster_sql.stat.exists
- (connected_services | default([]) | length) > 0 - (connected_services | default([]) | length) > 0
become: true become: true
block: block:
# `init/pg_cluster.sql` should be fetched from postgresql's backup directory before running initiating # `init/pg_cluster.sql` should be fetched from postgresql's backup directory before running initiating
- name: Deploy init cluster sql file - name: Deploy init cluster sql file
ansible.builtin.copy: ansible.builtin.copy:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/init/pg_cluster.sql" src: "{{ hostvars['console']['node']['data_path'] }}/sql/postgresql/pg_cluster.sql"
dest: "{{ node['home_path'] }}/containers/postgresql/init/00_pg_cluster.sql" dest: "{{ node['home_path'] }}/containers/postgresql/init/00_pg_cluster.sql"
owner: "{{ services['postgresql']['subuid'] }}" owner: "{{ services['postgresql']['subuid'] }}"
group: "{{ node['group'] }}" group: "{{ node['group'] }}"
@@ -113,7 +133,7 @@
- name: Deploy restoring data sql files - name: Deploy restoring data sql files
ansible.builtin.copy: ansible.builtin.copy:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/init/pg_{{ item }}.sql" src: "{{ hostvars['console']['node']['data_path'] }}/sql/postgresql/pg_{{ item }}.sql"
dest: "{{ node['home_path'] }}/containers/postgresql/init/{{ '%02d' | format(index_num + 1) }}_pg_{{ item }}.sql" dest: "{{ node['home_path'] }}/containers/postgresql/init/{{ '%02d' | format(index_num + 1) }}_pg_{{ item }}.sql"
owner: "{{ services['postgresql']['subuid'] }}" owner: "{{ services['postgresql']['subuid'] }}"
group: "{{ node['group'] }}" group: "{{ node['group'] }}"
@@ -192,8 +212,8 @@
{{ domain['internal'] }}_{{ node['name'] }}_postgres_\ {{ domain['internal'] }}_{{ node['name'] }}_postgres_\
pg{{ version['containers']['postgresql'] }}-vectorchord{{ version['containers']['vectorchord'] }}.tar" pg{{ version['containers']['postgresql'] }}-vectorchord{{ version['containers']['vectorchord'] }}.tar"
format: "oci-archive" format: "oci-archive"
force: false force: "{{ is_postgresql_containerfile.changed }}"
when: not container_archive_images.stat.exists when: not container_archive_images.stat.exists or is_postgresql_containerfile.changed
- name: Fetch container archive images - name: Fetch container archive images
ansible.builtin.fetch: ansible.builtin.fetch:
@@ -52,6 +52,13 @@
notify: "notification_restart_prometheus" notify: "notification_restart_prometheus"
no_log: true no_log: true
- name: Pull image
containers.podman.podman_image:
name: "docker.io/prom/prometheus"
tag: "{{ version['containers']['prometheus'] }}"
state: "present"
pull: true
- name: Deploy container file - name: Deploy container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/prometheus/prometheus.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/prometheus/prometheus.container.j2"
@@ -1,4 +1,20 @@
--- ---
- name: Initialize self-cert services list
ansible.builtin.set_fact:
cert_services: []
- name: Set self-cert services list
ansible.builtin.set_fact:
cert_services: >-
{{
services
| dict2items
| selectattr('value.dependency.cert', 'defined')
| selectattr('value.dependency.cert', 'equalto', true)
| map(attribute='key')
| list
}}
- name: Create x509-exporter directory - name: Create x509-exporter directory
ansible.builtin.file: ansible.builtin.file:
path: "{{ node['home_path'] }}/containers/{{ item }}" path: "{{ node['home_path'] }}/containers/{{ item }}"
@@ -22,7 +38,7 @@
become: true become: true
notify: "notification_restart_x509-exporter" notify: "notification_restart_x509-exporter"
- name: Deploy certificates - name: Deploy CA certificates
ansible.builtin.copy: ansible.builtin.copy:
content: | content: |
{{ item.value }} {{ item.value }}
@@ -35,23 +51,31 @@
value: "{{ hostvars['console']['ca']['root']['crt'] }}" value: "{{ hostvars['console']['ca']['root']['crt'] }}"
- name: "intermediate.crt" - name: "intermediate.crt"
value: "{{ hostvars['console']['ca']['intermediate']['crt'] }}" value: "{{ hostvars['console']['ca']['intermediate']['crt'] }}"
- name: "crowdsec.crt"
value: "{{ hostvars['console']['crowdsec']['crt'] }}"
- name: "blocky.crt"
value: "{{ hostvars['console']['blocky']['crt'] }}"
- name: "postgresql.crt"
value: "{{ hostvars['console']['postgresql']['crt'] }}"
- name: "ldap.crt"
value: "{{ hostvars['console']['ldap']['crt'] }}"
- name: "prometheus.crt"
value: "{{ hostvars['console']['prometheus']['crt'] }}"
- name: "loki.crt"
value: "{{ hostvars['console']['loki']['crt'] }}"
- name: "dsm.crt"
value: "{{ hostvars['console']['dsm']['crt'] }}"
become: true become: true
notify: "notification_restart_x509-exporter"
no_log: true no_log: true
- name: Deploy leaf certificates
ansible.builtin.copy:
content: |
{{ hostvars['console'][item]['crt'] }}
dest: "{{ node['home_path'] }}/containers/x509-exporter/certs/{{ item }}.crt"
owner: "{{ services['x509-exporter']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0440"
loop: "{{ cert_services }}"
become: true
notify: "notification_restart_x509-exporter"
no_log: true
- name: Pull image
containers.podman.podman_image:
name: "docker.io/enix/x509-certificate-exporter"
tag: "{{ version['containers']['x509-exporter'] }}"
state: "present"
pull: true
- name: Deploy container file - name: Deploy container file
ansible.builtin.template: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/x509-exporter/x509-exporter.container.j2" src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/x509-exporter/x509-exporter.container.j2"
+179
View File
@@ -0,0 +1,179 @@
---
- name: Check btrfs installation
ansible.builtin.shell: |
command -v btrfs
become: true # btrfs is located in /usr/sbin, which means root permission is needed.
changed_when: false
failed_when: false
register: "is_btrfs_installed"
- name: Install btrfs
ansible.builtin.apt:
name: "btrfs-progs"
state: "present"
become: true
when: is_btrfs_installed.rc != 0
- name: Mount data disk
block:
- name: Set hard data disk path
ansible.builtin.shell: |
set -o pipefail
ls -1 /dev/disk/by-id/ata-* | \
grep -F -e "{{ hardware['disk']['data']['serials'] | join('" -e "') }}" | \
grep -vE -- '-part[0-9]+$' | \
sort
changed_when: false
register: "data_disk_path"
- name: Check vmm_hdd filesystem already exists
ansible.builtin.command: |
blkid -L {{ hardware['disk']['data']['fs']['label'] }}
become: true
changed_when: false
failed_when: false
register: "is_data_disk_fs"
- name: Check disk number
ansible.builtin.fail:
msg: "Below 4 disks for RAID10, found {{ data_disk_path.stdout_lines | length }}"
when: (data_disk_path.stdout_lines | length) < hardware['disk']['data']['fs']['btrfs']['min_devices']
- name: Set btrfs raid10 volume
ansible.builtin.shell: |
mkfs.btrfs -f \
-L {{ hardware['disk']['data']['fs']['label'] }} \
-d {{ hardware['disk']['data']['fs']['btrfs']['data_profile'] }} \
-m {{ hardware['disk']['data']['fs']['btrfs']['metadata_profile'] }} \
{{ data_disk_path.stdout_lines | join(' ') }}
become: true
when:
- is_data_disk_fs.rc != 0
- (data_disk_path.stdout_lines | length) >= hardware['disk']['data']['fs']['btrfs']['min_devices']
changed_when: is_mkfs.rc == 0
register: "is_mkfs"
- name: Create mount volume
ansible.builtin.file:
path: "{{ hardware['disk']['data']['fs']['mount_point'] }}"
state: "directory"
owner: "root"
group: "root"
mode: "0711"
become: true
- name: Mount btrfs raid10 volume
ansible.posix.mount:
path: "{{ hardware['disk']['data']['fs']['mount_point'] }}"
src: "LABEL={{ hardware['disk']['data']['fs']['label'] }}"
state: "mounted"
fstype: "{{ hardware['disk']['data']['fs']['type'] }}"
opts: "{{ hardware['disk']['data']['fs']['mount_opts'] | join(',') }}"
become: true
- name: Set mounted btrfs volume permissions
ansible.builtin.file:
path: "{{ hardware['disk']['data']['fs']['mount_point'] }}"
state: "directory"
owner: "root"
group: "root"
mode: "0711"
become: true
- name: Mount backup disk
block:
- name: Set backup disk path
ansible.builtin.shell: |
set -o pipefail
ls -1 /dev/disk/by-id/ata-* | \
grep -F -e "{{ hardware['disk']['backup']['serials'] | join('" -e "') }}" | \
grep -vE -- '-part[0-9]+$' | \
sort
changed_when: false
register: "backup_disk_path"
- name: Check vmm_hdd filesystem already exists
ansible.builtin.command: |
blkid -L {{ hardware['disk']['backup']['fs']['label'] }}
become: true
changed_when: false
failed_when: false
register: "is_backup_disk_fs"
- name: Set btrfs volume
ansible.builtin.shell: |
mkfs.btrfs -f \
-L {{ hardware['disk']['backup']['fs']['label'] }} \
-d {{ hardware['disk']['backup']['fs']['btrfs']['data_profile'] }} \
-m {{ hardware['disk']['backup']['fs']['btrfs']['metadata_profile'] }} \
{{ backup_disk_path.stdout_lines | join(' ') }}
become: true
when:
- is_backup_disk_fs.rc != 0
- (backup_disk_path.stdout_lines | length) >= hardware['disk']['backup']['fs']['btrfs']['min_devices']
changed_when: is_mkfs.rc == 0
register: "is_mkfs"
- name: Create mount volume
ansible.builtin.file:
path: "{{ hardware['disk']['backup']['fs']['mount_point'] }}"
state: "directory"
owner: "root"
group: "root"
mode: "0711"
become: true
- name: Mount btrfs volume
ansible.posix.mount:
path: "{{ hardware['disk']['backup']['fs']['mount_point'] }}"
src: "LABEL={{ hardware['disk']['backup']['fs']['label'] }}"
state: "mounted"
fstype: "{{ hardware['disk']['backup']['fs']['type'] }}"
opts: "{{ hardware['disk']['backup']['fs']['mount_opts'] | join(',') }}"
become: true
- name: Set mounted btrfs volume permissions
ansible.builtin.file:
path: "{{ hardware['disk']['backup']['fs']['mount_point'] }}"
state: "directory"
owner: "root"
group: "root"
mode: "0711"
become: true
- name: Verify data disk is mounted
ansible.builtin.command: |
mountpoint -q {{ hardware['disk']['data']['fs']['mount_point'] }}
become: true
changed_when: false
- name: Verify backup disk is mounted
ansible.builtin.command: |
mountpoint -q {{ hardware['disk']['backup']['fs']['mount_point'] }}
become: true
changed_when: false
- name: Deploy btrfs scrub service and timer
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/vmm/btrfs/btrfs-scrub-{{ item }}.j2"
dest: "/etc/systemd/system/btrfs-scrub-{{ item }}"
owner: "root"
group: "root"
mode: "0644"
loop:
- "data.service"
- "data.timer"
- "backup.service"
- "backup.timer"
become: true
- name: Enable auto btrfs scrub
ansible.builtin.systemd:
name: "btrfs-scrub-{{ item }}.timer"
state: "started"
enabled: true
daemon_reload: true
loop:
- "data"
- "backup"
become: true
@@ -13,7 +13,9 @@
loop: loop:
- "images" - "images"
- "seeds" - "seeds"
- "data" - "disk"
- "disk/data"
- "disk/backup"
register: "is_libvirt_dir" register: "is_libvirt_dir"
- name: Create libvirt directory - name: Create libvirt directory
@@ -26,7 +28,6 @@
loop: "{{ is_libvirt_dir.results }}" loop: "{{ is_libvirt_dir.results }}"
when: not item.stat.exists when: not item.stat.exists
become: true become: true
no_log: true
- name: Set LIBVIRT_DEFAULT_URI - name: Set LIBVIRT_DEFAULT_URI
ansible.builtin.lineinfile: ansible.builtin.lineinfile:
@@ -74,6 +75,7 @@
- "images-pool" - "images-pool"
- "seeds-pool" - "seeds-pool"
- "data-pool" - "data-pool"
- "backup-pool"
- name: Start virtual storage pool - name: Start virtual storage pool
community.libvirt.virt_pool: community.libvirt.virt_pool:
@@ -84,6 +86,7 @@
- "images-pool" - "images-pool"
- "seeds-pool" - "seeds-pool"
- "data-pool" - "data-pool"
- "backup-pool"
- name: Autostart virtual storage pool - name: Autostart virtual storage pool
community.libvirt.virt_pool: community.libvirt.virt_pool:
@@ -94,3 +97,4 @@
- "images-pool" - "images-pool"
- "seeds-pool" - "seeds-pool"
- "data-pool" - "data-pool"
- "backup-pool"
-100
View File
@@ -1,100 +0,0 @@
---
- name: Check btrfs installation
ansible.builtin.shell: |
command -v btrfs
become: true # btrfs is located in /usr/sbin, which means root permission is needed.
changed_when: false
failed_when: false
register: "is_btrfs_installed"
ignore_errors: true
- name: Install btrfs
ansible.builtin.apt:
name: "btrfs-progs"
state: "present"
become: true
when: is_btrfs_installed.rc != 0
- name: Set hard disk path
ansible.builtin.shell: |
set -o pipefail
ls -1 /dev/disk/by-id/ata-* | \
grep -F -e "{{ hardware['hdd']['data'].values() | join('" -e "') }}" | \
grep -vE -- '-part[0-9]+$' | \
sort
changed_when: false
register: "hdd_path_list"
- name: Check vmm_hdd filesystem already exists
ansible.builtin.command: |
blkid -L {{ hardware['btrfs']['label'] }}
register: is_vmm_data
changed_when: false
failed_when: false
become: true
- name: Check disk number
ansible.builtin.fail:
msg: "Below 4 disks for RAID10, found {{ hdd_path_list.stdout_lines | length }}"
when: (hdd_path_list.stdout_lines | length) < 4
- name: Set btrfs raid10 volume
ansible.builtin.shell: |
mkfs.btrfs -f \
-L {{ hardware['btrfs']['label'] }} \
-d {{ hardware['btrfs']['level'] }} \
-m {{ hardware['btrfs']['level'] }} \
{{ hdd_path_list.stdout_lines | join(' ') }}
become: true
when:
- is_vmm_data.rc != 0
- (hdd_path_list.stdout_lines | length) >= 4
changed_when: is_mkfs.rc == 0
register: "is_mkfs"
- name: Create mount volume
ansible.builtin.file:
path: "{{ hardware['btrfs']['mount_point'] }}"
state: "directory"
owner: "root"
group: "root"
mode: "0711"
become: true
- name: Mount btrfs raid10 volume
ansible.posix.mount:
path: "{{ hardware['btrfs']['mount_point'] }}"
src: "LABEL={{ hardware['btrfs']['label'] }}"
state: "mounted"
fstype: "btrfs"
opts: "defaults,noatime,nodatacow,degraded,nofail"
become: true
- name: Set mounted btrfs volume permissions
ansible.builtin.file:
path: "{{ hardware['btrfs']['mount_point'] }}"
state: "directory"
owner: "root"
group: "root"
mode: "0711"
become: true
- name: Deploy btrfs scrub service and timer
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/vmm/btrfs/{{ item }}.j2"
dest: "/etc/systemd/system/{{ item }}"
owner: "root"
group: "root"
mode: "0644"
loop:
- "btrfs-scrub.service"
- "btrfs-scrub.timer"
become: true
- name: Enable auto btrfs scrub
ansible.builtin.systemd:
name: "btrfs-scrub.timer"
state: "started"
enabled: true
daemon_reload: true
become: true
+1 -2
View File
@@ -49,8 +49,7 @@
register: "is_seediso" register: "is_seediso"
- name: Create seed.iso - name: Create seed.iso
ansible.builtin.shell: ansible.builtin.shell: |
cmd: |
cloud-localds -N {{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/network-config \ cloud-localds -N {{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/network-config \
{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/seed.iso \ {{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/seed.iso \
{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/user-data \ {{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/user-data \
+12 -12
View File
@@ -28,8 +28,8 @@
become: true become: true
- name: Check deployed cloud-init file info - name: Check deployed cloud-init file info
ansible.builtin.command: ansible.builtin.command: |
cmd: "qemu-img info {{ node['libvirt_path'] }}/images/{{ target_vm }}.qcow2 --output json" qemu-img info {{ node['libvirt_path'] }}/images/{{ target_vm }}.qcow2 --output json
changed_when: false changed_when: false
failed_when: failed_when:
- deployed_cloudfile_info.rc != 0 - deployed_cloudfile_info.rc != 0
@@ -37,29 +37,29 @@
register: "deployed_cloudfile_info" register: "deployed_cloudfile_info"
- name: Resize deployed cloud-init file - name: Resize deployed cloud-init file
ansible.builtin.command: ansible.builtin.command: |
cmd: "qemu-img resize {{ node['libvirt_path'] }}/images/{{ target_vm }}.qcow2 {{ hostvars[target_vm]['vm']['storage'] }}G" qemu-img resize {{ node['libvirt_path'] }}/images/{{ target_vm }}.qcow2 {{ hostvars[target_vm]['vm']['storage'] }}G
when: when:
- deployed_cloudfile_info.rc == 0 - deployed_cloudfile_info.rc == 0
- (deployed_cloudfile_info.stdout | from_json)['virtual-size'] < (hostvars[target_vm]['vm']['storage'] | int * 1024 * 1024 * 1024) - (deployed_cloudfile_info.stdout | from_json)['virtual-size'] < (hostvars[target_vm]['vm']['storage'] | int * 1024 * 1024 * 1024)
changed_when: true changed_when: true
- name: Check app data raw image - name: Check bk/app raw image
ansible.builtin.stat: ansible.builtin.stat:
path: "{{ hardware['btrfs']['mount_point'] }}/{{ target_vm }}.raw" path: "{{ hardware['disk'][hostvars[target_vm]['vm']['data_storage']['pool']]['fs']['mount_point'] }}/{{ target_vm }}.raw"
get_checksum: false get_checksum: false
get_mime: false get_mime: false
get_attributes: false get_attributes: false
when: target_vm == "app" when: target_vm in ["bk", "app"]
register: "is_app_data" register: "is_app_data"
- name: Create app data raw image - name: Create bk/app raw image
ansible.builtin.command: ansible.builtin.command: |
# 3.5T qemu-img create -f raw {{ hardware['disk'][hostvars[target_vm]['vm']['data_storage']['pool']]['fs']['mount_point'] }}/{{ target_vm }}.raw \
cmd: "qemu-img create -f raw {{ hardware['btrfs']['mount_point'] }}/{{ target_vm }}.raw {{ hostvars[target_vm]['vm']['data_storage']['size'] }}T" {{ hostvars[target_vm]['vm']['data_storage']['size'] }}T
become: true become: true
when: when:
- target_vm == "app" - target_vm in ["bk", "app"]
- not is_app_data.stat.exists - not is_app_data.stat.exists
changed_when: true changed_when: true
+3 -3
View File
@@ -8,11 +8,11 @@
command: define command: define
- name: Deploy VM systemd file - name: Deploy VM systemd file
ansible.builtin.copy: ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/vmm/libvirt/services/{{ target_vm }}.service" src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/vmm/libvirt/services/{{ target_vm }}.service.j2"
dest: "{{ node['home_path'] }}/.config/systemd/user/{{ target_vm }}.service" dest: "{{ node['home_path'] }}/.config/systemd/user/{{ target_vm }}.service"
owner: "{{ ansible_user }}" owner: "{{ ansible_user }}"
group: "svadmins" group: "{{ node['group'] }}"
mode: "0400" mode: "0400"
- name: Register VM service - name: Register VM service
+48
View File
@@ -0,0 +1,48 @@
#!/usr/sbin/nft -f
flush ruleset
define NET4_SERVER = {{ hostvars['fw']['network4']['subnet']['server'] }}
define NET6_SERVER = {{ hostvars['fw']['network6']['subnet']['server'] }}
define HOSTS4_CONSOLE = { {{ hostvars['fw']['network4']['console'].values() | join(', ') }} }
define HOSTS6_CONSOLE = { {{ hostvars['fw']['network6']['console'].values() | join(', ') }} }
define HOSTS4_INFRA = {{ hostvars['fw']['network4']['infra']['server'] }}
define HOSTS6_INFRA = {{ hostvars['fw']['network6']['infra']['server'] }}
define HOSTS4_APP = {{ hostvars['fw']['network4']['app']['server'] }}
define HOSTS6_APP = {{ hostvars['fw']['network6']['app']['server'] }}
define PORTS_SSH = 22
define PORTS_HTTPS = 443
define PORTS_KOPIA = {{ services['kopia']['ports']['https'] }}
table inet nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
tcp dport $PORTS_HTTPS dnat to :$PORTS_KOPIA comment "dnat https ports to $PORTS_KOPIA"
}
chain postrouting {
}
chain output {
type nat hook output priority dstnat; policy accept;
oifname "lo" tcp dport $PORTS_HTTPS dnat to :$PORTS_KOPIA comment "dnat https ports to $PORTS_KOPIA out of LOCALHOST"
}
}
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state invalid drop comment "deny invalid connection"
ct state established, related accept comment "allow all connection already existing"
iifname "lo" accept comment "allow local connection: BK > BK"
meta l4proto { icmp, icmpv6 } accept comment "allow icmp connection: BK"
ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv4 ssh connection: CONSOLE > BK"
ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv6 ssh connection: CONSOLE > BK"
ip saddr { $HOSTS4_CONSOLE, $HOSTS4_INFRA, $HOSTS4_APP } tcp dport $PORTS_KOPIA ct original proto-dst $PORTS_HTTPS accept comment "allow ipv4 https connection: > BK"
ip6 saddr { $HOSTS6_CONSOLE, $HOSTS6_INFRA, $HOSTS6_APP } tcp dport $PORTS_KOPIA ct original proto-dst $PORTS_HTTPS accept comment "allow ipv6 https connection: > BK"
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
+2 -3
View File
@@ -4,6 +4,7 @@
{% if node['name'] == 'console' %} {% if node['name'] == 'console' %}
# Hosts IPv4 # Hosts IPv4
{{ hostvars['fw']['network4']['firewall']['server'] }} fw.{{ domain['internal'] }} {{ hostvars['fw']['network4']['firewall']['server'] }} fw.{{ domain['internal'] }}
{{ hostvars['fw']['network4']['bk']['server'] }} bk.{{ domain['internal'] }} kopia.{{ domain['internal'] }}
{{ hostvars['fw']['network4']['vmm']['client'] }} init.vmm.{{ domain['internal'] }} {{ hostvars['fw']['network4']['vmm']['client'] }} init.vmm.{{ domain['internal'] }}
{{ hostvars['fw']['network4']['vmm']['server'] }} vmm.{{ domain['internal'] }} {{ hostvars['fw']['network4']['vmm']['server'] }} vmm.{{ domain['internal'] }}
{{ hostvars['fw']['network4']['infra']['server'] }} infra.{{ domain['internal'] }} {{ hostvars['fw']['network4']['infra']['server'] }} infra.{{ domain['internal'] }}
@@ -11,14 +12,12 @@
{{ hostvars['fw']['network4']['app']['server'] }} app.{{ domain['internal'] }} {{ hostvars['fw']['network4']['app']['server'] }} app.{{ domain['internal'] }}
# Hosts IPv6 # Hosts IPv6
{{ hostvars['fw']['network6']['firewall']['server'] }} fw.{{ domain['internal'] }} {{ hostvars['fw']['network6']['firewall']['server'] }} fw.{{ domain['internal'] }}
{{ hostvars['fw']['network6']['bk']['server'] }} bk.{{ domain['internal'] }} kopia.{{ domain['internal'] }}
{{ hostvars['fw']['network6']['vmm']['client'] }} init.vmm.{{ domain['internal'] }} {{ hostvars['fw']['network6']['vmm']['client'] }} init.vmm.{{ domain['internal'] }}
{{ hostvars['fw']['network6']['vmm']['server'] }} vmm.{{ domain['internal'] }} {{ hostvars['fw']['network6']['vmm']['server'] }} vmm.{{ domain['internal'] }}
{{ hostvars['fw']['network6']['infra']['server'] }} infra.{{ domain['internal'] }} {{ hostvars['fw']['network6']['infra']['server'] }} infra.{{ domain['internal'] }}
{{ hostvars['fw']['network6']['auth']['server'] }} auth.{{ domain['internal'] }} {{ hostvars['fw']['network6']['auth']['server'] }} auth.{{ domain['internal'] }}
{{ hostvars['fw']['network6']['app']['server'] }} app.{{ domain['internal'] }} {{ hostvars['fw']['network6']['app']['server'] }} app.{{ domain['internal'] }}
# kopia repository
{{ hostvars['fw']['network4']['nas']['client'] }} nas.{{ domain['internal'] }}
{{ hostvars['fw']['network6']['nas']['client'] }} nas.{{ domain['internal'] }}
{% else %} {% else %}
# IPv4 # IPv4
# Crowdsec, blocky, bind(fw) # Crowdsec, blocky, bind(fw)
+2 -2
View File
@@ -1,6 +1,6 @@
[Resolve] [Resolve]
{% if node['name'] in ['vmm', 'fw'] %} {% if node['name'] in ["vmm", "fw"] %}
DNS=1.1.1.2 1.0.0.2 DNS=1.1.1.2 1.0.0.2
DNS=2606:4700:4700::1112 2606:4700:4700::1002 DNS=2606:4700:4700::1112 2606:4700:4700::1002
{% endif %} {% endif %}
cache=false Cache=false
+14 -23
View File
@@ -26,10 +26,11 @@ define HOSTS4_BLOCKY = {{ hostvars['fw']['network4']['blocky']['server'] }}
define HOSTS4_BIND = {{ hostvars['fw']['network4']['bind']['server'] }} define HOSTS4_BIND = {{ hostvars['fw']['network4']['bind']['server'] }}
define HOSTS4_CONSOLE = { {{ hostvars['fw']['network4']['console'].values() | join(', ') }} } define HOSTS4_CONSOLE = { {{ hostvars['fw']['network4']['console'].values() | join(', ') }} }
define HOSTS4_VMM = { {{ hostvars['fw']['network4']['vmm'].values() | join(', ') }} } define HOSTS4_VMM = { {{ hostvars['fw']['network4']['vmm'].values() | join(', ') }} }
define HOSTS4_BK = {{ hostvars['fw']['network4']['bk']['server'] }}
define HOSTS4_INFRA = {{ hostvars['fw']['network4']['infra']['server'] }} define HOSTS4_INFRA = {{ hostvars['fw']['network4']['infra']['server'] }}
define HOSTS4_AUTH = {{ hostvars['fw']['network4']['auth']['server'] }} define HOSTS4_AUTH = {{ hostvars['fw']['network4']['auth']['server'] }}
define HOSTS4_APP = {{ hostvars['fw']['network4']['app']['server'] }} define HOSTS4_APP = {{ hostvars['fw']['network4']['app']['server'] }}
define HOSTS4_NAS = {{ hostvars['fw']['network4']['nas']['client'] }} define HOSTS4_SWITCH = {{ hostvars['fw']['network4']['switch']['client'] }}
define HOSTS4_PRINTER = {{ hostvars['fw']['network4']['printer']['client'] }} define HOSTS4_PRINTER = {{ hostvars['fw']['network4']['printer']['client'] }}
define HOSTS6_FW = { {{ hostvars['fw']['network6']['firewall'].values() | join(', ') }} } define HOSTS6_FW = { {{ hostvars['fw']['network6']['firewall'].values() | join(', ') }} }
@@ -37,10 +38,10 @@ define HOSTS6_BLOCKY = {{ hostvars['fw']['network6']['blocky']['server'] }}
define HOSTS6_BIND = {{ hostvars['fw']['network6']['bind']['server'] }} define HOSTS6_BIND = {{ hostvars['fw']['network6']['bind']['server'] }}
define HOSTS6_CONSOLE = { {{ hostvars['fw']['network6']['console'].values() | join(', ') }} } define HOSTS6_CONSOLE = { {{ hostvars['fw']['network6']['console'].values() | join(', ') }} }
define HOSTS6_VMM = { {{ hostvars['fw']['network6']['vmm'].values() | join(', ') }} } define HOSTS6_VMM = { {{ hostvars['fw']['network6']['vmm'].values() | join(', ') }} }
define HOSTS6_BK = {{ hostvars['fw']['network6']['bk']['server'] }}
define HOSTS6_INFRA = {{ hostvars['fw']['network6']['infra']['server'] }} define HOSTS6_INFRA = {{ hostvars['fw']['network6']['infra']['server'] }}
define HOSTS6_AUTH = {{ hostvars['fw']['network6']['auth']['server'] }} define HOSTS6_AUTH = {{ hostvars['fw']['network6']['auth']['server'] }}
define HOSTS6_APP = {{ hostvars['fw']['network6']['app']['server'] }} define HOSTS6_APP = {{ hostvars['fw']['network6']['app']['server'] }}
define HOSTS6_NAS = {{ hostvars['fw']['network6']['nas']['client'] }}
define PORTS_SSH = 22 define PORTS_SSH = 22
define PORTS_WEB = { 80, 443 } define PORTS_WEB = { 80, 443 }
@@ -50,7 +51,6 @@ define PORTS_NTP = 123
define PORTS_VPN = 11290 define PORTS_VPN = 11290
define PORTS_CROWDSEC = 8080 define PORTS_CROWDSEC = 8080
define PORTS_NAS = { 5000, 5001 } define PORTS_NAS = { 5000, 5001 }
define PORTS_KOPIA = 51515
table inet nat { table inet nat {
chain prerouting { chain prerouting {
@@ -114,12 +114,12 @@ table inet filter {
iifname "lo" accept comment "allow local connection: FW > FW" iifname "lo" accept comment "allow local connection: FW > FW"
udp dport $PORTS_VPN accept comment "allow vpn connection: > FW" udp dport $PORTS_VPN accept comment "allow vpn connection: > FW"
iifname { $IF_CLIENT, $IF_SERVER, $IF_USER, $IF_WG } meta l4proto { icmp, icmpv6 } accept comment "allow icmp, icmpv6 connection: CLIENT/SERVER/USER/WG > FW" iifname { $IF_CLIENT, $IF_SERVER, $IF_USER, $IF_WG } meta l4proto { icmp, icmpv6 } accept comment "allow icmp, icmpv6 connection: CLIENT/SERVER/USER/WG > FW"
iifname { $IF_CLIENT, $IF_SERVER, $IF_WG } udp dport $PORTS_NTP accept comment "allow ntp connection: CLIENT/SERVER/USER/WG > FW" iifname { $IF_CLIENT, $IF_SERVER, $IF_WG } udp dport $PORTS_NTP accept comment "allow ntp connection: CLIENT/SERVER/WG > FW"
# Global chain contains "WAN !> :SSH_PORT" # Global chain contains "WAN !> :SSH_PORT"
ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv4 ssh connection: CONSOLE > FW" ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv4 ssh connection: CONSOLE > FW"
ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv6 ssh connection: CONSOLE > FW" ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv6 ssh connection: CONSOLE > FW"
ip saddr { $HOSTS4_VMM, $HOSTS4_INFRA, $HOSTS4_AUTH, $HOSTS4_APP } tcp dport $PORTS_CROWDSEC accept comment "allow ipv4 crowdsec lapi connection: SERVER > FW" ip saddr { $HOSTS4_VMM, $HOSTS4_BK, $HOSTS4_INFRA, $HOSTS4_AUTH, $HOSTS4_APP } tcp dport $PORTS_CROWDSEC accept comment "allow ipv4 crowdsec lapi connection: SERVER > FW"
ip6 saddr { $HOSTS6_VMM, $HOSTS6_INFRA, $HOSTS6_AUTH, $HOSTS6_APP } tcp dport $PORTS_CROWDSEC accept comment "allow ipv6 crowdsec lapi connection: SERVER > FW" ip6 saddr { $HOSTS6_VMM, $HOSTS6_BK, $HOSTS6_INFRA, $HOSTS6_AUTH, $HOSTS6_APP } tcp dport $PORTS_CROWDSEC accept comment "allow ipv6 crowdsec lapi connection: SERVER > FW"
# Global chain contains "WAN !> :DNS_PORT" # Global chain contains "WAN !> :DNS_PORT"
ip daddr $HOSTS4_BLOCKY udp dport $PORTS_DNS accept comment "allow ipv4 udp dns connection: !WAN > SERVER BLOCKY(FW)" ip daddr $HOSTS4_BLOCKY udp dport $PORTS_DNS accept comment "allow ipv4 udp dns connection: !WAN > SERVER BLOCKY(FW)"
ip daddr $HOSTS4_BLOCKY tcp dport $PORTS_DNS accept comment "allow ipv4 tcp dns connection: !WAN > SERVER BLOCKY(FW)" ip daddr $HOSTS4_BLOCKY tcp dport $PORTS_DNS accept comment "allow ipv4 tcp dns connection: !WAN > SERVER BLOCKY(FW)"
@@ -140,15 +140,12 @@ table inet filter {
# SSH connection # SSH connection
ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv4 ssh connection: CONSOLE > FW >" ip saddr $HOSTS4_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv4 ssh connection: CONSOLE > FW >"
ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv6 ssh connection: CONSOLE > FW >" ip6 saddr $HOSTS6_CONSOLE tcp dport $PORTS_SSH accept comment "allow ipv6 ssh connection: CONSOLE > FW >"
# Reverse proxy (WAN) # Reverse proxy for all
oifname $IF_SERVER ip daddr $HOSTS4_AUTH tcp dport $PORTS_WEB accept comment "allow ipv4 web connection: > FW > SERVER AUTH" oifname $IF_SERVER ip daddr $HOSTS4_AUTH tcp dport $PORTS_WEB accept comment "allow ipv4 web connection: > FW > SERVER AUTH"
oifname $IF_SERVER ip6 daddr $HOSTS6_AUTH tcp dport $PORTS_WEB accept comment "allow ipv6 web connection: > FW > SERVER AUTH" oifname $IF_SERVER ip6 daddr $HOSTS6_AUTH tcp dport $PORTS_WEB accept comment "allow ipv6 web connection: > FW > SERVER AUTH"
# Reverse proxy (SERVER) # Reverse proxy (SERVER) and Kopia (SERVER) for CONSOLE
oifname $IF_SERVER ip saddr $HOSTS4_CONSOLE ip daddr { $HOSTS4_INFRA, $HOSTS4_APP } tcp dport $PORTS_WEB accept comment "allow ipv4 web connection: CONSOLE > FW > SERVER INFRA/APP" oifname $IF_SERVER ip saddr $HOSTS4_CONSOLE ip daddr { $HOSTS4_BK, $HOSTS4_INFRA, $HOSTS4_APP } tcp dport $PORTS_WEB accept comment "allow ipv4 web connection: CONSOLE > FW > SERVER BK/INFRA/APP"
oifname $IF_SERVER ip6 saddr $HOSTS6_CONSOLE ip6 daddr { $HOSTS6_INFRA, $HOSTS6_APP } tcp dport $PORTS_WEB accept comment "allow ipv6 web connection: CONSOLE > FW > SERVER INFRA/APP" oifname $IF_SERVER ip6 saddr $HOSTS6_CONSOLE ip6 daddr { $HOSTS6_BK, $HOSTS6_INFRA, $HOSTS6_APP } tcp dport $PORTS_WEB accept comment "allow ipv6 web connection: CONSOLE > FW > SERVER BK/INFRA/APP"
# Kopia/NAS Console > NAS
oifname $IF_CLIENT ip saddr $HOSTS4_CONSOLE ip daddr $HOSTS4_NAS tcp dport { $PORTS_NAS, $PORTS_KOPIA } accept comment "allow ipv4 web connection (DSM, KOPIA): CONSOLE > FW > CLIENT NAS"
oifname $IF_CLIENT ip6 saddr $HOSTS6_CONSOLE ip6 daddr $HOSTS6_NAS tcp dport { $PORTS_NAS, $PORTS_KOPIA } accept comment "allow ipv6 web connection (DSM, KOPIA): CONSOLE > FW > CLIENT NAS"
# Printer # Printer
oifname $IF_CLIENT ip saddr $HOSTS4_CONSOLE ip daddr $HOSTS4_PRINTER accept comment "allow ipv4 printer connection: CONSOLE > FW > PRINTER" oifname $IF_CLIENT ip saddr $HOSTS4_CONSOLE ip daddr $HOSTS4_PRINTER accept comment "allow ipv4 printer connection: CONSOLE > FW > PRINTER"
@@ -162,19 +159,13 @@ table inet filter {
return return
} }
chain client { chain client {
oifname $IF_WAN ip saddr { $HOSTS4_CONSOLE, $HOSTS4_NAS } accept comment "allow ipv4 internet connection: CLIENT CONSOLE/NAS > FW > WAN" oifname $IF_WAN ip saddr { $HOSTS4_PRINTER, $HOSTS4_SWITCH } drop comment "deny ipv4 internet connection: CLIENT PRINTER/SWITCH !> FW > WAN"
oifname $IF_WAN ip6 saddr { $HOSTS6_CONSOLE, $HOSTS6_NAS } accept comment "allow ipv6 internet connection: CLIENT CONSOLE/NAS > FW > WAN" oifname $IF_WAN accept comment "allow internet connection: CLIENT > FW > WAN"
return return
} }
chain server { chain server {
# reverse proxy AUTH > NAS oifname $IF_WAN ip saddr { $HOSTS4_VMM, $HOSTS4_BK, $HOSTS4_INFRA, $HOSTS4_AUTH, $HOSTS4_APP } accept comment "allow ipv4 internet connection: SERVER VMM/BK/INFRA/AUTH/APP > FW > WAN"
oifname $IF_CLIENT ip saddr $HOSTS4_AUTH ip daddr $HOSTS4_NAS tcp dport $PORTS_NAS accept comment "allow ipv4 web connection(DSM): SERVER AUTH > FW > CLIENT NAS" oifname $IF_WAN ip6 saddr { $HOSTS6_VMM, $HOSTS6_BK, $HOSTS6_INFRA, $HOSTS6_AUTH, $HOSTS6_APP } accept comment "allow ipv6 internet connection: SERVER VMM/BK/INFRA/AUTH/APP > FW > WAN"
oifname $IF_CLIENT ip6 saddr $HOSTS6_AUTH ip6 daddr $HOSTS6_NAS tcp dport $PORTS_NAS accept comment "allow ipv6 web connection(DSM): SERVER AUTH > FW > CLIENT NAS"
# Kopia INFRA, APP > NAS
oifname $IF_CLIENT ip saddr { $HOSTS4_INFRA, $HOSTS4_APP } ip daddr $HOSTS4_NAS tcp dport $PORTS_KOPIA accept comment "allow ipv4 web connection(kopia): SERVER INFRA/APP > FW > CLIENT NAS"
oifname $IF_CLIENT ip6 saddr { $HOSTS6_INFRA, $HOSTS6_APP } ip6 daddr $HOSTS6_NAS tcp dport $PORTS_KOPIA accept comment "allow ipv6 web connection(kopia): SERVER INFRA/APP > FW > CLIENT NAS"
oifname $IF_WAN ip saddr { $HOSTS4_VMM, $HOSTS4_INFRA, $HOSTS4_AUTH, $HOSTS4_APP } accept comment "allow ipv4 internet connection: SERVER VMM/INFRA/AUTH/APP > FW > WAN"
oifname $IF_WAN ip6 saddr { $HOSTS6_VMM, $HOSTS6_INFRA, $HOSTS6_AUTH, $HOSTS6_APP } accept comment "allow ipv6 internet connection: SERVER VMM/INFRA/AUTH/APP > FW > WAN"
return return
} }
chain user { chain user {
+48 -16
View File
@@ -7,11 +7,13 @@ sudo:
console: ENC[AES256_GCM,data:RdvzU4VOU+ww1OVvLanD9KbCYom/yPHQ1DdjUBfG6l9nPHEapYqqvHpr6Oi3nDRfc2n5cR4R40i0DHCh01Eo,iv:X8RxKloim0jsDj8U/aY+rHARtrlTrvwNMqMcTmdPfes=,tag:eaMrWFdyU9jifh3SvBrE+A==,type:str] console: ENC[AES256_GCM,data:RdvzU4VOU+ww1OVvLanD9KbCYom/yPHQ1DdjUBfG6l9nPHEapYqqvHpr6Oi3nDRfc2n5cR4R40i0DHCh01Eo,iv:X8RxKloim0jsDj8U/aY+rHARtrlTrvwNMqMcTmdPfes=,tag:eaMrWFdyU9jifh3SvBrE+A==,type:str]
vmm: ENC[AES256_GCM,data:CqEAeHMgRkmsFYFGOyHic2TGYXlw/1VO4mMAaPSHqzGDoW6u6Gz29uho9EY=,iv:5fc0LkIQ/gVFTK7YEjnmA5ye2EEyh5/61VvTVarGOQA=,tag:yLwK2HchZvGZBFL4ZnxNaw==,type:str] vmm: ENC[AES256_GCM,data:CqEAeHMgRkmsFYFGOyHic2TGYXlw/1VO4mMAaPSHqzGDoW6u6Gz29uho9EY=,iv:5fc0LkIQ/gVFTK7YEjnmA5ye2EEyh5/61VvTVarGOQA=,tag:yLwK2HchZvGZBFL4ZnxNaw==,type:str]
fw: ENC[AES256_GCM,data:Iz9zt+M+ug6vxzjMAdGuSBSQ16+JrrXpfbsWUpoA184JEV+nC0xZi4eawLI=,iv:4lbQCgFdo5WzY5vFbn9dbkLN6iCoJNJ/5UXw74qOv7s=,tag:eCRh07yL5/D3Kzh6xgmDWg==,type:str] fw: ENC[AES256_GCM,data:Iz9zt+M+ug6vxzjMAdGuSBSQ16+JrrXpfbsWUpoA184JEV+nC0xZi4eawLI=,iv:4lbQCgFdo5WzY5vFbn9dbkLN6iCoJNJ/5UXw74qOv7s=,tag:eCRh07yL5/D3Kzh6xgmDWg==,type:str]
bk: ENC[AES256_GCM,data:mtpcOaoQzQzweKZG9toTXJ1C2wujyakkEP2axKCNXizKcQX575G42Ye3glU=,iv:SUZJFQbuxUoSB/fyk8NZZplCLG49dIFtnYqcxbXoJsg=,tag:Yy8yF/CwqLZP1cyOrTPJCA==,type:str]
infra: ENC[AES256_GCM,data:2KEo16JyMbcySxkPUA1qvQZP5YnfKlT/lJS8FnFWSoXEL508dwiWslSDPfI=,iv:xLah1BYaNuMlSWUufhdWupzPaXbLVgVwVfXO7dKSCcY=,tag:wqkJdWNf2h5ecSBDf3T8xg==,type:str] infra: ENC[AES256_GCM,data:2KEo16JyMbcySxkPUA1qvQZP5YnfKlT/lJS8FnFWSoXEL508dwiWslSDPfI=,iv:xLah1BYaNuMlSWUufhdWupzPaXbLVgVwVfXO7dKSCcY=,tag:wqkJdWNf2h5ecSBDf3T8xg==,type:str]
auth: ENC[AES256_GCM,data:Gv73925NEyxQEXmVC3YImOfzj99ZVDH+Jt3iEl0yEN69E/1VeqH67uG5kyQ=,iv:+Dd4kY0nDZIBnB+Ft7e8GD1v9a9NjRjU/QnwnXJLJ/w=,tag:X/hOwq1fxHPPhp5VtENWbw==,type:str] auth: ENC[AES256_GCM,data:Gv73925NEyxQEXmVC3YImOfzj99ZVDH+Jt3iEl0yEN69E/1VeqH67uG5kyQ=,iv:+Dd4kY0nDZIBnB+Ft7e8GD1v9a9NjRjU/QnwnXJLJ/w=,tag:X/hOwq1fxHPPhp5VtENWbw==,type:str]
app: ENC[AES256_GCM,data:/e7LF628qBL1+dPtfqV0myEp9MYBx4s1R6LG+HD9P/7LSsF2qG4eUl885GE=,iv:oU23xu+QTtYbT9/7Z8Q+CrCrpOJXs+Cgstvf8RASEZc=,tag:AvYzJuTKFt+dHm/uca+TGg==,type:str] app: ENC[AES256_GCM,data:/e7LF628qBL1+dPtfqV0myEp9MYBx4s1R6LG+HD9P/7LSsF2qG4eUl885GE=,iv:oU23xu+QTtYbT9/7Z8Q+CrCrpOJXs+Cgstvf8RASEZc=,tag:AvYzJuTKFt+dHm/uca+TGg==,type:str]
hash: hash:
fw: ENC[AES256_GCM,data:cI7ZkkxkNypzTRtChxC0HVp0YxwUHXDlcs+Mm1A2OxuGekr4t2IoXnF3OieQVB8LfjH14iJDhBAQxAjww9O3dsaKy1QQx8zCZ5IabDmBfLEsdhJVGHxTBw6PJHzhlW4+1QAYnxXcWqH6Tg==,iv:s/A8I30BP4PYBf+5lBxBXySx2atYn1MYdclA1Cb/VOY=,tag:tKBs1udztZV0T3/UfAiL5A==,type:str] fw: ENC[AES256_GCM,data:cI7ZkkxkNypzTRtChxC0HVp0YxwUHXDlcs+Mm1A2OxuGekr4t2IoXnF3OieQVB8LfjH14iJDhBAQxAjww9O3dsaKy1QQx8zCZ5IabDmBfLEsdhJVGHxTBw6PJHzhlW4+1QAYnxXcWqH6Tg==,iv:s/A8I30BP4PYBf+5lBxBXySx2atYn1MYdclA1Cb/VOY=,tag:tKBs1udztZV0T3/UfAiL5A==,type:str]
bk: ENC[AES256_GCM,data:tdZOY/Cyj0leqPpRqOpoudTLW00RQpzREz9gZ+wvwhcKR2tPA7IrDSSaJTt5EOYrfInwBL1x/Zq+JZ4b9+VWW/9+f8JWN0AW8IuCv+5aZ8b2/TKFM95P9a95n+JpkriwPp9Ca0ZQ8BdqpQ==,iv:NCXVJP0ZYQwNo7BmIeyKnHSIcQuUpQmccFLFRYZ+a1k=,tag:avOW/Xyy1tGSJbtp2vlvnw==,type:str]
infra: ENC[AES256_GCM,data:Ifk0g0CZOIzyTeTgSVlOj5J0TsIBNQTtZYsM+MNsZ/BGhNb/NADotrBRwpgK7Lts13TQ9eNZtcm4VgWVyWVIcM2HJ+1hAKMHcgHsOlaZNZa3vbiGS/X6xvD01vFeNWC1P0A7GDsvNS0B0A==,iv:PbwSvKNl4EmLBJ/la3ePx7hzJodtLGn57XvgM3X3xtc=,tag:Qahp1EARyRqmWr2BZ/pLJw==,type:str] infra: ENC[AES256_GCM,data:Ifk0g0CZOIzyTeTgSVlOj5J0TsIBNQTtZYsM+MNsZ/BGhNb/NADotrBRwpgK7Lts13TQ9eNZtcm4VgWVyWVIcM2HJ+1hAKMHcgHsOlaZNZa3vbiGS/X6xvD01vFeNWC1P0A7GDsvNS0B0A==,iv:PbwSvKNl4EmLBJ/la3ePx7hzJodtLGn57XvgM3X3xtc=,tag:Qahp1EARyRqmWr2BZ/pLJw==,type:str]
auth: ENC[AES256_GCM,data:ezk7MNsSRkF/dI8YhKB9CX+M8j876cRCkDqx64mZPaYNIWD7/tpbwqSTuTvoFsGJ9ikh3ZbNA4n3qMxMSsWstckHfcSgjUF56Bz9lCRvNqNCk/tDyj5aqxeHPXrbad4lwrgl0dPNFuPqxg==,iv:JEJnP+HnaxaLWpgsVmsLuTcxTMIA28l/ESCDnJcM1oQ=,tag:flDCxuD3L5IEfAX5BGu+YA==,type:str] auth: ENC[AES256_GCM,data:ezk7MNsSRkF/dI8YhKB9CX+M8j876cRCkDqx64mZPaYNIWD7/tpbwqSTuTvoFsGJ9ikh3ZbNA4n3qMxMSsWstckHfcSgjUF56Bz9lCRvNqNCk/tDyj5aqxeHPXrbad4lwrgl0dPNFuPqxg==,iv:JEJnP+HnaxaLWpgsVmsLuTcxTMIA28l/ESCDnJcM1oQ=,tag:flDCxuD3L5IEfAX5BGu+YA==,type:str]
app: ENC[AES256_GCM,data:xRr+kc1cvB2BK6DhQZQ21TvsgIgAxAJlWVMM7fbFTn9HObUIuz+a9MROGnduHKe8dp5bOkL97jlwZvk4qT8n51rYp4YvgKU/CQ7n89MqQO248hJp2MRMRWmom9Gh6HlzY4IHeMhceb/oYQ==,iv:BG4tPfwp5Qa9/H0h517fHjaE/ZIMy4vnAAQ4Fvqj2H8=,tag:meE8ZxXB8E4Pi/bS4dKMZA==,type:str] app: ENC[AES256_GCM,data:xRr+kc1cvB2BK6DhQZQ21TvsgIgAxAJlWVMM7fbFTn9HObUIuz+a9MROGnduHKe8dp5bOkL97jlwZvk4qT8n51rYp4YvgKU/CQ7n89MqQO248hJp2MRMRWmom9Gh6HlzY4IHeMhceb/oYQ==,iv:BG4tPfwp5Qa9/H0h517fHjaE/ZIMy4vnAAQ4Fvqj2H8=,tag:meE8ZxXB8E4Pi/bS4dKMZA==,type:str]
@@ -25,8 +27,8 @@ ca:
crt: ENC[AES256_GCM,data:t+yAyGjsbGUFfa/3wKqAHVgV15trtFrFHXRgBN5y1iJNXvqsHzdt4OO07o/d8lT2bh/UXZEHQDmx0VW+gKSouVzr+ZF2ENgXAW+d1cWWup7cLW+oC2LOf22gP3js53dGNS4+qRhPTi5M7XZztsAJgaI3+LAiDMoxoZn8jZZ2OKOB2038w8ZHCDGMUmvCMXJkk5u4o9zf8qLggdPk/MoAtQ4g4/5Q/gJsf5v6+ufZbSXnWWfwtBce7FStb3Bg06RIGG3LtDGzBxvMFpDJe3z0bidJtOlYyAJhOZF/knOTUwVlEt/Jhd9KoxRKYCMETj0eKO88bIyxZx9gmli7OuETWRyK+A8Y7xAdAoZxgeDJZjX4kcPsMy3vkGKSGRKDg+FMwX/PGwUDQmG+UyfmGqZUyc5fJWHKI8eY55jZoHR2U47tRvV3DcRlvfq8x1Ror1aMtaHfAYcTtxmhQxaWTBhpEQDMSBfMS85UMtNATQd9FXaIh3L6NB1hXCEa/3Tb03ULjkV9Ij92l041CdVUGhRbgz7iC7gy2aGap8fK4PopuqPeEsz306S1Mc1+FLrBz0Y4+545k+cNcEueKRXkColtdsTGU0JhftF3tXxynmx8W0kGKfG3o12VAN4Q8+yYPvE4XtTNVoJtzPeC+ksCem+w57gIAP+PbSdmnaEjsM/GrfTfGzJzcuCUKVDtSl8jh3B8f7f6dk0GSXftMnofdHlSXcAq3rG8oHoqCzS+k/VMz8o22uqcVHTiE0HKVK9h0jghDkkEYcGyiBsLPMlUxmkBmE8uwA==,iv:FyUTqDvjMajaHljcwnQZ9usEaL46hpvGOjNvIVUTMEA=,tag:K3h0hZfr0yjVhxpaG6bi3Q==,type:str] crt: ENC[AES256_GCM,data:t+yAyGjsbGUFfa/3wKqAHVgV15trtFrFHXRgBN5y1iJNXvqsHzdt4OO07o/d8lT2bh/UXZEHQDmx0VW+gKSouVzr+ZF2ENgXAW+d1cWWup7cLW+oC2LOf22gP3js53dGNS4+qRhPTi5M7XZztsAJgaI3+LAiDMoxoZn8jZZ2OKOB2038w8ZHCDGMUmvCMXJkk5u4o9zf8qLggdPk/MoAtQ4g4/5Q/gJsf5v6+ufZbSXnWWfwtBce7FStb3Bg06RIGG3LtDGzBxvMFpDJe3z0bidJtOlYyAJhOZF/knOTUwVlEt/Jhd9KoxRKYCMETj0eKO88bIyxZx9gmli7OuETWRyK+A8Y7xAdAoZxgeDJZjX4kcPsMy3vkGKSGRKDg+FMwX/PGwUDQmG+UyfmGqZUyc5fJWHKI8eY55jZoHR2U47tRvV3DcRlvfq8x1Ror1aMtaHfAYcTtxmhQxaWTBhpEQDMSBfMS85UMtNATQd9FXaIh3L6NB1hXCEa/3Tb03ULjkV9Ij92l041CdVUGhRbgz7iC7gy2aGap8fK4PopuqPeEsz306S1Mc1+FLrBz0Y4+545k+cNcEueKRXkColtdsTGU0JhftF3tXxynmx8W0kGKfG3o12VAN4Q8+yYPvE4XtTNVoJtzPeC+ksCem+w57gIAP+PbSdmnaEjsM/GrfTfGzJzcuCUKVDtSl8jh3B8f7f6dk0GSXftMnofdHlSXcAq3rG8oHoqCzS+k/VMz8o22uqcVHTiE0HKVK9h0jghDkkEYcGyiBsLPMlUxmkBmE8uwA==,iv:FyUTqDvjMajaHljcwnQZ9usEaL46hpvGOjNvIVUTMEA=,tag:K3h0hZfr0yjVhxpaG6bi3Q==,type:str]
password: ENC[AES256_GCM,data:ElXnqYyR9qAiBjPqR0HVsMcknp/qqCsBbs1zLfRVqYHSX68RkNVDWOWhrIo=,iv:xiBAV2J52aQbaA9VxdUvjiYg7JTnQyeuBukTFfDCjig=,tag:lZXVek8TSTcNtcu5VyUMUQ==,type:str] password: ENC[AES256_GCM,data:ElXnqYyR9qAiBjPqR0HVsMcknp/qqCsBbs1zLfRVqYHSX68RkNVDWOWhrIo=,iv:xiBAV2J52aQbaA9VxdUvjiYg7JTnQyeuBukTFfDCjig=,tag:lZXVek8TSTcNtcu5VyUMUQ==,type:str]
intermediate: intermediate:
key: ENC[AES256_GCM,data:xZB2VgzLgTleX/E27lie9Cy0Ham6iGZtSfmw/wfOqH/h/HBv754uYV5XPQyenj6Mst06WiiNl/gvzCZjNAoLiKPkGWvpWZeUjeclsb3QuWjIIArarjcOaA1XX0wxsizfAZ79FU4qjY+alJlN2EnWgiyYIq/bCdhMorYi9nn3z63Q2CetzDpMILfacv4aUzIqu6iX9sgJ4cwpzlAdl0vs7Q4jUZ1eNu00zb9Lbf3NSFUuafzDNSn4FFJ5H4nFqC/okLtFjfMrWv+XPXKR/EqA77cS2gW0g8bGtpZX51cNGYlIMdXj9Coet5tgj+UG4KzJSMoTFdiXHdR1jFAvmYUcFbX1wtbGtIqK3vKcVT1UBtkxQnj8dURzuetyj21qABR6WfPXVOfgIQrTdG4bUZEw1LZbEYd8w6L57NE=,iv:nspy2dXUIGvuyTkETzMxmeEPh0u4saxc5jHfsUMC93M=,tag:v7mMF2+asasRwqIyTSlgQQ==,type:str] key: ENC[AES256_GCM,data:DmzFVd4v7eAMXaTKXCJRJUq5efPOIndVUiuUxHZgS6mqkF3TfC9eaaf1E+cuaLqtjifGjc+j5AuTbNs8S76EV3sB+j9H5e+hiVSsECnrEYMFeOyWTS8Tr2CUjZUWlmvAKFYdqWnR7J9bMyaJwyxJKXSkgAocUQ5Ctd/Fyjacod2H5FTuzaS5XdWTEH1rOFv3lYZSqejjCUXASvbk5v2xEygHi6Y9vBUx8XGHiZs5QGhWAfEN/FJlozmhTOsDrzx37ozZTKnTECYEZZhGuM6oKmPWlSijsZVymFrh2LxSzYGJj5Cr9s6DJsraOuHS4A6K2gxhUNXFF7LSjnUOZxnCq9tleAUUsAwKrFfBaZA+74if2kvNouVo5T9EHnkb2zAbW4K5PFrteqMI+cvzxbsO0iOQkO5sCr+B0XE=,iv:Ip8BUzd/eNeYclMet4MlRhTaQ8Z8i3/nwFmFNp4SjHM=,tag:Ac+cCufRry7vDtKwdeItYQ==,type:str]
crt: ENC[AES256_GCM,data:4RrGKeUS+9oZN08WINaW61C7yGs6Atu/vA/w9GNGhC21wMWHoB3FXl6sxDkNAO+qZn0YhINXW6MF6VvmPh0Lu2nQ5wdLlhsgFat1fXrWcatqvHoD08Q6pWSVTXwN9ZLM038ucOj26Xs4C2mBCl2wddII59YzCKRcXIYoK7GWF3m3x5uWY+sP+8IZ2fQiHEaITFX1hg9tNItmWoRh7gCQ15yec6KTOuM9Ph2HI32oP1Lm4h3fW2SvIcgJqHcFObtequGFXpvZbSedesdR3v+gNVSr5oTVsEGoGwyALt/gGpK3zptTDsavARzsQPUXu3+QILyuNYHXP653g+VnSLMwEMuFdeQJaBeG4TF0Zo76dPuy8lPSawhGK1BJsEgUb++23q87nW/O5UdJsUJ7gIejrQQpH266nq8cw1Thyskypk0TrsMdrTWwOniWOLSUVf+5GZi9mLqNse89Qe9xyJlvocTdpZg7Bl9kDVFjLRO2IC8+r7NqD8PeOjxT8ojJNYXG3iDbdqyQtHtpETjLUN4ZHCo8EOdGIBAqnutV0gAxnKIcran86gtk6QIeYL62x0AgkDDEClCrQMZEOIMbhzPMml+4Y0SdcoA8DErrFiPeufDxak5gNLRJxOT/okOBi5/QK4deJ2Cbx0lSxB79d69Ol9OAKUNW855o/lcGD+Tx3bNXYzN+EaFmpku3Sv8Bvl3QloVQ4832w0bbwcqEoviuB8hDMqsmWXZS8D+cqL9uYZVObRJS8rR8QGPfPkSPy8NePWsuR1vznlyBT35eyRcKwVp+qweDIjHHgAIcSvSAVPoQ3EYT01WCpRPsiTIxh4IbLIYeqImFrb6Vn7S6tMmv3E3eCnuL/LfxiV1t3Q==,iv:bUDkP5wRWEqi9n9QEN9ETHFeWdAiEk8GUwTD4X7asRA=,tag:xYYYPlGQfhcK97tSPtM7dQ==,type:str] crt: ENC[AES256_GCM,data:nVzxH8m9/ShlGpfFZjbmP2ViRmm7b15rjXbG7ODwqiiGZE0peXiNs6LimTUZw2H69iEyI77eakW7hGjQbre9T97R1QKwmaQzSb1UNi+bj37B8KncxXxXxoKzCKa0Ebz//caA5xJTcuC8e9VwYwZUzuUJL24OP2QRUHClqZ7RYchyNjiK0ooig1nKqEg/nTpReg6Hz8aoIBBVkOxpOKjF3nFJXMZ96ID5caWU5mWdeO8s/gmAzcpr3HYAhV2HC4urybiP5/+N/jLc84JbnjQJu+5o5EJjkl/8zNrjaJxDr1WRduM2RlH6Gr6LcKiMfi6BVl5gu/W66c+ZjhGXED/uZ6IqRXcuasKe2hTW/QtBtLt+nEwzzkIj0fr+SY1FPjjlqX6tLyF9L1XI6n7bQWydljli4Bavnn5PX1cCwddfyuot5R4Zow4Y9xrEqT7e0dgnwRu/LEDdX2hpVmehK5ysrPyVFkg0GO7WwrqLbs8dGDGuz/cTXiL+LOygitPguSpmnJcBOQYxR3orPYTIk6uJOiV0X4tc1vt3iz5fg5K6OFLM7s+qV71IRXCJ1zLCY/1o4Vi6ADdkpBUheK1VY2QSH6ZftZk6Ti/Hgr+WcPSVzjrvQSqfUakXaB4o5Gbi5Px1jNzqE7/iTbpUYDMNohA91WqEnFu6Bl2OB5lZIo3uBCzzAa/1h/DogOMEwyUa+RQd88U2sDuPATTxnGJIjVYRbFqqFEf4WN1tYFOGA4dMx8mjpJAOOUxbjIJdeMFmErjVGC+ZNf362xO6kWHWcYPwspCNYEnso9+UAPnAPwUakwc8p4ak9oBVGDmXVHCa0hAiK7Hv7prKjcmzZlnnP2DYEy3lmwuCVADm,iv:tHC5Ss9zbm3Uy5leWj4oOcvCBoFXzCUjy0YnQl8TIN0=,tag:WgCzCTwWzuOTRLQpga5g1Q==,type:str]
password: ENC[AES256_GCM,data:aijMXt3hTo19xVChh1gplU8sUQjmX4Y+dSjS69Kw2cEqmEJB/pelihLH96c=,iv:zP1yDLGsbL0sxJq2PF+qe3c8rNT7Knz6vKaGwMVB2xs=,tag:Oazypz0OfAYI/eptqgaINw==,type:str] password: ENC[AES256_GCM,data:aijMXt3hTo19xVChh1gplU8sUQjmX4Y+dSjS69Kw2cEqmEJB/pelihLH96c=,iv:zP1yDLGsbL0sxJq2PF+qe3c8rNT7Knz6vKaGwMVB2xs=,tag:Oazypz0OfAYI/eptqgaINw==,type:str]
acme_key: ENC[AES256_GCM,data:vir3SKMdU8FsZ3fBNoSMrev3vreFG4Vsex7R4hIR7Ty68x9wqsO/YpJSNkw=,iv:e7AqVbmCOkVIaje6xF8QzISU0E3JfyU4GM7/361ybdc=,tag:HC/kMa/jmVqBwCsvR31WHQ==,type:str] acme_key: ENC[AES256_GCM,data:vir3SKMdU8FsZ3fBNoSMrev3vreFG4Vsex7R4hIR7Ty68x9wqsO/YpJSNkw=,iv:e7AqVbmCOkVIaje6xF8QzISU0E3JfyU4GM7/361ybdc=,tag:HC/kMa/jmVqBwCsvR31WHQ==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment] #ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
@@ -58,6 +60,8 @@ wireguard:
# #
#ENC[AES256_GCM,data:+kiy17Z7q3EiPgo4Ykk=,iv:vOi54XHHLNIO9U0ybpU9Cn68Ymj5W4vtQ2OhTkGAmRo=,tag:h3wdCo5UfNGlHqMpeeBf/A==,type:comment] #ENC[AES256_GCM,data:+kiy17Z7q3EiPgo4Ykk=,iv:vOi54XHHLNIO9U0ybpU9Cn68Ymj5W4vtQ2OhTkGAmRo=,tag:h3wdCo5UfNGlHqMpeeBf/A==,type:comment]
kopia: kopia:
key: ENC[AES256_GCM,data:7hdg6CoaIWPmfabk1ANXwn6VfpgGNpHsICeuxYfyiMsTiXF7PYIIl/gVY+bmkwIYUwTJ7Otip9eFKN56bej1qKSw0ukR1ZAB4mVGgazXPMBYoPkFTGE0mPWQbZVtlWlvIW25e6WpLkD7h0D3d+kV4GLK2vSHyNDfGZOQrU2qgd1PM0jgI2/HVcEYOIZ5k8QBDZ4rQjlt6pSkQUs2vO+NJxtqFziH89ONz05EYBpQnhsMC1zUQuiMKC+C0HCtVlRKiHBK0n+35mvxNDfUopX7GwycGenzC4ZZ4ExpfRkqDtZRmKU=,iv:4kI2bbCkq8R+zf8+RYBeC+78+4Rz3bLH5YMnuCFsrUA=,tag:i2YEcZoOhgcNP/LkGeja/g==,type:str]
crt: ENC[AES256_GCM,data:8BtSrcSFuJebJIKmLZPx1dspN+IqKAF76ulSZnN3t5PsSnD7sVNem/2wrLqILnH1M++ojzrqH6Y6/YRPPSuWITXgYQjKVmdE4k4C6hSSdsUYxzNgyT9VQRSr2BfVWFXrFWFTHDNQ8zBxA6dbSXm97TbqX85CKKutCB6wmvfIwmyrpfb3bKkJCh6orl+xobHKAKnSx1vyuzFljQc+7nvQwGq3sEiZSswjfS7Mdx+MfDfj0Ge6Fpbfck1mGKmj0MTFHUYGSKMWEShwk9fWBYjhzoDt2fDGRR4EIG9AIC7lO1JHDTjOIjePK0HD5EoOEUEKpXy/iDl8lzVbFudiUFRtg7X73hq05dFV8cb1BXFhjaxv55NrYiTNg6K18h+x5gouiCaGYbSd2CazkiQst2CXlRpNGuqnfEthRTYHZHwO33mI/4S53sZA2rhVD8gj/PheS4uP4aHztLOFBK3yLV4QnjkeUKtkG5SCOd46xg1+rbHrPl8ExWOQAqTJ/2m0GeBcAI+K2jZDdyJpATEWrvdW44jAytEQuzgACIUs8gOMdnEY8f1ck/JqG6OstTnataqvTnYOoKDa4RwrrzjXTP07WCQpBHShSYLFuEf1XhdZSfrFMqAhJjvCTvAvJkfzfC51u4/7wDLiyswtFIEc6rTMZTVXqWsb0Ca8xwsH+4yKUdsBAyWnhwq2ySzfg7ogxS7L9GMKe4b3y4+cmznleafZgq4UdPelT4coEiEFvDOXO/wzEwxzzo875Pqmm28TlTUDQSSDGq3UlGA758YH0UYA0457qjOFSF2kZqVde6KILxVAmu3kO390WXJbLCBd91euwOUvvgGWuu4Iz4PYjhQVXX9DcAHT7tXFGJLzexLjh/vSwYNniy+TgnkDeW7Ivr+mJW3gp8dHTk4Zp/LfeFUi4bnvAcetoAbo7czEGTNVHY6ob3Lw42vWvUk=,iv:d4UcuKoG/ysu0hl8hDPjOD4oDMkboG34Ul2Yh4TM7DY=,tag:tibe0jmza3V/gi2HXqkr9Q==,type:str]
repository: ENC[AES256_GCM,data:16V50bVVtecbF+TJcXHCx46ZPGNMgAhUOA0YbZHVTsCrOWQvTvcK2k8Iq3E=,iv:/wNbrE5GaFiQPNEp8wZ0JehbXkmah/gPm5ywNE6WVVM=,tag:vW82KTKtJ44++tqXON/SYw==,type:str] repository: ENC[AES256_GCM,data:16V50bVVtecbF+TJcXHCx46ZPGNMgAhUOA0YbZHVTsCrOWQvTvcK2k8Iq3E=,iv:/wNbrE5GaFiQPNEp8wZ0JehbXkmah/gPm5ywNE6WVVM=,tag:vW82KTKtJ44++tqXON/SYw==,type:str]
users: users:
console: ENC[AES256_GCM,data:v1QY7h6vMmzYq/PTmnLg3M5Iwc/Ljr/1M3nJGuUJMfPN2ATY+GIMUyhYu+0=,iv:32c4YrZfTiu7sv/c9tDItmAE8G1lvc1sm6JD1GRkYr0=,tag:kj1a32+bMUsRdusadoXDvg==,type:str] console: ENC[AES256_GCM,data:v1QY7h6vMmzYq/PTmnLg3M5Iwc/Ljr/1M3nJGuUJMfPN2ATY+GIMUyhYu+0=,iv:32c4YrZfTiu7sv/c9tDItmAE8G1lvc1sm6JD1GRkYr0=,tag:kj1a32+bMUsRdusadoXDvg==,type:str]
@@ -66,15 +70,26 @@ kopia:
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment] #ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
# #
# #
#ENC[AES256_GCM,data:OK1SKcHWst0rO4MCrEU/,iv:1z4/DaZoVTfQtM/dtKUNHjMmv0UDYayyYwv2yoE1YXQ=,tag:2emhffuIuwdlP/xUYk4bbA==,type:comment]
rclone:
google_drive:
oidc:
id: ENC[AES256_GCM,data:Z4LnW6WMwBbVf1n1sD6GWCQXUSuPe3PcKhSb3aJ7UhtzCaD9DUNn5m/2f+WaTbkv6EhrCDeGrQBnfxoSGvniE8VZ2BltSeDu,iv:CjcP+E4wyOWcghjcSHGPhbKcxfTD97uhVzRTUJVq75U=,tag:TpCr3eApSE2MsanJ5pu72w==,type:str]
secret: ENC[AES256_GCM,data:n81fc7PwTP9BSxjplwlf+A7tXhwkToHv6lDuav+fleBMC1o=,iv:ndFJpWINRVCL7wcZZ8KjEgs1YPgR6wtWig+3VR4Okgo=,tag:HGOTF4i5mhA4mr4Xnf0UTA==,type:str]
refresh_token: ENC[AES256_GCM,data:EEE8ExDhoBqPNM/t+q07ng0UYTU2AGNJEWL3ydZ5A10yOrHrdjMC0YtblQzlsA6tdkLCemaUZQXz9kEIHfTQr901AQALkfb5C9OoEnlXz579OXhDnuv9BJUi7tv+Hny5z5DEeVm/Fw==,iv:LyTHhKqzmO530zFqB0+dKlgi+/NEE/WaJw1CdMTLFls=,tag:nJVszyqv3kEQ7ehlBDe44w==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:gfsEXIOqhoTsiCI4uDjDeEY=,iv:SfJwBdIFY8Z4Nt2CxjuSY8PYKebQvKcg9n2xL3w7rsU=,tag:yrTNPBjrvnxydGK2X32Zlg==,type:comment] #ENC[AES256_GCM,data:gfsEXIOqhoTsiCI4uDjDeEY=,iv:SfJwBdIFY8Z4Nt2CxjuSY8PYKebQvKcg9n2xL3w7rsU=,tag:yrTNPBjrvnxydGK2X32Zlg==,type:comment]
crowdsec: crowdsec:
key: ENC[AES256_GCM,data:C7bMfJikh20PFQTe7UtP48SDUlSKKDMOul7dt9USZIVKq7LLBJV83vqbOc3xbteqPzwIYqBEndfqypSevpy/cLAPstQXL634fQGbel6trqbCApq/xjucUvnaqRKyUjk/TH3oRP9qXG8XDsgQ1o+I4b4E1alxLljMPN12wd2KIHfDGp+TURcC9DkK+NESIyQMLQg40cBaps1HcxXvg7FB1oJImM6AjqP9iybDfgkCaNAqUHxLyCHJI4rdYFflALHFkorl8jaQTazqWfuSu70x8j5tUJREksOS8arN3YIwXp4UGHQ=,iv:sbF2ZD6xS3Z3EYc6/5m3oKMghkR1q/IDzVwBX0OuTTI=,tag:NIuO8x3rP47oE/Y0EiNOvw==,type:str] key: ENC[AES256_GCM,data:50i2yh0vkAhAb1tYsU5ijd+QSkCQ/w3Mv4hHubixCmUBx/zR8YwkLCnCdSd+UMTYvm51KvIxN4FsNj0nrbfqBJ6pSoC0UXrxgF4cGRWC+dNtEJyDO+J7yFwp+8lYMO5TqTSqYwxu0RpqEbe5V9p4uYruFwfVY79f3+KGt3nOsktPIw/rpdvD8mlpM48ANi30813miwpAhn/x54QVj21deHxWuzauYI+wmOIPZKgLkLNokX50oq9SCJntuuYLaR8S4B9ji3BPEOS0CX6aanm8Mu4Pl6hnGcmyEXhvlYZWgohp3fI=,iv:0oKtj/PUAznINv3t6K0iJec7/ytqYF218p3XBIZOLZ0=,tag:V4wywnJeEZsf01l2f3LVJQ==,type:str]
crt: ENC[AES256_GCM,data:0Olvh8chXMx0tri9NeiWhka/bl5XRwdAQf55EwhVa2kTedETOBIjdgDqdsXhoREhannWK/1cXcxP7vpvRFMt5e06FsmPh8mSuuyRboVs9ys5p8KPYQcnlOZxfBU1J6DzE8Zq/tOf9cpdlcUVpPJ038tI7cokqhBvPGZIR2Q4/2BKWQnL8d0GvQoEfXOpNw63qQDynSvaSs/asfZf7yeYH6v3Tc4tNRBB5nl8sCq8GjTvm4xleRWax9qS0oroB/uY7S+5OCGLtJFo0A4eweOcEwWuqvpGqsOgs6s8bToeaSmPOUgsCQ2abiMtBWnyCxMxMCFNB+79lpByasf1iGRWlrhjQeUpIoWWAWU6oUbd4pMRy+j+rKV1/Cq4wF7cc7kSTh8BlFAK3Yr8DIDppiUUo53utPAl179ZkycNUzHY5Auh/jA9ZU1UZRbtIOBlIN6mVr/Y53EzigtVYlZRQ6aaQFutM8jGBnegfPhp3m+XY2WanYk1GKKj46Wh11g1YqIWVYpk5hlR1RdQoPsgZPf0yChblbdfQ14iRJqw/0pVPBvX6bKS6P2OaDHpCIBSpTE98VSEjXTkK0XU0Mu5YzyUWxIe5/BoRiF9gRFGHEDWwFWprTuFk3eUEaEZ9qoyWr0igmX73Be7y8Bre0jX1xSMjepSLV/0dSUnimhfAvT1TlhwNlxq+FGR0ZMsu8QmbYp1CqLcH93rQxoloHIs2T1+KfKAENwsjm2PshdqmOOoUkzANUmdilYCelkbXyUKXkLqFb8qnSV0jK6hG/ZVeXTzZPnODJ9Tow9bXKdxOwk16XpuMSHjCoIol2E0yD/0YKVBHAnYuz/Uz8Dl/ko//3+OaDD4TudV/nRyy4Ge4JI/kckiovMLma4dJSmADgOAXa+Ao+3N/vfUMF1F1DyRXUXsqHMygtlZZpGiswabq/MrjEvBPomzFWUmu9clWiPJ,iv:SQrBnbzApJscyGuNPE40uKsUdQCf4W73uUwanfyCGbU=,tag:KK+a0tLB+mmn4YWl5Yc0tQ==,type:str] crt: ENC[AES256_GCM,data:zcnyni/BcXXx+/9F0tBnSqffJhumnv/ob8kNRVdyhx1KU5arwPzhlBh98BBl6dTOy9Eo/pz9UiEmuPs46IqE1QGFb3bmzloq92pxOrkQwxwTPL9WROAHbd148fHmHVa2NC7VBpVuuM5t/3os6vJzdPgYHZC1k23SKKjCHAorqiIDso3ZBHfVJ12fZnEnnIWh/wWyvw4ap3plmkEHZC6zHfMBvH/IAFN6Fzzn9nNmOB54f0xT4cYcActH/lpVxDx3l5KOkM5aKXKbTxzSPUugm2X3rSKZlBgfqPBfA9dWUBqK7bfKIgYETdadP/1K2vJmscnNLPJ4DlZe9R9p/i8hdmx9Ls2xeIk6TOMxpnQ/iXKu2mSVD2L6A8cbid5kTjGEqcl8osQCsyOV8dR68beBFHdQlt/PvJjTKIAGilZPk9U+W9p70RaA9ibQU/WJJxrZvMgpJEMdbq5WLeu2c/TYXWEKyfNrpU3kLgzln+6bBEXEPk1MYWUfQJHqsWeXQzMpALGGNUPys0oaAKvFBlaEEetK8dk7tUcU4M2N6Sxn5+lLE/wSa4ZMMEFDdLEvxbfB7OyChUEzn5fXYZayEAmBgSJlWBkhbXLocfASjzluF4mrBHtSKbIZOnpFtB/mHubgeMZlWVD4FwYwkzoBuLz3quLq1zhBVvJTQDfL5lu3d6CQlGiv/Hl10Fy4Ne9QJ1bpfBaj6Ih+0WuYwtFfjwQdKvO4CZ1C5Fy4E9GiSxRQnixjG3JD/7JwnnmQriPyaWpiYumhwqrVktHcUHu3n7zWBb3P+UFMw0+JsOWaEjU3eg9m/S/z3y0eN8bd//a0fbPuBiakLODaSHbEK6ooKyc7qDzhuQMYBgdxHgC7iBhtMDiqZ2VHVaSigagE3494ObxFXq7Nc/ymWoIjhVoz0hKQ85eQosyiusCjThxT70DaAUOWvDJkDjPP+M123I3UjKT3Lg==,iv:+4LUsHW3T9cdqOQZXq9eEb3gH1VHCXts0jyBV+HMiIU=,tag:+E9sWyUYhzTYwv6f/3KAMA==,type:str]
bouncer: bouncer:
fw: ENC[AES256_GCM,data:wplc8z6YNuQi7bN6r27wSOmx7alVDWUBgU+pgvnH0exmRhHCHjbS9zX+4P0=,iv:fbBg0AlqOtbKgYjbiSPopJ0QwEryAEXfcc+YaUWI6xI=,tag:Ul5+MwKZyMevBIyvZH/hAQ==,type:str] fw: ENC[AES256_GCM,data:wplc8z6YNuQi7bN6r27wSOmx7alVDWUBgU+pgvnH0exmRhHCHjbS9zX+4P0=,iv:fbBg0AlqOtbKgYjbiSPopJ0QwEryAEXfcc+YaUWI6xI=,tag:Ul5+MwKZyMevBIyvZH/hAQ==,type:str]
caddy: ENC[AES256_GCM,data:fRyTH9/7OZ7oaz2n3o7DtXJCnH5l89fGSZtM3FH8sWzw8Iqj14t/qXsX5Vs=,iv:YQbozgWTmU+facWKeC+2ab2fvm47CwLbrprRiWKDRyg=,tag:Ki3hGXPJ4lWMXJYaDF0kaA==,type:str] caddy: ENC[AES256_GCM,data:fRyTH9/7OZ7oaz2n3o7DtXJCnH5l89fGSZtM3FH8sWzw8Iqj14t/qXsX5Vs=,iv:YQbozgWTmU+facWKeC+2ab2fvm47CwLbrprRiWKDRyg=,tag:Ki3hGXPJ4lWMXJYaDF0kaA==,type:str]
machine: machine:
vmm: ENC[AES256_GCM,data:CF49CU6iwC8LiUMPaGMFMNGjF0n9gpSplnGkkJNk14qEkvYFTgfoUPqc964=,iv:Qi6cTieniO++EltyUkabXqsPAEb0AEmdR1ramlisthI=,tag:G85rEh6STS9pDr1zbuNUdg==,type:str] vmm: ENC[AES256_GCM,data:CF49CU6iwC8LiUMPaGMFMNGjF0n9gpSplnGkkJNk14qEkvYFTgfoUPqc964=,iv:Qi6cTieniO++EltyUkabXqsPAEb0AEmdR1ramlisthI=,tag:G85rEh6STS9pDr1zbuNUdg==,type:str]
bk: ENC[AES256_GCM,data:+paUsZrY/lPv6xTcPMCeTOL4aIpTsnNHo1jVL6LyXky8UyDtsrt5xr6xQ0g=,iv:oI4BoR40rZN3jHFCx3jANdyVMAeO2Kt4EonUdIixveo=,tag:x/sHdgx7S0Aus0+QiopEyw==,type:str]
fw: ENC[AES256_GCM,data:uA3AfA394F8b0a2jGjU8ABHvKGNTsZM0O1woQc7gLdHte5Cn8SgfuyNgWu0=,iv:TCZ4NwJuTVPAbiWn6QWM7cRta2uXODHb/41Q1qslJsU=,tag:A7fGrietJuxyEUik3eVZLQ==,type:str] fw: ENC[AES256_GCM,data:uA3AfA394F8b0a2jGjU8ABHvKGNTsZM0O1woQc7gLdHte5Cn8SgfuyNgWu0=,iv:TCZ4NwJuTVPAbiWn6QWM7cRta2uXODHb/41Q1qslJsU=,tag:A7fGrietJuxyEUik3eVZLQ==,type:str]
infra: ENC[AES256_GCM,data:rNpo77YAdoRedzJonScaT6Fhr18+T6u6/bKEzC7PYOIzEpuKh/MqzIS6Np4=,iv:D8QND39D2eqBG0USHhcc2UCxpTSuGn4SCpTCOBO0RAE=,tag:1X8IK8DNsD2m6DdtxMQTyA==,type:str] infra: ENC[AES256_GCM,data:rNpo77YAdoRedzJonScaT6Fhr18+T6u6/bKEzC7PYOIzEpuKh/MqzIS6Np4=,iv:D8QND39D2eqBG0USHhcc2UCxpTSuGn4SCpTCOBO0RAE=,tag:1X8IK8DNsD2m6DdtxMQTyA==,type:str]
auth: ENC[AES256_GCM,data:neUWugEoUU+LrXijmUjd6063pvtyMuvBhiLtKR0BdAqkl126LN776x4cibs=,iv:OSu3S3AQNqk0PRR2kITKgLcniEsNhrNbpPIix3UIwDw=,tag:5OpA77ayasIQAYx7tYFD9Q==,type:str] auth: ENC[AES256_GCM,data:neUWugEoUU+LrXijmUjd6063pvtyMuvBhiLtKR0BdAqkl126LN776x4cibs=,iv:OSu3S3AQNqk0PRR2kITKgLcniEsNhrNbpPIix3UIwDw=,tag:5OpA77ayasIQAYx7tYFD9Q==,type:str]
@@ -97,15 +112,15 @@ bind:
# #
#ENC[AES256_GCM,data:FNnIRyidUh2urEgGgM85,iv:w6Z7/VLY9BtH4CNqchc/3GkWb4ez2Nb0TxdZF6RdND4=,tag:14vEc2qpBoOApdnci8ZTug==,type:comment] #ENC[AES256_GCM,data:FNnIRyidUh2urEgGgM85,iv:w6Z7/VLY9BtH4CNqchc/3GkWb4ez2Nb0TxdZF6RdND4=,tag:14vEc2qpBoOApdnci8ZTug==,type:comment]
blocky: blocky:
key: ENC[AES256_GCM,data:3hIpfdbwUzIvFhhVOl9TYoLvVLtFS0jdKSC9FGT2dSmYJP9f0qqrKEtH9+52GF3YUXvf0fkPoqAxxDf3iNh2ynAS7PMBOth3LS5mnY+NpRCZuod8PkyQOWCzkAeVla/JeAD3n3da4f8layWHY47u37XgeojQpyijCWKifEnpbjJdXVBKi440mSaFaORgDJkvSMRGcgF1o1HWz8/YricUIfv3xniQA3Ke8gg4/L9gHHFAqAZiKUBDDppHzuY5ua82FDWTgipPtoNdi+9xyeTmNdunrVAF3OrHwkNQqfLJrGOfrhU=,iv:TGbO2lfqjnsu6ZzcO5qAeQKSgE5qr2lQZi+3YuAlAGs=,tag:tE8bTnPpBXwDXYyB9YsOPA==,type:str] key: ENC[AES256_GCM,data:6VmmgxShlwwDdfYIr5TOX7uBmnNCambqFVJ8E1FalRUBVr+HFt9cUdVror78UyPwmH6beNI94EC2R06zQmNVxhaSYtt2Ise825jbx2zthm6sP6jVK1PpU33bF9+5VSoDU448ZvQRDyW9bv8Gz1MeKMthzn6LAkg1lE1sZ5lp45QRal3IUw44SXa/pxdc7tn+VcYRMQ3a1oVUTR2kBnqLUw7OdzIZpu9PUcCoVyN28fJmlZnIx23wOfDsCb31VpbDpj9vylVZpqX+clNmwNuh0HcxUdXF6U849XOou/c3bK3WbwE=,iv:V3IiC1Po5+nZmpUsFdcw1aUiPteBXJ9vWJztR4wi+/4=,tag:ucJhuIfnS14bfPixjAB6oQ==,type:str]
crt: ENC[AES256_GCM,data:vvT9evMqMW8isY3N0tvQCW0XFWIW98vVz0aO0o3habCbLJlB5wjF6TMA1u1xbJ9zQWX8kHTt62BxBngCHXtKFnnVN2q1hNFK/sGFpAJz/WXD/sJW8kHOAv00dwGl2/r1josB9hFmn52omxpryY2h3ZTgqLxoCpzYPoB1LvJzPKo0bS4ig+/qYbAyPe9pNbTmPzGjXutoGbOKXKAQvfZg0YNsR/nbdd0Y5eEdHL+0syH2wEZZ1ZBBNxnd9wiEmRoQHDDkDJ6VHAWfcgZcuX47jKak6LFBAOfj2lVIza78o7MSQsCT1M5DJMZu/K5mV9jJhftljnZ8MB9rX3rFcApHnFX9luLn5b7pHRwieWCNHM71gy3wHS9DFZXjYRpFqFTiXmAxtKxgL3wDIu7M3Ajrc1o1JMlsWMGVUa/InfF73NIMJMKrAPgSWXb4JgwF9HmGjbO5GiSAjRXvuFFmQBArvA7NRn6XFaRyHsig8T/5nQ4t+E0C1HjCkzMFVnUwq5C/3aEJij+cv2YaT5jVTZ5tvX/x0lykMLxd5Psy2Mqvw1++NjS1eOBmg/4q0Pero6zOl+s83fyoSCiXD+K8XHHe24M2IBITABC/Wf4L4yNrwE5S8qn7M6vbFZns1C4BpnIUqbtGeMbAx5reM30nXTWO9pI8Xl5zAPrb4gd7zdl5c6HLge3k8wdNqw2kBD/z4EDCNCPar3g4f1XMhcA1aB3FrHuLvHOkCkCmNbvZ4D4+Nams8HDQ7aNNStshLGt2Rdh8fzQ/KlQslJvgk0oLupnGuZzNWP+TO4tuR4DC/pfX9Uw3+1SDeeTFH/X4iaoSJJxqwC0D3pTvu4SUXilZ+MBE+mDEkB+PbNTuyuFkbUi9OyRFy3W175Mbr9BAdlSIAd70SpUiARqn7k3S5twV5pomxYyOaK+cuAJub/Gp8I0Y102P2rNqcASmA/Ocnogp,iv:m3r2kOi1XUVzLcKo/x9gWT22IDrnOlDYFaGxY2wd6Oo=,tag:6qOgMHBC4mrOTRJ61jhGAQ==,type:str] crt: ENC[AES256_GCM,data:9pxHw0OkY3i3qPPsJnSYgU+u6lDFtboDKpRr4mOgInAmKyMmOB4AOBoQ7KVXzJnS4crzNs96ipYmt+n813VOL2R4G6WVXtuvNra4leSZ5gvtVy4qNQHK7IUSeOu1iqGyMF++bvT9Q6mHBiN/QwylIWJu7LJULn57o2Rfl6akH2zlzgevK2gYC76dji1e9y1jhRY3VnwEhWgOYftDie4Em1StYn2xi4GcO1OuW9lcCggVTi1TruddcoIV9AYbjV3Y30RAKtZiYXnOTvOmsYm0Ea31955k2owxNM+NGwQDs94iZ1c0MG4cV+cxe8aT5xY5+n7ZmKQVsFAlkC+3aHqKxKzr/LUiFAXYoERoU3n/fAGuuP6OPsGMRZTyW1Y9VEsNzpzANWDw3V4QS/6PXqPWxHkW/UbazNu+BD0lfMEUAG6nYx7mAi70LOYwsKqT7pdIs9i7fC5G51cD41keDFnkxfQpBlrMWydravM08Oqj3sgrjnaY5JIdkrwH0g5P6P9d9fhc24iq6VnTC1CxzMU1W5hRHTEebMlJ6DvfGxgS6xTLWbFgzZi1BLY2meU6C0NVkbjIcRd0BQMfo10gS1LDFLZhpr1yqFr7QuGIYi0m+CIE6cGQXJCyzrOt7tQFedKlpy2o0yejdFEHmsx95bNdMvMsXNcw61r0QdrpKaWPShmKtpCWh7oFB8M9XnwzxI4ZKDWnAnP+j2Qp39pKK4mS/lNFqCwJ0mIhE5d4GjDlHA/NkhKYop17ZmxPORsKJ6kB5DSLx4VNTIcQoScH6+X3YU9cx82Betky4VzaGCp9DVZv65tA1dvJqdhROc1xtYr+5ooRc9PrQ4vvKE3rNn5XSR5CqM+udDh5x4okNrF7L9qkL4Z7kmHM51CPpuQl/HavKfsClBNUPcJPz3GtaPB8BvFlUh2NW3mrP6AeRZu90qq5nffMeVwkTcNgpVXv,iv:hjyOmwysUjIyopOeDo6qdD5MrUCnA2byPL5PizqqZCs=,tag:seg+fIrhd5dYrf2jCMloDQ==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment] #ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
# #
# #
#ENC[AES256_GCM,data:xUxguG12uiQAzJGMXaaqdgTfCw==,iv:kh2nqSVtBXaAhEywAdDPbbG0p2ljX4mtjVKYXCNL20c=,tag:XGaBtxPBHSaLRYZa97+kmw==,type:comment] #ENC[AES256_GCM,data:xUxguG12uiQAzJGMXaaqdgTfCw==,iv:kh2nqSVtBXaAhEywAdDPbbG0p2ljX4mtjVKYXCNL20c=,tag:XGaBtxPBHSaLRYZa97+kmw==,type:comment]
postgresql: postgresql:
key: ENC[AES256_GCM,data:XCBWU7Y/BG5kOeKqmNpqwyjePWrMzXUW2RUc+d3r8kfTMqVT2Hxe3Hh8qSCilsZOKoeEfraDKCMKBLmmaX/WGXtjnhOF87Y43i11jDPeMv4g0b3f3oh+ekckxG43pFpPUR8/IW3xB3otTdrp7Sw93xh1s6BcYVutL+opOVLwdB6JNlnx6ZAi+ppjmlHxinEa1UpnOkLC0JNIyp0i5xp5KMizNs4iNcduI3eWWZmj1z/lW1Q7dkH6rPIjtNQt0Ce8wpdsuJvPaZHHAZZ31KkSj/6n/sNhSQsgAvJNYBIsqZRG5lw=,iv:/1keHEeQzFuxaZD/Pw51IBIaBy3J/5fK7BcgF+A41Mc=,tag:Cx2AX0sPTwkmHODbuZNu3A==,type:str] key: ENC[AES256_GCM,data:Q7B1R5FaFG5sTFE33vKPCxTEE1QaA3uaICSVjWfUKkJPGfqOsvl7JIkwDN2O3UOy6IGXnxlAVUoN3DtH1H55jDDrR0miJHpuEkHn8hSAh2V9iiFjI+DtuliiBdXyQVwlKj3nlAD7stUTBE5oofAYaj43Ijv5BdslcnNOTaFaFo0UvbnehcBAkMnv9YyExto9dCw2ZzOexQs4Lzo2yybCNiTG9t1kJC1LyVcmjxMOSCcay4L+6o02/fJXJ4R/W7EYUYfjWIf8FeC/HVkPsU5TvxA7/uRFUUYro/1hOGkLfPGWDtw=,iv:T84T1dKJD7GPWNz+gPvzWsnebaw7cMjIWimQiIBixmY=,tag:NEvucfSk/ApdGZYB2LbLjA==,type:str]
crt: ENC[AES256_GCM,data:cnvAtbrzS3xpa+RQKhSO72xsPLAiloQZrbUL5asql6Zf2B4aNzepfZa9vlTObd4pG/nw1lIFIY4N1oh+L22j9snDXRX4BX5tANJBCiZrnqhvfDkT97xaK/86D9J6kyWmIYjlQ6bXBkvDhDII0eqigV3A/NDl8V9YApGHyAMuryWB69I4wjvVnlok2HSOgZxq0F/3Epp4hk8BuUTNvAcSeIAfpWePVHYtHRk0X3IT3KhR+Q16Ahm3fqDXFkAhs86NBaCl+kEFunGLyBqxecU8uYuU7gmofISqSDytI5ZGVt+oygHSkcQKrW/NBxY2yYs++8m5N0sLPfmtE8NFIMktpjHrUGEKnZmdUEjg7sFFRGhvpGyo77x8TPC3bD1rZJVgDwYCmKjyCO3VT9jPonV66rVOq5S8svm4pQlaT+BDPZXIqDQn4UHD7grKOdUA+zgvdBuVsUnngR/D34cPPm0Y2x4CLPmz4PBGZQu5Q4sCU+8vq/n8kNX1z2T1K/d40YBPlSunOZIZk6H5XMoy4Njftty2sIjraVy7udYEwqmUwfm9XlYqBa6QeofoxY7BaUrRjVUIcPrKLUZ13qddOoPV//gLtEDwcD37kyLw5ZbPKVdR/5rU48ENvP1UPFC47HDyhtA9/FzYweEZ1jEXSuxr6r5xJVcH5/2eyhW3Eo6ewwWeT26oVPj0zm6faeY6WVPXJX3fhMwNonAtTHzkfZCfFlDgizMtSMsMadzzTut8rlziEea9cuMS0EacIdzafoZgQsYq2ZrRhsYDbQNGAE/DzK3Hkrtp8eqJDNyRyCIsn1+B0A0ci8hADSHPS3q4tQD2JPb5zj6/0PNt0oIIBRcYuXgJW1nathtP718i3Hhi+cmqvZtza7XKUkxNYNYLO9hGnVTNY+mHD8HW94QdAQ8ikfF8tSBv0N4/ebyVIkaS9Nes8MyOQJbzfGhmmpeuo8jineQsf6w=,iv:6gXqS7C8lypzUvjExURswSwnUXG1bTC2+BxUkK0D36w=,tag:cd6URiL6TxM8GxyYirvYDw==,type:str] crt: ENC[AES256_GCM,data:JK3XeegWuX8Yr6jiskiQGLpT3tLmVFboCIUmpaikEiV3HXy3dsqeBwONoQO7AB06TWbG9UPKaPbXkMrnARESR560OvSkw8cCLqZSdEyYjvapEbhB68cmLM1ldETQfMWP6O4HXjZQStU2cj3jP7IDmCUiDPfOKosH9dFLpXDyafg5BayDkDjYk57TGhUIg48HGlQfgyGr2xqty/cdLAjVrOHbjJq9hoLHnPyz7Uv5AnqnGZmaRupFHRX2GojAJxJHu7aFacjfg9QeH5KwnfzZeY6umXb/Vq1cIEJdN2v8T9MvDODgweATaBup0LC3kLR2FuhyTn6fdjzFhXQPVCcYsUTYOaVctQm0HfGLRsR5Co63Um04dMHSslhvyx95JNyF/sn/Q2WwJ6famAo8ckdtGFuqX69K/ksI3I5hk2EIwp6DLTUH1LRHa8VoZl089adsLS/fiDGSfUFbzdY/Ki+J5MJHdoRsr0crQv2UXIpqjr68B4jfRBshk4IooJHTrDO/erg+NhC/S4thfPNibsEglowjbbYnz0vtr6pzchtNU/S5BUsL7uYh7vUv+ik/D8/tyLoboVN8dRd+wyCCpNX1sfwubPdobcvdtAjT51liv76VSTDKqY6hkEVuYQeqC5vTAL6xaD53IK/y5yVtwo99wAjj9gpXKw3Q76yAnJiWtd0xZzE7Gly4eKifTDK1zre5KnHmdI4ctktPX6a4w17TXuklQfAyBJWs/416vSYD5FEXFs1C8asPEBslO8DbAna0uGp591r/IBxPi6ulUd5RiQzeVRiEXKvAUFKf+wp/gjbBM1iQ6zVhTe2j+rmg5/AiqpSDFPbz4fAoo0fcjnwT+Y4WMVoaWKF2ml/fzoqB5Ot59TnNfDpwOuhZsImnbKTBL/WDG6B3AqXZozoP2TbJ5sqIm4We0uqAQ71MrfE2IaDvgukrbidcxq5ovxdmimgTSjYM93c=,iv:Ho10WtdWiwxMQqkW3LZcmCce/fCxqtK1L41yG0DPdmY=,tag:zf5yOLzGG1CxlJI/S3ppWg==,type:str]
#ENC[AES256_GCM,data:Zu3CNVkCUlW6BKGh/rhTTqrGv/7H2BG7,iv:vW4cAVvla/Ya0S89DTvo9k3do9517F+AHMLb36Ey19A=,tag:neDpBA97R77p88Im92xn8w==,type:comment] #ENC[AES256_GCM,data:Zu3CNVkCUlW6BKGh/rhTTqrGv/7H2BG7,iv:vW4cAVvla/Ya0S89DTvo9k3do9517F+AHMLb36Ey19A=,tag:neDpBA97R77p88Im92xn8w==,type:comment]
password: password:
postgres: ENC[AES256_GCM,data:XlpsKT0/3VgNesMdifvHlYZ2dh7mlMEnxi0MJpQZiQ+1tZ0/3zMxQ7+vwec=,iv:akcPRmDZQfFLxelG7V87UnNB8ez28PPLCmY1MYfzStU=,tag:14jvIKP7Htfh+/oMwLYC2Q==,type:str] postgres: ENC[AES256_GCM,data:XlpsKT0/3VgNesMdifvHlYZ2dh7mlMEnxi0MJpQZiQ+1tZ0/3zMxQ7+vwec=,iv:akcPRmDZQfFLxelG7V87UnNB8ez28PPLCmY1MYfzStU=,tag:14jvIKP7Htfh+/oMwLYC2Q==,type:str]
@@ -122,13 +137,14 @@ postgresql:
outline: ENC[AES256_GCM,data:0eJFCfHgS4olWXHOnUPixs4Dl5PoxJa+2H1mk3YgC4GUv+nX8gTPmzKTMVM=,iv:HGxX7aLODUc2nVLC8YXdet9qphU/wxMapWhk93YmHDM=,tag:6/2uckW/a24LgVFRH6E85Q==,type:str] outline: ENC[AES256_GCM,data:0eJFCfHgS4olWXHOnUPixs4Dl5PoxJa+2H1mk3YgC4GUv+nX8gTPmzKTMVM=,iv:HGxX7aLODUc2nVLC8YXdet9qphU/wxMapWhk93YmHDM=,tag:6/2uckW/a24LgVFRH6E85Q==,type:str]
memos: ENC[AES256_GCM,data:BaNTnZFZH4oMTnDkgrf2/fMTkO43rc9bSsgnDWrHJ/Z6+MZdMitpIMkrMN4=,iv:JsG3B0YweZYO96MW9NmoSsIG++gFq+jRUsozwJtWl3M=,tag:orLTUiW0inOJdD4YSp4baQ==,type:str] memos: ENC[AES256_GCM,data:BaNTnZFZH4oMTnDkgrf2/fMTkO43rc9bSsgnDWrHJ/Z6+MZdMitpIMkrMN4=,iv:JsG3B0YweZYO96MW9NmoSsIG++gFq+jRUsozwJtWl3M=,tag:orLTUiW0inOJdD4YSp4baQ==,type:str]
mealie: ENC[AES256_GCM,data:XbYHQv6HBWCXUBRmcbQZN5Y1Gw+V+Wra28Mp+m+ZGl8VRXsKMu5507vGHQM=,iv:zp4ZarqG9KshiBV8F8UksfI2QXmXHwqPw631r/5bYy8=,tag:jvsvXrUsCvpQGIbLV9jTYQ==,type:str] mealie: ENC[AES256_GCM,data:XbYHQv6HBWCXUBRmcbQZN5Y1Gw+V+Wra28Mp+m+ZGl8VRXsKMu5507vGHQM=,iv:zp4ZarqG9KshiBV8F8UksfI2QXmXHwqPw631r/5bYy8=,tag:jvsvXrUsCvpQGIbLV9jTYQ==,type:str]
homebox: ENC[AES256_GCM,data:EhNnltOBwLai5vEMt7Dih5Ug6h3ojrdbwhq4Vr0tg/p/0nqI9L7O/Le0B4w=,iv:14oyl916t0inr+W/lztQCjYiSQ0vIIwC9NmbezDuvvY=,tag:IiXZd3NU+dUvDrHpxJXFew==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment] #ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
# #
# #
#ENC[AES256_GCM,data:VuOcF5INAvCNDvXhcAc=,iv:zdTFTKaII606RjjDJbdUyv8jGba8abL7lJNTsPH5C74=,tag:cYSefZHKIuvHmAzoxierQg==,type:comment] #ENC[AES256_GCM,data:VuOcF5INAvCNDvXhcAc=,iv:zdTFTKaII606RjjDJbdUyv8jGba8abL7lJNTsPH5C74=,tag:cYSefZHKIuvHmAzoxierQg==,type:comment]
ldap: ldap:
key: ENC[AES256_GCM,data:OCje8b2x62vVQDV2DXvy28UxY9IIMtRoSLyXVFwNe+sRWA5prW67Vp0XcwwL00nP6hagkXGNRxy0eXx0VYXiktQBeQQe7TC5bUpzJlDCyGmi9BsbDhzShSoSM0v/TxX4UYZ16PbdVxyEIxlD5J/SpbQdg/VvVA6oJgLU4SfZCYmKRZ/gC3I4cKGzFJAT7NLAnC74/Wngz2nE6ipzXiQaDHnSuitLHF/RGoAgE5XyelyXag5wGaB8EAUgmuM8woI5g7RES9885bPOdt/Q1MUNNmEz7jIBH4AVGo8stxRioYmAcZ0=,iv:6Fi0DyvzmrQN+OVclRFZZyXCW8v1nfizj0saGkV7qTY=,tag:AkMtsUaRIgxNKZG1oYPTTg==,type:str] key: ENC[AES256_GCM,data:PwQ/AtsQbbM454iM0wpUjGRfxyxNY5lGDARv/XOdk0yMCHRsf9qHKaW37EwcqNe+MVTJH+sx8lHDdxRYF1gO1yj6kasEIbMeo9cIaGQHvey5dYdber/qUkcjuAXyhSZGSUXI3PR1CuAsiqNUEruh/eKyDZAvHTTY0Rc5jk4HLFzPqqBjBOMkA6VQXJ2I+v4s8W0T8/JEQ5l6avwYbaaInIIY+uPV+sY0mBczAuaHLyeA3V7VQNTxQ9lUgdfH/TpgBn9EBH2wWqIGk2zQ6XmVrmOarCo/+JqwLQVEyY5TTrNuBto=,iv:iYzoRXjH8NjPnX5nBhU2gTQXOekXMirjTGhmpGt3YAs=,tag:IxwtGNXx1i54Jnhn1aZx3w==,type:str]
crt: ENC[AES256_GCM,data:1SJlTokgS71mW3rEQG1fTLs1cp1Mraww58stg87Bf2PryFsKw88va4HB+bsKzkCRgykQoj8iDSqM7tc7Wze1HWz+bgFTgIqluRQpZtbcmfYVlqefdIUcJPAntqe/eEaA8Hj3ozTNMlKFspv13vPwjSJHGrHcektwlcEI58+S3lhu/IrIfdxryBm97E2UQczznRE3zuP3MiBYUV0oj9Bcm8KWDKqa3DLwudp5wwyw/OG6DGg48isEvNxaMJhuEkiMwMNR+zZXgAvYcYteMaW0p1UXNFHzxMpOWshU1zYL6U9vZkKfpVMoMoTPW3+SO+vxlJVafevStEipUFd48XmOo31uMQH9zWh/hbLM8j/fiTaW+kY89XwkQ9ZUOx8+YXgcfBb04FAbtLEXMbC/eF0meVdjAHv0TEBPF1a/F4m9Kqv1GkJ4RA8jHKFng7vWsRGl7WhmxrCxjrJrYu9ptP7iMvbaaqMWG1YOSwwZUe2HvrM7WTlJxeRukwvW3rOglAUdFODJhsWbATpobuu716fKLqDcprKa+vA5l7VMghqLf7tWRGXmT3O3RgTGDwqjokx0q0+4ib10cgzrRCkwuTBDiLYRdxd2eZFWumLOlKKQyVAMJ9YZmUnH2VNULazcN7Tznpqm3vdA8pC6Em7ELTxYTUvkaye27jRVyilkZvoX8oLiWyEpMpPAajoVntmPnGTF5ppChQ0EmyuFXlv0tsU3K+bxmM5VYVNy4S+1cMOvEwGDuSGJ9nZfS0BFm8NXDp+BbEIAa/DVc6yOjVEwi1Wh0khxbplkW9feWfkLqrdlxF2khNOTePIyEDMzs5/CRq+kzLy0U+7BeyX28jleRpeAQL6nlOZ6Ha3AyQUhxC1/KVOK/kgAlGVi0gyaxZy0yuF4whFKN7+oXB+CrJoCyX3mjrOVqQIOeNIK6tLac3hW/cATu43uDQ==,iv:BmdsX6o02n/ekhnTQrpTUgM3lqXCyQNYtMbexI1Ziho=,tag:7AI4lOFSXDxR7n1zoqcE1g==,type:str] crt: ENC[AES256_GCM,data:ulOZOUV23qfU2RATrXYFKPnPNW2vHShJe3O90XXoSA4bkUBA5Jz8uuAzCiVOZfx/Ni2uG6y5pP2x4ZnJADSrkfHD5P5IF3iUWWSgRo4NDDCY00r+fuPFP5DpOhwHl4LzdiHl8SBJ6YWBbhtT8sXVXFgmQIFLppuUD7WzJ4U2c251vF6G7Q0XemlkkNFq4fbkClTwogUyTRs2Dj0e187uilDkfCBS83oxMU5pB5tBvaFbLxaJmtNpaFRp0U2fgJqJrM7avZJeNUDr1hHttAw/TnANNK3X3mgFAruluTUGTS0dt8KPUlaUCf00I0t1F6l+cNktaTlnUtcp/HdWf0Rtg+tYBfFNgsGl3iB2z1utpab+6WsI2+LZYGezOLKojbFeYGNmVLkSucCSVAtuj48fqKFeObdLcBjihXilI151ie4m5BR+37h1Laob64C/n8lhNSm8QpTuIipV/3koyBKwIimMYYO8j8sHGQNJpdDuZXmYCEiXsdXZH2tFngWtlJ+39yV+GCjhKRYPkAWFKw+EtTSnPposC8fHPMLMZnB1hpsVmSy6VBDuZ2Qq96H+njgzWXIwhWcZteTyxp2fS6dNSG3zTYD2cp9qVrA4KhTlAjVojXdlRAv5Ayob9R89hD3WNKexe3QD/Nj1Hva7GyjEHqHijodYDNXCWsMgXdgItgwUz28vh+H8o5sSHCsfUDM2s7Y4w1rmKOkD4XpxTcyGM5zrNBacvhS1FzuDFYZ8BnN+STaQ1pvscVGtrys6EtXDBfrWbrIFnIhMGSp/GGUMhrT30gPV5VmzUqixRJzpKvYF1ljr8ybRu9Sf4xaprQNeFTTWq2KXonwK8JonbZJNwQQ6oDbp7AyuQD4EJD8GoXJUAy9H5TjnpjJsZH+RsTR6O19K+O45HQCqvZpEHfUUXu022VqrjmzRHnmB4bJKgb+BqE6YpQ==,iv:Vh9eqEun0E73s57RV53rHbjP5AWXn4NPjlEPwVDQ5VY=,tag:fxpzhMHk8Jmb60GHOHnYvw==,type:str]
seed_key: ENC[AES256_GCM,data:q6kodsHzwDuf0UHPSk9VbEI9pCwePJWcA7o6dQiZqyM=,iv:EbozH0UpLThEXjmWkNhkpHQxabH/K3/lJ8xki3lLGZo=,tag:rKO8csevxpH5kzzFWQoang==,type:str] seed_key: ENC[AES256_GCM,data:q6kodsHzwDuf0UHPSk9VbEI9pCwePJWcA7o6dQiZqyM=,iv:EbozH0UpLThEXjmWkNhkpHQxabH/K3/lJ8xki3lLGZo=,tag:rKO8csevxpH5kzzFWQoang==,type:str]
jwt_secret: ENC[AES256_GCM,data:AfPcqKAwdsHfiYHrZ6yKqOxD93gBcLEvZ4N3M8nhWMQ=,iv:awfSXZbc7Tzg8sRqUkp71TXivLb663ZjaxNkskE1Heg=,tag:e541/ejk7x+GOhJeoUPMGA==,type:str] jwt_secret: ENC[AES256_GCM,data:AfPcqKAwdsHfiYHrZ6yKqOxD93gBcLEvZ4N3M8nhWMQ=,iv:awfSXZbc7Tzg8sRqUkp71TXivLb663ZjaxNkskE1Heg=,tag:e541/ejk7x+GOhJeoUPMGA==,type:str]
#ENC[AES256_GCM,data:/5Po+8hjJg74ZBepaNWTzZy7JrTjiwo2DNFT76hZTUFKEdchNd4sfdy3tbVwL5y9QPC/kC3kvBZL2oA0+WzcUmd51Ht4/xS6CnUCpodBrSWNHu4H+ohdmz/jMplREeJVWAFHuTZROqB9v3hw3rYJ5Gb+5XROAuzT4pKfrPoJ1B+ysGUpuvybhrC1O5Tg6IPs5fvIiR3yExGcIFuywZBiiA==,iv:gupWDnXb2TD1N8GhHwpiYuz0sDciLX8V0ww9cFKtFNI=,tag:7eDx5RZOrNXOUshvdijV5w==,type:comment] #ENC[AES256_GCM,data:/5Po+8hjJg74ZBepaNWTzZy7JrTjiwo2DNFT76hZTUFKEdchNd4sfdy3tbVwL5y9QPC/kC3kvBZL2oA0+WzcUmd51Ht4/xS6CnUCpodBrSWNHu4H+ohdmz/jMplREeJVWAFHuTZROqB9v3hw3rYJ5Gb+5XROAuzT4pKfrPoJ1B+ysGUpuvybhrC1O5Tg6IPs5fvIiR3yExGcIFuywZBiiA==,iv:gupWDnXb2TD1N8GhHwpiYuz0sDciLX8V0ww9cFKtFNI=,tag:7eDx5RZOrNXOUshvdijV5w==,type:comment]
@@ -145,17 +161,24 @@ ldap:
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment] #ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
# #
# #
#ENC[AES256_GCM,data:6RVyF1gPUfKEvkV3RQ==,iv:0MTKlm5kE0kZi3E013Kk/Wo642BizBRmcHXR+Zwf/W8=,tag:SaQJ7lvFUuALxXWf41C24A==,type:comment]
mail:
key: ENC[AES256_GCM,data:2iT93HHmX3eCTtKb8/C5mI2uEwdck7R6TCXoLuWprfs6KMza8mwd+qDeYGauUHUojEplmopycWup1cVWyQRN2B3udxd7nR9YXcdL0ZNvjmEcjRKDicHEhIw3DVb7N5GuGkFDhc4dEx4gen5Lwu3c+b2hpL58fvZNmrldKV1Qs2jnyi4LcFxEaldPNAiJJA5CYC3M/FFrEDw+Zh1VP6rliz0wYvEoqsIanKgDs5sVkSw7IT9iBidg8EagPrlSEcYJOSHlNVJU2a28P45az0G1drw4BWiXASmCWk6CNr2WT26vz24=,iv:8h45V8wA83AHrej7ajzV3z3KUS2eu0fegjPJk7l8YoQ=,tag:kD+QVBEur6xSI0iLEthWeg==,type:str]
crt: ENC[AES256_GCM,data:v1nr+IQowiph7eRyENALTAXHt7NPoEdbyBcb3lVxUp9Ga6nGs7IPSyzMTfc3Am4cZ/6kRpXJG30cjINWpfhFkruS6SCPqMUcsxkVw6oLArbN62wV4umws6xh0pQNajTGY8ZNhya4RudWSLAtmIlbI0aneJKxrypPQKXeX+nML48TLcV8PicAhr4gyEk967IaHLCPK3GAuDwrD/b5NsaU3sVb5bHwcSsUKUBzdAYdHTDwsuOVwbrYT0egQ+Bcn44bY/EWw8SbIa90A+iqU6R4G9V2+/eHCSdqaNX27Yp+h3YgRJH+NqItiMlgeJ99bjvYjdSaOucmUE9gcUt7BFHpEuCI6nBGduFu/PEsFd1vNB/jKjLidN/wjcHHXXfmLy1vw8ut8ns9cl3Ufyk2VcwTfexKTuZbcAIlDdc2HGB03Z8bju8Ci96+j6cZEgv04eUZSl/5erRuyrIrA/erC09J3gqz3ojMTPsGxmQs8Rbkv6ZWM2mrsBizZq3K3XMCAP/eC1072pnOjgE91PzDUmQwBSm2xxyvjDDjJxp0M5EVdTQ/GiJXtV/Fwq8NvhI1P3nkQoDOEz+i3I1ZNrsRPLoaC+HKd+DdnO24slTUXXYO2/j9/Y3z+gjj25WR3Q1iFzKXcVH5pPVToDavMKLhlchcXI0FvqjKPYyqAY1uNEg1oVlqcyD/CcOUur1ugNQGriXPf+//nb3WZgxfcZiCwyee4oCAa3OxSMIaENn3QQ6QVGNocNanvulcA9LwIMU8qXp0+AixtFvbTlM/LHBWy10YDH2LKg7kZ9ePd6JnSFYIdB8gKhnbolrtLVIpC9NDcyzYosFrZ1NsvGgEiy+5+tLl+XERaZunulZ3VBG+4w583/PfeIZ4l7kRde1HWkym5oI0IluQG9MagyIv2a2fSScZEIClDPkOJqFaL6WszVViAgB3pAL3dEr8+48=,iv:bByFvLj8L+yZ2ErlkDBHGRhnNVQsFOe7q3WwyGVWQOU=,tag:VK8iwa8m0thEBNyTvEZOZw==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:NronfCPkbPQLilb38VmliNn0Yg==,iv:AbC7xk46CJ5dqU55IbyPX+OZVEROz+OGnJfxoZmaKwE=,tag:GEsziOOFhDF16Vjqx59SNw==,type:comment] #ENC[AES256_GCM,data:NronfCPkbPQLilb38VmliNn0Yg==,iv:AbC7xk46CJ5dqU55IbyPX+OZVEROz+OGnJfxoZmaKwE=,tag:GEsziOOFhDF16Vjqx59SNw==,type:comment]
prometheus: prometheus:
key: ENC[AES256_GCM,data:MNmUv4J5qVRB2NH3vFcIPGsx8ZB7ggYLK/4HyI2hBE+KhBGgh/9GeIauN6VDxO0xPqVe6xsY41vMDE8K5wmQyvTOi2fyXzL6LDxPHKVZVUKMjRgiYKJJh9hghzVeQwKwTjfZ+eXFgSKf+ENpSgh4+zbFqm0eVhhZy6EQ38494IlwS/UsojC831xg0OeeHNF5QrE7rIG8zo+rjsntpWZbJzSM9BgzFAAfW38Ywi03lstbJi8IEq/gFmZjQxU3CFHicD0X/jKY/uBxZB8lu8Km2ZevGDLFGwGX3zpcYxou3667m9M=,iv:1Px2X4RKD1sbQ9NhFW9rf0Q8cu0ex8P2RjmR5wUmFbA=,tag:rKkYDav55LfUwUueaA9Qfg==,type:str] key: ENC[AES256_GCM,data:3/x/3FSbr/3uv1ziG79E/eQ7ysV8G6+tyGWC57fJjLSlNpTFsp+oc3lYWJbaTkDdazWz53CmrBrT3r2Lo4gMb6+CsxQjZWBCs7M7eJXB1p+a1ZwWOVndN0IWWnB9HkK2cmFh260s06FmPRNsnaBx3TvscWlr0+qcnmBxHE9tfT/k3ud3euhlMNovrKFnjSaPtMtDmBHFnr23ogcOBoe8/b29wtVC9ILh3B8qU30Rqsnu1kQhAYCPVrZhwYzAoVjX83uou8QV/GjaTgvbaRS3J/mK9kxRzspgb0zKxC/TPjptrxM=,iv:+Ly48Af4d/SCw5/WUKmzrkMzDXFRfc+RaCjiS7BEg5I=,tag:tUdZdfgY8cPz2M1RmtskZQ==,type:str]
crt: ENC[AES256_GCM,data:0eNafjanGCWtqCiavj5vAQKi9nczPShx0w9dfULmP03sPZTh74FCZwZvu2vQ8i0GbKNZdHMKYAP/Utyd1XdttaVr4Kvf6ggkQXj5a0AOakRmTOjkO2WhZtWUVd/fJSfcsifa1gG+x5O32yVZXx4pWSVtcV57g+BnksTyt5JBnPz+u5pEBK0VZKRSjIjlvanLM+l/Dp1tyrmKarFX+28bCDUxB3I6wZUEnF35wUNbu6pVMcR8JofQG6KrmsjixMWPRDz+u1w8b/+nTGOXyykUUjxH7a6wEf7/RTGNBwT44CrSACxybJMCed2MBjY42jA0Lm4ISwE8epvOkpptu7NRyEgMiVke5mNSH9ZGaUe6mCBpbUVkL+tUQG5rwclsL6ijaCyqsWSD5bb2i6wGhmPe5/ERKxmLjOWNeAQSf1HiJc/bSXOSpt15DuGgwwJ4jfebOqdshUy7CMc7KclQj7ppqhTYhRHbM1mJwCJr6QGVDh5xSzFDSH1qbCRdeXkPEkm7WxRJbAtzY73UmO4eqhsp5n6+PtiFNNqQg66mOGF8N7PlEKh2vcoxgtjnTTVHVlgiAHuT2TMWNuhO3qwJeF6G3zApFSPuJWcEH7PGAeezL+qUF2TzHVthOHQMUNFr1m8i4ms/hCE9DGSv5oo+X7YKO6xcIe00xNQEzMNk+HqmAKed9pl/eBHhD62UvQNZh66e1VjWpOE/ig0hP6vgKSwyQL6xUtJWWzYl184KcWokw+O9Vyw2FCR++0iu+Zn+PIYYQg4Vwpqd5VM0cj0tIB7W1+aLz8hGIOgQKDjQUshWeMxEjESILgb3+7lNyZkKT/y48ocHL/dedHRLXuxUcSQ6ZUGhWf33so7763Gimo2hK3jmIaprnx4LGyiBKPPxkSl+Bt7seUiFJ041olDmO+fUDvi0ko166CA+3mUxeoeNRh74J2RPHR8dmy1okp1NLEQztyHw4Ps=,iv:14bMOT+Fn8j2kFDQxTuwtsTyYnp4fIF0WRpQntz4afE=,tag:fWnktLbiQzG8UExa3nspUA==,type:str] crt: ENC[AES256_GCM,data:Vs69VLwR7Gw+pPuyXmyX8wRgS07fPO9+pgQOdWfTSFNcPY3M7IK08qDCxfZad3Y2/hVtW0afTq6RJWYXTr5faW1GYcp4ur1sPliU5qOYod9yJhZlxDhHPVaYfTrY1y8zy4ynW0C9tprx3AD9kGXUyXEPO2lQBgdfd50YIN0VUvTH8PC5AX+zJyytfGrfGHZlJDVBbQu3jOiuaDuyV6dszQf09PnVNaF8w67T0VUBS/01BJz46JPU/Enkzixz/ZH70wU4kHqG+77Pq4SXs1sg4kTK17Vb7px6HaOiqDy+si7nSU4Y0yQ1rKu3aqGfaz0EmKlmrxFx6RphJ1GMY+gm8k53PJubYb90DF5b/T+DYCGICYmLt9p4SEIYu3FXXcBvUkMn/Y5GGDfkbIOJLo/VqzUaGrLzy6uv90c4iGCG0FvuM+FWJAXiIC533MZt+zeEZilB5QHNqsIdLahi5kN2LCFhKHtYJVUohCt59cU0Ir3V1XTFJH8PsYAqZIwJQOhPUYmnm7GSPAWWK4i3UNH20wQY7h09MxyEgZhjcAUjtsdtZErfDykvDU4Vc+qQrH9vKGEHRberP3a/logWcYNBn3PiTPEqW3aOsVz8PdabUyFDsRymi+0eBKk5mQX4ttsPTTFZ80/t2lHoefe/SdVxGig2X+d3buUwCgXf/DZ/3KfYcZEw6Ge+HIPjYPbiJRureugy4bmL1HmhrsQCGen/mTubPH31eE33W/X4ewOgRGLjVBq6GNiJDya7jKLDn68AFX5PV+Gi7+iQAmm6zczfGWN4MR5UX14GhBNUs3NBHxx07/0Z8F+4JLMNprR+Kr/PpBP8fsOeDlbRKauQeuTaHmPkESTYtTmdzoBzV/sCwH6w2pbNoYrGLEjElhhOk3slBwaUJwQ/O+jTvw69SsmRjFrOzty7tVUEp1amNMJ976k2rYeMZehlTMk6KAewTNdI/XivEIg=,iv:J+6oHMZTFZmsDcyizC7vdJ1D1aHRJ9lcgIsCPx1fj9U=,tag:XtyFeB50RPRaW7j1JYu2jA==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment] #ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
# #
# #
#ENC[AES256_GCM,data:8Pk3De3AWQPtW+o18w==,iv:O05B1JyftUqN/0/pCi5HReEOltp5jJ6GRER5+NXkoMY=,tag:Tl4duRnv+EoZ4xWVwMfEWA==,type:comment] #ENC[AES256_GCM,data:8Pk3De3AWQPtW+o18w==,iv:O05B1JyftUqN/0/pCi5HReEOltp5jJ6GRER5+NXkoMY=,tag:Tl4duRnv+EoZ4xWVwMfEWA==,type:comment]
loki: loki:
key: ENC[AES256_GCM,data:gtQ3j59WJd3YxreCMoR70VZBJubaR8UfoeAEYgZR8KGIYkEGPnBCMEmBlu/L4qZO0fHg0DLSN/ixLbmvbOluTMNF1rbj/5W4F0O79YI2RztXZ3oxrtYf4dRPxIoCuOQi9PtD5VrduBUGGhvDW9yae9QxzQ+Ca7KwMHgOLu/5+VW6YdQRBdgEQycSDsdMvRTmFwnQuSxuQhWxhu9GqR2WGx3cinQIZ8ewr147aOiZNgUjnHLfYjtzRXqQtK0HEvjNVKBWPuOWLYRa+h10TQlKMQMZn7x7QJlDZhsF/aRqVRNwYc0=,iv:0vVdSLKOgFTwvUbW1uU2vINYwnXMIYIzOl+2BqsJ7Vk=,tag:nm34OwNXseUTzO/KUmT2Vg==,type:str] key: ENC[AES256_GCM,data:9D6ZrmJTAMUf6B2k1Kzl64KgTWwe+kDTTSH9d+Ho++hHnCMKr9ORytJUsaglSip7/X6guRXh2v6s9PuTlEvEhrsAcvj1gFU1nilmq8plOzWh52U1xtpNh8Lf0z5qUYUoG4XjR2kG80B431n/iov/N5/1QWx3PauUAdSWK8ljlZ/1rPBtNjdXWCQzI7zD6p7qKUvXifp2j6r4hlkb9tJH8/t5rlD0LRU7vA7xWg06UayUw94dfgCLVDfB5zqtwPKhot4BkELMUVaUPmJoW3p1ifhZ/JOgLbB0wgt1DMmu6iI8cuw=,iv:9iJBus8P+LnhOc0YDIzwiaKRbp2kc52rW7pyayKDPKs=,tag:pDjlecxjJtdI2OY/x8SpcA==,type:str]
crt: ENC[AES256_GCM,data:O1if/oi5wJQNhHftNEwRhSvdnloaiE8EIJ0dlY9DO2Lml1rz5+2LfwGnN/mHGFOkIZri2AhizPUqXios5kKYgdh7ib4jD2C4DC8crKO9XiNiiChzqE0WqP/sda9UJL9zzmmm3WtkGljcL1iyr4zuCvH0uuIMX6W+NohIu19JT9wqamwMHBCEYuQ6gFAVOBnsz5Rsa6v2LBsIsUBadAzngUcrIztT1UO0cHiplBq5s+TkC96wWrlAUiaV1Lcf1aABDrI6o2u4uv6Vwv/d4AQrEpaNvH1N3un/M3lOIek53atwMYw598/BAioJfZXRTQ4qeqcv9+WxFJSpG6XrWxx941St6N3ITJcAMVmKQFfupj257oyazHF4oqyJKsgXQBTXlMdLPDLH/HTRVfv5k1qD5RQ6AXJrMy4NQrE4BlLBPkLU1wxyg2REqd6eKMgw1PQdqTeZHZrQCGzxWeY+rv/0v5jwSFzC/YY+hOZRz3BRpfufWC9mZQZpNoH8yccVhPybVT22YMMVljLUEg/0BICm9Q4mSMpc9hEJ7VwHZo5pT4DuNiVjComTpcnnrEgK3yYGBB6jsAAkU+zNmOZ6AkCvKAma2DVbOhwUx1ZuBruc4GsfJcHGWqWogr4zBpgDg9FOtLF28yQpfKDWZEdx1eq1Bu9gFhK1FoBxrzd7mX5ADn0XeRbFDn/G+C24ShA+D+rmhARAdCtz6M4uk5IZ3w+L8NA/qWyZ+bgaXX8KrpDOV+/7KFStD4FXkVk20+IaMpb6OSYskqPq1ICI0MIFsONajO8gCd026B6WD/hLsGvkLL/58IwtAd+bRBceXHgoqXeTjyqNgKhhiqmKejZUphzrIsMx+GWdP70GOdcj41I5PSN0GbMnXQTRPGJo/GYN4pP3TbtmVrEvs5rMuGe0WiDiXQGM2hAreGMnt43Ge7DjyB+BPAx6ZA==,iv:1E1u18aWSRZFKewRnH+pJKN9xCpFUcJ0Dy4kq4yMprY=,tag:nmI9X0IrT545vUWhoIdhHg==,type:str] crt: ENC[AES256_GCM,data:cl6K1gEzaKpwr/hksXhjtQty1UGbhAIqB4YNJccfFAOx65YOc1VQ3pIMn+L/IvDQMmuJRRm7zlGdYBnrexhWwuNlcnEi6e0Q25ulneJbrkg77v7rB+ap9VWZsafTRusRlObGTA01liV21UsaDA/Kknt+PFZTAdO8EC6KXegYgAVDNIhiEKUDsaZMrdVFkTSJ00qK9zfwDJ5mcTYM5A14o+3HyK/nMXKYqR+yxwQqLVYVvD6M8SjLbe9VJfBJlOsOe6toTOHUGglBnQr7x0lsEdBvk9UZ3+S2bKpU1qqY7OIxSSjeOZ7YWUC7r8D8lhz2yIOKRFvzJPm10ZxSDq4sn4jIs/hPXIgRTfO4h33pjOhqeTM5q6SRslYpKNsudYYrI++vog2B3b8qhg5II5yJ1Xhe3MqfH4pJeIZcYS8+uIrSMPujhR5q6jVhXwoCKVpifktmz+vopmEFfXzdnaboXYtj//bbhgn0wRxONBYv3dOfQMAVDtptqNJC9iskiZTeZdNmrMTko8BhU/cZF3VML0fTVo8XAQiMvFuk5FaaJaMVFW0sbuyoR3izCm0HGMsjyHmwRov3AarzHkjj7CTuMmZ0kDPrmzPHylgasfuh7W4VTOKN9Ld6umWR2YpBYKSrrnnr7rfag2Ll7ywEcl/Sj1ZymIlsixokiMGwE564AN1MqnsYc5uiCXfo6aUg6nnbUlEg8U0j6pQWICTkFCSjKpD9RgL/FqhcsY+qiGL+pPLHBYXUVo/uARup545+2MG1PA/vCGP/WTp36siXskx3wrQywHg1TIuhTsB0rh499lJhtXP4uStX4vHbE9dDjSOss56FFENn6kc84PInv1ulWcMLKFqEfI/KTgzH2E8NImcJORne+vWkMYOpoCfHTpIQizj6/+5W/5OPKgknpMUH2MaLusopbGNDk2uC5m1my1uirT+AGg==,iv:eTcuF44+5wemJmnTQWKMQnsVH40UlyNtQPLCOklMzdY=,tag:Um5r0IUKw4/VQR7HxKaaZg==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment] #ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
# #
# #
@@ -279,6 +302,15 @@ mealie:
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment] #ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
# #
# #
#ENC[AES256_GCM,data:b74wua/tFSoef2fq5jZhNQ==,iv:RDtz7Y6eFQKiVVnNvoLAfzE4xo8t7RFiKjLTbd0xo80=,tag:iUS7ofvuVj6ZTsy8zA6KSg==,type:comment]
homebox:
api_secret: ENC[AES256_GCM,data:BT6m0D9Xwa1tnQQRzpUnEF4bjLFne297oS3p8HM8Q/1Vakrf+uFcfS0C4MU=,iv:5WeWyfe8kt+AWwsV3YXxfLVuSEE8lYmNFxrXyRZzISc=,tag:cYd6U3BxqyGst+UsMpRypA==,type:str]
oidc:
secret: ENC[AES256_GCM,data:26flutXrbmP4UqyfQs4PmROQGwrJhmkTw2Ujro0jg+q5nfy1mN5i5zKcnAg=,iv:a/fwjeE7MVByIG/L8Tq2ORjF4aSOwWSusER0c3ySBV8=,tag:kkx4hAlfff42Qghe+l9uLg==,type:str]
hash: ENC[AES256_GCM,data:CRdr7WWotsMujhH5PFEFNNF/y0xLjLu6TZc93/eIZyzFZPp9kdHcVyMs8pnyQTMT5r3ynWRsT17N8s7X84uZNqPCu1o4KGvNR5UioiSecHdov1LoJbE1mYCCm2H34PEFwpjSMP013ipz0ybuaYqMTASOn1B/lOUt2bP6yj9NnlBVPUg=,iv:K4iH1ZykdgcL9a0eqCB6PPCU/8jGpX9NEt3yljbOVpY=,tag:EpWG3NEwioRietOi/IbvmA==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:T4Wtn49AAxPd2QUFTR+q,iv:bH5goGWBDqumAat9dUv2OwfCUJUpuVqncTMqMBZUXhI=,tag:G+W6hHA+yftQ+4RJpXrxHg==,type:comment] #ENC[AES256_GCM,data:T4Wtn49AAxPd2QUFTR+q,iv:bH5goGWBDqumAat9dUv2OwfCUJUpuVqncTMqMBZUXhI=,tag:G+W6hHA+yftQ+4RJpXrxHg==,type:comment]
switch: switch:
admin: admin:
@@ -310,7 +342,7 @@ sops:
k+uyWPPi+enFkVaceSwMFrA66uaWWrwAj11sXEB7yzvGFPrnAGezjQ== k+uyWPPi+enFkVaceSwMFrA66uaWWrwAj11sXEB7yzvGFPrnAGezjQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
recipient: age120wuwcmsm845ztsvsz46pswj5je53uc2n35vadklrfqudu6cxuusxetk7y recipient: age120wuwcmsm845ztsvsz46pswj5je53uc2n35vadklrfqudu6cxuusxetk7y
lastmodified: "2026-06-12T13:44:23Z" lastmodified: "2026-06-23T00:53:05Z"
mac: ENC[AES256_GCM,data:FMOY7qMDSCzvOUL44zmwLwUVAXfYkat1JbiNeBVQFuUrC4lAwuukxW9MCPs5plj84LOAUMVgMofyudFJh5VKTR6Y0EnB5ft0NnbGgwMwzQnQn7d9Mcg9xPca3ccSbSGNx0UrC+8lTjXuzhoawMQ5ZXZ3ZK0k7JrFQ2El7UUwxEA=,iv:+oj0bvsDo8gidUn6m0FOeWsJOxIXPHhzvtiIbQ1VgcY=,tag:8xLcthizKqWjqg2eQvJlRA==,type:str] mac: ENC[AES256_GCM,data:30XGjw0JCuUTo5nbcAYkIeMyJ2H50f8F9hdTArYLxAlRz0iffx0n7BXH/LLtI/5FKcOmfhoHP/CT22wcSFxKAPzWD5Ce/xNGAFNoTftodU4CE+/VHn7VFhWYaXVjnQs2duuy4QHQvcDa8uMo+c7ZunqrkZO0zU5fKSYOaJMLloQ=,iv:MyMgnJ96P9RoDYxsbJVZnnK1q82o5AB/hueMXeQhKqQ=,tag:1s288++ruxdUfSnyP8/ecA==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.13.1 version: 3.13.1
@@ -15,7 +15,7 @@ HostName=gitea
PublishPort={{ services['gitea']['ports']['http'] }}:3000/tcp PublishPort={{ services['gitea']['ports']['http'] }}:3000/tcp
Volume=%h/data/containers/gitea:/data:rw Volume=%h/data/containers/gitea/data:/data:rw
Volume=%h/containers/gitea/ssl:/etc/ssl/gitea:ro Volume=%h/containers/gitea/ssl:/etc/ssl/gitea:ro
# General # General
@@ -23,7 +23,7 @@ Environment="TZ={{ timezone }}"
Environment="GITEA__server__DISABLE_SSH=true" Environment="GITEA__server__DISABLE_SSH=true"
# Database # Database
Environment="GITEA__database__DB_TYPE=postgres" Environment="GITEA__database__DB_TYPE=postgres"
Environment="GITEA__database__HOST={{ services['postgresql']['domain'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }}" Environment="GITEA__database__HOST={{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }}"
Environment="GITEA__database__NAME=gitea_db" Environment="GITEA__database__NAME=gitea_db"
Environment="GITEA__database__USER=gitea" Environment="GITEA__database__USER=gitea"
Secret=GITEA__database__PASSWD,type=env Secret=GITEA__database__PASSWD,type=env
@@ -34,7 +34,7 @@ Environment="GITEA__oauth2_client__ACCOUNT_LINKING=auto"
# OIDC configuration # OIDC configuration
Environment="GITEA__openid__ENABLE_OPENID_SIGNIN=false" Environment="GITEA__openid__ENABLE_OPENID_SIGNIN=false"
Environment="GITEA__openid__ENABLE_OPENID_SIGNUP=true" Environment="GITEA__openid__ENABLE_OPENID_SIGNUP=true"
Environment="GITEA__openid__WHITELISTED_URIS={{ services['authelia']['domain'] }}.{{ domain['public'] }}" Environment="GITEA__openid__WHITELISTED_URIS={{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}"
# automatic create user via authelia # automatic create user via authelia
Environment="GITEA__service__DISABLE_REGISTRATION=false" Environment="GITEA__service__DISABLE_REGISTRATION=false"
Environment="GITEA__service__ALLOW_ONLY_EXTERNAL_REGISTRATION=true" Environment="GITEA__service__ALLOW_ONLY_EXTERNAL_REGISTRATION=true"
@@ -42,7 +42,7 @@ Environment="GITEA__service__SHOW_REGISTRATION_BUTTON=false"
[Service] [Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }} ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always Restart=always
RestartSec=10s RestartSec=10s
TimeoutStopSec=120 TimeoutStopSec=120
@@ -0,0 +1,49 @@
[Quadlet]
DefaultDependencies=false
[Unit]
Description=Homebox
[Container]
Image=ghcr.io/sysadminsmedia/homebox:{{ version['containers']['homebox'] }}
ContainerName=homebox
HostName=homebox
PublishPort={{ services['homebox']['ports']['http'] }}:7745
# Volumes
Volume=%h/data/containers/homebox/data:/data:rw
Volume=%h/containers/homebox/ssl:/etc/ssl/homebox:ro
# Environment
Environment="TZ={{ timezone }}"
Secret=HBOX_AUTH_API_KEY_PEPPER,type=env
# OIDC
Environment="HBOX_OIDC_ENABLED=true"
Environment="HBOX_OIDC_ISSUER_URL=https://{{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}"
Environment="HBOX_OIDC_CLIENT_ID=homebox"
Environment="HBOX_OIDC_SCOPE=openid profile email groups"
Environment="HBOX_OPTIONS_TRUST_PROXY=true"
Environment="HBOX_OIDC_ALLOWED_GROUPS=admins,users"
Environment="HBOX_OPTIONS_ALLOW_LOCAL_LOGIN=false"
Secret=HBOX_OIDC_CLIENT_SECRET,type=env
# Database
Environment="HBOX_DATABASE_DRIVER=postgres"
Environment="HBOX_DATABASE_HOST={{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}"
Environment="HBOX_DATABASE_PORT={{ services['postgresql']['ports']['tcp'] }}"
Environment="HBOX_DATABASE_USERNAME=homebox"
Environment="HBOX_DATABASE_DATABASE=homebox_db"
Environment="HBOX_DATABASE_SSL_MODE=verify-full"
Environment="HBOX_DATABASE_SSL_ROOT_CERT=/etc/ssl/homebox/{{ root_cert_filename }}"
Secret=HBOX_DATABASE_PASSWORD,type=env
[Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always
RestartSec=10s
TimeoutStopSec=120
[Install]
WantedBy=default.target
@@ -20,7 +20,7 @@ AddDevice=/dev/dri:/dev/dri
PodmanArgs=--group-add keep-groups PodmanArgs=--group-add keep-groups
# Volumes # Volumes
Volume=%h/data/containers/immich:/data:rw Volume=%h/data/containers/immich/data:/data:rw
Volume=%h/containers/immich/ssl:/etc/ssl/immich:ro Volume=%h/containers/immich/ssl:/etc/ssl/immich:ro
# Environment # Environment
@@ -34,7 +34,7 @@ Environment="REDIS_PORT={{ services['immich']['ports']['redis'] }}"
Environment="REDIS_DBINDEX=0" Environment="REDIS_DBINDEX=0"
# Database # Database
Environment="DB_HOSTNAME={{ services['postgresql']['domain'] }}.{{ domain['internal'] }}" Environment="DB_HOSTNAME={{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}"
Environment="DB_PORT={{ services['postgresql']['ports']['tcp'] }}" Environment="DB_PORT={{ services['postgresql']['ports']['tcp'] }}"
Environment="DB_USERNAME=immich" Environment="DB_USERNAME=immich"
Environment="DB_DATABASE_NAME=immich_db" Environment="DB_DATABASE_NAME=immich_db"
@@ -44,7 +44,7 @@ Environment="NODE_EXTRA_CA_CERTS=/etc/ssl/immich/{{ root_cert_filename }}"
Secret=IMMICH_DB_PASSWORD,target=/run/secrets/DB_PASSWORD Secret=IMMICH_DB_PASSWORD,target=/run/secrets/DB_PASSWORD
[Service] [Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }} ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always Restart=always
RestartSec=10s RestartSec=10s
TimeoutStopSec=120 TimeoutStopSec=120
@@ -21,7 +21,7 @@ Environment="ALLOW_PASSWORD_LOGIN=false"
# Database (PostgreSQL) # Database (PostgreSQL)
Environment="DB_ENGINE=postgres" Environment="DB_ENGINE=postgres"
Environment="POSTGRES_SERVER={{ services['postgresql']['domain'] }}.{{ domain['internal'] }}" Environment="POSTGRES_SERVER={{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}"
Environment="POSTGRES_PORT={{ services['postgresql']['ports']['tcp'] }}" Environment="POSTGRES_PORT={{ services['postgresql']['ports']['tcp'] }}"
Environment="POSTGRES_USER=mealie" Environment="POSTGRES_USER=mealie"
Environment="POSTGRES_DB=mealie_db" Environment="POSTGRES_DB=mealie_db"
@@ -32,7 +32,7 @@ Secret=MEALIE_POSTGRES_PASSWORD,type=env,target=POSTGRES_PASSWORD
# OIDC # OIDC
Environment="OIDC_AUTH_ENABLED=true" Environment="OIDC_AUTH_ENABLED=true"
Environment="OIDC_SIGNUP_ENABLED=true" Environment="OIDC_SIGNUP_ENABLED=true"
Environment="OIDC_CONFIGURATION_URL=https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}/.well-known/openid-configuration" Environment="OIDC_CONFIGURATION_URL=https://{{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}/.well-known/openid-configuration"
Environment="OIDC_CLIENT_ID=mealie" Environment="OIDC_CLIENT_ID=mealie"
Environment="OIDC_AUTO_REDIRECT=false" Environment="OIDC_AUTO_REDIRECT=false"
Environment="OIDC_ADMIN_GROUP=admins" Environment="OIDC_ADMIN_GROUP=admins"
@@ -40,7 +40,7 @@ Environment="OIDC_USER_GROUP=users"
Secret=MEALIE_OIDC_CLIENT_SECRET,type=env,target=OIDC_CLIENT_SECRET Secret=MEALIE_OIDC_CLIENT_SECRET,type=env,target=OIDC_CLIENT_SECRET
[Service] [Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }} ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always Restart=always
RestartSec=10s RestartSec=10s
TimeoutStopSec=120 TimeoutStopSec=120
@@ -25,7 +25,7 @@ Environment="MEMOS_DRIVER=postgres"
Secret=MEMOS_DSN,type=env Secret=MEMOS_DSN,type=env
[Service] [Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }} ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always Restart=always
RestartSec=10s RestartSec=10s
TimeoutStopSec=120 TimeoutStopSec=120
@@ -4,6 +4,9 @@ DefaultDependencies=false
[Unit] [Unit]
Description=Nextcloud Description=Nextcloud
After=redis_nextcloud.service
Wants=redis_nextcloud.service
[Container] [Container]
Image=docker.io/library/nextcloud:{{ version['containers']['nextcloud'] }} Image=docker.io/library/nextcloud:{{ version['containers']['nextcloud'] }}
ContainerName=nextcloud ContainerName=nextcloud
@@ -29,7 +29,7 @@ Secret=OUTLINE_SECRET_KEY,type=env,target=SECRET_KEY
Secret=OUTLINE_UTILS_SECRET,type=env,target=UTILS_SECRET Secret=OUTLINE_UTILS_SECRET,type=env,target=UTILS_SECRET
# Database # Database
Environment="DATABASE_HOST={{ services['postgresql']['domain'] }}.{{ domain['internal'] }}" Environment="DATABASE_HOST={{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}"
Environment="DATABASE_PORT={{ services['postgresql']['ports']['tcp'] }}" Environment="DATABASE_PORT={{ services['postgresql']['ports']['tcp'] }}"
Environment="DATABASE_NAME=outline_db" Environment="DATABASE_NAME=outline_db"
Environment="DATABASE_USER=outline" Environment="DATABASE_USER=outline"
@@ -47,9 +47,9 @@ Environment="FILE_STORAGE_UPLOAD_MAX_SIZE=262144000"
# OIDC # OIDC
Environment="OIDC_CLIENT_ID=outline" Environment="OIDC_CLIENT_ID=outline"
Environment="OIDC_AUTH_URI=https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}/api/oidc/authorization" Environment="OIDC_AUTH_URI=https://{{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}/api/oidc/authorization"
Environment="OIDC_TOKEN_URI=https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}/api/oidc/token" Environment="OIDC_TOKEN_URI=https://{{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}/api/oidc/token"
Environment="OIDC_USERINFO_URI=https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}/api/oidc/userinfo" Environment="OIDC_USERINFO_URI=https://{{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}/api/oidc/userinfo"
Environment="OIDC_USERNAME_CLAIM=preferred_username" Environment="OIDC_USERNAME_CLAIM=preferred_username"
Environment="OIDC_DISPLAY_NAME=Authelia" Environment="OIDC_DISPLAY_NAME=Authelia"
Environment="OIDC_SCOPES=openid offline_access profile email" Environment="OIDC_SCOPES=openid offline_access profile email"
@@ -69,7 +69,7 @@ Secret=OUTLINE_OIDC_CLIENT_SECRET,type=env,target=OIDC_CLIENT_SECRET
Environment="LOG_LEVEL=warn" Environment="LOG_LEVEL=warn"
[Service] [Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }} ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always Restart=always
RestartSec=10s RestartSec=10s
TimeoutStopSec=120 TimeoutStopSec=120
@@ -35,7 +35,7 @@ Secret=PAPERLESS_SECRET_KEY,type=env
Environment="PAPERLESS_REDIS=redis://host.containers.internal:{{ services['paperless']['ports']['redis'] }}" Environment="PAPERLESS_REDIS=redis://host.containers.internal:{{ services['paperless']['ports']['redis'] }}"
# Database # Database
Environment="PAPERLESS_DBHOST={{ services['postgresql']['domain'] }}.{{ domain['internal'] }}" Environment="PAPERLESS_DBHOST={{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}"
Environment="PAPERLESS_DBPORT={{ services['postgresql']['ports']['tcp'] }}" Environment="PAPERLESS_DBPORT={{ services['postgresql']['ports']['tcp'] }}"
Environment="PAPERLESS_DBNAME=paperless_db" Environment="PAPERLESS_DBNAME=paperless_db"
Environment="PAPERLESS_DBUSER=paperless" Environment="PAPERLESS_DBUSER=paperless"
@@ -50,7 +50,7 @@ Environment="PAPERLESS_SOCIALACCOUNT_ALLOW_SIGNUPS=true"
Secret=PAPERLESS_SOCIALACCOUNT_PROVIDERS,type=env Secret=PAPERLESS_SOCIALACCOUNT_PROVIDERS,type=env
[Service] [Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }} ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always Restart=always
RestartSec=10s RestartSec=10s
TimeoutStopSec=120 TimeoutStopSec=120
@@ -29,7 +29,7 @@ Secret=SURE_SECRET_KEY_BASE,type=env,target=SECRET_KEY_BASE
# PostgreSQL # PostgreSQL
Environment="POSTGRES_USER=sure" Environment="POSTGRES_USER=sure"
Environment="POSTGRES_DB=sure_db" Environment="POSTGRES_DB=sure_db"
Environment="DB_HOST={{ services['postgresql']['domain'] }}.{{ domain['internal'] }}" Environment="DB_HOST={{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}"
Environment="DB_PORT={{ services['postgresql']['ports']['tcp'] }}" Environment="DB_PORT={{ services['postgresql']['ports']['tcp'] }}"
Environment="PGSSLMODE=verify-full" Environment="PGSSLMODE=verify-full"
Environment="PGSSLROOTCERT=/etc/ssl/sure/{{ root_cert_filename }}" Environment="PGSSLROOTCERT=/etc/ssl/sure/{{ root_cert_filename }}"
@@ -40,7 +40,7 @@ Environment="REDIS_URL=redis://host.containers.internal:{{ services['sure']['por
# OIDC - Authelia # OIDC - Authelia
Environment="OIDC_CLIENT_ID=sure" Environment="OIDC_CLIENT_ID=sure"
Environment="OIDC_ISSUER=https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}" Environment="OIDC_ISSUER=https://{{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}"
Environment="OIDC_REDIRECT_URI=https://{{ services['sure']['domain']['public'] }}.{{ domain['public'] }}/auth/openid_connect/callback" Environment="OIDC_REDIRECT_URI=https://{{ services['sure']['domain']['public'] }}.{{ domain['public'] }}/auth/openid_connect/callback"
Secret=SURE_OIDC_CLIENT_SECRET,type=env,target=OIDC_CLIENT_SECRET Secret=SURE_OIDC_CLIENT_SECRET,type=env,target=OIDC_CLIENT_SECRET
Environment="OIDC_BUTTON_LABEL=Sign in with Authelia" Environment="OIDC_BUTTON_LABEL=Sign in with Authelia"
@@ -58,7 +58,7 @@ Environment="EXCHANGE_RATE_PROVIDER=yahoo_finance"
Environment="SECURITIES_PROVIDER=yahoo_finance" Environment="SECURITIES_PROVIDER=yahoo_finance"
[Service] [Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }} ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always Restart=always
RestartSec=10s RestartSec=10s
TimeoutStopSec=120 TimeoutStopSec=120
@@ -29,7 +29,7 @@ Secret=SURE_SECRET_KEY_BASE,type=env,target=SECRET_KEY_BASE
# PostgreSQL # PostgreSQL
Environment="POSTGRES_USER=sure" Environment="POSTGRES_USER=sure"
Environment="POSTGRES_DB=sure_db" Environment="POSTGRES_DB=sure_db"
Environment="DB_HOST={{ services['postgresql']['domain'] }}.{{ domain['internal'] }}" Environment="DB_HOST={{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}"
Environment="DB_PORT={{ services['postgresql']['ports']['tcp'] }}" Environment="DB_PORT={{ services['postgresql']['ports']['tcp'] }}"
Environment="PGSSLMODE=verify-full" Environment="PGSSLMODE=verify-full"
Environment="PGSSLROOTCERT=/etc/ssl/sure/{{ root_cert_filename }}" Environment="PGSSLROOTCERT=/etc/ssl/sure/{{ root_cert_filename }}"
@@ -40,7 +40,7 @@ Environment="REDIS_URL=redis://host.containers.internal:{{ services['sure']['por
# OIDC - Authelia # OIDC - Authelia
Environment="OIDC_CLIENT_ID=sure" Environment="OIDC_CLIENT_ID=sure"
Environment="OIDC_ISSUER=https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}" Environment="OIDC_ISSUER=https://{{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}"
Environment="OIDC_REDIRECT_URI=https://{{ services['sure']['domain']['public'] }}.{{ domain['public'] }}/auth/openid_connect/callback" Environment="OIDC_REDIRECT_URI=https://{{ services['sure']['domain']['public'] }}.{{ domain['public'] }}/auth/openid_connect/callback"
Secret=SURE_OIDC_CLIENT_SECRET,type=env,target=OIDC_CLIENT_SECRET Secret=SURE_OIDC_CLIENT_SECRET,type=env,target=OIDC_CLIENT_SECRET
Environment="OIDC_BUTTON_LABEL=Sign in with Authelia" Environment="OIDC_BUTTON_LABEL=Sign in with Authelia"
@@ -58,7 +58,7 @@ Environment="EXCHANGE_RATE_PROVIDER=yahoo_finance"
Environment="SECURITIES_PROVIDER=yahoo_finance" Environment="SECURITIES_PROVIDER=yahoo_finance"
[Service] [Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }} ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always Restart=always
RestartSec=10s RestartSec=10s
TimeoutStopSec=120 TimeoutStopSec=120
@@ -15,7 +15,7 @@ HostName=vaultwarden
PublishPort={{ services['vaultwarden']['ports']['http'] }}:80/tcp PublishPort={{ services['vaultwarden']['ports']['http'] }}:80/tcp
Volume=%h/data/containers/vaultwarden:/data:rw Volume=%h/data/containers/vaultwarden/data:/data:rw
Volume=%h/containers/vaultwarden/ssl:/etc/ssl/vaultwarden:ro Volume=%h/containers/vaultwarden/ssl:/etc/ssl/vaultwarden:ro
Environment="TZ={{ timezone }}" Environment="TZ={{ timezone }}"
@@ -25,7 +25,7 @@ Secret=VW_ADMIN_TOKEN,type=env,target=ADMIN_TOKEN
Secret=VW_DATABASE_URL,type=env,target=DATABASE_URL Secret=VW_DATABASE_URL,type=env,target=DATABASE_URL
[Service] [Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }} ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always Restart=always
RestartSec=10s RestartSec=10s
TimeoutStopSec=120 TimeoutStopSec=120
@@ -56,9 +56,9 @@ Exec=--config /config/authelia.yaml
# Wait for dependency # Wait for dependency
# They run as rootless podman container, so their port is not opened until they are normally running # They run as rootless podman container, so their port is not opened until they are normally running
# Check their ports with nc command # Check their ports with nc command
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }} ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
# services['ldap']['ports']['ldaps'] is 6360, but nftables works on 636 the original port # services['ldap']['ports']['ldaps'] is 6360, but nftables works on 636 the original port
ExecStartPre=/usr/bin/nc -zv {{ services['ldap']['domain'] }}.{{ domain['internal'] }} 636 ExecStartPre=/usr/bin/nc -zv {{ services['ldap']['domain']['internal'] }}.{{ domain['internal'] }} 636
ExecStartPre=sleep 5 ExecStartPre=sleep 5
Restart=always Restart=always
RestartSec=10s RestartSec=10s
@@ -30,12 +30,12 @@ identity_validation:
# Authentication backend provider configuration # Authentication backend provider configuration
authentication_backend: authentication_backend:
ldap: ldap:
# ldaps uses 636 -> NAT automatically change port 636 in output packet -> 2636 which lldap server uses. # ldaps uses 636 -> NAT automatically change port 636 in output packet -> 6360 which lldap server uses.
address: 'ldaps://{{ services['ldap']['domain'] }}.{{ domain['internal'] }}' address: 'ldaps://{{ services['ldap']['domain']['internal'] }}.{{ domain['internal'] }}'
implementation: 'lldap' implementation: 'lldap'
# tls configuration, it uses certificates_directory's /etc/ssl/authelia/{{ root_cert_filename }} # tls configuration, it uses certificates_directory's /etc/ssl/authelia/{{ root_cert_filename }}
tls: tls:
server_name: '{{ services['ldap']['domain'] }}.{{ domain['internal'] }}' server_name: '{{ services['ldap']['domain']['internal'] }}.{{ domain['internal'] }}'
skip_verify: false skip_verify: false
# LLDAP base DN # LLDAP base DN
base_dn: '{{ domain['dc'] }}' base_dn: '{{ domain['dc'] }}'
@@ -53,7 +53,7 @@ access_control:
default_policy: 'deny' default_policy: 'deny'
rules: rules:
# authelia portal # authelia portal
- domain: '{{ services['authelia']['domain'] }}.{{ domain['public'] }}' - domain: '{{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}'
policy: 'bypass' policy: 'bypass'
# - domain: 'test.ilnmors.com' # - domain: 'test.ilnmors.com'
# policy: 'one_factor' # policy: 'one_factor'
@@ -68,7 +68,7 @@ session:
cookies: cookies:
- name: 'authelia_public_session' - name: 'authelia_public_session'
domain: '{{ domain['public'] }}' domain: '{{ domain['public'] }}'
authelia_url: 'https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}' authelia_url: 'https://{{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}'
same_site: 'lax' same_site: 'lax'
# This authelia doesn't use Redis. # This authelia doesn't use Redis.
@@ -77,12 +77,12 @@ session:
storage: storage:
encryption_key: '' # $AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE is designated in container file encryption_key: '' # $AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE is designated in container file
postgres: postgres:
address: 'tcp://{{ services['postgresql']['domain'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }}' address: 'tcp://{{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }}'
database: 'authelia_db' database: 'authelia_db'
username: 'authelia' username: 'authelia'
password: '' # $AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE is designated in container file password: '' # $AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE is designated in container file
tls: tls:
server_name: '{{ services['postgresql']['domain'] }}.{{ domain['internal'] }}' server_name: '{{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}'
skip_verify: false skip_verify: false
# Notification provider # Notification provider
@@ -94,47 +94,18 @@ notifier:
identity_providers: identity_providers:
oidc: oidc:
hmac_secret: '' # $AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE hmac_secret: '' # $AUTHELIA_IDENTITY_PROVIDERS_OIDC_HMAC_SECRET_FILE
jwks:{% raw %} jwks:
- algorithm: 'RS256' - algorithm: 'RS256'
use: 'sig' use: 'sig'
key: {{ secret "/run/secrets/AUTHELIA_JWKS_RS256" | mindent 10 "|" | msquote }} key: {% raw %}{{ secret "/run/secrets/AUTHELIA_JWKS_RS256" | mindent 10 "|" | msquote }}{% endraw %}{{ '' }}
- algorithm: 'ES256' - algorithm: 'ES256'
use: 'sig' use: 'sig'
key: {{ secret "/run/secrets/AUTHELIA_JWKS_ES256" | mindent 10 "|" | msquote }}{% endraw %} key: {% raw %}{{ secret "/run/secrets/AUTHELIA_JWKS_ES256" | mindent 10 "|" | msquote }}{% endraw %}{{ '' }}
lifespans: lifespans:
access_token: '1h' access_token: '1h'
id_token: '1h' id_token: '1h'
refresh_token: '720h' refresh_token: '720h'
clients: clients:
# https://www.authelia.com/integration/openid-connect/clients/synology-dsm/
- client_id: 'dsm'
client_name: 'dsm'
consent_mode: 'implicit'
# It depends on application
# hash value generate:
# podman exec -it authelia sh
# authelia crypto hash generate pbkdf2 --password 'password'
client_secret: '{{ hostvars['console']['dsm']['oidc']['hash'] }}'
# If there were not client secret, public should be `true` [true | false]
public: false
authorization_policy: 'one_factor'
require_pkce: false
pkce_challenge_method: ''
redirect_uris:
- 'https://{{ services['nas']['domain'] }}.{{ domain['internal'] }}:{{ services['nas']['ports']['https'] }}'
scopes:
- 'openid'
- 'profile'
- 'groups'
- 'email'
response_types:
- 'code'
grant_types:
- 'authorization_code'
access_token_signed_response_alg: 'none'
userinfo_signed_response_alg: 'none'
# [ client_secret_post | client_secret_basic ]
token_endpoint_auth_method: 'client_secret_post'
# https://www.authelia.com/integration/openid-connect/clients/gitea/ # https://www.authelia.com/integration/openid-connect/clients/gitea/
- client_id: 'gitea' - client_id: 'gitea'
client_name: 'gitea' client_name: 'gitea'
@@ -319,3 +290,24 @@ identity_providers:
access_token_signed_response_alg: 'none' access_token_signed_response_alg: 'none'
userinfo_signed_response_alg: 'none' userinfo_signed_response_alg: 'none'
token_endpoint_auth_method: 'client_secret_basic' token_endpoint_auth_method: 'client_secret_basic'
# https://www.authelia.com/integration/openid-connect/clients/homebox/
- client_id: 'homebox'
client_name: 'homebox'
consent_mode: 'implicit'
client_secret: '{{ hostvars['console']['homebox']['oidc']['hash'] }}'
public: false
authorization_policy: 'one_factor'
require_pkce: true
pkce_challenge_method: 'S256'
redirect_uris:
- 'https://{{ services['homebox']['domain']['public'] }}.{{ domain['public'] }}/api/v1/users/login/oidc/callback'
scopes:
- 'openid'
- 'groups'
- 'email'
- 'profile'
response_types:
- 'code'
grant_types:
- 'authorization_code'
token_endpoint_auth_method: 'client_secret_basic'
@@ -19,9 +19,9 @@ Image={{ domain['internal'] }}/{{ node['name'] }}/caddy:{{ version['containers']
ContainerName=caddy_{{ node['name'] }} ContainerName=caddy_{{ node['name'] }}
HostName=caddy_{{ node['name'] }} HostName=caddy_{{ node['name'] }}
{% if node['name'] == 'infra' %} {% if node['name'] == 'infra' %}
AddHost={{ services['ca']['domain'] }}.{{ domain['internal'] }}:host-gateway AddHost={{ services['ca']['domain']['internal'] }}.{{ domain['internal'] }}:host-gateway
AddHost={{ services['prometheus']['domain'] }}.{{ domain['internal'] }}:host-gateway AddHost={{ services['prometheus']['domain']['internal'] }}.{{ domain['internal'] }}:host-gateway
AddHost={{ services['loki']['domain'] }}.{{ domain['internal'] }}:host-gateway AddHost={{ services['loki']['domain']['internal'] }}.{{ domain['internal'] }}:host-gateway
{% endif %} {% endif %}
PublishPort={{ services['caddy']['ports']['http'] }}:80/tcp PublishPort={{ services['caddy']['ports']['http'] }}:80/tcp
@@ -0,0 +1,92 @@
{% if node['name'] == 'auth' %}
{
# CrowdSec LAPI connection
crowdsec {
api_url https://{{ services['crowdsec']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['crowdsec']['ports']['https'] }}
api_key "{file./run/secrets/CADDY_CROWDSEC_KEY}"
}
}
# Snippets
# CrowdSec log for parser
(crowdsec_log) {
log {
output file /log/access.log {
mode 0644
roll_size 100MiB
roll_keep 1
}
format json
}
}
{% endif %}
{% if node['name'] == 'app' %}
{
servers {
# Only accept packets from auth main caddy
trusted_proxies static {{ hostvars['fw']['network4']['auth']['server'] }} {{ hostvars['fw']['network6']['auth']['server'] }}
}
}
{% endif %}
# Private TLS ACME with DNS-01-challenge
(private_tls) {
tls {
issuer acme {
dir https://{{ services['ca']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['ca']['ports']['https'] }}/acme/acme@{{ domain['internal'] }}/directory
dns rfc2136 {
server {{ services['bind']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['bind']['ports']['dns'] }}
key_name acme-key
key_alg hmac-sha256
key "{file./run/secrets/CADDY_ACME_KEY}"
}
resolvers {{ services['bind']['domain']['internal'] }}.{{ domain['internal'] }}
}
}
}
# Node domain
{{ node['name'] }}.{{ domain['internal'] }} {
import private_tls
metrics
}
# Applications
{% for item in caddy_services %}
{% set service = services[item] %}
{% set web_type = service['dependency']['web'] %}
{% if node['name'] == 'auth' %}
{% if service['domain']['public'] == '@' %}
{{ domain['public'] }} {
{% else %}
{{ service['domain']['public'] }}.{{ domain['public'] }} {
{% endif %}
import crowdsec_log
route {
crowdsec
{% if web_type == 'auth-public' %}
reverse_proxy host.containers.internal:{{ service['ports']['http'] }}
{% else %}
reverse_proxy https://{{ service['domain']['internal'] }}.{{ domain['internal'] }} {
header_up Host {http.reverse_proxy.upstream.host}
}
{% endif %}
}
}
{% elif node['name'] == 'infra' %}
{{ service['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
route {
{% if service['ports']['https'] is defined %}
reverse_proxy https://{{ service['domain']['internal'] }}.{{ domain['internal'] }}:{{ service['ports']['https'] }}
{% else %}
reverse_proxy host.containers.internal:{{ service['ports']['http'] }}
{% endif %}
}
}
{% elif node['name'] == 'app' %}
{{ service['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
reverse_proxy host.containers.internal:{{ service['ports']['http'] }} {
header_up Host {http.request.header.X-Forwarded-Host}
}
}
{% endif %}
{% endfor %}{{ '' }}
@@ -1,91 +0,0 @@
{
servers {
# Only accept packets from auth main caddy
trusted_proxies static {{ hostvars['fw']['network4']['auth']['server'] }} {{ hostvars['fw']['network6']['auth']['server'] }}
}
}
# Private TLS ACME with DNS-01-challenge
(private_tls) {
tls {
issuer acme {
dir https://{{ services['ca']['domain'] }}.{{ domain['internal'] }}:{{ services['ca']['ports']['https'] }}/acme/acme@{{ domain['internal'] }}/directory
dns rfc2136 {
server {{ services['bind']['domain'] }}.{{ domain['internal'] }}:{{ services['bind']['ports']['dns'] }}
key_name acme-key
key_alg hmac-sha256
key "{file./run/secrets/CADDY_ACME_KEY}"
}
resolvers {{ services['bind']['domain'] }}.{{ domain['internal'] }}
}
}
}
{{ node['name'] }}.{{ domain['internal'] }} {
import private_tls
metrics
}
# test.app.ilnmors.internal {
# import private_tls
# root * /usr/share/caddy
# file_server
# }
{{ services['vaultwarden']['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
reverse_proxy host.containers.internal:{{ services['vaultwarden']['ports']['http'] }} {
header_up Host {http.request.header.X-Forwarded-Host}
}
}
{{ services['gitea']['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
reverse_proxy host.containers.internal:{{ services['gitea']['ports']['http'] }} {
header_up Host {http.request.header.X-Forwarded-Host}
}
}
{{ services['immich']['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
reverse_proxy host.containers.internal:{{ services['immich']['ports']['http'] }} {
header_up Host {http.request.header.X-Forwarded-Host}
}
}
{{ services['paperless']['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
reverse_proxy host.containers.internal:{{ services['paperless']['ports']['http'] }} {
header_up Host {http.request.header.X-Forwarded-Host}
}
}
{{ services['nextcloud']['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
reverse_proxy host.containers.internal:{{ services['nextcloud']['ports']['http'] }} {
header_up Host {http.request.header.X-Forwarded-Host}
}
}
{{ services['collabora']['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
reverse_proxy host.containers.internal:{{ services['collabora']['ports']['http'] }} {
header_up Host {http.request.header.X-Forwarded-Host}
}
}
{{ services['sure']['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
reverse_proxy host.containers.internal:{{ services['sure']['ports']['http'] }} {
header_up Host {http.request.header.X-Forwarded-Host}
}
}
{{ services['outline']['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
reverse_proxy host.containers.internal:{{ services['outline']['ports']['http'] }} {
header_up Host {http.request.header.X-Forwarded-Host}
}
}
{{ services['memos']['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
reverse_proxy host.containers.internal:{{ services['memos']['ports']['http'] }} {
header_up Host {http.request.header.X-Forwarded-Host}
}
}
{{ services['mealie']['domain']['internal'] }}.{{ domain['internal'] }} {
import private_tls
reverse_proxy host.containers.internal:{{ services['mealie']['ports']['http'] }} {
header_up Host {http.request.header.X-Forwarded-Host}
}
}
@@ -1,162 +0,0 @@
{
# CrowdSec LAPI connection
crowdsec {
api_url https://{{ services['crowdsec']['domain'] }}.{{ domain['internal'] }}:{{ services['crowdsec']['ports']['https'] }}
api_key "{file./run/secrets/CADDY_CROWDSEC_KEY}"
}
}
# Snippets
# CrowdSec log for parser
(crowdsec_log) {
log {
output file /log/access.log {
mode 0644
roll_size 100MiB
roll_keep 1
}
format json
}
}
# Private TLS ACME with DNS-01-challenge
(private_tls) {
tls {
issuer acme {
dir https://{{ services['ca']['domain'] }}.{{ domain['internal'] }}:{{ services['ca']['ports']['https'] }}/acme/acme@{{ domain['internal'] }}/directory
dns rfc2136 {
server {{ services['bind']['domain'] }}.{{ domain['internal'] }}:{{ services['bind']['ports']['dns'] }}
key_name acme-key
key_alg hmac-sha256
key "{file./run/secrets/CADDY_ACME_KEY}"
}
resolvers {{ services['bind']['domain'] }}.{{ domain['internal'] }}
}
}
}
# Public domain
{{ services['authelia']['domain'] }}.{{ domain['public'] }} {
import crowdsec_log
route {
crowdsec
reverse_proxy host.containers.internal:{{ services['authelia']['ports']['http'] }}
}
}
# test.ilnmors.com {
# import crowdsec_log
# route {
# crowdsec
# forward_auth host.containers.internal:9091 {
# # Authelia Forward Auth endpoint URI
# uri /api/authz/forward-auth
# copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
# }
# root * /usr/share/caddy
# file_server
# }
# }
# test.app.ilnmors.com {
# import crowdsec_log
# route {
# crowdsec
# reverse_proxy https://test.app.ilnmors.internal {
# header_up Host {http.reverse_proxy.upstream.host}
# }
# }
# }
{{ services['vaultwarden']['domain']['public'] }}.{{ domain['public'] }} {
import crowdsec_log
route {
crowdsec
reverse_proxy https://{{ services['vaultwarden']['domain']['internal'] }}.{{ domain['internal'] }} {
header_up Host {http.reverse_proxy.upstream.host}
}
}
}
{{ services['gitea']['domain']['public'] }}.{{ domain['public'] }} {
import crowdsec_log
route {
crowdsec
reverse_proxy https://{{ services['gitea']['domain']['internal'] }}.{{ domain['internal'] }} {
header_up Host {http.reverse_proxy.upstream.host}
}
}
}
{{ services['immich']['domain']['public'] }}.{{ domain['public'] }} {
import crowdsec_log
route {
crowdsec
reverse_proxy https://{{ services['immich']['domain']['internal'] }}.{{ domain['internal'] }} {
header_up Host {http.reverse_proxy.upstream.host}
}
}
}
{{ services['paperless']['domain']['public'] }}.{{ domain['public'] }} {
import crowdsec_log
route {
crowdsec
reverse_proxy https://{{ services['paperless']['domain']['internal'] }}.{{ domain['internal'] }} {
header_up Host {http.reverse_proxy.upstream.host}
}
}
}
{{ services['nextcloud']['domain']['public'] }}.{{ domain['public'] }} {
import crowdsec_log
route {
crowdsec
reverse_proxy https://{{services['nextcloud']['domain']['internal'] }}.{{ domain['internal'] }} {
header_up Host {http.reverse_proxy.upstream.host}
}
}
}
{{ services['collabora']['domain']['public'] }}.{{ domain['public'] }} {
import crowdsec_log
route {
crowdsec
reverse_proxy https://{{services['collabora']['domain']['internal'] }}.{{ domain['internal'] }} {
header_up Host {http.reverse_proxy.upstream.host}
}
}
}
{{ services['sure']['domain']['public'] }}.{{ domain['public'] }} {
import crowdsec_log
route {
crowdsec
reverse_proxy https://{{services['sure']['domain']['internal'] }}.{{ domain['internal'] }} {
header_up Host {http.reverse_proxy.upstream.host}
}
}
}
{{ services['outline']['domain']['public'] }}.{{ domain['public'] }} {
import crowdsec_log
route {
crowdsec
reverse_proxy https://{{services['outline']['domain']['internal'] }}.{{ domain['internal'] }} {
header_up Host {http.reverse_proxy.upstream.host}
}
}
}
{{ services['memos']['domain']['public'] }}.{{ domain['public'] }} {
import crowdsec_log
route {
crowdsec
reverse_proxy https://{{services['memos']['domain']['internal'] }}.{{ domain['internal'] }} {
header_up Host {http.reverse_proxy.upstream.host}
}
}
}
{{ services['mealie']['domain']['public'] }}.{{ domain['public'] }} {
import crowdsec_log
route {
crowdsec
reverse_proxy https://{{services['mealie']['domain']['internal'] }}.{{ domain['internal'] }} {
header_up Host {http.reverse_proxy.upstream.host}
}
}
}
# Internal domain
{{ node['name'] }}.{{ domain['internal'] }} {
import private_tls
metrics
}
@@ -1,41 +0,0 @@
# Private TLS ACME with DNS-01-challenge
(private_tls) {
tls {
issuer acme {
dir https://{{ services['ca']['domain'] }}.{{ domain['internal'] }}:{{ services['ca']['ports']['https'] }}/acme/acme@{{ domain['internal'] }}/directory
dns rfc2136 {
server {{ services['bind']['domain'] }}.{{ domain['internal'] }}:{{ services['bind']['ports']['dns'] }}
key_name acme-key
key_alg hmac-sha256
key "{file./run/secrets/CADDY_ACME_KEY}"
}
resolvers {{ services['bind']['domain'] }}.{{ domain['internal'] }}
}
}
}
{{ node['name'] }}.{{ domain['internal'] }} {
import private_tls
metrics
}
{{ services['ldap']['domain'] }}.{{ domain['internal'] }} {
import private_tls
route {
reverse_proxy host.containers.internal:{{ services['ldap']['ports']['http'] }}
}
}
{{ services['prometheus']['domain'] }}.{{ domain['internal'] }} {
import private_tls
route {
reverse_proxy https://{{ services['prometheus']['domain'] }}.{{ domain['internal'] }}:{{ services['prometheus']['ports']['https'] }}
}
}
{{ services['grafana']['domain'] }}.{{ domain['internal'] }} {
import private_tls
route {
reverse_proxy host.containers.internal:{{ services['grafana']['ports']['http'] }}
}
}
@@ -6,7 +6,7 @@
"address": ":9000", "address": ":9000",
"insecureAddress": "", "insecureAddress": "",
"dnsNames": [ "dnsNames": [
"{{ services['ca']['domain'] }}.{{ domain['internal'] }}" "{{ services['ca']['domain']['internal'] }}.{{ domain['internal'] }}"
], ],
"logger": { "logger": {
"format": "text" "format": "text"
@@ -1,6 +1,6 @@
{ {
"ca-url": "https://{{ services['ca']['domain'] }}.{{ domain['internal'] }}:{{ services['ca']['ports']['https'] }}", "ca-url": "https://{{ services['ca']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['ca']['ports']['https'] }}",
"ca-config": "/home/step/config/ca.json", "ca-config": "/home/step/config/ca.json",
"fingerprint": "215c851d2d0d2dbf90fc3507425207c29696ffd587c640c94a68dddb1d84d8e8", "fingerprint": "",
"root": "/home/step/certs/{{ root_cert_filename }}" "root": "/home/step/certs/{{ root_cert_filename }}"
} }
@@ -8,13 +8,13 @@ provisioning = /etc/grafana/provisioning
[server] [server]
protocol = http protocol = http
http_port = {{ services['grafana']['ports']['http'] }} http_port = {{ services['grafana']['ports']['http'] }}
domain = {{ services['grafana']['domain'] }}.{{ domain['internal'] }} domain = {{ services['grafana']['domain']['internal'] }}.{{ domain['internal'] }}
root_url = http://{{ services['grafana']['domain'] }}.{{ domain['internal'] }}/ root_url = https://{{ services['grafana']['domain']['internal'] }}.{{ domain['internal'] }}/
router_logging = false router_logging = false
[database] [database]
type = postgres type = postgres
host = {{ services['postgresql']['domain'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }} host = {{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }}
name = grafana_db name = grafana_db
user = grafana user = grafana
password = $__file{/run/secrets/GF_DB_PASSWORD} password = $__file{/run/secrets/GF_DB_PASSWORD}
@@ -1,6 +1,6 @@
# https://github.com/lldap/lldap/blob/main/example_configs/grafana_ldap_config.toml # https://github.com/lldap/lldap/blob/main/example_configs/grafana_ldap_config.toml
[[servers]] [[servers]]
host = "{{ services['ldap']['domain'] }}.{{ domain['internal'] }}" host = "{{ services['ldap']['domain']['internal'] }}.{{ domain['internal'] }}"
port = {{ services['ldap']['ports']['ldaps'] }} port = {{ services['ldap']['ports']['ldaps'] }}
# Activate STARTTLS or LDAPS # Activate STARTTLS or LDAPS
use_ssl = true use_ssl = true
@@ -4,7 +4,7 @@ apiVersion: 1
datasources: datasources:
- name: Prometheus - name: Prometheus
type: prometheus type: prometheus
url: https://{{ services['prometheus']['domain'] }}.{{ domain['internal'] }}:{{ services['prometheus']['ports']['https'] }} url: https://{{ services['prometheus']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['prometheus']['ports']['https'] }}
access: proxy access: proxy
isDefault: true isDefault: true
jsonData: jsonData:
@@ -16,7 +16,7 @@ datasources:
- name: Loki - name: Loki
type: loki type: loki
url: https://{{ services['loki']['domain'] }}.{{ domain['internal'] }}:{{ services['loki']['ports']['https'] }} url: https://{{ services['loki']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['loki']['ports']['https'] }}
access: proxy access: proxy
jsonData: jsonData:
tlsAuth: false tlsAuth: false
@@ -26,4 +26,4 @@ datasources:
maxLines: 1000 maxLines: 1000
secureJsonData: secureJsonData:
tlsCACert: "$__file{/etc/ssl/grafana/{{ root_cert_filename }}}" tlsCACert: "$__file{/etc/ssl/grafana/{{ root_cert_filename }}}"
httpHeaderValue1: "{{ domain['internal'] }} " httpHeaderValue1: "{{ domain['internal'] }}"
@@ -13,10 +13,10 @@ Image=docker.io/grafana/grafana:{{ version['containers']['grafana'] }}
ContainerName=grafana ContainerName=grafana
HostName=grafana HostName=grafana
AddHost={{ services['postgresql']['domain'] }}.{{ domain['internal'] }}:host-gateway AddHost={{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}:host-gateway
AddHost={{ services['ldap']['domain'] }}.{{ domain['internal'] }}:host-gateway AddHost={{ services['ldap']['domain']['internal'] }}.{{ domain['internal'] }}:host-gateway
AddHost={{ services['prometheus']['domain'] }}.{{ domain['internal'] }}:host-gateway AddHost={{ services['prometheus']['domain']['internal'] }}.{{ domain['internal'] }}:host-gateway
AddHost={{ services['loki']['domain'] }}.{{ domain['internal'] }}:host-gateway AddHost={{ services['loki']['domain']['internal'] }}.{{ domain['internal'] }}:host-gateway
PublishPort={{ services['grafana']['ports']['http'] }}:3000/tcp PublishPort={{ services['grafana']['ports']['http'] }}:3000/tcp
@@ -13,7 +13,7 @@ Image=docker.io/lldap/lldap:{{ version['containers']['ldap'] }}
ContainerName=ldap ContainerName=ldap
HostName=ldap HostName=ldap
# They are at the same host (for Pasta, it is needed) # They are at the same host (for Pasta, it is needed)
AddHost={{ services['postgresql']['domain'] }}.{{ domain['internal'] }}:host-gateway AddHost={{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}:host-gateway
# For LDAPS - 636 > 6360 nftables # For LDAPS - 636 > 6360 nftables
PublishPort={{ services['ldap']['ports']['ldaps'] }}:6360/tcp PublishPort={{ services['ldap']['ports']['ldaps'] }}:6360/tcp
# Web UI # Web UI
@@ -1,29 +1,28 @@
# @authcomment@ # @authcomment@
# TYPE DATABASE USER ADDRESS METHOD # TYPE DATABASE USER ADDRESS METHOD
# Local host `trust` # Local host `trust`
local all all trust local all all trust
# Local monitoring connection (host - infra VM) `trust` # Local monitoring connection (host - infra VM) `trust`
hostssl postgres alloy {{ hostvars['fw']['network4']['infra']['server'] }}/32 trust hostssl postgres alloy {{ hostvars['fw']['network4']['infra']['server'] }}/32 trust
hostssl postgres alloy {{ hostvars['fw']['network6']['infra']['server'] }}/128 trust hostssl postgres alloy {{ hostvars['fw']['network6']['infra']['server'] }}/128 trust
hostssl postgres alloy {{ hostvars['fw']['network4']['subnet']['lla'] }} trust hostssl postgres alloy {{ hostvars['fw']['network4']['subnet']['lla'] }} trust
hostssl postgres alloy {{ hostvars['fw']['network6']['subnet']['lla'] }} trust hostssl postgres alloy {{ hostvars['fw']['network6']['subnet']['lla'] }} trust
# Local connection (in postgresql container) needs password (127.0.0.1 - container loopback) # Local connection (in postgresql container) needs password (127.0.0.1 - container loopback)
host all all 127.0.0.1/32 scram-sha-256 host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256 host all all ::1/128 scram-sha-256
# Local connection (host - infra VM) needs password (169.254.1.0/24 - link_local subnet for containers in pasta mode) # Local connection (host - infra VM) needs password (169.254.1.0/24 - link_local subnet for containers in pasta mode)
hostssl all all {{ hostvars['fw']['network4']['infra']['server'] }}/32 scram-sha-256 hostssl all all {{ hostvars['fw']['network4']['infra']['server'] }}/32 scram-sha-256
hostssl all all {{ hostvars['fw']['network6']['infra']['server'] }}/128 scram-sha-256 hostssl all all {{ hostvars['fw']['network6']['infra']['server'] }}/128 scram-sha-256
hostssl all all {{ hostvars['fw']['network4']['subnet']['lla'] }} scram-sha-256 hostssl all all {{ hostvars['fw']['network4']['subnet']['lla'] }} scram-sha-256
hostssl all all {{ hostvars['fw']['network6']['subnet']['lla'] }} scram-sha-256 hostssl all all {{ hostvars['fw']['network6']['subnet']['lla'] }} scram-sha-256
# auth VM # auth VM
hostssl all all {{ hostvars['fw']['network4']['auth']['server'] }}/32 scram-sha-256 hostssl all all {{ hostvars['fw']['network4']['auth']['server'] }}/32 scram-sha-256
hostssl all all {{ hostvars['fw']['network6']['auth']['server'] }}/128 scram-sha-256 hostssl all all {{ hostvars['fw']['network6']['auth']['server'] }}/128 scram-sha-256
# app VM (Applications, 192.168.10.13) # app VM (Applications, 192.168.10.13)
hostssl all all {{ hostvars['fw']['network4']['app']['server'] }}/32 scram-sha-256 hostssl all all {{ hostvars['fw']['network4']['app']['server'] }}/32 scram-sha-256
hostssl all all {{ hostvars['fw']['network6']['app']['server'] }}/128 scram-sha-256 hostssl all all {{ hostvars['fw']['network6']['app']['server'] }}/128 scram-sha-256
@@ -11,8 +11,12 @@ StandardOutput=journal
StandardError=journal StandardError=journal
ExecStartPre=/usr/bin/podman exec postgresql sh -c "mkdir -p /backups/cluster && chown postgres:root /backups/cluster && chmod 770 /backups/cluster" ExecStartPre=/usr/bin/podman exec postgresql sh -c "mkdir -p /backups/cluster && chown postgres:root /backups/cluster && chmod 770 /backups/cluster"
ExecStartPre=/usr/bin/podman exec postgresql sh -c "mkdir -p /backups/sql && chown postgres:root /backups/sql && chmod 770 /backups/sql"
# Run the script # Run the script
ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c 'pg_dumpall -U postgres --schema-only | grep -v -E "CREATE ROLE postgres" > /backups/cluster/pg_cluster_$(date "+%%Y-%%m-%%d").sql' ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c 'pg_dumpall -U postgres --schema-only | grep -v -E "CREATE ROLE postgres" > /backups/cluster/pg_cluster_$(date "+%%Y-%%m-%%d").sql'
ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c "find /backups/cluster -maxdepth 1 -type f -mtime +7 -delete" ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c 'cp /backups/cluster/pg_cluster_$(date "+%%Y-%%m-%%d").sql /backups/sql/pg_cluster.sql'
ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c "find /backups/cluster -maxdepth 1 -type f -name 'pg_cluster_*.sql' -mtime +7 -delete"
ExecStart=/usr/bin/podman exec postgresql sh -c "chown -R postgres:root /backups/cluster && chmod 660 /backups/cluster/*" ExecStart=/usr/bin/podman exec postgresql sh -c "chown -R postgres:root /backups/cluster && chmod 660 /backups/cluster/*"
ExecStart=/usr/bin/podman exec postgresql sh -c "chown -R postgres:root /backups/sql && chmod 660 /backups/sql/pg_cluster.sql"
@@ -11,6 +11,7 @@ StandardOutput=journal
StandardError=journal StandardError=journal
ExecStartPre=/usr/bin/podman exec postgresql sh -c "mkdir -p /backups/%i && chown postgres:root /backups/%i && chmod 770 /backups/%i" ExecStartPre=/usr/bin/podman exec postgresql sh -c "mkdir -p /backups/%i && chown postgres:root /backups/%i && chmod 770 /backups/%i"
ExecStartPre=/usr/bin/podman exec postgresql sh -c "mkdir -p /backups/sql && chown postgres:root /backups/sql && chmod 770 /backups/sql"
# Run the script # Run the script
## DB Connection ## DB Connection
@@ -21,5 +22,7 @@ ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c 'printf "SET session
ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c 'pg_dump -U postgres -d %i_db --data-only >> /backups/%i/pg_%i_$(date "+%%Y-%%m-%%d").sql' ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c 'pg_dump -U postgres -d %i_db --data-only >> /backups/%i/pg_%i_$(date "+%%Y-%%m-%%d").sql'
## reset session replication role ## reset session replication role
ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c 'printf "SET session_replication_role = origin;\n" >> /backups/%i/pg_%i_$(date "+%%Y-%%m-%%d").sql' ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c 'printf "SET session_replication_role = origin;\n" >> /backups/%i/pg_%i_$(date "+%%Y-%%m-%%d").sql'
ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c "find /backups/%i -maxdepth 1 -type f -mtime +7 -delete" ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c 'cp -a /backups/%i/pg_%i_$(date "+%%Y-%%m-%%d").sql /backups/sql/pg_%i.sql'
ExecStart=/usr/bin/podman exec -u postgres postgresql sh -c "find /backups/%i -maxdepth 1 -type f -name 'pg_%i_*.sql' -mtime +7 -delete"
ExecStart=/usr/bin/podman exec postgresql sh -c "chown -R postgres:root /backups/%i && chmod 660 /backups/%i/*" ExecStart=/usr/bin/podman exec postgresql sh -c "chown -R postgres:root /backups/%i && chmod 660 /backups/%i/*"
ExecStart=/usr/bin/podman exec postgresql sh -c "chown -R postgres:root /backups/sql && chmod 660 /backups/sql/pg_%i.sql"
@@ -24,7 +24,7 @@ scrape_configs:
scheme: "https" scheme: "https"
tls_config: tls_config:
ca_file: "/etc/ssl/prometheus/{{ root_cert_filename }}" ca_file: "/etc/ssl/prometheus/{{ root_cert_filename }}"
server_name: "{{ services['prometheus']['domain'] }}.{{ domain['internal'] }}" server_name: "{{ ['internal'] }}.{{ domain['internal'] }}"
static_configs: static_configs:
- targets: ["localhost:9090"] - targets: ["localhost:9090"]
# The label name is added as a label `label_name=<label_value>` to any timeseries scraped from this config. # The label name is added as a label `label_name=<label_value>` to any timeseries scraped from this config.
@@ -1,7 +1,7 @@
groups: groups:
- name: node_exporters_heartbeat - name: node_exporters_heartbeat
rules: rules:
{% for instance in ['vmm', 'fw', 'infra', 'auth', 'app'] %} {% for instance in ["vmm", "fw", "infra", "auth", "app"] %}
- alert: {{ instance }}_node_exporter_down - alert: {{ instance }}_node_exporter_down
expr: | expr: |
(present_over_time(up{instance="{{ instance }}"}[5m]) or on() vector(0)) == 0 (present_over_time(up{instance="{{ instance }}"}[5m]) or on() vector(0)) == 0
@@ -25,7 +25,7 @@ groups:
description: "postgresql node is down for 5 mins." description: "postgresql node is down for 5 mins."
- name: Certificate_expiry_check - name: Certificate_expiry_check
rules: rules:
{% for filename in ['root.crt', 'intermediate.crt', 'crowdsec.crt', 'blocky.crt', 'postgresql.crt', 'ldap.crt', 'prometheus.crt', 'loki.crt', 'dsm.crt'] %} {% for filename in ["root.crt", "intermediate.crt", "crowdsec.crt", "blocky.crt", "kopia.crt", "postgresql.crt", "ldap.crt", "prometheus.crt", "loki.crt"] %}
- alert: {{ filename | replace('.', '_') }}_is_expired_soon - alert: {{ filename | replace('.', '_') }}_is_expired_soon
expr: | expr: |
max(x509_cert_not_after{filename="{{ filename }}"}) - time() < 2592000 max(x509_cert_not_after{filename="{{ filename }}"}) - time() < 2592000
@@ -0,0 +1,13 @@
[gdrive]
type = drive
client_id = {{ hostvars['console']['rclone']['google_drive']['oidc']['id'] }}
client_secret = {{ hostvars['console']['rclone']['google_drive']['oidc']['secret'] }}
scope = drive
token = {{
{
"access_token":"expired",
"token_type":"Bearer",
"refresh_token":hostvars['console']['rclone']['google_drive']['refresh_token'],
"expiry":"1970-01-01T00:00:00Z",
} | to_json
}}
@@ -0,0 +1,28 @@
[Unit]
Description=Daily Kopia rclone backup service
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
# logging
StandardOutput=journal
StandardError=journal
Environment="RCLONE_CONFIG=/etc/secrets/{{ node['uid'] }}/rclone/rclone.config"
ExecStart=/usr/bin/rclone copy %h/data/kopia/ gdrive:kopia \
--transfers=4 \
--checkers=4 \
--tpslimit=8 \
--tpslimit-burst=4 \
--drive-chunk-size=64M \
--retries=20 \
--low-level-retries=10 \
--retries-sleep=30s \
--timeout=3m \
--contimeout=30s \
--drive-stop-on-upload-limit \
--stats=30s \
--log-level=INFO
@@ -0,0 +1,10 @@
[Unit]
Description=Daily Kopia rclone backup timer
[Timer]
OnCalendar=*-*-* 09:00:00
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
@@ -6,7 +6,7 @@
//// Metric ouput //// Metric ouput
prometheus.remote_write "prometheus" { prometheus.remote_write "prometheus" {
endpoint { endpoint {
url = "https://{{ services['prometheus']['domain'] }}.{{ domain['internal'] }}:{{ services['prometheus']['ports']['https'] }}/api/v1/write" url = "https://{{ services['prometheus']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['prometheus']['ports']['https'] }}/api/v1/write"
} }
} }
@@ -71,8 +71,8 @@ prometheus.scrape "system" {
////// For Crowdsec metrics ////// For Crowdsec metrics
prometheus.scrape "crowdsec" { prometheus.scrape "crowdsec" {
targets = [ targets = [
{ "__address__" = "{{ services['crowdsec']['domain'] }}.{{ domain['internal'] }}:6060", "job" = "crowdsec" }, { "__address__" = "{{ services['crowdsec']['domain']['internal'] }}.{{ domain['internal'] }}:6060", "job" = "crowdsec" },
{ "__address__" = "{{ services['crowdsec']['domain'] }}.{{ domain['internal'] }}:60601", "job" = "crowdsec-bouncer" }, { "__address__" = "{{ services['crowdsec']['domain']['internal'] }}.{{ domain['internal'] }}:60601", "job" = "crowdsec-bouncer" },
] ]
honor_labels = true honor_labels = true
forward_to = [prometheus.relabel.default_label.receiver] forward_to = [prometheus.relabel.default_label.receiver]
@@ -83,7 +83,7 @@ prometheus.scrape "crowdsec" {
////// For postgresql metrics ////// For postgresql metrics
prometheus.exporter.postgres "postgresql" { prometheus.exporter.postgres "postgresql" {
data_source_names = [ data_source_names = [
"postgres://alloy@{{ services['postgresql']['domain'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }}/postgres?sslmode=verify-full", "postgres://alloy@{{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }}/postgres?sslmode=verify-full",
] ]
} }
prometheus.scrape "postgresql" { prometheus.scrape "postgresql" {
@@ -99,7 +99,7 @@ prometheus.scrape "x509" {
} }
{% endif %} {% endif %}
{% if node['name'] in ['infra', 'auth', 'app'] %} {% if node['name'] in ["infra", "auth", "app"] %}
////// For Input Caddy metrics ////// For Input Caddy metrics
prometheus.scrape "caddy" { prometheus.scrape "caddy" {
targets = [ targets = [
@@ -114,7 +114,7 @@ prometheus.scrape "caddy" {
//// Logs output //// Logs output
loki.write "loki" { loki.write "loki" {
endpoint { endpoint {
url = "https://{{ services['loki']['domain'] }}.{{ domain['internal'] }}:{{ services['loki']['ports']['https'] }}/loki/api/v1/push" url = "https://{{ services['loki']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['loki']['ports']['https'] }}/loki/api/v1/push"
tenant_id = "{{ domain['internal'] }}" tenant_id = "{{ domain['internal'] }}"
} }
} }
@@ -8,7 +8,7 @@ log_compression: true
log_max_size: 100 log_max_size: 100
log_max_backups: 3 log_max_backups: 3
log_max_age: 30 log_max_age: 30
api_url: "https://{{ services['crowdsec']['domain'] }}.{{ domain['internal'] }}:{{ services['crowdsec']['ports']['https'] }}" api_url: "https://{{ services['crowdsec']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['crowdsec']['ports']['https'] }}"
api_key: "{{ hostvars['console']['crowdsec']['bouncer']['fw'] }}" api_key: "{{ hostvars['console']['crowdsec']['bouncer']['fw'] }}"
insecure_skip_verify: false insecure_skip_verify: false
disable_ipv6: false disable_ipv6: false
@@ -1,3 +1,3 @@
url: https://{{ services['crowdsec']['domain'] }}.{{ domain['internal'] }}:{{ services['crowdsec']['ports']['https'] }} url: https://{{ services['crowdsec']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['crowdsec']['ports']['https'] }}
login: {{ node['name'] }} login: {{ node['name'] }}
password: {{ hostvars['console']['crowdsec']['machine'][node['name']] }} password: {{ hostvars['console']['crowdsec']['machine'][node['name']] }}
@@ -28,8 +28,10 @@ BindPaths=/etc/secrets/{{ kopia_uid }}
BindPaths=/var/cache/kopia BindPaths=/var/cache/kopia
EnvironmentFile=/etc/secrets/{{ kopia_uid }}/kopia.env EnvironmentFile=/etc/secrets/{{ kopia_uid }}/kopia.env
ExecStartPre=/usr/bin/nc -zv {{ services['kopia']['domain']['internal'] }}.{{ domain['internal'] }} 443
ExecStartPre=/usr/bin/kopia repository connect server \ ExecStartPre=/usr/bin/kopia repository connect server \
--url=https://{{ services['kopia']['domain'] }}.{{ domain['internal'] }}:{{ services['kopia']['ports']['https'] }} \ --url=https://{{ services['kopia']['domain']['internal'] }}.{{ domain['internal'] }}:443 \
--override-username={{ node['name'] }} \ --override-username={{ node['name'] }} \
--override-hostname={{ node['name'] }}.{{ domain['internal'] }} --override-hostname={{ node['name'] }}.{{ domain['internal'] }}
@@ -0,0 +1,24 @@
[Unit]
Description=Kopia repository server
Wants=network-online.target
After=network-online.target
[Service]
# logging
StandardOutput=journal
StandardError=journal
EnvironmentFile=/etc/secrets/{{ node['uid'] }}/kopia.env
ExecStartPre=/usr/bin/kopia repository connect filesystem \
--path={{ node['home_path'] }}/data/kopia/repository
ExecStart=/usr/bin/kopia server start \
--no-ui \
--tls-cert-file=/etc/kopia/ssl/kopia.crt \
--tls-key-file=/etc/kopia/ssl/kopia.key \
--address=0.0.0.0:{{ services['kopia']['ports']['https'] }} \
--log-level=info
[Install]
WantedBy=default.target
@@ -1,4 +1,8 @@
{% if node['name'] == "bk" %}
KOPIA_PASSWORD={{ hostvars['console']['kopia']['repository'] }}
{% elif node['name'] in ["infra", "app"] %}
KOPIA_PASSWORD={{ hostvars['console']['kopia']['users'][node['name']] }} KOPIA_PASSWORD={{ hostvars['console']['kopia']['users'][node['name']] }}
{% endif %}
KOPIA_CONFIG_PATH=/etc/kopia/repository.config KOPIA_CONFIG_PATH=/etc/kopia/repository.config
KOPIA_CACHE_DIRECTORY=/var/cache/kopia KOPIA_CACHE_DIRECTORY=/var/cache/kopia
KOPIA_LOG_DIR=/var/cache/kopia/logs KOPIA_LOG_DIR=/var/cache/kopia/logs
@@ -9,5 +9,4 @@ $TTL 86400
) )
IN NS bind.ilnmors.internal. IN NS bind.ilnmors.internal.
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR fw.ilnmors.internal. 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR fw.ilnmors.internal.
1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR nas.ilnmors.internal.
0.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR console.ilnmors.internal. 0.2.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR console.ilnmors.internal.
@@ -9,5 +9,6 @@ $TTL 86400
) )
IN NS bind.ilnmors.internal. IN NS bind.ilnmors.internal.
1 IN PTR fw.ilnmors.internal. 1 IN PTR fw.ilnmors.internal.
11 IN PTR nas.ilnmors.internal. 2 IN PTR switch.ilnmors.internal.
20 IN PTR console.ilnmors.internal. 20 IN PTR console.ilnmors.internal.
101 IN PTR printer.ilnmors.internal.
@@ -11,6 +11,7 @@ $TTL 86400
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR fw.ilnmors.internal. 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR fw.ilnmors.internal.
2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR blocky.ilnmors.internal. 2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR blocky.ilnmors.internal.
3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR bind.ilnmors.internal. 3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR bind.ilnmors.internal.
9.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR bk.ilnmors.internal.
0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR vmm.ilnmors.internal. 0.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR vmm.ilnmors.internal.
1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR infra.ilnmors.internal. 1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR infra.ilnmors.internal.
2.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR auth.ilnmors.internal. 2.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR auth.ilnmors.internal.

Some files were not shown because too many files have changed in this diff Show More