Compare commits

...
57 Commits
Author SHA1 Message Date
il 927b5b4934 feat(repo): IaaS baseline 2026-06-17 13:17:24 +09:00
il a6bba986a5 fix(crowdsec): update whitelist.yaml to prevent false positive
false positive:
- outline session problem (LePresidente/http-generic-401-bf)
2026-05-17 00:00:46 +09:00
il 24eff8f3eb chore(outline): fix HSTS annotation typo 2026-05-16 21:16:28 +09:00
il 9be4276676 feat(memos): release memos
deployment notes:
- compare to Affine, maybe outline + memos can be substituted for affine
2026-05-16 21:04:53 +09:00
il 1256122081 feat(outline): release outline
deployment notes:
- compare to Affine (Affine is heavy and their whtieboard and canvas is not used enough)
- don't restart this when it initiates, redis lock causes failure
2026-05-16 20:56:43 +09:00
il f28661e664 refactor(convention): add existing 'site' tag to convention 2026-05-15 10:16:36 +09:00
il a09712c142 refactor(script): update edit_secret.sh to optimize log print logic 2026-05-15 10:12:42 +09:00
il a7e2320b21 chore(script): archive a extract_secret.sh script
archived stack: extract_secret.sh
2026-05-15 09:19:59 +09:00
il 24c83029e9 refactor(playbook): update convention and remove deprecated tag
update notes:
- remove tags 'update', 'upgrade' from convention.yaml
- remove tags 'update' from playbooks/app/site.yaml
2026-05-15 09:04:51 +09:00
il ac64b3c04e docs(readme): add RPO on readme 2026-05-13 17:12:59 +09:00
il 26d696f813 refactor(all): update hardcoded internal domain to ansible variable 2026-05-12 08:08:04 +09:00
il 1096981ef2 feat(paperless): change paperless OCR engine model from tesseract_fast to tesseract_best 2026-05-12 08:00:37 +09:00
il e1936b494d fix(crowdsec): update whitelist.yaml to prevent false positive
false positive:
- nextcloud chunk problem (crowdsecurity/http-crawl-non_statics)
- change expression 'chunks.mjs' to 'chunk.mjs'
2026-05-11 19:40:50 +09:00
il 0afc841b69 chore(chromium): archive a removed stack from console
archived stack: chromium
2026-05-11 19:37:25 +09:00
il a39122eb4b fix(crowdsec): update whitelist.yaml to prevent false positive
false positive:
- nextcloud chunk problem (crowdsecurity/http-crawl-non_statics)
2026-05-11 19:34:22 +09:00
il 0f4da0bb53 feat(backup): add archiving of runtime binary packages 2026-05-11 01:37:15 +09:00
il 1dd1c53e2a feat(backup): add archiving of deployed container images 2026-05-11 00:52:28 +09:00
il 530407c162 refactor(all): update hardcoded timezone 'Asia/Seoul' to ansible variable 'timezone' 2026-05-10 18:44:28 +09:00
il 11ab2f5205 fix(sure): correct task name and subuid variable reference 2026-05-10 14:39:54 +09:00
il 4527e39d0f chore(app): archive removed stacks from app
archived stacks:
- actual-budget
- ezbookkeeping
- opencloud
- trilium
- vikunja
- wikijs
2026-05-10 00:07:51 +09:00
il 02fa912cb1 feat(trilium): release trilium
deployment notes:
- oidc error (users cannot access at once, it needs login twice when using oidc
2026-05-09 22:38:57 +09:00
il aceef4bdaa refactor(authelia): update authelia.yaml.j2 to fix redirect_uris from hardcoded uris to ansible variables 2026-05-09 21:44:11 +09:00
il 64aad4fcf0 docs(all): fix markdown syntax and snippets 2026-05-09 20:54:32 +09:00
il 81244d55a7 feat(wiki.js): release wiki.js
deployment notes:
- use this as personal/family wiki system
- compare to affine / memos and triliumNext
2026-05-09 17:50:05 +09:00
il 1cfd024285 refactor(x509-exporter): update notification to restart x509-exporter when its config.yaml is changed 2026-05-09 17:42:35 +09:00
il 26115c5660 feat(redis): update redis from 8.6.1 to 8.6.3
update notes:
- run 'ansible-playbook playbooks/app/site.yaml --tags "site"' so that update all redis at onece
2026-05-09 13:55:28 +09:00
il acef35ca8b feat(postgresql): update postgresql and vectorchord extension
update notes:
- update postgresql version from 18.2 to 18.3
- update vectorchord version from 0.5.3 to 1.1.1
- add update flow and notice to postgresql.md
2026-05-09 13:54:10 +09:00
il b531170bd7 feat(vaultwardne): update vaultwarden from 1.35.8 to 1.36.0 2026-05-09 12:56:22 +09:00
il ad586c3cd3 feat(grafana): update grafana from 12.3.3 to 13.0.1 2026-05-09 12:50:36 +09:00
il 6dfef08f7b feat(prometheus): update prometheus from v3.9.1 to v3.11.3 2026-05-09 12:44:44 +09:00
il 934dd314a8 feat(x509-exporter): update x509-exporter from 3.21.0 to 4.1.0
update notes:
- '--listen-address' and '--watch-dir' cli flags are deprecated
- add '--config' cli flag and config.yaml
2026-05-09 12:44:05 +09:00
il 2529a918df feat(loki): update loki version from 3.6.5 to 3.7.1 2026-05-09 12:17:16 +09:00
il 7dfa20d3dd feat(ldap): update lldap version from 0.6.2 to 0.6.3 2026-05-09 11:56:19 +09:00
il 329620c7d7 feat(alloy): update alloy version from 1.13.0 to 1.16.1 2026-05-09 11:52:25 +09:00
il f820e89cf6 refactor(roles): update binary application installation flow
update notes:
- keep set_cli_tools responsible only for console CLI tools
- download and install kopia from the kopia role
- download and install blocky from the blocky role
- download and install alloy from the alloy role
- reduce console artifact staging for service binaries
2026-05-09 10:46:29 +09:00
il a05951f883 fix(crowdsec): optimize whitelist expressions
update notes:
- add http_status and http_verb for each expressions (actual budget, immich, opencloud)
- fix crowdsec and issues documents
2026-05-07 10:32:11 +09:00
il b404a9e459 fix(crowdsec): update whitelist.yaml to prevent false positive
false positive:
- nextcloud thumbnail/preview 404 problem (crowdsecurity/http-probing)
2026-05-07 10:27:34 +09:00
il 3b4b56f53f fix(nftables): update fw nftables to allow vpn connection regardless of crowdsec ban 2026-05-07 09:22:49 +09:00
il f697715065 feat(sure): release sure (we-promise/sure)
deployment notes:
- let's try three of budget apps, actual budget, ezbookkeeping, and sure
2026-05-06 18:52:31 +09:00
il be7f215380 feat(ezbookkeeping): release ezbookkeeping
deployment notes:
- use ezbookkeeping for budget
- compare to actual budget
- it has no RBAC and sharing budget, try to sure (we-promise/sure)
2026-05-06 15:56:19 +09:00
il 26e0fe4f8b docs(ADR): update ADR 007 - backup to add checking rule and flows 2026-05-06 14:30:25 +09:00
il 2bb1f015e0 fix(kopia): update the bound home path from %h to ansible variable
update note:
- hotfix
- backups haven't run since commit '9f236b6fa5'
- the root service unit's %h always indicates root's home path
- backup service is verified
2026-05-06 14:06:22 +09:00
il 0f546e13b3 fix(btrfs): update btrfs scrub path
update notes:
- from '{{ node['home_path'] }}/data' to '{{ storage['btrfs']['mount_point'] }}'
2026-05-06 10:33:57 +09:00
il ba8b312bf2 feat(btrfs): update btrfs scrub service and timer on app vm 2026-05-06 08:15:53 +09:00
il 6fcedd9162 feat(collabora): release collabora
deployment note:
- link to nextcloud
- document opening is verified (including korean fonts)
2026-05-05 21:20:31 +09:00
il 6ca4f61d50 docs(nextcloud): update security warning decisions and background job annotation
update notes:
- trusted_proxies warning
- HSTS option warning
- background job mode annotation
2026-05-05 20:09:00 +09:00
il 15c09cb899 docs(nextcloud): update how to disable auto generated contacts from nextcloud account 2026-05-03 12:05:11 +09:00
il 880857a70a fix(crowdsec): update parser 'crowdsecurity/nextcloud-whitelist'
update note:
- deprecate custom whitelist expression
- apply 'crowdsecurity/nextcloud-whitelist' parser
2026-05-03 07:19:59 +09:00
il 70bf539546 docs(issues): fix crowdsec whitelist regex to whitelist expressions 2026-05-02 20:40:10 +09:00
il 5dd38b7e49 fix(crowdsec): update whitelist.yaml to prevent false positive
false positive:
- chunk problems (crowdsecurity/http-crawl-non_statics)
- directory upload 404 problem (crowdsecurity/http-probing)
2026-05-02 20:38:48 +09:00
il 33d94211d1 docs(issues): fix crowdsec command 'cscli decision list' to 'cscli decision delete' 2026-05-02 19:46:51 +09:00
il 278dd3cebe feat(nextcloud): release nextcloud
deployment note:
- use nextcloud for groupware
- consider replacing vikunja and opencloud
2026-05-02 19:22:05 +09:00
il d1dcb1984a feat(vaultwarden): update vaultwarden version from 1.35.4 to 1.35.8 2026-04-30 10:03:33 +09:00
il 37c986177b feat(blocky): update blocky version from 0.28.2 to 0.29.0 2026-04-30 10:01:18 +09:00
il 17326b1b15 feat(step-ca): update step-ca version from 0.29.0 to 0.30.2
update note:
- step-ca container doesn't support $PWDPATH anymore
- add --password-file argument to exec
2026-04-30 09:56:22 +09:00
il 88e1383202 feat(x509-exporter): update x509-exporter version from 3.19.1 to 3.21.0 2026-04-30 09:19:42 +09:00
il c9b4707cb2 refactor(x509-exporter): change handler from enable to restart 2026-04-30 09:18:44 +09:00
315 changed files with 3788 additions and 28601 deletions
+7 -5
View File
@@ -1,8 +1,10 @@
.ansible
data/bin/*
data/volumes/*
data/images/*
docs/archives/textfiles/
docs/notes/*
data/images/containers/*
data/images/seeds/*
data/vmm_init/*
*.raw
*.tar
*.qcow2
*.sql
*.iso
!.gitkeep
-26
View File
@@ -1,26 +0,0 @@
# ilnmors homelab README
This homelab project implements single-node On-premise IaaS system. The homelab contains virtual machines which are divided by their roles, such as private firewall, DNS, PKI, LDAP and database, SSO\(OIDC\). The standard domain is used to implement this system without specific vendors. All components are defined as code and initiated by IaC \(Ansible\) except hypervisor initial configuration.
## RTO times
- Feb/25/2026 - Reprovisioning Hypervisor and vms
- RTO: 1 hour 30 min - verified
- Manual install and set vmm: 20 min
- Create and reprovision fw including services: 15 min
- Create and reprovision infra including services: 20 min
- Create and reprovision auth including services: 10 min
- Create and reprovision app except services: 10 min
- Intermediate tasks (ACME issuance, DNS propagation, etc.): 15 min
- Mar/5/2026 - Reprovisioning Hardware and Hypervisor and vms
- RTO: 2 hour 20 min
- console: 15min - verified
- certificate: 0 min \(When it needs to be created, RTO will be 20 min) - not verified
- wireguard: 0 min \(When it needs to be created, RTO will be 1 min) - not verified
- hypervisor\(+fw\): 45 min - verified
- switch: 1 min - verified
- dsm: 30 min - verified
- kopia: 0 min \(When it needs to be created, RTO will be 10 min) - verified
- Extra vms: 30 min - verified
- Etc: 30 min
+13 -11
View File
@@ -1,27 +1,28 @@
---
# `""` should be used for every string values
# except name, boolean, varible(environment) name, number (only for decimal)
# String values need `""`
# Task names, boolean values, environment names, decimal numbers don't need `""`
- name: Convention task
delegate_to: "host"
delegate_facts: true
environment:
env: "environment"
env: "value"
ansible.builtin.file:
# Identifier: name:, src, dest, url
path: "/path/of/example"
# State
# Identifier: name, src, dest, url, etc.
path: "/example/path"
# state parameters
state: "directory"
owner: "root"
group: "root"
mode: "0640"
# optional data
# optional parameters
recurse: true
loop:
- "list"
loop_control:
label: "{{ item }}"
become: true
# become_user: "root"
# default become user is root
become_user: "user"
when: condition.stat.exists
changed_when: condition.rc != 0
failed_when: condition.rc == 0
@@ -30,10 +31,11 @@
listen: "notification_example"
no_log: true
run_once: true
# Ensure execution even if it fails (it prints errors on the screen, but it ignores them)
ignore_errors: true
tags:
- "always"
- "init"
- "upgrade"
- "update"
- "site"
- "[service_name]"
# when: "'tags' is not in ansible_run_tags"
+64 -49
View File
@@ -1,5 +1,6 @@
---
# Global vars
timezone: "Asia/Seoul"
ansible_ssh_private_key_file: "/etc/secrets/{{ hostvars['console']['node']['uid'] }}/id_console"
# CA
@@ -7,8 +8,7 @@ root_cert_filename: "ilnmors_root_ca.crt"
intermediate_cert_filename: "ilnmors_intermediate_ca.crt"
intermediate_key_filename: "ilnmors_intermediate_ca.key"
# local SAN and SSH SAN should be updated manually on host_vars
# Domains
domain:
public: "ilnmors.com"
internal: "ilnmors.internal"
@@ -97,7 +97,7 @@ services:
public: "gitea"
internal: "gitea.app"
ports:
http: "3000"
http: "3001"
subuid: "100999"
immich:
domain:
@@ -109,13 +109,6 @@ services:
immich-ml:
ports:
http: "3003"
actualbudget:
domain:
public: "budget"
internal: "budget.app"
ports:
http: "5006"
subuid: "101000"
paperless:
domain:
public: "paperless"
@@ -124,63 +117,85 @@ services:
http: "8001"
redis: "6380"
subuid: "100999"
vikunja:
nextcloud:
domain:
public: "vikunja"
internal: "vikunja.app"
public: "nextcloud"
internal: "nextcloud.app"
ports:
http: "3456"
http: "8002"
redis: "6382"
subuid: "100032"
collabora:
domain:
public: "collabora"
internal: "collabora.app"
ports:
http: "9980"
subuid: "101000"
sure:
domain:
public: "sure"
internal: "sure.app"
ports:
http: "3002"
redis: "6383"
subuid: "100999"
opencloud:
outline:
domain:
public: "opencloud"
internal: "opencloud.app"
public: "outline"
internal: "outline.app"
ports:
http: "9200"
subuid: "100999"
manticore:
subuid: "100998"
affine:
http: "3004"
redis: "6384"
subuid: "101000"
memos:
domain:
public: "affine"
internal: "affine.app"
public: "memos"
internal: "memos.app"
ports:
http: "3010"
redis: "6381"
manticore: "9308"
http: "3005"
subuid: "110000"
mealie:
domain:
public: "mealie"
internal: "mealie.app"
ports:
http: "9001"
subuid: "100910"
version:
packages:
sops: "3.12.1"
step: "0.29.0"
kopia: "0.22.3"
blocky: "0.28.2"
alloy: "1.13.0"
sops: "3.13.1"
step: "0.30.2"
kopia: "0.23.0"
blocky: "0.29.0"
alloy: "1.16.1"
containers:
# common
caddy: "2.11.2"
caddy: "2.11.4"
# infra
step: "0.29.0"
ldap: "v0.6.2"
x509-exporter: "3.19.1"
prometheus: "v3.9.1"
loki: "3.6.5"
grafana: "12.3.3"
step: "0.30.2"
ldap: "v0.6.3"
x509-exporter: "4.1.0"
prometheus: "v3.12.0"
loki: "3.7.1"
grafana: "13.0.1"
## Postgresql
postgresql: "18.2"
postgresql: "18.4"
# For immich - https://github.com/immich-app/base-images/blob/main/postgres/versions.yaml
# pgvector: "v0.8.1"
vectorchord: "0.5.3"
vectorchord: "1.1.1"
# Auth
authelia: "4.39.19"
authelia: "4.39.20"
# App
vaultwarden: "1.35.4"
vaultwarden: "1.36.0"
gitea: "1.26.1"
redis: "8.6.1"
redis: "8.8.0"
immich: "v2.7.5"
actualbudget: "26.3.0"
paperless: "2.20.15"
vikunja: "2.2.2"
opencloud: "4.0.6"
manticore: "25.0.0"
affine: "0.26.3"
nextcloud: "33.0.5"
collabora: "25.04.10.3.1"
sure: "0.7.1"
outline: "1.8.1"
memos: "0.29.1"
mealie: "v3.19.2"
+28 -2
View File
@@ -1,7 +1,33 @@
---
node:
name: "vmm"
group: "svadmins"
uid: 2000
home_path: "/home/vmm"
ssh_san: "vmm,vmm_init,vmm.ilnmors.internal,init.vmm.ilnmors.internal"
local_san: "localhost vmm.ilnmors.internal"
libvirt_path: "/var/lib/libvirt"
ssh_san: "{{ node['name'] }},{{ node['name'] }}_init,{{ node['name'] }}.{{ domain['internal'] }},init.{{ node['name'] }}.{{ domain['internal'] }}"
local_san: "localhost {{ node['name'] }}.{{ domain['internal'] }}"
hardware:
mac:
nic0: "c8:ff:bf:07:02:34"
nic1: "c8:ff:bf:07:02:33"
sfpp0: "c8:ff:bf:07:02:31"
sfpp1: "c8:ff:bf:07:02:32"
igpu:
id: "8086:4628"
address: "0000:00:02.0"
domain: "0x0000"
bus: "0x00"
slot: "0x02"
function: "0x0"
hdd:
data:
hdd0: "WMC6N0E617S8"
hdd1: "P6HVTL0W"
hdd2: "P2GH354H"
hdd3: "P6GJKSMP"
btrfs:
label: "DATA"
level: "raid10"
mount_point: "{{ node['libvirt_path'] }}/data"
+15 -16
View File
@@ -2,17 +2,29 @@
# Node Factors
node:
name: "app"
group: "svadmins"
uid: 2004
home_path: "/home/app"
ssh_san: "app,app.ilnmors.internal"
local_san: "localhost app.ilnmors.internal"
ssh_san: "{{ node['name'] }},{{ node['name'] }}.{{ domain['internal'] }}"
local_san: "localhost {{ node['name'] }}.{{ domain['internal'] }}"
# VM Factors
vm:
name: "app"
cpu: 4
cpu: 6
cpu_pin: |
<vcpupin vcpu='0' cpuset='0'/>
<vcpupin vcpu='1' cpuset='1'/>
<vcpupin vcpu='2' cpuset='2'/>
<vcpupin vcpu='3' cpuset='3'/>
<vcpupin vcpu='4' cpuset='10'/>
<vcpupin vcpu='5' cpuset='11'/>
<emulatorpin cpuset='10-11'/>
shares: 1024
memory: 16
storage: 256
data_storage:
name: "vdb"
size: 3.5
lan_mac: "0a:49:6e:4d:03:00"
lan_net: "lan-net"
lan_group: "vlan10-access"
@@ -26,16 +38,3 @@ vm:
bus: "0x00"
slot: "0x02"
function: "0x0"
sata_controller: # Additional SATA Controller
address: "0000:04:00.0"
domain: "0x0000"
bus: "0x04"
slot: "0x00"
function: "0x0"
# BTRFS configuration for hdd which is passthroughed
storage:
btrfs:
label: "APP_DATA"
level: "raid10"
mount_point: "/home/app/data"
+8 -3
View File
@@ -2,15 +2,20 @@
# Node Factors
node:
name: "auth"
group: "svadmins"
uid: 2003
home_path: "/home/auth"
ssh_san: "auth,auth.ilnmors.internal"
local_san: "localhost auth.ilnmors.internal"
ssh_san: "{{ node['name'] }},{{ node['name'] }}.{{ domain['internal'] }}"
local_san: "localhost {{ node['name'] }}.{{ domain['internal'] }}"
# VM Factors
vm:
name: "auth"
cpu: 2
shares: 512
cpu_pin: |
<vcpupin vcpu='0' cpuset='8'/>
<vcpupin vcpu='1' cpuset='9'/>
<emulatorpin cpuset='8-9'/>
shares: 1024
memory: 2
storage: 64
lan_mac: "0a:49:6e:4d:02:00"
+8 -8
View File
@@ -10,17 +10,17 @@ age_key: !vault |
33653638373537323363316363646534323362353836373665636265663939353862663532313230
30643038313138626464626161373835646665326334393834616234643931656536343130316238
61656264643830616639
# Node Factors
node:
name: "console"
group: "svadmins"
uid: 2999
home_path: "/home/console"
workspace_path: "{{ node.home_path }}/workspace"
homelab_path: "{{ node.home_path }}/workspace/homelab"
data_path: "{{ node.homelab_path }}/data"
config_path: "{{ node.homelab_path }}/config"
ssh_san: "console,console.ilnmors.internal"
workspace_path: "{{ node['home_path'] }}/workspace"
homelab_path: "{{ node['home_path'] }}/workspace/homelab"
data_path: "{{ node['homelab_path'] }}/data"
config_path: "{{ node['homelab_path'] }}/config"
ssh_san: "{{ node['name'] }},{{ node['name'] }}.{{ domain['internal'] }}"
ssh_users: "vmm,fw,infra,auth,app"
# add the hostname of wsl, it is needed to improve the sudo problem
local_san: "localhost console.ilnmors.internal surface"
# ansible_python_interpreter: "{{ ansible_playbook_python }}"
local_san: "localhost {{ node['name'] }} {{ node['name'] }}.{{ domain['internal'] }}"
+11 -4
View File
@@ -2,15 +2,22 @@
# Node Factors
node:
name: "fw"
group: "svadmins"
uid: 2001
home_path: "/home/fw"
ssh_san: "fw,fw.ilnmors.internal"
local_san: "localhost fw.ilnmors.internal"
ssh_san: "{{ node['name'] }},{{ node['name'] }}.{{ domain['internal'] }}"
local_san: "localhost {{ node['name'] }}.{{ domain['internal'] }}"
# VM Factors
vm:
name: "fw"
cpu: 2
cpu: 4
cpu_pin: |
<vcpupin vcpu='0' cpuset='0'/>
<vcpupin vcpu='1' cpuset='1'/>
<vcpupin vcpu='2' cpuset='4'/>
<vcpupin vcpu='3' cpuset='5'/>
<emulatorpin cpuset='4-5'/>
shares: 2048
memory: 4
storage: 64
@@ -21,7 +28,7 @@ vm:
lan_group: "vlan-trunk"
# Network Factors
# LLA is like MAC address for L3 (Network layer). Usually, subnet is used to seperate network.
# LLA is like MAC address for L3 (Network layer). Usually, subnet is used to separate network.
network4:
subnet:
client: "192.168.1.0/24"
+11 -4
View File
@@ -2,16 +2,23 @@
# Node Factors
node:
name: "infra"
group: "svadmins"
uid: 2002
home_path: "/home/infra"
ssh_san: "infra,infra.ilnmors.internal"
local_san: "localhost infra.ilnmors.internal"
ssh_san: "{{ node['name'] }},{{ node['name'] }}.{{ domain['internal'] }}"
local_san: "localhost {{ node['name'] }}.{{ domain['internal'] }}"
# VM Factors
vm:
name: "infra"
cpu: 2
shares: 1024
cpu: 4
cpu_pin: |
<vcpupin vcpu='0' cpuset='2'/>
<vcpupin vcpu='1' cpuset='3'/>
<vcpupin vcpu='2' cpuset='6'/>
<vcpupin vcpu='3' cpuset='7'/>
<emulatorpin cpuset='6-7'/>
shares: 2048
memory: 6
storage: 256
lan_mac: "0a:49:6e:4d:01:00"
+1 -1
View File
@@ -11,4 +11,4 @@ vmm ansible_host=vmm.ilnmors.internal ansible_user=vmm
fw ansible_host=fw.ilnmors.internal ansible_user=fw
infra ansible_host=infra.ilnmors.internal ansible_user=infra
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
+42 -26
View File
@@ -20,12 +20,13 @@
- name: Set become password
ansible.builtin.set_fact:
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['app'] }}"
no_log: true
tags: ["always"]
tasks:
- name: Set timezone to Asia/Seoul
- name: Set timezone
community.general.timezone:
name: Asia/Seoul
name: "{{ timezone }}"
become: true
tags: ["init", "timezone"]
@@ -97,10 +98,10 @@
become: true
tags: ["init", "install-packages"]
- name: Set raid
- name: Set data volume
ansible.builtin.include_role:
name: "app"
tasks_from: "node/set_raid"
tasks_from: "node/set_data_volume"
apply:
tags: ["init", "raid"]
tags: ["init", "raid"]
@@ -142,8 +143,8 @@
name: "common"
tasks_from: "services/set_alloy"
apply:
tags: ["init", "update", "alloy"]
tags: ["init", "update", "alloy"]
tags: ["init", "alloy"]
tags: ["init", "alloy"]
- name: Set kopia
ansible.builtin.include_role:
@@ -185,14 +186,6 @@
tags: ["site", "immich"]
tags: ["site", "immich"]
- name: Set actual budget
ansible.builtin.include_role:
name: "app"
tasks_from: "services/set_actual-budget"
apply:
tags: ["site", "actual-budget"]
tags: ["site", "actual-budget"]
- name: Set paperless
ansible.builtin.include_role:
name: "app"
@@ -201,30 +194,53 @@
tags: ["site", "paperless"]
tags: ["site", "paperless"]
- name: Set vikunja
- name: Set nextcloud
ansible.builtin.include_role:
name: "app"
tasks_from: "services/set_vikunja"
tasks_from: "services/set_nextcloud"
apply:
tags: ["site", "vikunja"]
tags: ["site", "vikunja"]
tags: ["site", "nextcloud"]
tags: ["site", "nextcloud"]
- name: Set opencloud
- name: Set collabora
ansible.builtin.include_role:
name: "app"
tasks_from: "services/set_opencloud"
tasks_from: "services/set_collabora"
apply:
tags: ["site", "opencloud"]
tags: ["site", "opencloud"]
tags: ["site", "collabora"]
tags: ["site", "collabora"]
- name: Set affine
- name: Set sure
ansible.builtin.include_role:
name: "app"
tasks_from: "services/set_affine"
tasks_from: "services/set_sure"
apply:
tags: ["site", "affine"]
tags: ["site", "affine"]
tags: ["site", "sure"]
tags: ["site", "sure"]
- name: Set outline
ansible.builtin.include_role:
name: "app"
tasks_from: "services/set_outline"
apply:
tags: ["site", "outline"]
tags: ["site", "outline"]
- name: Set memos
ansible.builtin.include_role:
name: "app"
tasks_from: "services/set_memos"
apply:
tags: ["site", "memos"]
tags: ["site", "memos"]
- name: Set mealie
ansible.builtin.include_role:
name: "app"
tasks_from: "services/set_mealie"
apply:
tags: ["site", "mealie"]
tags: ["site", "mealie"]
- name: Flush handlers right now
ansible.builtin.meta: "flush_handlers"
+3 -2
View File
@@ -20,12 +20,13 @@
- name: Set become password
ansible.builtin.set_fact:
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['auth'] }}"
no_log: true
tags: ["always"]
tasks:
- name: Set timezone to Asia/Seoul
- name: Set timezone
community.general.timezone:
name: Asia/Seoul
name: "{{ timezone }}"
become: true
tags: ["init", "timezone"]
+28 -30
View File
@@ -20,13 +20,14 @@
- name: Set become password
ansible.builtin.set_fact:
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['console'] }}"
no_log: true
tags: ["always"]
tasks:
# init
- name: Set timezone to Asia/Seoul
- name: Set timezone
community.general.timezone:
name: Asia/Seoul
name: "{{ timezone }}"
become: true
tags: ["init", "timezone"]
@@ -70,32 +71,6 @@
tags: ["init", "ssh_client"]
tags: ["init", "ssh_client"]
- name: Check file permissions
ansible.builtin.file:
path: "{{ node['workspace_path'] }}/{{ item }}"
state: "directory"
owner: "{{ ansible_user }}"
group: "svadmins"
mode: "u=rwX,g=,o="
recurse: true
loop:
- "homelab/ansible"
- "homelab/config"
- "homelab/docs"
- "university"
tags: ["init", "site", "file_permission"]
# kopia snashot is mounted on homelab/data/volumes.
# NEVER CHANGE permission and owners
- name: Download vm cloud-init
ansible.builtin.get_url:
url: "https://cdimage.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2"
dest: "{{ node['data_path'] }}/images/debian-13-generic-amd64.qcow2"
owner: "console"
group: "svadmins"
mode: "0600"
tags: ["init", "site", "cloud-init-image"]
- name: Install packages
ansible.builtin.apt:
name:
@@ -108,8 +83,6 @@
- "logrotate"
- "nftables"
- "build-essential"
- "g++"
- "gcc"
- "fuse3"
state: "present"
become: true
@@ -122,3 +95,28 @@
apply:
tags: ["init", "site", "tools"]
tags: ["init", "site", "tools"]
- name: Set vmm_init config
ansible.builtin.include_role:
name: "console"
tasks_from: "node/create_vmm_init"
apply:
tags: ["site", "vmm_init"]
tags: ["site", "vmm_init"]
- name: Download vm cloud-init
ansible.builtin.get_url:
url: "https://cdimage.debian.org/images/cloud/trixie/latest/debian-13-generic-amd64.qcow2"
dest: "{{ node['data_path'] }}/images/debian-13-generic-amd64.qcow2"
owner: "console"
group: "svadmins"
mode: "0600"
tags: ["init", "site", "cloud-init-image"]
- name: Set kopia
ansible.builtin.include_role:
name: "common"
tasks_from: "services/set_kopia"
apply:
tags: ["init", "site", "kopia"]
tags: ["init", "site", "kopia"]
+5 -4
View File
@@ -20,12 +20,13 @@
- name: Set become password
ansible.builtin.set_fact:
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['fw'] }}"
no_log: true
tags: ["always"]
tasks:
- name: Set timezone to Asia/Seoul
- name: Set timezone
community.general.timezone:
name: Asia/Seoul
name: "{{ timezone }}"
become: true
tags: ["init", "timezone"]
@@ -162,8 +163,8 @@
name: "fw"
tasks_from: "services/set_bind"
apply:
tags: ["init", "update", "bind"]
tags: ["init", "update", "bind"]
tags: ["init", "bind"]
tags: ["init", "bind"]
- name: Set blocky
ansible.builtin.include_role:
+3 -2
View File
@@ -20,12 +20,13 @@
- name: Set become password
ansible.builtin.set_fact:
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['infra'] }}"
no_log: true
tags: ["always"]
tasks:
- name: Set timezone to Asia/Seoul
- name: Set timezone
community.general.timezone:
name: Asia/Seoul
name: "{{ timezone }}"
become: true
tags: ["init", "timezone"]
+1
View File
@@ -36,6 +36,7 @@
- name: Set become password
ansible.builtin.set_fact:
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['vmm'] }}"
no_log: true
- name: Create seed file
ansible.builtin.include_role:
+12 -2
View File
@@ -27,12 +27,13 @@
- name: Set become password
ansible.builtin.set_fact:
ansible_become_pass: "{{ hostvars['console']['sudo']['password']['vmm'] }}"
no_log: true
tags: ["always"]
tasks:
# init
- name: Set timezone to Asia/Seoul
- name: Set timezone
community.general.timezone:
name: Asia/Seoul
name: "{{ timezone }}"
become: true
tags: ["init", "timezone"]
@@ -100,6 +101,14 @@
tags: ["init", "linger"]
tags: ["init", "linger"]
- name: Set raid
ansible.builtin.include_role:
name: "vmm"
tasks_from: "node/set_raid"
apply:
tags: ["init", "raid"]
tags: ["init", "raid"]
- name: Set libvirt
ansible.builtin.include_role:
name: "vmm"
@@ -155,6 +164,7 @@
- ksmtuned
- libvirt-daemon-system
- virt-top
- btrfs-progs
- python3
- python3-apt
- python3-libvirt
+50 -25
View File
@@ -43,17 +43,6 @@
listen: "notification_restart_immich-ml"
ignore_errors: true # noqa: ignore-errors
- name: Restart actual-budget
ansible.builtin.systemd:
name: "actual-budget.service"
state: "restarted"
enabled: true
scope: "user"
daemon_reload: true
changed_when: false
listen: "notification_restart_actual-budget"
ignore_errors: true # noqa: ignore-errors
- name: Restart paperless
ansible.builtin.systemd:
name: "paperless.service"
@@ -65,37 +54,73 @@
listen: "notification_restart_paperless"
ignore_errors: true # noqa: ignore-errors
- name: Restart vikunja
- name: Restart nextcloud
ansible.builtin.systemd:
name: "vikunja.service"
name: "nextcloud.service"
state: "restarted"
enabled: true
scope: "user"
daemon_reload: true
scope: "user"
when: is_nextcloud_init.stat.exists
changed_when: false
listen: "notification_restart_vikunja"
listen: "notification_restart_nextcloud"
ignore_errors: true # noqa: ignore-errors
- name: Restart opencloud
- name: Restart collabora
ansible.builtin.systemd:
name: "opencloud.service"
name: "collabora.service"
state: "restarted"
enabled: true
daemon_reload: true
scope: "user"
when: is_opencloud_init.stat.exists
daemon_reload: true
changed_when: false
listen: "notification_restart_opencloud"
listen: "notification_restart_collabora"
ignore_errors: true # noqa: ignore-errors
- name: Restart affine
- name: Restart sure
ansible.builtin.systemd:
name: "affine.service"
name: "{{ item }}"
state: "restarted"
enabled: true
daemon_reload: true
scope: "user"
when: is_affine_init.stat.exists
daemon_reload: true
loop:
- "sure-web.service"
- "sure-worker.service"
changed_when: false
listen: "notification_restart_affine"
listen: "notification_restart_sure"
ignore_errors: true # noqa: ignore-errors
- name: Restart outline
ansible.builtin.systemd:
name: "outline.service"
state: "restarted"
enabled: true
scope: "user"
daemon_reload: true
when: is_outline_init.stat.exists
changed_when: false
listen: "notification_restart_outline"
ignore_errors: true # noqa: ignore-errors
- name: Restart memos
ansible.builtin.systemd:
name: "memos.service"
state: "restarted"
enabled: true
scope: "user"
daemon_reload: true
changed_when: false
listen: "notification_restart_memos"
ignore_errors: true # noqa: ignore-errors
- name: Restart mealie
ansible.builtin.systemd:
name: "mealie.service"
state: "restarted"
enabled: true
scope: "user"
daemon_reload: true
changed_when: false
listen: "notification_restart_mealie"
ignore_errors: true # noqa: ignore-errors
@@ -0,0 +1,41 @@
---
- name: Check app data volume filesystem already exists
ansible.builtin.command:
cmd: "blkid /dev/{{ vm['data_storage']['name'] }}"
register: is_app_data
changed_when: false
failed_when: false
become: true
- name: Create ext4 filesystem on app data raw
ansible.builtin.command:
cmd: "mkfs.ext4 -F /dev/{{ vm['data_storage']['name'] }}"
when: is_app_data.rc != 0
changed_when: true
become: true
- name: Set data volume path
ansible.builtin.file:
path: "{{ node['home_path'] }}/data"
state: "directory"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0770"
- name: Mount app data volume
ansible.posix.mount:
path: "{{ node['home_path'] }}/data"
src: "/dev/{{ vm['data_storage']['name'] }}"
opts: "noatime"
state: "mounted"
fstype: "ext4"
become: true
- name: Set app data volume path permissions
ansible.builtin.file:
path: "{{ node['home_path'] }}/data"
state: "directory"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0770"
become: true
@@ -1,70 +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-path/*{{ vm['pass_through']['sata_controller']['address'] }}* | \
grep -v '\.0$' | \
sort
changed_when: false
register: "hdd_path_list"
- name: Check app_hdd filesystem already exists
ansible.builtin.command: |
blkid -L {{ storage['btrfs']['label'] }}
register: is_app_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 {{ storage['btrfs']['label'] }} \
-d {{ storage['btrfs']['level'] }} \
-m {{ storage['btrfs']['level'] }} \
{{ hdd_path_list.stdout_lines | join(' ') }}
become: true
when:
- is_app_data.rc != 0
- (hdd_path_list.stdout_lines | length) >= 4
changed_when: is_mkfs.rc == 0
register: "is_mkfs"
- name: Mount btrfs raid10 volume
ansible.posix.mount:
path: "{{ storage['btrfs']['mount_point'] }}"
src: "LABEL={{ storage['btrfs']['label'] }}"
state: "mounted"
fstype: "btrfs"
opts: "defaults,noatime,compress=zstd:3,autodefrag,degraded,nofail"
become: true
- name: Set hard disk path permissions
ansible.builtin.file:
path: "{{ storage['btrfs']['mount_point'] }}"
state: "directory"
owner: "{{ ansible_user }}"
group: "svadmins"
mode: "0770"
become: true
@@ -0,0 +1,37 @@
---
- name: Deploy container file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/collabora/collabora.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/collabora.container"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_collabora"
- name: Enable collabora.service
ansible.builtin.systemd:
name: "collabora.service"
state: "started"
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/docker.io_collabora_code_{{ version['containers']['collabora'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "docker.io/collabora/code:{{ version['containers']['collabora'] }}"
dest: "{{ node['home_path'] }}/archives/containers/docker.io_collabora_code_{{ version['containers']['collabora'] }}.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/docker.io_collabora_code_{{ version['containers']['collabora'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -4,7 +4,7 @@
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['gitea']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "data/containers/gitea"
@@ -18,7 +18,7 @@
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/gitea/ssl/{{ root_cert_filename }}"
owner: "{{ services['gitea']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0440"
become: true
notify: "notification_restart_gitea"
@@ -38,7 +38,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/gitea/gitea.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/gitea.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_gitea"
@@ -49,3 +49,23 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/docker.io_gitea_gitea_{{ version['containers']['gitea'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "docker.io/gitea/gitea:{{ version['containers']['gitea'] }}"
dest: "{{ node['home_path'] }}/archives/containers/docker.io_gitea_gitea_{{ version['containers']['gitea'] }}.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/docker.io_gitea_gitea_{{ version['containers']['gitea'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -8,7 +8,7 @@
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['redis']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "containers/redis"
@@ -21,7 +21,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.conf.j2"
dest: "{{ node['home_path'] }}/containers/redis/{{ redis_service }}/redis.conf"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
register: "is_redis_conf"
@@ -30,7 +30,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/redis_{{ redis_service }}.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
register: "is_redis_containerfile"
@@ -56,7 +56,7 @@
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "data/containers/immich"
@@ -71,7 +71,7 @@
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/immich/ssl/{{ root_cert_filename }}"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0440"
notify: "notification_restart_immich"
no_log: true
@@ -90,7 +90,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/immich/immich.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/immich.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_immich"
@@ -99,7 +99,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/immich/immich-ml.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/immich-ml.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_immich-ml"
@@ -118,3 +118,38 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
loop:
- image: "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"
file: "ghcr.io_immich-app_immich-machine-learning_{{ version['containers']['immich'] }}-openvino"
- image: "ghcr.io/immich-app/immich-server:{{ version['containers']['immich'] }}"
file: "ghcr.io_immich-app_immich-server_{{ version['containers']['immich'] }}"
loop_control:
label: "{{ item.file }}"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "{{ item.item.image }}"
dest: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
format: "oci-archive"
force: false
loop: "{{ container_archive_images.results }}"
loop_control:
label: "{{ item.item.file }}"
when: not item.stat.exists
- name: Fetch container archive images
ansible.builtin.fetch:
src: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
loop: "{{ container_archive_images.results }}"
loop_control:
label: "{{ item.item.file }}"
@@ -0,0 +1,77 @@
---
- name: Create mealie directory
ansible.builtin.file:
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['mealie']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "data/containers/mealie"
- "data/containers/mealie/data"
- "containers/mealie"
- "containers/mealie/ssl"
become: true
- name: Deploy root certificate
ansible.builtin.copy:
content: |
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/mealie/ssl/{{ root_cert_filename }}"
owner: "{{ services['mealie']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0440"
become: true
notify: "notification_restart_mealie"
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: "MEALIE_POSTGRES_PASSWORD"
value: "{{ hostvars['console']['postgresql']['password']['mealie'] }}"
- name: "MEALIE_OIDC_CLIENT_SECRET"
value: "{{ hostvars['console']['mealie']['oidc']['secret'] }}"
notify: "notification_restart_mealie"
no_log: true
- name: Deploy mealie.container file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/mealie/mealie.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/mealie.container"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_mealie"
- name: Enable mealie.service
ansible.builtin.systemd:
name: "mealie.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_mealie-recipes_mealie_{{ version['containers']['mealie'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "ghcr.io/mealie-recipes/mealie:{{ version['containers']['mealie'] }}"
dest: "{{ node['home_path'] }}/archives/containers/ghcr.io_mealie-recipes_mealie_{{ version['containers']['mealie'] }}.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_mealie-recipes_mealie_{{ version['containers']['mealie'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -0,0 +1,74 @@
---
- name: Create memos directory
ansible.builtin.file:
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['memos']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "data/containers/memos"
- "data/containers/memos/data"
- "containers/memos"
- "containers/memos/ssl"
become: true
- name: Deploy root certificate
ansible.builtin.copy:
content: |
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/memos/ssl/{{ root_cert_filename }}"
owner: "{{ services['memos']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0440"
become: true
notify: "notification_restart_memos"
no_log: true
- name: Register secret value to podman secret
containers.podman.podman_secret:
name: "MEMOS_DSN"
data: "postgresql://memos:{{ hostvars['console']['postgresql']['password']['memos'] | urlencode | replace('/', '%2F') }}\
@{{ services['postgresql']['domain'] }}.{{ domain['internal'] }}/memos_db?sslmode=verify-full&\
sslrootcert=/etc/ssl/memos/{{ root_cert_filename }}"
state: "present"
force: true
no_log: true
notify: "notification_restart_memos"
- name: Deploy memos.container file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/memos/memos.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/memos.container"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_memos"
- name: Enable memos.service
ansible.builtin.systemd:
name: "memos.service"
state: "started"
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/docker.io_neosmemo_memos_{{ version['containers']['memos'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "docker.io/neosmemo/memos:{{ version['containers']['memos'] }}"
dest: "{{ node['home_path'] }}/archives/containers/docker.io_neosmemo_memos_{{ version['containers']['memos'] }}.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/docker.io_neosmemo_memos_{{ version['containers']['memos'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -0,0 +1,209 @@
---
- name: Set redis service name
ansible.builtin.set_fact:
redis_service: "nextcloud"
- name: Create redis_nextcloud directory
ansible.builtin.file:
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['redis']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "containers/redis"
- "containers/redis/{{ redis_service }}"
- "containers/redis/{{ redis_service }}/data"
become: true
- name: Deploy redis config file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.conf.j2"
dest: "{{ node['home_path'] }}/containers/redis/{{ redis_service }}/redis.conf"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
register: "is_redis_conf"
- name: Deploy redis container file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/redis_{{ redis_service }}.container"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
register: "is_redis_containerfile"
- name: Enable (Restart) redis service
ansible.builtin.systemd:
name: "redis_{{ redis_service }}.service"
state: "restarted"
enabled: true
daemon_reload: true
scope: "user"
when: is_redis_conf.changed or is_redis_containerfile.changed # noqa: no-handler
- name: Create nextcloud directory
ansible.builtin.file:
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['nextcloud']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "data/containers/nextcloud"
- "data/containers/nextcloud/html"
- "containers/nextcloud"
- "containers/nextcloud/ssl"
- "containers/nextcloud/ini"
become: true
- name: Check data directory empty
ansible.builtin.stat:
path: "{{ node['home_path'] }}/data/containers/nextcloud/.init"
register: "is_nextcloud_init"
- name: Deploy root certificate
ansible.builtin.copy:
content: |
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/nextcloud/ssl/{{ root_cert_filename }}"
owner: "{{ services['nextcloud']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0440"
become: true
notify: "notification_restart_nextcloud"
no_log: true
- name: Initialize nextcloud
when: not is_nextcloud_init.stat.exists
block:
- name: Execute init command (Including pulling image)
containers.podman.podman_container:
name: "nextcloud_init"
image: "docker.io/library/nextcloud:{{ version['containers']['nextcloud'] }}"
command: "/bin/true"
state: "started"
rm: true
detach: false
env:
NEXTCLOUD_UPDATE: "1"
NEXTCLOUD_ADMIN_USER: "{{ hostvars['console']['nextcloud']['admin']['id'] }}"
NEXTCLOUD_ADMIN_PASSWORD: "{{ hostvars['console']['nextcloud']['admin']['password'] }}"
POSTGRES_HOST: "{{ services['postgresql']['domain'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }}"
POSTGRES_DB: "nextcloud_db"
POSTGRES_USER: "nextcloud"
POSTGRES_PASSWORD: "{{ hostvars['console']['postgresql']['password']['nextcloud'] }}"
PGSSLMODE: "verify-full"
PGSSLROOTCERT: "/etc/ssl/nextcloud/{{ root_cert_filename }}"
PGSSLCERTMODE: "disable"
REDIS_HOST: "host.containers.internal"
REDIS_HOST_PORT: "{{ services['nextcloud']['ports']['redis'] }}"
volume:
- "{{ node['home_path'] }}/containers/nextcloud/ssl:/etc/ssl/nextcloud:ro"
- "{{ node['home_path'] }}/data/containers/nextcloud/html:/var/www/html:rw"
no_log: true
- name: Create .init file
ansible.builtin.file:
path: "{{ node['home_path'] }}/data/containers/nextcloud/.init"
state: "touch"
mode: "0644"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
- name: Deploy config files
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/nextcloud/config/{{ item }}.j2"
dest: "{{ node['home_path'] }}/data/containers/nextcloud/html/config/{{ item }}"
owner: "{{ services['nextcloud']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0640"
loop:
- "background.config.php"
- "cache.config.php"
- "domain.config.php"
- "local_remote.config.php"
- "user_oidc.config.php"
become: true
notify: "notification_restart_nextcloud"
- name: Deploy opcache.ini file
ansible.builtin.copy:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/nextcloud/ini/{{ item }}"
dest: "{{ node['home_path'] }}/containers/nextcloud/ini/{{ item }}"
group: "{{ node['group'] }}"
mode: "0644"
loop:
- "opcache.ini"
- "upload.ini"
notify: "notification_restart_nextcloud"
- name: Deploy nextcloud.container file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/nextcloud/nextcloud.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/nextcloud.container"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_nextcloud"
- name: Deploy nextcloud-cron service
ansible.builtin.copy:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/nextcloud/systemd/{{ item }}"
dest: "{{ node['home_path'] }}/.config/systemd/user/{{ item }}"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
loop:
- "nextcloud-cron.service"
- "nextcloud-cron.timer"
- name: Enable nextcloud.service
ansible.builtin.systemd:
name: "nextcloud.service"
state: "started"
enabled: true
daemon_reload: true
scope: "user"
- name: Enable nextcloud-cron.timer
ansible.builtin.systemd:
name: "nextcloud-cron.timer"
state: "started"
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
loop:
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
- image: "docker.io/library/nextcloud:{{ version['containers']['nextcloud'] }}"
file: "docker.io_library_nextcloud_{{ version['containers']['nextcloud'] }}"
loop_control:
label: "{{ item.file }}"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "{{ item.item.image }}"
dest: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
format: "oci-archive"
force: false
loop: "{{ container_archive_images.results }}"
loop_control:
label: "{{ item.item.file }}"
when: not item.stat.exists
- name: Fetch container archive images
ansible.builtin.fetch:
src: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
loop: "{{ container_archive_images.results }}"
loop_control:
label: "{{ item.item.file }}"
@@ -0,0 +1,152 @@
---
- name: Set redis service name
ansible.builtin.set_fact:
redis_service: "outline"
- name: Create redis_outline directory
ansible.builtin.file:
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['redis']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "containers/redis"
- "containers/redis/{{ redis_service }}"
- "containers/redis/{{ redis_service }}/data"
become: true
- name: Deploy redis config file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.conf.j2"
dest: "{{ node['home_path'] }}/containers/redis/{{ redis_service }}/redis.conf"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
register: "is_redis_conf"
- name: Deploy redis container file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/redis_{{ redis_service }}.container"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
register: "is_redis_containerfile"
- name: Enable (Restart) redis service
ansible.builtin.systemd:
name: "redis_{{ redis_service }}.service"
state: "restarted"
enabled: true
daemon_reload: true
scope: "user"
when: is_redis_conf.changed or is_redis_containerfile.changed # noqa: no-handler
- name: Create outline directory
ansible.builtin.file:
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['outline']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "data/containers/outline"
- "data/containers/outline/data"
- "containers/outline"
- "containers/outline/ssl"
become: true
- name: Check data directory empty
ansible.builtin.stat:
path: "{{ node['home_path'] }}/data/containers/outline/.init"
register: "is_outline_init"
- name: Create .init file
ansible.builtin.file:
path: "{{ node['home_path'] }}/data/containers/outline/.init"
state: "touch"
mode: "0644"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
when: not is_outline_init.stat.exists
- name: Deploy root certificate
ansible.builtin.copy:
content: |
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/outline/ssl/{{ root_cert_filename }}"
owner: "{{ services['outline']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0440"
become: true
notify: "notification_restart_outline"
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: "OUTLINE_SECRET_KEY"
value: "{{ hostvars['console']['outline']['session_secret'] }}"
- name: "OUTLINE_UTILS_SECRET"
value: "{{ hostvars['console']['outline']['utils_secret'] }}"
- name: "OUTLINE_DATABASE_PASSWORD"
value: "{{ hostvars['console']['postgresql']['password']['outline'] }}"
- name: "OUTLINE_OIDC_CLIENT_SECRET"
value: "{{ hostvars['console']['outline']['oidc']['secret'] }}"
notify: "notification_restart_outline"
no_log: true
- name: Deploy outline.container file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/outline/outline.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/outline.container"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_outline"
- name: Enable outline.service
ansible.builtin.systemd:
name: "outline.service"
state: "started"
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
loop:
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
- image: "docker.io/outlinewiki/outline:{{ version['containers']['outline'] }}"
file: "docker.io_outlinewiki_outline_{{ version['containers']['outline'] }}"
loop_control:
label: "{{ item.file }}"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "{{ item.item.image }}"
dest: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
format: "oci-archive"
force: false
loop: "{{ container_archive_images.results }}"
loop_control:
label: "{{ item.item.file }}"
when: not item.stat.exists
- name: Fetch container archive images
ansible.builtin.fetch:
src: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
loop: "{{ container_archive_images.results }}"
loop_control:
label: "{{ item.item.file }}"
@@ -8,7 +8,7 @@
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['redis']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "containers/redis"
@@ -21,7 +21,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.conf.j2"
dest: "{{ node['home_path'] }}/containers/redis/{{ redis_service }}/redis.conf"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
register: "is_redis_conf"
@@ -30,7 +30,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/redis_{{ redis_service }}.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
register: "is_redis_containerfile"
@@ -48,7 +48,7 @@
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['paperless']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "data/containers/paperless"
@@ -57,8 +57,16 @@
- "data/containers/paperless/consume"
- "containers/paperless"
- "containers/paperless/ssl"
- "containers/paperless/build"
become: true
- name: Deploy containerfile for build
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/paperless/build/paperless.containerfile.j2"
dest: "{{ node['home_path'] }}/containers/paperless/build/Containerfile"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0640"
- name: Deploy root certificate
ansible.builtin.copy:
@@ -66,12 +74,24 @@
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/paperless/ssl/{{ root_cert_filename }}"
owner: "{{ services['paperless']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0440"
become: true
notify: "notification_restart_paperless"
no_log: true
- name: Build paperless container image
containers.podman.podman_image:
name: "{{ domain['internal'] }}/{{ node['name'] }}/paperless-ngx"
# check tags from container file
tag: "{{ version['containers']['paperless'] }}"
state: "build"
path: "{{ node['home_path'] }}/containers/paperless/build"
- name: Prune paperless dangling images
containers.podman.podman_prune:
image: true
- name: Register secret value to podman secret
containers.podman.podman_secret:
name: "{{ item.name }}"
@@ -111,7 +131,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/paperless/paperless.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/paperless.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_paperless"
@@ -122,3 +142,36 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
loop:
- image: "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'] }}"
file: "{{ domain['internal'] }}_{{ node['name'] }}_paperless-ngx_{{ version['containers']['paperless'] }}"
loop_control:
label: "{{ item.file }}"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "{{ item.item.image }}"
dest: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
format: "oci-archive"
force: false
loop: "{{ container_archive_images.results }}"
loop_control:
label: "{{ item.item.file }}"
when: not item.stat.exists
- name: Fetch container archive images
ansible.builtin.fetch:
src: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
loop: "{{ container_archive_images.results }}"
loop_control:
label: "{{ item.item.file }}"
@@ -0,0 +1,143 @@
---
- name: Set redis service name
ansible.builtin.set_fact:
redis_service: "sure"
- name: Create redis_sure directory
ansible.builtin.file:
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['redis']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "containers/redis"
- "containers/redis/{{ redis_service }}"
- "containers/redis/{{ redis_service }}/data"
become: true
- name: Deploy redis config file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.conf.j2"
dest: "{{ node['home_path'] }}/containers/redis/{{ redis_service }}/redis.conf"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
register: "is_redis_conf"
- name: Deploy redis container file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/redis/redis.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/redis_{{ redis_service }}.container"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
register: "is_redis_containerfile"
- name: Enable (Restart) redis service
ansible.builtin.systemd:
name: "redis_{{ redis_service }}.service"
state: "restarted"
enabled: true
daemon_reload: true
scope: "user"
when: is_redis_conf.changed or is_redis_containerfile.changed # noqa: no-handler
- name: Create sure directory
ansible.builtin.file:
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['sure']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "data/containers/sure"
- "data/containers/sure/storage"
- "containers/sure"
- "containers/sure/ssl"
become: true
- name: Deploy root certificate
ansible.builtin.copy:
content: |
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/sure/ssl/{{ root_cert_filename }}"
owner: "{{ services['sure']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0440"
become: true
notify: "notification_restart_sure"
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: "SURE_SECRET_KEY_BASE"
value: "{{ hostvars['console']['sure']['session_secret'] }}"
- name: "SURE_POSTGRES_PASSWORD"
value: "{{ hostvars['console']['postgresql']['password']['sure'] }}"
- name: "SURE_OIDC_CLIENT_SECRET"
value: "{{ hostvars['console']['sure']['oidc']['secret'] }}"
notify: "notification_restart_sure"
no_log: true
- name: Deploy sure.container file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/sure/{{ item }}.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/{{ item }}"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0644"
loop:
- "sure-web.container"
- "sure-worker.container"
notify: "notification_restart_sure"
- name: Enable sure.service
ansible.builtin.systemd:
name: "{{ item }}"
state: "started"
enabled: true
daemon_reload: true
scope: "user"
loop:
- "sure-web.service"
- "sure-worker.service"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
loop:
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
- image: "ghcr.io/we-promise/sure:{{ version['containers']['sure'] }}"
file: "ghcr.io_we-promise_sure_{{ version['containers']['sure'] }}"
loop_control:
label: "{{ item.file }}"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "{{ item.item.image }}"
dest: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
format: "oci-archive"
force: false
loop: "{{ container_archive_images.results }}"
loop_control:
label: "{{ item.item.file }}"
when: not item.stat.exists
- name: Fetch container archive images
ansible.builtin.fetch:
src: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
loop: "{{ container_archive_images.results }}"
loop_control:
label: "{{ item.item.file }}"
@@ -4,7 +4,7 @@
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "data/containers/vaultwarden"
@@ -17,7 +17,7 @@
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/vaultwarden/ssl/{{ root_cert_filename }}"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0440"
become: true
notify: "notification_restart_vaultwarden"
@@ -44,7 +44,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/vaultwarden/vaultwarden.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/vaultwarden.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_vaultwarden"
@@ -55,3 +55,23 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/docker.io_vaultwarden_server_{{ version['containers']['vaultwarden'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "docker.io/vaultwarden/server:{{ version['containers']['vaultwarden'] }}"
dest: "{{ node['home_path'] }}/archives/containers/docker.io_vaultwarden_server_{{ version['containers']['vaultwarden'] }}.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/docker.io_vaultwarden_server_{{ version['containers']['vaultwarden'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -4,7 +4,7 @@
path: "{{ node['home_path'] }}/containers/{{ item }}"
state: "directory"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "authelia"
@@ -17,7 +17,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/auth/authelia/config/authelia.yaml.j2"
dest: "{{ node['home_path'] }}/containers/authelia/config/authelia.yaml"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0600"
become: true
notify: "notification_restart_authelia"
@@ -29,7 +29,7 @@
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/authelia/certs/{{ root_cert_filename }}"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0440"
become: true
no_log: true
@@ -65,7 +65,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/auth/authelia/authelia.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/authelia.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_authelia"
@@ -76,3 +76,23 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/docker.io_authelia_authelia_{{ version['containers']['authelia'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "docker.io/authelia/authelia:{{ version['containers']['authelia'] }}"
dest: "{{ node['home_path'] }}/archives/containers/docker.io_authelia_authelia_{{ version['containers']['authelia'] }}.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/docker.io_authelia_authelia_{{ version['containers']['authelia'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -22,7 +22,7 @@
path: "{{ node['home_path'] }}/.config/systemd/user"
state: "directory"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0700"
- name: Create quadlet directory
@@ -30,5 +30,14 @@
path: "{{ node['home_path'] }}/.config/containers/systemd"
state: "directory"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0700"
- name: Set data volume path
ansible.builtin.file:
path: "{{ node['home_path'] }}/data"
state: "directory"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0770"
when: node['name'] in ["infra", "app"]
@@ -11,7 +11,7 @@
- name: Deploy networkd files
ansible.builtin.template:
src: "{{ item }}"
dest: "/etc/systemd/network/{{ item | basename }}"
dest: "/etc/systemd/network/{{ item | basename | replace('.j2', '') }}"
owner: "root"
group: "systemd-network"
mode: "0640"
@@ -1,13 +1,14 @@
---
- name: Gather system facts (hardware)
- name: Gather ystem facts (hardware)
ansible.builtin.setup:
gather_subset:
- hardware
become: true
- name: Deploy alloy deb file (x86_64)
ansible.builtin.copy:
src: "{{ hostvars['console']['node']['data_path'] }}/bin/alloy-{{ version['packages']['alloy'] }}-amd64.deb"
- name: Download alloy deb file (x86_64)
ansible.builtin.get_url:
url: "https://github.com/grafana/alloy/releases/download/v{{ version['packages']['alloy'] }}/\
alloy-{{ version['packages']['alloy'] }}-1.amd64.deb"
dest: "/var/cache/apt/archives/alloy-{{ version['packages']['alloy'] }}.deb"
owner: "root"
group: "root"
@@ -15,9 +16,10 @@
become: true
when: ansible_facts['architecture'] == "x86_64"
- name: Deploy alloy deb file (aarch64)
ansible.builtin.copy:
src: "{{ hostvars['console']['node']['data_path'] }}/bin/alloy-{{ version['packages']['alloy'] }}-arm64.deb"
- name: Download alloy deb file (aarch64)
ansible.builtin.get_url:
url: "https://github.com/grafana/alloy/releases/download/v{{ version['packages']['alloy'] }}/\
alloy-{{ version['packages']['alloy'] }}-1.arm64.deb"
dest: "/var/cache/apt/archives/alloy-{{ version['packages']['alloy'] }}.deb"
owner: "root"
group: "root"
@@ -30,6 +32,7 @@
deb: "/var/cache/apt/archives/alloy-{{ version['packages']['alloy'] }}.deb"
state: "present"
become: true
notify: "notification_restart_alloy"
- name: Deploy alloy config
ansible.builtin.template:
@@ -64,6 +67,19 @@
become: true
notify: "notification_restart_alloy"
- name: Set ACL for data directory
ansible.posix.acl:
path: "{{ item }}"
entity: "alloy"
etype: "user"
permissions: "x"
state: "present"
loop:
- "{{ node['home_path'] }}"
- "{{ node['home_path'] }}/data"
become: true
when: node['name'] == "app"
- name: Enable alloy service
ansible.builtin.systemd:
name: "alloy.service"
@@ -71,3 +87,10 @@
enabled: true
daemon_reload: true
become: true
- name: Fetch deb bin file
ansible.builtin.fetch:
src: "/var/cache/apt/archives/alloy-{{ version['packages']['alloy'] }}.deb"
dest: "{{ hostvars['console']['node']['data_path'] }}/bin/"
flat: true
become: true
@@ -4,7 +4,7 @@
ansible.builtin.file:
path: "{{ node['home_path'] }}/containers/{{ item }}"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
state: "directory"
mode: "0770"
loop:
@@ -18,7 +18,7 @@
ansible.builtin.file:
path: /var/log/caddy
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
state: "directory"
mode: "0755"
become: true
@@ -48,7 +48,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/common/caddy/build/caddy.containerfile.j2"
dest: "{{ node['home_path'] }}/containers/caddy/build/Containerfile"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0640"
- name: Deploy root crt for build
@@ -56,7 +56,7 @@
content: "{{ hostvars['console']['ca']['root']['crt'] }}"
dest: "{{ node['home_path'] }}/containers/caddy/build/{{ root_cert_filename }}"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0640"
no_log: true
@@ -77,7 +77,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/common/caddy/etc/{{ node['name'] }}/Caddyfile.j2"
dest: "{{ node['home_path'] }}/containers/caddy/etc/Caddyfile"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0600"
notify: "notification_restart_caddy"
@@ -86,7 +86,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/common/caddy/caddy.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/caddy.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_caddy"
@@ -97,3 +97,23 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/{{ domain['internal'] }}_{{ node['name'] }}_caddy_{{ version['containers']['caddy'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "{{ domain['internal'] }}/{{ node['name'] }}/caddy:{{ version['containers']['caddy'] }}"
dest: "{{ node['home_path'] }}/archives/containers/{{ domain['internal'] }}_{{ node['name'] }}_caddy_{{ version['containers']['caddy'] }}.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/{{ domain['internal'] }}_{{ node['name'] }}_caddy_{{ version['containers']['caddy'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -36,10 +36,15 @@
ansible.builtin.set_fact:
acquisd_list:
fw:
collection: "crowdsecurity/suricata"
collection:
- "crowdsecurity/suricata"
parser: []
config: "suricata.yaml"
auth:
collection: "crowdsecurity/caddy"
collection:
- "crowdsecurity/caddy"
parser:
- "crowdsecurity/nextcloud-whitelist"
config: "caddy.yaml"
- name: Deploy crowdsec-update service files
@@ -181,7 +186,8 @@
block:
- name: Install crowdsec collection
ansible.builtin.command:
cmd: "cscli collections install {{ acquisd_list[node['name']]['collection'] }}"
cmd: "cscli collections install {{ item }}"
loop: "{{ acquisd_list[node['name']]['collection'] }}"
become: true
changed_when: "'overwrite' not in is_collection_installed.stderr"
failed_when:
@@ -189,6 +195,17 @@
- "'already installed' not in is_collection_installed.stderr"
register: "is_collection_installed"
- name: Install crowdsec parser
ansible.builtin.command:
cmd: "cscli parsers install {{ item }}"
loop: "{{ acquisd_list[node['name']]['parser'] }}"
become: true
changed_when: "'overwrite' not in is_parser_installed.stderr"
failed_when:
- is_parser_installed.rc != 0
- "'already installed' not in is_parser_installed.stderr"
register: "is_parser_installed"
- name: Create crowdsec acquis.d directory
ansible.builtin.file:
path: "/etc/crowdsec/acquis.d"
@@ -298,7 +315,3 @@
enabled: true
daemon_reload: true
become: true
# cscli bouncers list
# cscli machines list
# cscli metrics
@@ -5,36 +5,38 @@
- hardware
become: true
- name: Check kopia installation
ansible.builtin.shell: |
command -v kopia
changed_when: false
failed_when: false
register: "is_kopia_installed"
ignore_errors: true
- name: Set console kopia
when: node['name'] == 'console'
block:
- name: Apply cli tools (x86_64)
- 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"
- is_kopia_installed.rc != 0
- name: Apply cli tools (aarch64)
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"
- is_kopia_installed.rc != 0
- name: Connect kopia server
when: ansible_facts['architecture'] == "aarch64"
- name: Connect console kopia server
environment:
KOPIA_PASSWORD: "{{ hostvars['console']['kopia']['user']['console'] }}"
KOPIA_PASSWORD: "{{ hostvars['console']['kopia']['users']['console'] }}"
ansible.builtin.shell: |
/usr/bin/kopia repository connect server \
--url=https://{{ services['kopia']['domain'] }}.{{ domain['internal'] }}:{{ services['kopia']['ports']['https'] }} \
@@ -51,30 +53,36 @@
- name: Set kopia uid
ansible.builtin.set_fact:
kopia_uid: 951
- name: Deploy kopia deb file (x86_64)
ansible.builtin.copy:
src: "{{ hostvars['console']['node']['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-amd64.deb"
- name: Download kopia deb file (x86_64)
ansible.builtin.get_url:
url: "https://github.com/kopia/kopia/releases/download/v{{ version['packages']['kopia'] }}/\
kopia_{{ version['packages']['kopia'] }}_linux_amd64.deb"
dest: "/var/cache/apt/archives/kopia-{{ version['packages']['kopia'] }}.deb"
owner: "root"
group: "root"
mode: "0644"
become: true
when: ansible_facts['architecture'] == "x86_64"
- name: Deploy kopia deb file (aarch64)
ansible.builtin.copy:
src: "{{ hostvars['console']['node']['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-arm64.deb"
- name: Download kopia deb file (aarch64)
ansible.builtin.get_url:
url: "https://github.com/kopia/kopia/releases/download/v{{ version['packages']['kopia'] }}/\
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
when: ansible_facts['architecture'] == "aarch64"
- name: Create kopia group
ansible.builtin.group:
name: "kopia"
gid: "{{ kopia_uid }}"
state: "present"
become: true
- name: Create kopia user
ansible.builtin.user:
name: "kopia"
@@ -85,6 +93,7 @@
comment: "Kopia backup User"
state: "present"
become: true
- name: Create kopia directory
ansible.builtin.file:
path: "{{ item.name }}"
@@ -101,12 +110,13 @@
mode: "0700"
become: true
no_log: true
- name: Install kopia
ansible.builtin.apt:
deb: "/var/cache/apt/archives/kopia-{{ version['packages']['kopia'] }}.deb"
state: "present"
become: true
when: is_kopia_installed.rc != 0
- name: Deploy kopia env
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/kopia/kopia.env.j2"
@@ -116,6 +126,7 @@
mode: "0400"
become: true
no_log: true
- name: Deploy kopia service files
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/kopia/{{ item }}.j2"
@@ -128,6 +139,7 @@
- "kopia-backup.service"
- "kopia-backup.timer"
become: true
- name: Enable auto kopia rules update
ansible.builtin.systemd:
name: "kopia-backup.timer"
@@ -11,7 +11,7 @@
ansible.builtin.file:
path: "{{ node['home_path'] }}/containers"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
state: "directory"
mode: "0700"
@@ -19,11 +19,22 @@
ansible.builtin.file:
path: "{{ node['home_path'] }}/data/containers"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
state: "directory"
mode: "0770"
when: node['name'] == "app"
- name: Create container image archive directory
ansible.builtin.file:
path: "{{ item }}"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
state: "directory"
mode: "0700"
loop:
- "{{ node['home_path'] }}/archives"
- "{{ node['home_path'] }}/archives/containers"
- name: Install podman and reset ssh connection for initiating
when: is_podman_installed.rc != 0
become: true
-7
View File
@@ -1,8 +1 @@
---
- name: Register font
ansible.builtin.shell: |
fc-cache -f -v
become: true
changed_when: false
listen: "notification_update_font"
ignore_errors: true # noqa: ignore-errors
@@ -0,0 +1,90 @@
---
- name: Create vmm_init directory
ansible.builtin.file:
path: "{{ node['data_path'] }}/{{ item }}"
state: "directory"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0750"
loop:
- "vmm_init"
- "vmm_init/grub.d"
- "vmm_init/modprobe.d"
- "vmm_init/networkd"
- "vmm_init/ssh"
- "vmm_init/ssh/sshd_config.d"
- "vmm_init/sysctl.d"
- name: Create nftables.conf
ansible.builtin.template:
src: "{{ node['config_path'] }}/node/vmm/nftables.conf.j2"
dest: "{{ node['data_path'] }}/vmm_init/nftables.conf"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0640"
- name: Create grub.d iommu config
ansible.builtin.copy:
content: |
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"
dest: "{{ node['data_path'] }}/vmm_init/grub.d/iommu.cfg"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0640"
- name: Create modprobe.d vfio config
ansible.builtin.copy:
content: |
options vfio-pci ids={{ hostvars['vmm']['hardware']['igpu']['id'] }}
softdep i915 pre: vfio-pci
# softdep ahci pre: vfio-pci # sata controller
dest: "{{ node['data_path'] }}/vmm_init/modprobe.d/vfio.conf"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0640"
- name: Create networkd network config
ansible.builtin.template:
src: "{{ item }}"
dest: "{{ node['data_path'] }}/vmm_init/networkd/{{ item | basename | replace('.j2', '') }}"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0640"
loop: "{{ query('fileglob', hostvars['console']['node']['config_path'] + '/node/vmm/networkd/*') | sort }}"
- name: Create ssh CA
ansible.builtin.copy:
content: |
{{ hostvars['console']['ssh']['ca']['pub'] }}
dest: "{{ node['data_path'] }}/vmm_init/ssh/local_ssh_ca.pub"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0640"
- name: Create ssh config
ansible.builtin.copy:
content: "{{ item.value }}"
dest: "{{ node['data_path'] }}/vmm_init/ssh/sshd_config.d/{{ item.name }}"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0640"
loop:
- name: "prohibit_root.conf"
value: |
PermitRootLogin no
- name: "ssh_ca.conf"
value: |
TrustedUserCAKeys /etc/ssh/local_ssh_ca.pub
loop_control:
label: "{{ item.name }}"
- name: Create sysctl.d bridge config
ansible.builtin.copy:
content: |
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
dest: "{{ node['data_path'] }}/vmm_init/sysctl.d/bridge.conf"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0640"
@@ -22,7 +22,7 @@
run_once: true
no_log: true
- name: Load decrypted secret vaules in console
- name: Load decrypted secret values in console
ansible.builtin.set_fact:
"{{ item.key }}": "{{ item.value }}"
loop: "{{ decrypted_secrets.stdout | from_yaml | dict2items }}"
@@ -66,8 +66,8 @@
content: |
{{ hostvars['console']['ssh']['ca']['key'] }}
dest: "/run/user/{{ node['uid'] }}/local_ssh_ca_private_key"
owner: "console"
group: "svadmins"
owner: "{{ ansible_user }}"
group: "{{ node['group'] }}"
mode: "0400"
no_log: true
- name: Sign on ssh console key (pub file)
@@ -91,7 +91,7 @@
path: "{{ node['home_path'] }}/.ssh"
state: "directory"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0700"
- name: Create ssh config file
@@ -105,5 +105,5 @@
{% endfor %}
dest: "{{ node['home_path'] }}/.ssh/config"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0600"
@@ -31,7 +31,7 @@
sops_{{ version['packages']['sops'] }}_{{ item }}.deb"
dest: "{{ node['data_path'] }}/bin/sops-{{ version['packages']['sops'] }}-{{ item }}.deb"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0600"
loop:
- "amd64"
@@ -43,43 +43,7 @@
step-cli_{{ version['packages']['step'] }}-1_{{ item }}.deb"
dest: "{{ node['data_path'] }}/bin/step-{{ version['packages']['step'] }}-{{ item }}.deb"
owner: "{{ ansible_user }}"
group: "svadmins"
mode: "0600"
loop:
- "amd64"
- "arm64"
- 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: "svadmins"
mode: "0600"
loop:
- "amd64"
- "arm64"
- name: Download blocky
ansible.builtin.get_url:
url: "https://github.com/0xERR0R/blocky/releases/download/v{{ version['packages']['blocky'] }}/\
blocky_v{{ version['packages']['blocky'] }}_Linux_{{ item }}.tar.gz"
dest: "{{ node['data_path'] }}/bin/blocky-{{ version['packages']['blocky'] }}-{{ item }}.tar.gz"
owner: "{{ ansible_user }}"
group: "svadmins"
mode: "0600"
loop:
- "x86_64"
- "arm64"
- name: Download alloy
ansible.builtin.get_url:
url: "https://github.com/grafana/alloy/releases/download/v{{ version['packages']['alloy'] }}/\
alloy-{{ version['packages']['alloy'] }}-1.{{ item }}.deb"
dest: "{{ node['data_path'] }}/bin/alloy-{{ version['packages']['alloy'] }}-{{ item }}.deb"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0600"
loop:
- "amd64"
@@ -92,7 +56,6 @@
loop:
- "sops-{{ version['packages']['sops'] }}-amd64.deb"
- "step-{{ version['packages']['step'] }}-amd64.deb"
- "kopia-{{ version['packages']['kopia'] }}-amd64.deb"
become: true
when: ansible_facts['architecture'] == "x86_64"
@@ -103,6 +66,5 @@
loop:
- "sops-{{ version['packages']['sops'] }}-arm64.deb"
- "step-{{ version['packages']['step'] }}-arm64.deb"
- "kopia-{{ version['packages']['kopia'] }}-arm64.deb"
become: true
when: ansible_facts['architecture'] == "aarch64"
+1 -1
View File
@@ -44,7 +44,7 @@
ansible.builtin.systemd:
name: "blocky.service"
state: "restarted"
enabled: "true"
enabled: true
daemon_reload: true
become: true
changed_when: false
@@ -25,7 +25,7 @@
become: true
when: is_bind_installed.rc != 0
- name: Deploy acem.key
- name: Deploy acme.key
ansible.builtin.copy:
content: "{{ hostvars['console']['bind']['acme_key'] }}"
dest: "/etc/bind/acme.key"
+32 -16
View File
@@ -23,7 +23,7 @@
state: "present"
become: true
- name: Create blocky etc directory
- name: Create blocky directory
ansible.builtin.file:
path: "{{ item }}"
owner: "blocky"
@@ -31,28 +31,38 @@
mode: "0750"
state: "directory"
loop:
- "/home/blocky"
- "/home/blocky/bin"
- "/etc/blocky"
- "/etc/blocky/ssl"
become: true
- name: Deploy blocky binary file (x86_64)
ansible.builtin.unarchive:
src: "{{ hostvars['console']['node']['data_path'] }}/bin/blocky-{{ version['packages']['blocky'] }}-x86_64.tar.gz"
dest: "/usr/local/bin/"
owner: "root"
group: "root"
mode: "0755"
extra_opts:
- "--strip-components=0"
- "--wildcards"
- "blocky"
- name: Download blocky (x86_64)
ansible.builtin.get_url:
url: "https://github.com/0xERR0R/blocky/releases/download/v{{ version['packages']['blocky'] }}/\
blocky_v{{ version['packages']['blocky'] }}_Linux_x86_64.tar.gz"
dest: "/home/blocky/bin/blocky-{{ version['packages']['blocky'] }}.tar.gz"
owner: "blocky"
group: "blocky"
mode: "0600"
become: true
when: ansible_facts['architecture'] == "x86_64"
notify: "notification_restart_blocky"
- name: Deploy blocky binary file (aarch64)
- name: Download blocky (aarch64)
ansible.builtin.get_url:
url: "https://github.com/0xERR0R/blocky/releases/download/v{{ version['packages']['blocky'] }}/\
blocky_v{{ version['packages']['blocky'] }}_Linux_arm64.tar.gz"
dest: "/home/blocky/bin/blocky-{{ version['packages']['blocky'] }}.tar.gz"
owner: "blocky"
group: "blocky"
mode: "0600"
become: true
when: ansible_facts['architecture'] == "aarch64"
- name: Deploy blocky binary file
ansible.builtin.unarchive:
src: "{{ hostvars['console']['node']['data_path'] }}/bin/blocky-{{ version['packages']['blocky'] }}-arm64.tar.gz"
src: "/home/blocky/bin/blocky-{{ version['packages']['blocky'] }}.tar.gz"
remote_src: true
dest: "/usr/local/bin/"
owner: "root"
group: "root"
@@ -62,7 +72,6 @@
- "--wildcards"
- "blocky"
become: true
when: ansible_facts['architecture'] == "aarch64"
notify: "notification_restart_blocky"
- name: Deploy blocky config
@@ -115,3 +124,10 @@
enabled: true
daemon_reload: true
become: true
- name: Fetch deb bin file
ansible.builtin.fetch:
src: "/home/blocky/bin/blocky-{{ version['packages']['blocky'] }}.tar.gz"
dest: "{{ hostvars['console']['node']['data_path'] }}/bin/"
flat: true
become: true
@@ -6,7 +6,7 @@
API_KEY={{ hostvars['console']['ddns']['api_key'] }}
dest: "/etc/secrets/{{ node['uid'] }}/ddns.env"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0400"
become: true
no_log: true
@@ -16,7 +16,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/ddns/ddns.sh"
dest: "/usr/local/bin"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0711"
become: true
@@ -25,7 +25,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/fw/ddns/{{ item }}.j2"
dest: "{{ node['home_path'] }}/.config/systemd/user/{{ item }}"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0600"
validate: "/usr/bin/systemd-analyze verify %s"
loop:
+2 -2
View File
@@ -26,7 +26,7 @@
become: true
notify: "notification_restart_kea4"
- name: Create kea-dhcp-server.service.d
- name: Create kea-dhcp4-server.service.d
ansible.builtin.file:
path: "/etc/systemd/system/kea-dhcp4-server.service.d"
state: "directory"
@@ -35,7 +35,7 @@
mode: "0755"
become: true
- name: Set kea-dhcp-server.service.d/override.conf
- name: Set kea-dhcp4-server.service.d/override.conf
ansible.builtin.copy:
dest: "/etc/systemd/system/kea-dhcp4-server.service.d/override.conf"
content: |
+3 -3
View File
@@ -2,7 +2,7 @@
ansible.builtin.systemd:
name: "ca.service"
state: "restarted"
enabled: "true"
enabled: true
daemon_reload: true
scope: "user"
changed_when: false
@@ -73,10 +73,10 @@
listen: "notification_restart_grafana"
ignore_errors: true # noqa: ignore-errors
- name: Enable x509-exporter.service
- name: Restart x509-exporter.service
ansible.builtin.systemd:
name: "x509-exporter.service"
state: "started"
state: "restarted"
enabled: true
daemon_reload: true
scope: "user"
@@ -3,7 +3,7 @@
ansible.builtin.file:
path: "{{ node['home_path'] }}/containers/{{ item }}"
owner: "{{ services['ca']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
state: "directory"
mode: "0770"
loop:
@@ -29,7 +29,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ca/config/{{ item }}.j2"
dest: "{{ node['home_path'] }}/containers/ca/config/{{ item }}"
owner: "{{ services['ca']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0400"
loop:
- "ca.json"
@@ -43,7 +43,7 @@
{{ item.value }}
dest: "{{ item.path }}/{{ item.name }}"
owner: "{{ services['ca']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "{{ item.mode }}"
loop:
- name: "{{ root_cert_filename }}"
@@ -67,7 +67,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ca/ca.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/ca.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_ca"
@@ -78,3 +78,23 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/docker.io_smallstep_step-ca_{{ version['containers']['step'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "docker.io/smallstep/step-ca:{{ version['containers']['step'] }}"
dest: "{{ node['home_path'] }}/archives/containers/docker.io_smallstep_step-ca_{{ version['containers']['step'] }}.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/docker.io_smallstep_step-ca_{{ version['containers']['step'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -3,7 +3,7 @@
ansible.builtin.file:
path: "{{ node['home_path'] }}/containers/{{ item }}"
owner: "{{ services['grafana']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
state: "directory"
mode: "0770"
loop:
@@ -11,6 +11,7 @@
- "grafana/data"
- "grafana/etc"
- "grafana/etc/provisioning"
- "grafana/etc/provisioning/datasources"
- "grafana/etc/dashboards"
- "grafana/ssl"
become: true
@@ -21,7 +22,7 @@
{{ hostvars['console']['ca']['root']['crt'] }}
dest: "{{ node['home_path'] }}/containers/grafana/ssl/{{ root_cert_filename }}"
owner: "{{ services['grafana']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0400"
become: true
notify: "notification_restart_grafana"
@@ -39,16 +40,16 @@
- name: "LDAP_BIND_PASSWORD"
value: "{{ hostvars['console']['ldap']['password']['grafana'] }}"
- name: "GF_ADMIN_PASSWORD"
value: "{{ hostvars['console']['grafana']['user']['password'] }}"
value: "{{ hostvars['console']['grafana']['admin']['password'] }}"
notify: "notification_restart_grafana"
no_log: true
- name: Deploy configruation files
- name: Deploy configuration files
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/grafana/etc/{{ item }}.j2"
dest: "{{ node['home_path'] }}/containers/grafana/etc/{{ item }}"
owner: "{{ services['grafana']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0400"
loop:
- "grafana.ini"
@@ -62,7 +63,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/grafana/etc/provisioning/datasources/datasources.yaml.j2"
dest: "{{ node['home_path'] }}/containers/grafana/etc/provisioning/datasources/datasources.yaml"
owner: "{{ services['grafana']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0400"
become: true
notify: "notification_restart_grafana"
@@ -72,7 +73,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/grafana/grafana.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/grafana.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_grafana"
@@ -83,3 +84,23 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/docker.io_grafana_grafana_{{ version['containers']['grafana'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "docker.io/grafana/grafana:{{ version['containers']['grafana'] }}"
dest: "{{ node['home_path'] }}/archives/containers/docker.io_grafana_grafana_{{ version['containers']['grafana'] }}.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/docker.io_grafana_grafana_{{ version['containers']['grafana'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -3,7 +3,7 @@
ansible.builtin.file:
path: "{{ node['home_path'] }}/containers/{{ item }}"
owner: "{{ services['ldap']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
state: "directory"
mode: "0770"
loop:
@@ -18,7 +18,7 @@
{{ item.value }}
dest: "{{ node['home_path'] }}/containers/ldap/ssl/{{ item.name }}"
owner: "{{ services['ldap']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "{{ item.mode }}"
loop:
- name: "{{ root_cert_filename }}"
@@ -33,8 +33,8 @@
value: "{{ hostvars['console']['ldap']['key'] }}"
mode: "0400"
become: true
notify: "notification_restart_ldap"
no_log: true
notify: "notification_restart_ldap"
- name: Register secret value to podman secret
containers.podman.podman_secret:
@@ -51,14 +51,15 @@
value: "{{ hostvars['console']['ldap']['seed_key'] }}"
- name: "LLDAP_JWT_SECRET"
value: "{{ hostvars['console']['ldap']['jwt_secret'] }}"
notify: "notification_restart_ldap"
no_log: true
notify: "notification_restart_ldap"
- name: Initiate ldap (When = false, If DB data does not exist in postgresql, activate this block)
# The reason why this task doesn't use the way to check ".init" file is this tasks can override original database.
# Absent of ".init" file cannot guarantee DB is empty.
when: false
become: true
no_log: true
block:
- name: Register extra secret value to podman secret
containers.podman.podman_secret:
@@ -75,7 +76,7 @@
rm: true
detach: false
env:
TZ: "Asia/Seoul"
TZ: "{{ timezone }}"
LLDAP_LDAP_BASE_DN: "{{ domain['dc'] }}"
secrets:
- "LLDAP_DATABASE_URL,type=env"
@@ -97,7 +98,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ldap/ldap.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/ldap.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_ldap"
@@ -108,3 +109,23 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/docker.io_lldap_lldap_{{ version['containers']['ldap'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "docker.io/lldap/lldap:{{ version['containers']['ldap'] }}"
dest: "{{ node['home_path'] }}/archives/containers/docker.io_lldap_lldap_{{ version['containers']['ldap'] }}.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/docker.io_lldap_lldap_{{ version['containers']['ldap'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -4,7 +4,7 @@
path: "{{ node['home_path'] }}/containers/{{ item }}"
state: "directory"
owner: "{{ services['loki']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "loki"
@@ -18,7 +18,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/loki/etc/loki.yaml.j2"
dest: "{{ node['home_path'] }}/containers/loki/etc/loki.yaml"
owner: "{{ services['loki']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0600"
become: true
notify: "notification_restart_loki"
@@ -30,7 +30,7 @@
{{ item.value }}
dest: "{{ node['home_path'] }}/containers/loki/ssl/{{ item.name }}"
owner: "{{ services['loki']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "{{ item.mode }}"
loop:
- name: "{{ root_cert_filename }}"
@@ -53,7 +53,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/loki/loki.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/loki.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_loki"
@@ -64,3 +64,23 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/docker.io_grafana_loki_{{ version['containers']['loki'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "docker.io/grafana/loki:{{ version['containers']['loki'] }}"
dest: "{{ node['home_path'] }}/archives/containers/docker.io_grafana_loki_{{ version['containers']['loki'] }}.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/docker.io_grafana_loki_{{ version['containers']['loki'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -3,30 +3,33 @@
ansible.builtin.set_fact:
connected_services:
- "ldap"
- "authelia"
- "grafana"
- "authelia"
- "vaultwarden"
- "gitea"
- "immich"
- "paperless"
- "vikunja"
- "affine"
- "nextcloud"
- "sure"
- "outline"
- "memos"
- "mealie"
- name: Create postgresql directory
ansible.builtin.file:
path: "{{ node['home_path'] }}/containers/{{ item }}"
path: "{{ node['home_path'] }}/{{ item }}"
state: "directory"
owner: "{{ services['postgresql']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "postgresql"
- "postgresql/data"
- "postgresql/config"
- "postgresql/ssl"
- "postgresql/init"
- "postgresql/backups"
- "postgresql/build"
- "data/containers/postgresql/backups"
- "containers/postgresql"
- "containers/postgresql/data"
- "containers/postgresql/config"
- "containers/postgresql/ssl"
- "containers/postgresql/init"
- "containers/postgresql/build"
become: true
- name: Deploy containerfile for build
@@ -34,7 +37,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/build/postgresql.containerfile.j2"
dest: "{{ node['home_path'] }}/containers/postgresql/build/Containerfile"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0640"
- name: Build postgresql container image
@@ -54,7 +57,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/config/{{ item }}.j2"
dest: "{{ node['home_path'] }}/containers/postgresql/config/{{ item }}"
owner: "{{ services['postgresql']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0600"
loop:
- "postgresql.conf"
@@ -69,7 +72,7 @@
{{ item.value }}
dest: "{{ node['home_path'] }}/containers/postgresql/ssl/{{ item.name }}"
owner: "{{ services['postgresql']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "{{ item.mode }}"
loop:
- name: "{{ root_cert_filename }}"
@@ -94,24 +97,26 @@
register: "is_postgresql_init"
- name: Prepare initiating DB
when: not is_postgresql_init.stat.exists
when:
- not is_postgresql_init.stat.exists
- (connected_services | default([]) | length) > 0
become: true
block:
# `init/pg_cluster.sql` should be fetched from postgresql's backup directory before running initiating
- name: Deploy init cluster sql file
ansible.builtin.copy:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/init/pg_cluster.sql"
dest: "{{ node['home_path'] }}/containers/postgresql/init/0_pg_cluster.sql"
dest: "{{ node['home_path'] }}/containers/postgresql/init/00_pg_cluster.sql"
owner: "{{ services['postgresql']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0600"
- name: Deploy restoring data sql files
ansible.builtin.copy:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/init/pg_{{ item }}.sql"
dest: "{{ node['home_path'] }}/containers/postgresql/init/{{ 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'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0600"
loop: "{{ connected_services }}"
loop_control:
@@ -123,14 +128,14 @@
state: "touch"
mode: "0644"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
- name: Deploy container file
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/postgresql.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/postgresql.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_postgresql"
@@ -139,7 +144,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/services/{{ item }}"
dest: "{{ node['home_path'] }}/.config/systemd/user/{{ item }}"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
loop:
- "postgresql-cluster-backup.service"
@@ -171,3 +176,29 @@
daemon_reload: true
scope: "user"
loop: "{{ connected_services }}"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/\
{{ domain['internal'] }}_{{ node['name'] }}_postgres_\
pg{{ version['containers']['postgresql'] }}-vectorchord{{ version['containers']['vectorchord'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "{{ domain['internal'] }}/{{ node['name'] }}/postgres:pg{{ version['containers']['postgresql'] }}-vectorchord{{ version['containers']['vectorchord'] }}"
dest: "{{ node['home_path'] }}/archives/containers/\
{{ domain['internal'] }}_{{ node['name'] }}_postgres_\
pg{{ version['containers']['postgresql'] }}-vectorchord{{ version['containers']['vectorchord'] }}.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/\
{{ domain['internal'] }}_{{ node['name'] }}_postgres_\
pg{{ version['containers']['postgresql'] }}-vectorchord{{ version['containers']['vectorchord'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -4,7 +4,7 @@
path: "{{ node['home_path'] }}/containers/{{ item }}"
state: "directory"
owner: "{{ services['prometheus']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "prometheus"
@@ -18,7 +18,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/prometheus/etc/{{ item }}.j2"
dest: "{{ node['home_path'] }}/containers/prometheus/etc/{{ item }}"
owner: "{{ services['prometheus']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0600"
loop:
- "prometheus.yaml"
@@ -34,7 +34,7 @@
{{ item.value }}
dest: "{{ node['home_path'] }}/containers/prometheus/ssl/{{ item.name }}"
owner: "{{ services['prometheus']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "{{ item.mode }}"
loop:
- name: "{{ root_cert_filename }}"
@@ -57,7 +57,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/prometheus/prometheus.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/prometheus.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_prometheus"
@@ -68,3 +68,23 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/docker.io_prom_prometheus_{{ version['containers']['prometheus'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "docker.io/prom/prometheus:{{ version['containers']['prometheus'] }}"
dest: "{{ node['home_path'] }}/archives/containers/docker.io_prom_prometheus_{{ version['containers']['prometheus'] }}.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/docker.io_prom_prometheus_{{ version['containers']['prometheus'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -4,20 +4,31 @@
path: "{{ node['home_path'] }}/containers/{{ item }}"
state: "directory"
owner: "{{ services['x509-exporter']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0770"
loop:
- "x509-exporter"
- "x509-exporter/config"
- "x509-exporter/certs"
become: true
- name: Deploy config.yaml
ansible.builtin.copy:
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/x509-exporter/config/config.yaml"
dest: "{{ node['home_path'] }}/containers/x509-exporter/config/config.yaml"
owner: "{{ services['x509-exporter']['subuid'] }}"
group: "{{ node['group'] }}"
mode: "0440"
become: true
notify: "notification_restart_x509-exporter"
- name: Deploy certificates
ansible.builtin.copy:
content: |
{{ item.value }}
dest: "{{ node['home_path'] }}/containers/x509-exporter/certs/{{ item.name }}"
owner: "{{ services['x509-exporter']['subuid'] }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0440"
loop:
- name: "root.crt"
@@ -46,7 +57,7 @@
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/x509-exporter/x509-exporter.container.j2"
dest: "{{ node['home_path'] }}/.config/containers/systemd/x509-exporter.container"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
notify: "notification_restart_x509-exporter"
@@ -57,3 +68,23 @@
enabled: true
daemon_reload: true
scope: "user"
- name: Check container archive images
ansible.builtin.stat:
path: "{{ node['home_path'] }}/archives/containers/docker.io_enix_x509-certificate-exporter_{{ version['containers']['x509-exporter'] }}.tar"
register: container_archive_images
- name: Save container archive images
containers.podman.podman_save:
image:
- "docker.io/enix/x509-certificate-exporter:{{ version['containers']['x509-exporter'] }}"
dest: "{{ node['home_path'] }}/archives/containers/docker.io_enix_x509-certificate-exporter_{{ version['containers']['x509-exporter'] }}.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/docker.io_enix_x509-certificate-exporter_{{ version['containers']['x509-exporter'] }}.tar"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
flat: true
@@ -9,15 +9,16 @@
- name: Check libvirt directory
ansible.builtin.stat:
path: "/var/lib/libvirt/{{ item }}"
path: "{{ node['libvirt_path'] }}/{{ item }}"
loop:
- "images"
- "seeds"
- "data"
register: "is_libvirt_dir"
- name: Create libvirt directory
ansible.builtin.file:
path: "/var/lib/libvirt/{{ item.item }}"
path: "{{ node['libvirt_path'] }}/{{ item.item }}"
state: "directory"
owner: "root"
group: "root"
@@ -72,6 +73,7 @@
loop:
- "images-pool"
- "seeds-pool"
- "data-pool"
- name: Start virtual storage pool
community.libvirt.virt_pool:
@@ -81,6 +83,7 @@
loop:
- "images-pool"
- "seeds-pool"
- "data-pool"
- name: Autostart virtual storage pool
community.libvirt.virt_pool:
@@ -90,3 +93,4 @@
loop:
- "images-pool"
- "seeds-pool"
- "data-pool"
+100
View File
@@ -0,0 +1,100 @@
---
- 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
+9 -9
View File
@@ -1,13 +1,13 @@
---
# This task is located in vmm roles because of its attributes,
# but all process should be run in "console".
# At the playbook, `delegate_to: "console"` option is applyed by `apply:`.
# At the playbook, `delegate_to: "console"` option is applied by `apply:`.
- name: Create images directory
ansible.builtin.file:
path: "{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}"
state: "directory"
owner: "console"
group: "svadmins"
owner: "{{ hostvars['console']['node']['name'] }}"
group: "{{ hostvars['console']['node']['group'] }}"
mode: "0700"
- name: Create temp meta-data
@@ -16,8 +16,8 @@
instance-id: vm-{{ target_vm }}
local-hostname: {{ target_vm }}
dest: "{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/meta-data"
owner: "console"
group: "svadmins"
owner: "{{ hostvars['console']['node']['name'] }}"
group: "{{ hostvars['console']['node']['group'] }}"
mode: "0600"
register: "vm_meta_data"
no_log: true
@@ -26,8 +26,8 @@
ansible.builtin.template:
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/vmm/libvirt/seeds/user-data.j2"
dest: "{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/user-data"
owner: "console"
group: "svadmins"
owner: "{{ hostvars['console']['node']['name'] }}"
group: "{{ hostvars['console']['node']['group'] }}"
mode: "0600"
register: "vm_user_data"
no_log: true
@@ -37,8 +37,8 @@
content: |
network: {config: disabled}
dest: "{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/network-config"
owner: "console"
group: "svadmins"
owner: "{{ hostvars['console']['node']['name'] }}"
group: "{{ hostvars['console']['node']['group'] }}"
mode: "0600"
register: "vm_network_config"
no_log: true
+29 -10
View File
@@ -1,16 +1,16 @@
---
- name: Check vm cloud-init
ansible.builtin.stat:
path: "/var/lib/libvirt/images/debian-13.qcow2"
path: "{{ node['libvirt_path'] }}/images/debian-13.qcow2"
become: true
register: is_cloud_init_file
- name: Deploy vm cloud-init
ansible.builtin.copy:
src: "{{ hostvars['console']['node']['data_path'] }}/images/debian-13-generic-amd64.qcow2"
dest: "/var/lib/libvirt/images/debian-13.qcow2"
dest: "{{ node['libvirt_path'] }}/images/debian-13.qcow2"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
force: false
become: true
@@ -18,10 +18,10 @@
- name: Remote copy vm cloud-init file
ansible.builtin.copy:
src: "/var/lib/libvirt/images/debian-13.qcow2"
dest: "/var/lib/libvirt/images/{{ target_vm }}.qcow2"
src: "{{ node['libvirt_path'] }}/images/debian-13.qcow2"
dest: "{{ node['libvirt_path'] }}/images/{{ target_vm }}.qcow2"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
remote_src: true
force: false
@@ -29,7 +29,7 @@
- name: Check deployed cloud-init file info
ansible.builtin.command:
cmd: "qemu-img info /var/lib/libvirt/images/{{ target_vm }}.qcow2 --output json"
cmd: "qemu-img info {{ node['libvirt_path'] }}/images/{{ target_vm }}.qcow2 --output json"
changed_when: false
failed_when:
- deployed_cloudfile_info.rc != 0
@@ -38,18 +38,37 @@
- name: Resize deployed cloud-init file
ansible.builtin.command:
cmd: "qemu-img resize /var/lib/libvirt/images/{{ target_vm }}.qcow2 {{ hostvars[target_vm]['vm']['storage'] }}G"
cmd: "qemu-img resize {{ node['libvirt_path'] }}/images/{{ target_vm }}.qcow2 {{ hostvars[target_vm]['vm']['storage'] }}G"
when:
- deployed_cloudfile_info.rc == 0
- (deployed_cloudfile_info.stdout | from_json)['virtual-size'] < (hostvars[target_vm]['vm']['storage'] | int * 1024 * 1024 * 1024)
changed_when: true
- name: Check app data raw image
ansible.builtin.stat:
path: "{{ hardware['btrfs']['mount_point'] }}/{{ target_vm }}.raw"
get_checksum: false
get_mime: false
get_attributes: false
when: target_vm == "app"
register: "is_app_data"
- name: Create app data raw image
ansible.builtin.command:
# 3.5T
cmd: "qemu-img create -f raw {{ hardware['btrfs']['mount_point'] }}/{{ target_vm }}.raw {{ hostvars[target_vm]['vm']['data_storage']['size'] }}T"
become: true
when:
- target_vm == "app"
- not is_app_data.stat.exists
changed_when: true
- name: Deploy vm seed.iso
ansible.builtin.copy:
src: "{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/seed.iso"
dest: "/var/lib/libvirt/seeds/{{ target_vm }}_seed.iso"
dest: "{{ node['libvirt_path'] }}/seeds/{{ target_vm }}_seed.iso"
owner: "{{ ansible_user }}"
group: "svadmins"
group: "{{ node['group'] }}"
mode: "0644"
become: true
when: deployed_cloudfile_info.rc == 0
+3
View File
@@ -16,6 +16,9 @@
{{ hostvars['fw']['network6']['infra']['server'] }} infra.{{ domain['internal'] }}
{{ hostvars['fw']['network6']['auth']['server'] }} auth.{{ 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 %}
# IPv4
# Crowdsec, blocky, bind(fw)
+4 -2
View File
@@ -78,10 +78,12 @@ table inet filter {
set crowdsec6-blacklists {
type ipv6_addr
flags timeout
}
}
chain global {
# invalid packets
ct state invalid drop comment "deny invalid connection"
# VPN connection exception handling
udp dport $PORTS_VPN return comment "return vpn connection to input and forward chain"
# crowdsec
ip saddr @crowdsec-blacklists counter drop comment "deny all crowdsec blacklist"
ip6 saddr @crowdsec6-blacklists counter drop comment "deny all ipv6 crowdsec blacklist"
@@ -112,7 +114,7 @@ table inet filter {
iifname "lo" accept comment "allow local connection: FW > 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 } 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/USER/WG > FW"
# Global chain contains "WAN !> :SSH_PORT"
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"
@@ -1,5 +0,0 @@
[Match]
MACAddress=c8:ff:bf:05:aa:b0
[Link]
Name=eth0
@@ -0,0 +1,5 @@
[Match]
MACAddress={{ hostvars['vmm']['hardware']['mac']['nic0'] }}
[Link]
Name=eth0
@@ -1,5 +0,0 @@
[Match]
MACAddress=c8:ff:bf:05:aa:b1
[Link]
Name=eth1
@@ -0,0 +1,5 @@
[Match]
MACAddress={{ hostvars['vmm']['hardware']['mac']['nic1'] }}
[Link]
Name=eth1
@@ -1,28 +0,0 @@
[Match]
Name=vlan1
[Network]
# IPv4
Address=192.168.1.10/24
# IPv6
Address=fd00:1::10/64
[RoutingPolicyRule]
From=192.168.1.10/32
Table=1
Priority=100
[Route]
Destination=192.168.1.0/24
Scope=link
Table=1
[RoutingPolicyRule]
From=fd00:1::10/128
Table=61
Priority=100
[Route]
Destination=fd00:1::/64
Scope=link
Table=61
@@ -0,0 +1,28 @@
[Match]
Name=vlan1
[Network]
# IPv4
Address={{ hostvars['fw']['network4']['vmm']['client'] }}/24
# IPv6
Address={{ hostvars['fw']['network6']['vmm']['client'] }}/64
[RoutingPolicyRule]
From={{ hostvars['fw']['network4']['vmm']['client'] }}/32
Table=1
Priority=100
[Route]
Destination={{ hostvars['fw']['network4']['subnet']['client'] }}
Scope=link
Table=1
[RoutingPolicyRule]
From={{ hostvars['fw']['network6']['vmm']['client'] }}/128
Table=61
Priority=100
[Route]
Destination={{ hostvars['fw']['network6']['subnet']['client'] }}
Scope=link
Table=61
@@ -1,32 +0,0 @@
[Match]
Name=vlan10
[Network]
RequiredForOnline=false
# IPv4
Address=192.168.10.10/24
Gateway=192.168.10.1
DNS=192.168.10.2
# IPv6
Address=fd00:10::10/64
Gateway=fd00:10::1
DNS=fd00:10::2
[RoutingPolicyRule]
From=192.168.10.10/32
Table=2
Priority=100
[Route]
Destination=0.0.0.0/0
Gateway=192.168.10.1
Table=2
[RoutingPolicyRule]
From=fd00:10::10/128
Table=62
Priority=100
[Route]
Destination=::/0
Gateway=fd00:10::1
Table=62
@@ -0,0 +1,32 @@
[Match]
Name=vlan10
[Network]
RequiredForOnline=false
# IPv4
Address={{ hostvars['fw']['network4']['vmm']['server'] }}/24
Gateway={{ hostvars['fw']['network4']['firewall']['server'] }}
DNS={{ hostvars['fw']['network4']['blocky']['server'] }}
# IPv6
Address={{ hostvars['fw']['network6']['vmm']['server'] }}/64
Gateway={{ hostvars['fw']['network6']['firewall']['server'] }}
DNS={{ hostvars['fw']['network6']['blocky']['server'] }}
[RoutingPolicyRule]
From={{ hostvars['fw']['network4']['vmm']['server'] }}/32
Table=2
Priority=100
[Route]
Destination=0.0.0.0/0
Gateway={{ hostvars['fw']['network4']['firewall']['server'] }}
Table=2
[RoutingPolicyRule]
From={{ hostvars['fw']['network6']['vmm']['server'] }}/128
Table=62
Priority=100
[Route]
Destination=::/0
Gateway={{ hostvars['fw']['network6']['firewall']['server'] }}
Table=62
+9 -5
View File
@@ -3,7 +3,7 @@
set -e
# Varibles
# Variables
KEY_PATH="$HOME/workspace/homelab/config/secrets"
TMP_PATH="/run/user/$UID"
SECRET_FILE="$1"
@@ -19,7 +19,11 @@ log() {
local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
local level="$1"
local msg="$2"
echo "time=\"$timestamp\" level=\"$level\" msg=\"$msg\" source=\"edit_secret.sh\"">&2
if [ "$level" == "error" ]; then
echo "time=\"$timestamp\" level=\"$level\" msg=\"$msg\" source=\"edit_secret.sh\"">&2
else
echo "time=\"$timestamp\" level=\"$level\" msg=\"$msg\" source=\"edit_secret.sh\"">&1
fi
}
# Secret file check
@@ -58,9 +62,9 @@ cleanup() {
trap cleanup EXIT
# Get GPG password from prompt
echo -n "Enter GPG passphrase: " >&2
echo -n "Enter GPG passphrase: " >&1
read -s GPG_PASSPHRASE
echo "" >&2
echo "" >&1
# Decrypt age-key on the tmpfs (memory)
echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 \
@@ -68,7 +72,7 @@ echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 \
--decrypt "$KEY_PATH/age-key.gpg" &&\
chmod 600 "$TMP_PATH/age-key"
# Unset environment varibles
# Unset environment Variables
unset GPG_PASSPHRASE
# Check the key on memory
+83 -57
View File
@@ -59,10 +59,10 @@ wireguard:
#ENC[AES256_GCM,data:+kiy17Z7q3EiPgo4Ykk=,iv:vOi54XHHLNIO9U0ybpU9Cn68Ymj5W4vtQ2OhTkGAmRo=,tag:h3wdCo5UfNGlHqMpeeBf/A==,type:comment]
kopia:
repository: ENC[AES256_GCM,data:16V50bVVtecbF+TJcXHCx46ZPGNMgAhUOA0YbZHVTsCrOWQvTvcK2k8Iq3E=,iv:/wNbrE5GaFiQPNEp8wZ0JehbXkmah/gPm5ywNE6WVVM=,tag:vW82KTKtJ44++tqXON/SYw==,type:str]
user:
console: ENC[AES256_GCM,data:LZQEz7JS8CMMSlGB2/FS15VHAbko6YpCaWDZDa9tXVnmYLwFs8F39/u8kLI=,iv:WrYox/3LweqafWl96fxmezTFhKHB/2XSDSLwHljdpw0=,tag:bPwqkdeexXItkbpPQQ6klg==,type:str]
infra: ENC[AES256_GCM,data:fwvu96Zhao5RthZptxhuv2NobY1riQzpvD4Ardc8UTwN6+HyfFVR31yTTqk=,iv:jqFEKsP2npZgeRL3E3Va7oLzbHShBO4FxLRYwnfLtys=,tag:qXescWki6oPaaSrhMsUw9g==,type:str]
app: ENC[AES256_GCM,data:VVs8lfo8ZsbYfeKIwtaFCrpV82SguR/xxNnMZXXp8YOBP+6F2Vs5jeDtTTs=,iv:L2mS2RhiUlB9Oq4gwVs8WNF4r8vYv6zg6Fqnpe9hSoM=,tag:WYjtPdD2Lny9Kc+dWVupjw==,type:str]
users:
console: ENC[AES256_GCM,data:v1QY7h6vMmzYq/PTmnLg3M5Iwc/Ljr/1M3nJGuUJMfPN2ATY+GIMUyhYu+0=,iv:32c4YrZfTiu7sv/c9tDItmAE8G1lvc1sm6JD1GRkYr0=,tag:kj1a32+bMUsRdusadoXDvg==,type:str]
infra: ENC[AES256_GCM,data:WdugcvTJEy3/kxjCMeN16u96XM+59sOBF/z88p9f0lPVzi78ZmIZPjf835M=,iv:6G4rry8fCjhB+MF5B3TVf1w0LDSA6farVwyxAp8nKQE=,tag:+mCSrVmo7zuj782swmRFPw==,type:str]
app: ENC[AES256_GCM,data:5A17rXYUBPkFRpcHTOBCGmm9j6uMHtvKkLTpHsYZeRJkoSrA4k9IhVpjNA0=,iv:kJzowaheVckLUKae6xXeIVi+Jc+Mhee/jjmS91im9dc=,tag:f1uXU6JRD4mxAYMlFTWoew==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
@@ -117,8 +117,11 @@ postgresql:
gitea: ENC[AES256_GCM,data:l+pBCzyQa3000SE9z1R4htD0V0ONsBtKy92dfgsVYsZ3XlEyVJDIBOsugwM=,iv:5t/oHW1vFAmV/s2Ze/cV9Vuqo96Qu6QvZeRbio7VX2s=,tag:4zeQaXiXIzBpy+tXsxmN7Q==,type:str]
immich: ENC[AES256_GCM,data:11jvxTKA/RL0DGL6y2/X092hnDohj6yTrYGK4IVojqBd1gCOBnDvUjgmx14=,iv:oBfHxsx9nxhyKY/WOuWfybxEX2bf+lHEtsaifFRS9lg=,tag:tAfkBdgQ8ZEkLIFcDICKDw==,type:str]
paperless: ENC[AES256_GCM,data:6VBrBbjVoam7SkZCSvoBTdrfkUoDghdGTiBmFLul04X/okXOHeC5zusJffY=,iv:iZumcJ3TWwZD77FzYx8THwCqC+EbnXUBrEKuPh3zgV8=,tag:u2m8SppAdxZ/duNdpuS3oQ==,type:str]
vikunja: ENC[AES256_GCM,data:/+wQdoFPTBG2elI9kZbAVWrHZ0DhMaYr4dc+2z9QNdb3TcDS2PEia0JuSAg=,iv:MViZTyUD8YqMmxSTWCQpJ30f/KQdQGOzPlRHHsQ8lAw=,tag:zov3POno139dkMxFDpj2gg==,type:str]
affine: ENC[AES256_GCM,data:XPXrcszsV06YqCJZ7CDqc4rCwqqNlbtLCFYfLAQ8jamLtft8L2UVrMA4WZo=,iv:vrWdBeckxB9tmEE628j4jhU+hSpE6TXYMGt0hh1Cg84=,tag:hlWwWUGht8NqWTZREMsa1Q==,type:str]
nextcloud: ENC[AES256_GCM,data:ROsximNuWYMTZktmLJPx7W1Qol/uT+APgwoCtFO/6ZYYc3KxKvlk344eqEc=,iv:4d+MrfIHjJKAcwhvZ3g4go66uZcieuL7lngKErJd+fg=,tag:QbWOtxeCbiu62GyrE2atXg==,type:str]
sure: ENC[AES256_GCM,data:FULJ2gjJ2gZC3s324itW+CjGRBHIP9RnOqw5TT1UaiUhb7UHAPm1na+LsZk=,iv:c0GnVZkxprJUzPPq3TCQaZvAes9QQuvDXqgVLLaiQIg=,tag:uDxy/Lkd2hNK4AWwMNMslw==,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]
mealie: ENC[AES256_GCM,data:XbYHQv6HBWCXUBRmcbQZN5Y1Gw+V+Wra28Mp+m+ZGl8VRXsKMu5507vGHQM=,iv:zp4ZarqG9KshiBV8F8UksfI2QXmXHwqPw631r/5bYy8=,tag:jvsvXrUsCvpQGIbLV9jTYQ==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
@@ -136,8 +139,9 @@ ldap:
user: ENC[AES256_GCM,data:DT9h51o6z70A4QeoKvCbUo98JFxILgB5tkHeX60CZuCl0GHTa//mRpIUEvo=,iv:Pa9iqXeKDHHBz524zeRImYEkXmY50s7Z+Z4KYt3sNT4=,tag:UTS5VIqbRA66UVDrDXwuPQ==,type:str]
authelia: ENC[AES256_GCM,data:G8ZGsLKqEmMzQ5NMAgirF5BQraHNqixtI6dyyaeNhTdXebjJZML52xL36p4=,iv:ZtHAsFYmrQxr+qoQLPW/eme0+nsT148KRsXmW/LNLlU=,tag:Pvjs/eylkgxJpmGBsRmjcw==,type:str]
grafana: ENC[AES256_GCM,data:vWmU3ZKcolETWAY74C3OMD8gMXDeYk+DqssACL0xefIPi5IkbrhYWmnWAnA=,iv:wcRms3Zp8kPM4USRPVa0UHpCTK36SWhK9C8yHSWu2Cs=,tag:gU5S/6fdMZVd/ih3Yd5uJA==,type:str]
il: ENC[AES256_GCM,data:/CyMeo1+rIUAYiB25nI0,iv:jsyiiRN5z9GqcUnTZ0CZo4s+umTc2zeY2FPp+tVOC9o=,tag:cwOHcqMysCxX57w3a+Pzpg==,type:str]
morsalin: ENC[AES256_GCM,data:YryNch8hF6rx,iv:bNIBur3Jcib8BvKjJ0MejpemsurYTP8rCxo6b2R5yEo=,tag:9dIIgqEPtbeixtgJ1OtMnQ==,type:str]
users:
il: ENC[AES256_GCM,data:9b9OU4Nt60/XdUrwnhJh,iv:7ZqOYqM2aibgcFRxw1ZvOdBJMZUfOVbNa+2sMzrXAns=,tag:x87IG/HETASiC9/HwyW1Ig==,type:str]
morsalin: ENC[AES256_GCM,data:rERjBNLZXSKT,iv:VuD8ZGfrd0wQ/5TCgLhLN459ZHPepcZyv8Kdl7TsMc4=,tag:Xp/fjve1xn0Wjk7ExShCLw==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
@@ -157,9 +161,9 @@ loki:
#
#ENC[AES256_GCM,data:yHgd8KBDPYeMjKzUOimdOA==,iv:ozyRymtPEII2luBads2GHyLf4Vdhf4EXNaF82SNmQm4=,tag:1mOJAmR5kVRBjm0SbQkqlw==,type:comment]
grafana:
user:
id: ENC[AES256_GCM,data:32LNqOb8pzi0/18=,iv:YJrYaQRE+veDhaEUefGWLbNJo1toHGmEOpqrNV3IDfg=,tag:ENryvH9ec3EbDhBB2bdHug==,type:str]
password: ENC[AES256_GCM,data:MFw7TAvzpL0EW2o+w6hF5qrLYVkn0HsQOXqBk9AQq7GxK4uAEDCi/YL3goI=,iv:HSpJL2CZKXHQYhOJLy6HzWARootl8Y1yMGhaMT0XRfM=,tag:t0VHDYHCZJwDcR1VcRFdCw==,type:str]
admin:
id: ENC[AES256_GCM,data:qwz/L8jQXvZKlic=,iv:s0PL4GwTvr/SfzuFgZESADnepagt+QKwt8XmqsMLr0c=,tag:2ozh3jpPFuqXJAx/DpgF6A==,type:str]
password: ENC[AES256_GCM,data:BDTWzGBsyr6dw3tQSCn5tFDk0IZxNc/Y6LYX6ytn1EpLhBr2CW3YE5Dsk7g=,iv:cbYmvG3EZO5ytYtoIAKpewdE81NMqP4YXrdsj7n87SA=,tag:wuFamPPldQYJAKeX7zLFnA==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
@@ -181,18 +185,25 @@ vaultwarden:
admin:
password: ENC[AES256_GCM,data:FzD80H5lPNyjTRGd/IcIGir35KLF8gN3qmTzEQrlfutHh08mk0Vh9X8irHA=,iv:cfn5432g2MvkuBJLB2zDJmU0sLgMefVvpy0bP/4/oPY=,tag:7MHEv8XswdQZNTARvxs55g==,type:str]
hash: ENC[AES256_GCM,data:Ae7bhnL5pxfNV3+r/PCDIpxx0tHcNiB/s4sm7OoxVpp+tcEpXZ9vsv38sZjx+Z8t2vlmiYHc72PEdapcAihleuLMBPM1dAVn8LqzzWtVhfmCOoUZI8Z5L3VL8eyyz6npiw==,iv:c2MEIbrnVsR+bUx3zLLTnKSElFTH7JRl23HmmTlWEBg=,tag:mnMrER9pQEKAdloYMeRa3g==,type:str]
il:
password: ENC[AES256_GCM,data:mhLb55ENatpE59Rbzk2Uq6iBKc0Jj/9x4fOANJOHR0WvSxTQRKJ94cCq9Ykp/chWbdgYYPrwU5oD0Yo17zqb,iv:6bzKq5WaKhuOsQ8zSSH9ZrQYbDPB1nv/bFoQou1ycL4=,tag:bSmuUodl+/9nzxZ7YBoezA==,type:str]
morsalin:
password: ENC[AES256_GCM,data:ibg5/MfLH7pSY2pEmjM=,iv:+aV5muP/9BYoKwTGQxKEL+IGY9P+O3GVKGgSuTzT+U0=,tag:rgqcmJvd1RtvWJ91PCxYIg==,type:str]
users:
il:
id: ENC[AES256_GCM,data:V4kWLbzhIM7ONCt7PtxB56oilw==,iv:b9mkOmmOmyvlYI11ASRh4GQl3NxnvtoC9jAx5DuRSwM=,tag:Eo5a5UnvGVXY1jofbMgqQQ==,type:str]
password: ENC[AES256_GCM,data:Ay0aPgrP75z3n/xyELAPhi4Ov4a62M3lhtpByDkc++TGq+a2bmpdt0OhBfsCSjY/6ads1EUhqQYscTE86Eln,iv://EEyABWzFn9kiKxjz92zKbzUtbnAPf9oNxf9s0nlLo=,tag:cZpqyTXJuO2yQByHMTWwtA==,type:str]
morsalin:
id: ENC[AES256_GCM,data:fXTVMR2iUa1lfyLjG3UI1Xuys80ylFEQ+A==,iv:KqRhjFULUc9BjGEepBu9I3aZparaxRhLos8Ztz3jPyE=,tag:1E8DgiXt810B7UYZLE+0yw==,type:str]
password: ENC[AES256_GCM,data:e8H0wYtCbVEDDXctbJQ=,iv:Bewk1rEsDPD5NVzZfEM2QfzNttwklI6KL7kFgFU3qvY=,tag:0U8Vg39ZD05AWMp6hQkkzA==,type:str]
eunkyoung:
id: ENC[AES256_GCM,data:OubNz5ueQU/KksljCvS/X29rhDjvipkgzik=,iv:mULicCrst9ciC7lAJrYIPV8Kx4Z/JAEbupO/Kti5DoA=,tag:0U/WQnZ8ZCL5yfkbd7Y6oA==,type:str]
password: ENC[AES256_GCM,data:M3MqxQTZdd+SS/nd,iv:KEBZ8eBAwVm0mTwDf3bJRWwtUN/M+an6BMV9N34pXq4=,tag:Qxxca3kq5NH6YbJWK002Gg==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:HAN9BBEl1CW11LAf3x8=,iv:hwqCErtmPqGJ+y86D9MoxJwixvbcJONlyT900Y5DOug=,tag:kCxsG353ltbOCKLe85adCg==,type:comment]
gitea:
il:
password: ENC[AES256_GCM,data:Bs5/t5mNbSv5+ek9gNHZp5qqxitM4Kq0Xgh2JV6LiFw9lZJSOVT4JPLRP5M=,iv:z50+naWOTVL8lEgBgm51j6hLjS8ve2UcRRKukvtykM0=,tag:TF9rPxjoLe/vAyvl23PiCg==,type:str]
token: ENC[AES256_GCM,data:CiYEXEKLLRDp++iga5YmhyPB2bSvqhhDgSOhmiulp9n9SsBVQ3s5MQ==,iv:+oetgEH/IORz74Xoz5zgDjD3BLyledZTqlYlCWaDrRk=,tag:S9O09YEMuSexuNW3ojEw5Q==,type:str]
admin:
id: ENC[AES256_GCM,data:PtE=,iv:44l071j9ZLt3T2BbpAho70soiHxzBqp4KeITxrjdem8=,tag:yQt8jyEadk/GnrxnCPVKdA==,type:str]
password: ENC[AES256_GCM,data:EazzQF9D/s5TtYKBApzLQT3S7a0itGm7wGtHRMi6J0C3I/gBNhpgeF6dk8k=,iv:SGSiAlqOO7LvTlyVmOHU13Vq7OANo3eAeBCwioFpi3Y=,tag:4Vz8FRHEv9G+at/zZq4YMg==,type:str]
token: ENC[AES256_GCM,data:z12Oq4OFCCjCXn85cVSfSzxWt7b0ytuA6TAn3Xf5CIhvKuoQD43WnA==,iv:BP8WDOAXkuA9fMjfLR7BTyTqjEbjSmwgSrJfqCutwmQ=,tag:s7ys3V+QnU/Nmkccm3rcDw==,type:str]
oidc:
secret: ENC[AES256_GCM,data:qjQosi83oaK47wX4VtDktDFlIU3FQgmDpwyiSgJNPDq2Dtc/QEKzdv5/ZpQ=,iv:aUJx5a6Wj7lhaD19aPiZWIE/MWKUgH0muxtTSkwfg8M=,tag:DttjXee7ntxRAbqbFq6qeQ==,type:str]
hash: ENC[AES256_GCM,data:iVls8UzdP6JTfRosET6nsk3RcEtFQ8ak6GtPuBjcqAv3lyA9oSLwvvC8MvGaT1aHCB+5y/lspuloHEaAcVGNuzGCIVLg9Adut4a7LYDTHNOZnJIKLj8ldL1ytD5XVdbeBhZGCqoTs088oO0HVCQiDzpJL5NdmM3Ru6egyYBCLLUOlPA=,iv:er63GEC+kxNDscvspvvLiq17VSg0GeZ2w3jmGojF9PM=,tag:F1pDpaQrVdomIlZ8psVpAw==,type:str]
@@ -201,63 +212,77 @@ gitea:
#
#ENC[AES256_GCM,data:HvMeGuC8JwK50pO1E/nm,iv:5NFTyjesMX0ZnBpH+hEv8jQ0G2NvrDtT23CUyLbQcUo=,tag:qWmPvQpADTeD+W8nWXRQvA==,type:comment]
immich:
il:
password: ENC[AES256_GCM,data:PbDFc4m7rNPPN1mCjcvhbKwf/EbiJxdvO/iMspf9jMuCqQyGv7h6VrZqk98=,iv:hlMAp5wXXkFO9+ekq3A2/ioF/EX8Uau0puhb4TAHkRQ=,tag:pfS0W2JNaFNMpBlKgZ3Pjw==,type:str]
admin:
id: ENC[AES256_GCM,data:DclWIxkt7yZl/8EXSWpOKhVR8g==,iv:ekuWHM9tzQEGRj5Dz6txgh5H89dWVRojjICd7td3QSo=,tag:ZSBvlXtGrNn9T82Agn/vtg==,type:str]
password: ENC[AES256_GCM,data:AcaAeRVzeKCp9Hhx202DMuVTOmoPdXrUqpgwg6Nj/F7b9rCnQRwpsGGmuw0=,iv:z/PhfW75B08K+zbxBrEtBKFYWxTdRdgaicSYHe6yyJ0=,tag:8K+9QHjUF6lHhwnNDT9L8A==,type:str]
oidc:
secret: ENC[AES256_GCM,data:9ENcp2Ns21OLXDY05zRoSdP+93EiwSH8MGzZZpxK7sToe4QLUXWt9w6xQIE=,iv:Q/VcnArZHs/J2YLRVFXt3Mp+LYfuq4PD/trqO8Simig=,tag:BY/mOyZpYmoAc7NrASlmSA==,type:str]
hash: ENC[AES256_GCM,data:mrML2CWFFtGjq8wfWipVpv+pjJRSHe74VGC7Eoa6588R5C/sCnC3W5aI+dsRCZN3LRCjHAkOJJgjeYrwcXYdKRauXsAYR51dNSsHqqSN3WebLxapRDwcYu5e4j5RN1aPHsysr7GaQ4hhe5rKW4ORCGC3Cp3Ob+LChPy4bdCAZG3bN9k=,iv:Q4hmqhq+dvIr7DxCpcqP4E0NKyFZkOeTnDpGctmCxXM=,tag:/gji6AFkHnYwkQf3FSQUxA==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:bzMt0Ox0Za4dOhoo7S6dYCdK32JI9Q==,iv:PRTryIJk0tR545XY0LoHwklvsJp5+A5bEljNmzUvRhY=,tag:EVsjRUGMOadaNbMu0Xr4XA==,type:comment]
actualbudget:
oidc:
secret: ENC[AES256_GCM,data:TE2umZ9Vvr7cSfA2+TAfRadIWZN3hyOKQ6U9NqJFm5e9iiw1avI+QlnYcKI=,iv:rUWoclBRqh0tsGnMq29395Fn2NP7AXnSCd0s+S8jQ6I=,tag:qPX/TcdIo6BJeex7wmi02Q==,type:str]
hash: ENC[AES256_GCM,data:UjhNkGj+sxbnmPUx1V5kVYwZnzsB0aEvN8YV29lcvMbSnf9xpQWwD5C93Zu8SYrnS/p88qZpGBgAjr9Pcly3y0H1YMRt9zzbHZU3Uo0DPDrSWRQdeB/8LkcM/cwMAs8arS6PO03ECNnN5Z6aTmFdFnLjUkvUuSWMFscItAzMzhWCpeY=,iv:B06LI7Cq3NN8haOLfN3gWIpUFnvdUlq6D2XmARojDpk=,tag:MflE8qcY5j/aAA7xfPCqng==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:McPUAbIUvtC1gdPaxTgAxAMCMWcLfg==,iv:Tp6idRf7he3sYzo8LW596C905JAaoTIhIoDUzSyRT0k=,tag:4mZQ0Swu1X9uuwjsRNhr2A==,type:comment]
paperless:
session_secret: ENC[AES256_GCM,data:siwCs2noeVpg9DCEZybnmo/oz11BdrHSTnHciMOu/6g=,iv:XVjhu10TIujIdUopN9+TVVqRade9EvItDWxym6YXnZs=,tag:TxLYm+4Bo7IMaTQBtMg9pQ==,type:str]
il:
password: ENC[AES256_GCM,data:9bJHf+chTg1rppgNVafNgEuvwQ69Gx+w5d65hu68q9XeeaVb2pO9HE4BOgg=,iv:1kaXBg/iOoIZxDjEVEdaMJLDtp6zQjep3vxLmIgQN5o=,tag:+MgX8Oa3tmhjx6u9aHkDfQ==,type:str]
admin:
id: ENC[AES256_GCM,data:8uo=,iv:f/qtpDb1Xe0M6Gd2VFP2vXULCd7WOn7TCxLlaK1dDbA=,tag:eNRMPJtLlA3Vjj79bSFxuA==,type:str]
password: ENC[AES256_GCM,data:TAA+TRTYRUSw47nE7oPDQmOtCBZpf2WyxUIIzftWq16wQhseODhH0R74X+Q=,iv:V0tzSvW5iYzEUgcxempmyD9ermVAqg673liiysT4jJ4=,tag:GuxtZ7EvgwvlFWwg+C6Jsg==,type:str]
oidc:
secret: ENC[AES256_GCM,data:wjRDVCJsINM4z5946a6uZD+6bhN5BChLMdRzgMEJFGRGFNcXd7A1p2Iqn4I=,iv:Y4QDA09L8ULKr4hhvoiduzCD8Hifo1gAnpzjCr8e520=,tag:R0RvGxYnXo3zwykXJykRug==,type:str]
hash: ENC[AES256_GCM,data:pali6WwPNhJA+6QL4O+tKv42PnpGqmojb8JQUZLqxGizv1bJSCgdUN8upCy5Ke0DYZs5P+JY5vh23xfMZFnHduGxGwOuPX6J5lYgvJRV58LqS3/+yIBBprTJyro3MwsurTTEWesgKMr8/2H9lirhaLjWUOSPxAmQ6e4wPNpHycDVyj4=,iv:cg2trI7t1MfIcMo1/M+IY6JEl2msDoKRGgAx/Y5nyGk=,tag:gnOq7sBq9z5zrRY0yhIabg==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:V7DJHA2JQirfBsrCGhXrhg==,iv:+jYqX9hGNnuyYj9o9LpCYFVOoD6nSrtc4t40Ag0mMzo=,tag:1wSxKtkJm42reUxdwYDvlg==,type:comment]
vikunja:
session_secret: ENC[AES256_GCM,data:CMyw8JGHyTczGsrOJJwQBKfXMU4Sudvwkur1Lgx4o64=,iv:F2VmpqddiDT4jGaGDKGl6FARsQOt3lLz3X6TjC2MIVU=,tag:UJYyzrl/FX1BNwY4ROFncA==,type:str]
oidc:
secret: ENC[AES256_GCM,data:QwqndYsfr+fh9OLkHYtLYCa6WUdhnL7A4btz1d1eelTwq3Kps5S6BUN5qZg=,iv:51N8byIAAUh4ky7YBAuEJOBEWu1d9AX5W1m37/cLlCM=,tag:GD7jbxNGd748TCPgqsxyMg==,type:str]
hash: ENC[AES256_GCM,data:ORifyT4u1V2CyBCNBgF72wwS2i05mlzA4iIVEa1cH9aaE69PdiQvGGzMHK+tmlfpVaVQEENSt1QDUSSlMyeuZT/3a0JwAvlz+XDbpS7bicL2cB6DCa4JyEd/rbGRXs0/COfxPxXzYv7jq9gd2uSJ+cCGYb/93WuEXSEI6PHi+FF7N94=,iv:FVSGySa4YB2vwenqSagBzxeIexg91ewvcQMix+etmng=,tag:yyQtOgzOZypba+rV3A1K9g==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:EsRGZP7snPchEAMoQN5PoQpiOA==,iv:A/8POGq3pIw7aX5S2vyKtI2vPqH0FT6yZnpe/vVbifw=,tag:BgUYHX2zxIL7yLS0JbI1Yg==,type:comment]
opencloud:
#ENC[AES256_GCM,data:PZS7EbvMHqHGorNUGAWj4dk1,iv:vOE+djRAvBTMM51kHi6kG5Arw3uPXlJt1d/BpcEaD0c=,tag:AuoCHLQz42CYvVVdKFWu1Q==,type:comment]
nextcloud:
admin:
password: ENC[AES256_GCM,data:VKG7sNTTLHCXRGf4SAlR91+hvc7PaNrnpJX/4kItVcT9W1Hdl/yKgHHD7M8=,iv:WwWnx9KuN+i/Ugwv+HY4IGDZrLHk71hsobGFOn9kml0=,tag:SS6ihrtZjLnlAJR59lw+gw==,type:str]
id: ENC[AES256_GCM,data:uSov7SN1yB1PhTc=,iv:5yxabQcY/XsBhn531xZg3XYsnxl3K59WuN7Vz9M4XG0=,tag:BBnfZPppw+SDGsV8dK2F+Q==,type:str]
password: ENC[AES256_GCM,data:j/wFr5EV00WegWxIGj1k3U13sQjf1GgUofGbh9+i916uudfdklhcurujhiY=,iv:aHEKjLvS5lnayRX/NJ98DxQ40mfqssidubDaP2RVb3k=,tag:zQRE9AsiAlXe58r4VFJiaQ==,type:str]
oidc:
secret: ENC[AES256_GCM,data:Sr4KkKkYdkU0UWdpfUF7PyiGoerjBiw+sOFcENyLxw0FRXGG0Y8gv5uGb4Q=,iv:LbGsNM3+iY7bWFQe88TepVKUdiRQWZ+K7Ubn6ze6lV4=,tag:SbcfIAMW9ZprgahOFU4IQQ==,type:str]
hash: ENC[AES256_GCM,data:CkstbIYQmi72QhsbJZN0lQedgCn7TmGpYcYj0n+NvJIoTlol8G9N/88cwGbVoGK9nEISv54FL94cEJFppnMIuj0BHrhasrZsyI2/Lj52YLWdwNJWNQ+iYt+Ifp/1kI0zqmdoajzZ5DS2w/1evCBC1+JdfTRlpVXmSsHUIPIHelBRj90=,iv:vwvT5TTkF4woxXOvrRRqmrdLXf19s47NIDtdT+zLp0U=,tag:KC0MS0DTH6j3zIHOjCFOSA==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:k55osvepVeB1RC5hZ4IF,iv:AlhfmWwn/DiSESWc+ULJSOLUhnrKAIfWr7MeiwV8qc8=,tag:hOgptwUcY6nVxPIhu+DYgw==,type:comment]
affine:
secret_key: ENC[AES256_GCM,data:LLX78DpYnha1JWhgw0sHLzIVq/oIzvT+nB7zgli4mroGbnt7WZaXCx34zKkYRwYj/+0L4IFFVdkzKtK5DO84SgFkS2Bk2iNdCMqIx80CpyiD8IWAcyRu5d6hh82PlgyxU80T/4nbLbIn0GLubPTTeUX8GC3VxRU=,iv:DnmvbhlygSHes0jAkIm4+WXMUQLzr4R4dNa33rO67v8=,tag:+2wlh+/ekiTyShWM4XBbUw==,type:str]
il:
password: ENC[AES256_GCM,data:4zxiQAzXTR+fraRjYT657BIwSqrih3lMPFFSibQdardRMjskAbuRYIQA6mo=,iv:ub3giRG9vCFSuwRXDazYTqWbjENzQUWR36290Kruj1o=,tag:C2Ixd2eTEgzBvUNCNBtJuA==,type:str]
#ENC[AES256_GCM,data:Fsqc2JDp9dvfgiCjdQ==,iv:3DALKKEXaP8hzXRvxD4CgfFpOiPPsOa16OB94n8WKp8=,tag:K+FF3zGrc0YLXWK/R2L3Ow==,type:comment]
sure:
session_secret: ENC[AES256_GCM,data:InHsz/jld8E9TwI8MWpxk9x2I7dxlIsY9R6jtDK2pBA=,iv:HY5yXEC2Dce26e9/vXTIWELvVd9ZjhcCwFD0jhz5pPw=,tag:LLSJovZ0RH3CUK+se7R4Ag==,type:str]
oidc:
secret: ENC[AES256_GCM,data:eRDBrqLZR7MFLlsUwk7Wg7FzxDov7vJLIWQRuKq7vrXbPSJkMcy9jfG2rL4=,iv:UaSoi7gODXgjzihJIDVIdDHJcSAZNV8UKfGeM6YzxqI=,tag:cOUDblcMStP8E4fp+s1WRQ==,type:str]
hash: ENC[AES256_GCM,data:jE1CvFo+mjb/Xc3Ft5ky7on03vcnv79cw/5g/xaldXsv94VRrIjmfGMgHAj07r8j5mDpP34A5bYO1PSe9DYrwRcsXa9OUQuzm/8avFy9wVZDhBUUAGR+jiW1BP9hc6nmSpPVPtle+3sbqOB0ZMjXWwlcAcuknOtuhH1mzwmaDP9yf+M=,iv:CSSaXY/6MpHBMhPLUWPkabIeJ9zpZkcVjiEhxVF0zJM=,tag:f72ekkjJs7Qmh1K9wC8L9w==,type:str]
secret: ENC[AES256_GCM,data:9BSvpcU9BJctSN9bkPIAsRxg8JNHTWvOKdpJFhm//CUDm/Xc7oC/ANHf5no=,iv:JVQLl/rp65kZSK/4SpVXxtiac3Z35XNkxWm2+lEdq/c=,tag:WgfaORiNlrO+wHSdnl4CWQ==,type:str]
hash: ENC[AES256_GCM,data:EjJ+1fP7/9wG2jG0Jv2hxMLtErqxjHBstRjru79dd5ZXhqwT7S+jpLfl9WpZU9qi20ps9YP4qe7G08p6NJNXjYhQj852GQxEORRh/9StAZsPt3p8w+ePZSVbivPQH+FpPKWYxoH0VR7y3TnL66R0tKRLh1fNTc5jRy5rU5r1bfs1jZ0=,iv:0y9FxW4QdD7qHz3bPRWlwHFpvOsvlYhVrOItB6BzaE8=,tag:Wc7MZhP3QRYmvZcjpoEWtQ==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:H6BtfLuevnDCEpHSmf6pxQ==,iv:9Jw0UZwVwS2It7c4e1rAN/BEiqDKp9DHD4W9xdpJ/Vs=,tag:Xj8HKvxgCA260CXBVK2S1A==,type:comment]
outline:
session_secret: ENC[AES256_GCM,data:A26j8/ghGA9MjDiuq+H84iTFXkHZp3l3LbGKO9w+Cgv+u1dkTF5q4zuBnOSBi+Tnz+2Y4jIoxsac+CS0dguRMg==,iv:NzJiJxVxOvud3e4mP8urnHrqugE8SmjFVnZtwfzrUzs=,tag:YR/jexb3G0HfC2qHpn6fPA==,type:str]
utils_secret: ENC[AES256_GCM,data:ACI+NZzqHBsYeb4WwTJ1nfJcy6zNwJn2hBqA93aM5cgNWQ4KtQHDXgmS6UTwmSpxrteiaH25J3Np03H3eQoVeA==,iv:nitwxxwTPQvoQXGLVMnk2zsdC7M+JIXkTY4zJdQ3DFo=,tag:IQewG7EE9IgQk+Rfz7M5Iw==,type:str]
oidc:
secret: ENC[AES256_GCM,data:zR6sN205C51BIiQxLYOwC4ZbTYGr2AveiPeEbdadairmfnNJkGOtm0zT4Gg=,iv:uyYoJYuAuH/Gy2dlLr2SkkLYq+lMdwBgmzUsEj1EAKc=,tag:uhgvE6BagvPPKf7Y3NaGfA==,type:str]
hash: ENC[AES256_GCM,data:xOibOUdmfhvUk6HABHf/MGIaUqRtrmbBpD5eTIrlt+Ll5IxuIaECMIyBufqV6KStoNsAxtlWmPqoVYROnVh7Z50ntywP6w6YNFbihMGr5tYnNBAS2ITViCq0Z7GQpNVmhNkFbmZv4bX14YOI557CS1KeDVrKrHnZ3fPgEgDwEiUdCwo=,iv:3lVQEw/gmTvJ6wteyKhAHAYUUw1AfKku8YEveddJTZU=,tag:0jimA4vof+nKOQtCOrVFdw==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:Fis0K+QOQwUfHItGI5U=,iv:kRmt4WhV6bBwN7Xl2xLrbxnKuLKTBC5nI9ZnQSIgIwo=,tag:whb1oOEX+fry9GS1+RlPrA==,type:comment]
memos:
oidc:
secret: ENC[AES256_GCM,data:+rX8znej0jjXybmUjoI7DkybNkNeg15Py7bav665Uej48I5ZAZbUiKwccNo=,iv:UzcCqXxvweosRL8afhyRBB2ERm1PNs+tuxeDwL7Mcu8=,tag:+gJWSAq2BpSlSw/iwhIbpA==,type:str]
hash: ENC[AES256_GCM,data:D7+37XTpDFRabT5YEh9nfxO1Q9Sdc98jAxPsjkPzj7bthn1H0dlLYZSJ2Fy8Ye4vjIFO+TZ6HWx8N4cSwHTfgls3EYFh1TW0FUnyCY1kYd/+ljfZB9Y6M+i5zb5nEIBHI32Sk7/B20cGnr0SUb3EKU+SmnACgZ0fjKKyUpSzGu75MH8=,iv:3RkTpgy85JPJqu6AEKrw8RY2O+L/CldPuPpN9ln54u8=,tag:Nl0DL5tVenA/fdRNOGyPkA==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
#ENC[AES256_GCM,data:ATLTbBi1RsBr2ldHDDH4,iv:RFbPz/46BIGYv9Wo5Jxw5Swi4Xo2JgIEI4IsO4rCQoQ=,tag:i7/2ItQSFurrmdNaBWwWAA==,type:comment]
mealie:
oidc:
secret: ENC[AES256_GCM,data:ldsfwWnexNNM4r+aP2h+woQROwbp9MpxAz8E/o1Q53GxcEwtixqvP6QZGoo=,iv:6M/lfuDU3IOd0nxLi2l02OD5FopErhSCp6AhxBGTI1k=,tag:3w0p+wi9T1PqNmgoM59gug==,type:str]
hash: ENC[AES256_GCM,data:YmziHxsFPJ93uMNG6/EUiPEfMvvAZM8/S5854GJ/fPPTMvXj9cM2sovkSrcNd7H0ac5KDJIcJoD9SC5lWKCAbjKzxHvI6CdI63SM8bExrDL2PVSGAf29VLU/cz8rQtZS39GWz2v5GWlpk67Emy0T115vruIGfDlan8zgQKK7YIWyVMs=,iv:xmnBYjBIWq6P2g5DyMh+wYskmJRcVDREGL/yYhJHyRs=,tag:qMWXHiLmAy5UvWFvv3Ct8g==,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]
switch:
password: ENC[AES256_GCM,data:qu0f9L7A0eFq/UCpaRs=,iv:W8LLOp3MSfd/+EfNEZNf91K8GgI5eUfVPoWTRES2C0Y=,tag:Q5FlAOfwqwJwPvd7k6i+0g==,type:str]
admin:
password: ENC[AES256_GCM,data:cwBJRIO3eUgezyN60dU=,iv:Ab+EpURW+MYT7RTcPHi4FvQiv4m6TDhAb1/xexkIHCE=,tag:JEWZ3cqoAfAPfwXz7KmINQ==,type:str]
#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment]
#
#
@@ -265,8 +290,9 @@ switch:
dsm:
key: ENC[AES256_GCM,data:jxQRPNuioZbznadJa7sdhbntABsi+nc6Y5TJsyMXwKRvVUbQw8p3snp75d9WVmOfq4uj8wBGen0noa/6xtWo4ZiHsIg1Svh/5xAN37zueB6NmK/z+BW2y8HaIkNhjcinusnT2SWE2ahguizMNM90FpXgmTt9Zv7wVwRkifDLWpH+rs5zmyMWPtpT2RN3+k7tVh8XWVevek/DxG4h+jtoYhTVzndMC5oe/A60MHBJCj6kaksGlX3vIDbRo5A0FEKX8uWI6k6U2osFc4SHIvpljYmPagj3EwPaTc3mbl8IJsXFVH4=,iv:7O5oQa1fELjIt6f3nQ+fWDFirAexgioS36/Nozh656o=,tag:t1RHmY8QC6mE9PVPJg426Q==,type:str]
crt: ENC[AES256_GCM,data:N32+8CItiwbW8drpnL65weS35SY8uP8vcw9wBDFOxGFQjs6EyEwsMUVh1ndMpmDSUKWz7c7ji0HisC710RqnZw9l2NMg6R57DeXR/WsLW4LiAT7sFuDBcqorTB+6Nk0K9wLLdnsKpUQgl8oV9ffnWXZdfI5skKCDMNB40WJAYY/3wx9iT3wDQWaunq/1NT0SZHrtXXTj1JYiLbfDaTwTvkuqqUv1cXvOjonL2Cp4aNT/zjwK6c/TRbKdhIs/7tnUUE/lJx74eARfrMQy/3y6h2xK9pgruASuJxMw9Tyaj6Ya0FMNMIezO3GPQbFCE/IRfmCE6vX2RXUjVqX8wd/d4m4KNuMsN3hbwC3vQ6r+DcYdaTUfGIu96xfKSiSax/ZPQ4JhTyqthkGgpE0Ob67aVELrZkyhc/kvvSxafVSvP63C/nHPQnXMgitdRddYFq7487Vbq03frxiyID1WkqeUavc+Tn3dyA8c7aqVvbW6vZCAwUzbKD0nwPuBUtKZQpJKxHvtx2390PW7a214zkPLcw5LH3FnNacopiNfs6dNEeW/UsGysYkoBRXfrAPMX4UL53TvUTrpuCBhthJ4rgqjhgTfq9GtomP7piuf/tnMAO33qSHPM3w2ocLWeLyOiqYESFmXoBAsiu33LVzuVryFVw75pgrGAsc2wwKhcu4JC0cNgUE44ENIIjffVQX/mcvPvHxuI05vtzM0N8kOFPwG7iAVrO1eUEpwUjZwUwkk8QRsuIhZ6W7aYx7TLdPDpjmy6XCYGNHZgHg6jU7v18KkPep1YarAnsVYFzHQwfZIMOzW7DHlHq38NJW8lWq7zkg+kY6JDVy0nttlAUSskWNeCHdI5Xy3Rz3t7V6t1+UxkSy3roQCZOYjiaknwrXSctsgqucKaJCq4w0Tty36kaIXwOQYVm9JqDIztOmer4fW8Es7OEbLwA==,iv:26fGb288JEbtA0UcAmiYcN+UunrUOw2S6fKjGMetgwE=,tag:GmUJb9LJ186HNOF4AhfmLg==,type:str]
il:
password: ENC[AES256_GCM,data:6LiNif7aIGgGBBdVYpl4K8L8ev6EPru5x6HvX2yJ0oiDQb6G9AI+ZsaKamc=,iv:Y+eijt1PmNZR9c9uCzBnzJT9BDc3w/P4VzsbvrPRU64=,tag:2KKRtTSYzrJKy9VX/2J5eQ==,type:str]
admin:
id: ENC[AES256_GCM,data:/Js=,iv:GyEcag6KxEHy6xApfzEo+dZF9NOtkOoYaJZEzPa8ing=,tag:W/4zaDxdw42Ap4DVE9ogAQ==,type:str]
password: ENC[AES256_GCM,data:/rgn1Eogw3F2EqArMJXL8Ri4y1W04hGzxy4w1Ct5/ysBjjHGgRbxd9tXSf0=,iv:PISJ0a113rlEL0z0yo+nBYNQNU6Ht0PgFWZzooxIgi0=,tag:UZl0EiVcaVPq1v0MtNCXFQ==,type:str]
oidc:
secret: ENC[AES256_GCM,data:IXJNy9PmMPn9uowSMMrNPYqaW5PZ13JTeu1t7eNlapxmnV3EAl3I3xbMK5A=,iv:UcG2E6zgoKkPfUiHr0A+gvnApCkBJG2GROfacwD634Q=,tag:nSFn9yaCadJGlGy/aCvc2A==,type:str]
hash: ENC[AES256_GCM,data:Y2/FNYbID0trRS5UpP2MX6UcLWxlRoXu9VLeU9DU9whEwNLbf4gYrxI7Q7etQe6HidBuoIJNxKajf3t0fI0ptbXnJaxzMh/v/CsiDg2p568o3KIyfB1PruGRKUrTuJneREUHg5jRXMYCwcRUQ4C5WgAyjd2spGlTQO0OLEqh0wkTtvs=,iv:YTYoaBy3QwlSrmx/K5woiXAHrh0RkawF+uQ4rQuP7WU=,tag:Ej6ZjTFvKjw6BrXbd0lf0g==,type:str]
@@ -275,8 +301,7 @@ dsm:
#
sops:
age:
- recipient: age120wuwcmsm845ztsvsz46pswj5je53uc2n35vadklrfqudu6cxuusxetk7y
enc: |
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0TVVta2V6UHB4V3NmV0tR
V0hmbUw1bUpSSk4zQXZ4MHlaVzdJU0VSWm1VCnZaMUg1cjJyOEFyOWxPNm9lWkVm
@@ -284,7 +309,8 @@ sops:
UmliaFNxVTBqRkI1QWJpWGpTRWxETW8KEY/8AfU73UOzCGhny1cNnd5dCNv7bHXt
k+uyWPPi+enFkVaceSwMFrA66uaWWrwAj11sXEB7yzvGFPrnAGezjQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-04-06T14:32:22Z"
mac: ENC[AES256_GCM,data:OFiSsBBAzOUoOwnAwhaplQQ8k2kUo+Avzk475BpaiOJoaB2c0wsJ3siP15tcLMrav4Qw8boZFo64v+rjdMoNI/MRo1EOYWNr1ZRMqHzwmQeaiMH2QcfoRZ0oLqrn5ekQztuPR9ULjDYZb63AwVGmzseUf4R5lGXgdgN5tjU/pH4=,iv:hqzDwryMuJ7JnkBazzDSznw05m7k61Sk61aPgO3JtpU=,tag:Lhhlgwy+YuQ1S0hkbsjecg==,type:str]
recipient: age120wuwcmsm845ztsvsz46pswj5je53uc2n35vadklrfqudu6cxuusxetk7y
lastmodified: "2026-06-12T13:44:23Z"
mac: ENC[AES256_GCM,data:FMOY7qMDSCzvOUL44zmwLwUVAXfYkat1JbiNeBVQFuUrC4lAwuukxW9MCPs5plj84LOAUMVgMofyudFJh5VKTR6Y0EnB5ft0NnbGgwMwzQnQn7d9Mcg9xPca3ccSbSGNx0UrC+8lTjXuzhoawMQ5ZXZ3ZK0k7JrFQ2El7UUwxEA=,iv:+oj0bvsDo8gidUn6m0FOeWsJOxIXPHhzvtiIbQ1VgcY=,tag:8xLcthizKqWjqg2eQvJlRA==,type:str]
unencrypted_suffix: _unencrypted
version: 3.12.1
version: 3.13.1
@@ -0,0 +1,25 @@
[Quadlet]
DefaultDependencies=false
[Unit]
Description=Collabora Online
[Container]
Image=docker.io/collabora/code:{{ version['containers']['collabora'] }}
ContainerName=collabora
HostName=collabora
PublishPort={{ services['collabora']['ports']['http'] }}:9980/tcp
Environment="TZ={{ timezone }}"
Environment="aliasgroup1=https://{{ services['nextcloud']['domain']['public'] }}.{{ domain['public'] }}"
# Environment="aliasgroup2=other_server_FQDN"
Environment="extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:server_name={{ services['collabora']['domain']['public'] }}.{{ domain['public'] }} --o:admin_console.enable=false"
[Service]
Restart=always
RestartSec=10s
TimeoutStopSec=120
[Install]
WantedBy=default.target
@@ -19,7 +19,7 @@ Volume=%h/data/containers/gitea:/data:rw
Volume=%h/containers/gitea/ssl:/etc/ssl/gitea:ro
# General
Environment="TZ=Asia/Seoul"
Environment="TZ={{ timezone }}"
Environment="GITEA__server__DISABLE_SSH=true"
# Database
Environment="GITEA__database__DB_TYPE=postgres"
@@ -21,7 +21,7 @@ PodmanArgs=--group-add keep-groups
Volume=%h/containers/immich/ml/cache:/cache:rw
Environment="TZ=Asia/Seoul"
Environment="TZ={{ timezone }}"
[Service]
Restart=always
@@ -24,7 +24,7 @@ Volume=%h/data/containers/immich:/data:rw
Volume=%h/containers/immich/ssl:/etc/ssl/immich:ro
# Environment
Environment="TZ=Asia/Seoul"
Environment="TZ={{ timezone }}"
# The new environment from version 2.7.0 to enable CSP
Environment="IMMICH_HELMET_FILE=true"
@@ -0,0 +1,49 @@
[Quadlet]
DefaultDependencies=false
[Unit]
Description=Mealie
[Container]
Image=ghcr.io/mealie-recipes/mealie:{{ version['containers']['mealie'] }}
ContainerName=mealie
HostName=mealie
PublishPort={{ services['mealie']['ports']['http'] }}:9000/tcp
# Volumes
Volume=%h/data/containers/mealie/data:/app/data:rw
Volume=%h/containers/mealie/ssl:/etc/ssl/mealie:ro
# General
Environment="TZ={{ timezone }}"
Environment="BASE_URL=https://{{ services['mealie']['domain']['public'] }}.{{ domain['public'] }}"
Environment="ALLOW_PASSWORD_LOGIN=false"
# Database (PostgreSQL)
Environment="DB_ENGINE=postgres"
Environment="POSTGRES_SERVER={{ services['postgresql']['domain'] }}.{{ domain['internal'] }}"
Environment="POSTGRES_PORT={{ services['postgresql']['ports']['tcp'] }}"
Environment="POSTGRES_USER=mealie"
Environment="POSTGRES_DB=mealie_db"
Environment="PGSSLMODE=verify-full"
Environment="PGSSLROOTCERT=/etc/ssl/mealie/{{ root_cert_filename }}"
Secret=MEALIE_POSTGRES_PASSWORD,type=env,target=POSTGRES_PASSWORD
# OIDC
Environment="OIDC_AUTH_ENABLED=true"
Environment="OIDC_SIGNUP_ENABLED=true"
Environment="OIDC_CONFIGURATION_URL=https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}/.well-known/openid-configuration"
Environment="OIDC_CLIENT_ID=mealie"
Environment="OIDC_AUTO_REDIRECT=false"
Environment="OIDC_ADMIN_GROUP=admins"
Environment="OIDC_USER_GROUP=users"
Secret=MEALIE_OIDC_CLIENT_SECRET,type=env,target=OIDC_CLIENT_SECRET
[Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always
RestartSec=10s
TimeoutStopSec=120
[Install]
WantedBy=default.target
@@ -0,0 +1,34 @@
[Quadlet]
DefaultDependencies=false
[Unit]
Description=Memos
[Container]
Image=docker.io/neosmemo/memos:{{ version['containers']['memos'] }}
ContainerName=memos
HostName=memos
PublishPort={{ services['memos']['ports']['http'] }}:5230/tcp
# Volumes
Volume=%h/data/containers/memos/data:/var/opt/memos:rw
Volume=%h/containers/memos/ssl:/etc/ssl/memos:ro
# General
Environment="TZ={{ timezone }}"
Environment="MEMOS_MODE=prod"
Environment="MEMOS_PORT=5230"
Environment="MEMOS_INSTANCE_URL=https://{{ services['memos']['domain']['public'] }}.{{ domain['public'] }}"
# Database (PostgreSQL)
Environment="MEMOS_DRIVER=postgres"
Secret=MEMOS_DSN,type=env
[Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always
RestartSec=10s
TimeoutStopSec=120
[Install]
WantedBy=default.target
@@ -0,0 +1,5 @@
<?php
$CONFIG = [
// Background jobs mode is auto-detected as 'cron' when nextcloud-cron.timer runs cron.php via CLI. No explicit config required.
'maintenance_window_start' => 18,
];
@@ -0,0 +1,12 @@
<?php
$CONFIG = [
'memcache.local' => '\OC\Memcache\APCu',
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
'host' => 'host.containers.internal',
'port' => {{ services['nextcloud']['ports']['redis'] }},
'timeout' => 1.5,
'dbindex' => 0,
],
];
@@ -0,0 +1,9 @@
<?php
$CONFIG = [
'trusted_domains' => [
'{{ services['nextcloud']['domain']['public'] }}.{{ domain['public'] }}',
],
'overwritehost' => '{{ services['nextcloud']['domain']['public'] }}.{{ domain['public'] }}',
'overwriteprotocol' => 'https',
'overwrite.cli.url' => 'https://{{ services['nextcloud']['domain']['public'] }}.{{ domain['public'] }}',
];
@@ -0,0 +1,4 @@
<?php
$CONFIG = [
'allow_local_remote_servers' => true,
];
@@ -0,0 +1,9 @@
<?php
$CONFIG = [
'user_oidc' => [
'default_token_endpoint_auth_method' => 'client_secret_post',
'auto_provision' => true,
'soft_auto_provision' => true,
'disable_account_creation' => false,
],
];
@@ -0,0 +1,14 @@
; /usr/local/etc/php/conf.d/opcache-recommended.ini
; OPcache tuning
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=512
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.save_comments=1
opcache.revalidate_freq=60
opcache.fast_shutdown=1
; APCu CLI activate
apc.enable_cli=1
@@ -0,0 +1,6 @@
; /usr/local/etc/php/conf.d/nextcloud-upload.ini
upload_max_filesize=16G
post_max_size=16G
memory_limit=1024M
max_execution_time=3600
max_input_time=3600
@@ -0,0 +1,36 @@
[Quadlet]
DefaultDependencies=false
[Unit]
Description=Nextcloud
[Container]
Image=docker.io/library/nextcloud:{{ version['containers']['nextcloud'] }}
ContainerName=nextcloud
HostName=nextcloud
PublishPort={{ services['nextcloud']['ports']['http'] }}:80
Volume=%h/containers/nextcloud/ssl:/etc/ssl/nextcloud:ro
Volume=%h/containers/nextcloud/ini/opcache.ini:/usr/local/etc/php/conf.d/opcache-recommended.ini:ro
Volume=%h/containers/nextcloud/ini/upload.ini:/usr/local/etc/php/conf.d/upload.ini:ro
Volume=%h/data/containers/nextcloud/html:/var/www/html:rw
# General
Environment="TZ={{ timezone }}"
# PostgreSQL
Environment="PGSSLMODE=verify-full"
Environment="PGSSLROOTCERT=/etc/ssl/nextcloud/{{ root_cert_filename }}"
## libpq in Nextcloud automatically tries to use a client certificate for mTLS. Therefore, when only TLS is required, then disable the option explicitly.
Environment="PGSSLCERTMODE=disable"
# Redis
Environment="REDIS_HOST=host.containers.internal"
Environment="REDIS_HOST_PORT={{ services['nextcloud']['ports']['redis'] }}"
[Service]
Restart=always
RestartSec=10s
TimeoutStopSec=120
[Install]
WantedBy=default.target
@@ -0,0 +1,8 @@
[Unit]
Description=Nextcloud cron.php
Requires=nextcloud.service
After=nextcloud.service
[Service]
Type=oneshot
ExecStart=/usr/bin/podman exec -u www-data nextcloud php -f /var/www/html/cron.php
@@ -0,0 +1,10 @@
[Unit]
Description=Run Nextcloud cron every 5 minutes
[Timer]
OnBootSec=5min
OnUnitActiveSec=5min
Unit=nextcloud-cron.service
[Install]
WantedBy=timers.target
@@ -0,0 +1,78 @@
[Quadlet]
DefaultDependencies=false
[Unit]
Description=Outline
After=redis_outline.service
Wants=redis_outline.service
[Container]
Image=docker.io/outlinewiki/outline:{{ version['containers']['outline'] }}
ContainerName=outline
HostName=outline
PublishPort={{ services['outline']['ports']['http'] }}:3000/tcp
# Volumes
Volume=%h/data/containers/outline/data:/var/lib/outline/data:rw
Volume=%h/containers/outline/ssl:/etc/ssl/outline:ro
# General
Environment="TZ={{ timezone }}"
Environment="NODE_ENV=production"
Environment="URL=https://{{ services['outline']['domain']['public'] }}.{{ domain['public'] }}"
Environment="PORT=3000"
#Environment="FORCE_HTTPS=true" #HSTS function is not required
# Secrets
Secret=OUTLINE_SECRET_KEY,type=env,target=SECRET_KEY
Secret=OUTLINE_UTILS_SECRET,type=env,target=UTILS_SECRET
# Database
Environment="DATABASE_HOST={{ services['postgresql']['domain'] }}.{{ domain['internal'] }}"
Environment="DATABASE_PORT={{ services['postgresql']['ports']['tcp'] }}"
Environment="DATABASE_NAME=outline_db"
Environment="DATABASE_USER=outline"
Environment="PGSSLMODE=verify-full"
Environment="NODE_EXTRA_CA_CERTS=/etc/ssl/outline/{{ root_cert_filename }}"
Secret=OUTLINE_DATABASE_PASSWORD,type=env,target=DATABASE_PASSWORD
# Redis
Environment="REDIS_URL=redis://host.containers.internal:{{ services['outline']['ports']['redis'] }}"
# Storage
Environment="FILE_STORAGE=local"
Environment="FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data"
Environment="FILE_STORAGE_UPLOAD_MAX_SIZE=262144000"
# OIDC
Environment="OIDC_CLIENT_ID=outline"
Environment="OIDC_AUTH_URI=https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}/api/oidc/authorization"
Environment="OIDC_TOKEN_URI=https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}/api/oidc/token"
Environment="OIDC_USERINFO_URI=https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}/api/oidc/userinfo"
Environment="OIDC_USERNAME_CLAIM=preferred_username"
Environment="OIDC_DISPLAY_NAME=Authelia"
Environment="OIDC_SCOPES=openid offline_access profile email"
Environment="OIDC_DISABLE_REDIRECT=true"
Secret=OUTLINE_OIDC_CLIENT_SECRET,type=env,target=OIDC_CLIENT_SECRET
# Mail
#Environment="SMTP_HOST=smtp.example.com"
#Environment="SMTP_PORT=587"
#Environment="SMTP_USERNAME=outline@example.com"
#Environment="SMTP_PASSWORD=change_me"
#Environment="SMTP_FROM_EMAIL=outline@example.com"
#Environment="SMTP_REPLY_EMAIL=outline@example.com"
#Environment="SMTP_SECURE=false"
# Optional
Environment="LOG_LEVEL=warn"
[Service]
ExecStartPre=/usr/bin/nc -zv {{ services['postgresql']['domain'] }}.{{ domain['internal'] }} {{ services['postgresql']['ports']['tcp'] }}
Restart=always
RestartSec=10s
TimeoutStopSec=120
[Install]
WantedBy=default.target

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