move to recommended file and directory structure

This commit is contained in:
Tobias Petrich 2025-12-27 02:06:33 +01:00
parent 7c2c5e06b2
commit 3cb956b607
No known key found for this signature in database
GPG Key ID: 220BE847F99B1B62
47 changed files with 246 additions and 324 deletions

View File

@ -1,217 +0,0 @@
- name: Deploy services
hosts: all
become: yes
tasks:
# Install base software for rootless podman containers
- name: Check if systemd-container is installed
ansible.builtin.command:
cmd: "zypper se -i systemd-container"
register: systemd_container_installed
ignore_errors: yes
- name: Check if podman is installed
ansible.builtin.command:
cmd: "zypper se -i podman"
register: podman_installed
ignore_errors: yes
- name: Install software if not installed
ansible.builtin.command:
cmd: "transactional-update --non-interactive pkg in systemd-container podman"
become: yes
when: systemd_container_installed.rc != 0 or podman_installed.rc != 0
register: software_installed
- name: Reboot if software was installed
ansible.builtin.reboot:
when: software_installed.changed
# Deploy services as rootless containers
- name: Deploy traefik
include_role:
name: rootless-podman-service
apply:
tags:
- traefik
vars:
service_name: "traefik"
systemd_service_name: "traefik"
quadlet_template_src: "./my_service_templates"
tags:
- traefik
- name: Deploy wekantesting
include_role:
name: rootless-podman-service
apply:
tags:
- wekan
- wekantesting
vars:
service_name: "wekantesting"
systemd_service_name: "null" #"wekantesting-pod"
quadlet_template_src: "./my_service_templates"
tags:
- wekan
- wekantesting
- name: Deploy wekan
include_role:
name: rootless-podman-service
apply:
tags:
- wekan
vars:
service_name: "wekan"
systemd_service_name: "null" #"wekan-pod"
quadlet_template_src: "./my_service_templates"
tags:
- wekan
- name: Deploy gitea
include_role:
name: rootless-podman-service
apply:
tags:
- gitea
vars:
service_name: "gitea"
systemd_service_name: "gitea-pod"
quadlet_template_src: "./my_service_templates"
tags:
- gitea
- name: Deploy mumble
include_role:
name: rootless-podman-service
apply:
tags:
- mumble
vars:
service_name: "mumble"
systemd_service_name: "mumble"
quadlet_template_src: "./my_service_templates"
tags:
- mumble
- name: Deploy bitwarden
include_role:
name: rootless-podman-service
apply:
tags:
- bitwarden
vars:
service_name: "bitwarden"
systemd_service_name: "bitwarden"
quadlet_template_src: "./my_service_templates"
tags:
- bitwarden
- name: Deploy actual
include_role:
name: rootless-podman-service
apply:
tags:
- actual
vars:
service_name: "actual"
systemd_service_name: "actual"
quadlet_template_src: "./my_service_templates"
tags:
- actual
- name: Deploy nextcloud
include_role:
name: rootless-podman-service
apply:
tags:
- nextcloud
vars:
service_name: "nextcloud"
systemd_service_name: "nextcloud-pod"
quadlet_template_src: "./my_service_templates"
service_directories:
- db
- data
tags:
- nextcloud
- name: Deploy paperless
include_role:
name: rootless-podman-service
apply:
tags:
- paperless
vars:
service_name: "paperless"
systemd_service_name: "paperless-pod"
quadlet_template_src: "./my_service_templates"
service_directories:
- br
- db
- data
- media
- export
- consume
tags:
- paperless
- name: Deploy bookstack
include_role:
name: rootless-podman-service
apply:
tags:
- bookstack
vars:
service_name: "bookstack"
systemd_service_name: "bookstack-pod"
quadlet_template_src: "./my_service_templates"
service_directories:
- db
- data
tags:
- bookstack
- name: Deploy rustdesk
include_role:
name: rootless-podman-service
apply:
tags:
- rustdesk
vars:
service_name: "rustdesk"
systemd_service_name: "rustdesk-pod"
quadlet_template_src: "./my_service_templates"
service_directories:
- data
tags:
- rustdesk
- name: Deploy languagetool
include_role:
name: rootless-podman-service
apply:
tags:
- languagetool
vars:
service_name: "languagetool"
systemd_service_name: "languagetool"
quadlet_template_src: "./my_service_templates"
service_directories:
- ngrams
tags:
- languagetool
- name: Deploy sgnarva
include_role:
name: rootless-podman-service
apply:
tags:
- sgnarva
vars:
service_name: "sgnarva"
systemd_service_name: "sgnarva-pod"
quadlet_template_src: "./my_service_templates"
service_directories:
- sgnarvaweb
- sgnarvadb
tags:
- sgnarva

View File

@ -1,13 +1,62 @@
$ANSIBLE_VAULT;1.1;AES256;podman_hosts
34396465333337346339653661356338373861326337663939616531623866336233653963353739
6264653732373635336563333732303735653532393865350a313135343361633034623239643339
31326238316333326166366638623963653635623533623833333862646462333363353066663434
6536343138643462320a393638643763633433363861326139326536663439633566386664393964
37366533323633376436396431383231346438643136326138643565343239393734643662386232
31373630376164623663333361323531626165646236393732353031313636623434323931633434
33343834356237376264383064393135663435323134373561306166306561356431656434633834
66653039633833643930303331323236633532343731613137383835643338373364633834653264
34643861366665336638656261373531343233353735353435643431303835376635356331373437
38306537643730646131666665396466366161303165303539663438666461623335366532376666
34356161383031353939343531333062623064353865636437633436613334663866346163316664
32383134333464663133
$ANSIBLE_VAULT;1.2;AES256;podman_hosts
34663362613164623866623535646637643134393861343463323666323930353635623931353964
3033393864646661323066363964313164373432366138630a323932626361316339666361386564
30656431323730316262663163623462396134353633393438356366326265616533343363633336
3430333963356332660a353039333564363739616635383535396365636131663637393961383364
66373734353338626133313233373063616237313933326335313861663232643935643430366337
30623439366563376564623239383035376332343334623764326662643430626231343131393831
33303737633430363964373630633261383630623363623939306536333434623964616661623861
66636239326364646639386564663936656265666330643963353932653264373932373437383838
36353462616537306632356262653038303138633238623534633233643432663162333062393831
66626135613865343635653133343735383265353534356137353734376536356465663636333833
38316539613261353631353266616565306533626239346139626439373933386361323061366164
32623236666337636239323566663263303839333731353332316563373436313365316234623763
38333134666531386439363535386537643830336133353233636266366666653935376166313762
64376131346562643565646436643765633731613434366265386433383639393364366238313663
61333164626430333462333634383161633764656134333030333861393566616633383438323066
34323033316163666665326330393061633533336564613632663539636237336437643239316464
37313338363731363635363337346565363631376132613665326239316136653939363734373035
61313236663739343330313466663533373434633365346336326363313230353564396466373133
32346433646666316130346630653062643564353061666466623830613461373134613664356134
61633836316264623536383636353064613465366263393465366430623132393432613961393761
37396531313361353436646563313433393836313831336164396130643235663534643037303064
37616135626366366661663233623436316563366465333663373132666465313539323737323133
63653636376136306531616561376363363231653564333131366534643339393566316130376537
32303265326165326334653965636561376536616439396639333736346536663462613031323030
32333565636235343435636238383232376263313364666231323262323439336261333137653132
32643362303763636137316365323434306430616230653064623538316533396235653932633865
33333938646536356538366531353361363135356634363238386365663963323032383839386166
66353932663037373235623931646533336266376634643337323232326264343633373139383533
63363330313138626331376462353433346637663139386466613465383832666264363430633038
35356262356563303531303937383864313239396563343162666535303566663131613665623062
37313964363132633962626631616531633434393961666462393636363637636266343961663164
36623231653135663938623238313337333533633231643161366262383935336264336639383165
32363465313761636639336532346333646337373337363764303435623266356564626132336537
63613062613135396233653261373638323162343563303137363965373232313230363436323562
34303032363630373436613838343834383535383030623466613961623330623536396136363366
66396230643130343436316434396465313939363037636263303938353735626437326535373537
38316361656639643337626330383437376638333033666566613764323432636663313433636236
39333732363666363762376365623435353832653738393239643839326335656431343438343562
30633861663339633261356433333866636430633531333632323065626465323264373465333731
61343336336262626666663538613931396536626439383735643836356131386136313938393062
32343263366430396635646666323737633130363035396136333633323339636666316438326166
34346334326565663163653661643561656338666432393538633065303961333439366263633430
66663161326463346465643865346164356135386637393730396130636233346565333839336365
61346561663239353964613163656333323265306431373036623734633861633232353561326336
62643737633537353065353463306662313739313734376337656132313434666366343132306230
33353461343933626232663030386530383363616161396536663234326432623465353930376437
31353939376365386266376135636133316464366365313537356565333564386633376366326232
31323235646134373133346338333564616533643432616264383432346465363965383764616361
38303239616530306132306131353062373761326663343264343961353833343732373435613834
34346462343037643663376230366465616161376632336564393463633535643462326132646538
35376333316261613363323865386633663862393365313139336234613435646264376366636362
33373031643961393935333937396564306164343138623737366132373737396234306332616463
37356330323064626261616665376133666535333336323338653831393135333436336631343461
37386164656461623330613035373234613365326338653338306639613430653638363030356533
37623234383132323333343662346332663436326533613332323731613834646431336562383562
30663830313166613536623432636437356266363662306335386235653539663033323034313362
38336564313538643238343635323534646264653537356631643031346432396363633338363865
34393135363832303033346465316162656662313431336633346135666261303331373562663563
62633833303261323432333138353662343430356231663437353631386163333633643961366139
34353864626137656333663530376231346535316332636462616338336538313333663263646138
3230

View File

@ -7,6 +7,4 @@
- rootless_host
- traefik
- backup
#- name: deploy services
# import_playbook: deploy_services.yml
- services

View File

@ -1,16 +0,0 @@
[Unit]
Description=Bookstack database
[Container]
ContainerName=bookstack-db
Image=lscr.io/linuxserver/mariadb:11.4.5
Volume=/var/vol/bookstack/db:/config:Z
Environment=PUID=1000
Environment=PGID=1000
Environment=TZ=Europe/Berlin
Environment=MYSQL_ROOT_PASSWORD=<REDACTED>
Environment=MYSQL_DATABASE=<REDACTED>
Environment=MYSQL_USER=<REDACTED>
Environment=MYSQL_PASSWORD=<REDACTED>
AutoUpdate=registry
Pod=bookstack.pod

View File

@ -1,13 +0,0 @@
[Unit]
Description=SGNarva Wordpress database
[Container]
ContainerName=sgnarva-db
Image=docker.io/mysql:8
Volume=/var/vol/sgnarva/sgnarvadb:/var/lib/mysql:Z
Environment=MYSQL_ROOT_PASSWORD=REDACTED
Environment=MYSQL_DATABASE=REDACTED
Environment=MYSQL_USER=REDACTED
Environment=MYSQL_PASSWORD=REDACTED
AutoUpdate=registry
Pod=sgnarva.pod

View File

@ -0,0 +1,2 @@
---
btrfs_base_path: "/var/vol"

View File

@ -8,9 +8,12 @@
mode: '0755'
- name: Copy Quadlet files to the user's systemd directory
ansible.builtin.copy:
src: "{{ quadlet_template_src }}/{{ service_name }}/"
dest: "/home/{{ service_name }}/.config/containers/systemd/"
with_fileglob: "../templates/{{ service_name }}/*.j2"
loop_control:
loop_var: template_path
ansible.builtin.template:
src: "{{ template_path }}"
dest: "/home/{{ service_name }}/.config/containers/systemd/{{ template_path | basename | regex_replace('.j2', '') }}"
owner: "{{ service_name }}"
group: "{{ service_name }}"
mode: '0644'

View File

@ -1,10 +1,4 @@
---
- name: Ensure Btrfs base path exists
ansible.builtin.file:
path: "{{ btrfs_base_path }}"
state: directory
mode: '0755'
- name: Create Btrfs subvolume
ansible.builtin.command:
cmd: "btrfs subvolume create {{ btrfs_base_path }}/{{ service_name }}"

View File

@ -1,16 +1,20 @@
---
- name: Check if service directories exist
ansible.builtin.stat:
path: "{{ btrfs_base_path }}/{{ service_name }}/{{ item }}"
path: "{{ btrfs_base_path }}/{{ service_name }}/{{ service_dir }}"
loop: "{{ service_directories }}"
loop_control:
loop_var: service_dir
register: directory_stats
- name: Create service directories in BTRFS subvolume (only if they don't exist)
ansible.builtin.file:
path: "{{ btrfs_base_path }}/{{ service_name }}/{{ item.item }}"
path: "{{ btrfs_base_path }}/{{ service_name }}/{{ results.item }}"
state: directory
owner: "{{ service_name }}"
group: "{{ service_name }}"
mode: '0755'
loop: "{{ directory_stats.results }}"
when: not item.stat.exists
loop_control:
loop_var: results
when: not results.stat.exists

View File

@ -0,0 +1,48 @@
---
- name: Initial setup for rootless podman services
include_tasks: setup.yml
- name: Create users
loop: "{{ services | dict2items }}"
include_tasks: create_user.yml
vars:
service_name: "{{ item.key }}"
- name: Ensure Btrfs base path exists
ansible.builtin.file:
path: "{{ btrfs_base_path }}"
state: directory
mode: '0755'
- name: Create Btrfs subvolume
loop: "{{ services | dict2items }}"
include_tasks: create_btrfs_subvolume.yml
vars:
service_name: "{{ item.key }}"
- name: Create service directories
loop: "{{ services | dict2items }}"
include_tasks: create_service_directories.yml
when: " item.value.service_directories is defined and item.value.service_directories | length > 0"
vars:
service_name: "{{ item.key }}"
service_directories: "{{ item.value.service_directories }}"
- name: Enable linger for the user
loop: "{{ services | dict2items }}"
ansible.builtin.command:
cmd: "loginctl enable-linger {{ item.key }}"
- name: Copy Quadlet files
loop: "{{ services | dict2items }}"
include_tasks: copy_quadlet_files.yml
vars:
service_name: "{{ item.key }}"
- name: Enable and start main service
loop: "{{ services | dict2items }}"
include_tasks: enable_service.yml
vars:
service_name: "{{ item.key }}"
systemd_service_name: "{{ item.value.systemd_service_name }}"
force_systemd_restart: "{{ item.value.force_systemd_restart | default(false) }}"

View File

@ -0,0 +1,19 @@
- name: Check if systemd-container is installed
ansible.builtin.command:
cmd: "zypper se -i systemd-container"
register: systemd_container_installed
ignore_errors: yes
- name: Check if podman is installed
ansible.builtin.command:
cmd: "zypper se -i podman"
register: podman_installed
ignore_errors: yes
- name: Install software if not installed
ansible.builtin.command:
cmd: "transactional-update --non-interactive pkg in systemd-container podman"
become: yes
when: systemd_container_installed.rc != 0 or podman_installed.rc != 0
register: software_installed
- name: Reboot if software was installed
ansible.builtin.reboot:
when: software_installed.changed

View File

@ -0,0 +1,16 @@
[Unit]
Description=Bookstack database
[Container]
ContainerName=bookstack-db
Image=lscr.io/linuxserver/mariadb:11.4.5
Volume=/var/vol/bookstack/db:/config:Z
Environment=PUID=1000
Environment=PGID=1000
Environment=TZ=Europe/Berlin
Environment=MYSQL_ROOT_PASSWORD={{ service_secrets.bookstack.mysql_root_pw }}
Environment=MYSQL_DATABASE={{ service_secrets.bookstack.mysql_database }}
Environment=MYSQL_USER={{ service_secrets.bookstack.mysql_user }}
Environment=MYSQL_PASSWORD={{ service_secrets.bookstack.mysql_pw }}
AutoUpdate=registry
Pod=bookstack.pod

View File

@ -12,11 +12,11 @@ Environment=APP_URL=https://bookstack.rohrschacht.de
# APP_KEY must be a unique key. Generate your own by running
# docker run -it --rm --entrypoint /bin/bash lscr.io/linuxserver/bookstack:latest appkey
# You should keep the "base64:" part for the option value.
Environment=APP_KEY=<REDACTED>
Environment=DB_HOST=localhost
Environment=APP_KEY={{ service_secrets.bookstack.app_key }}
Environment=DB_HOST=127.0.0.1
Environment=DB_PORT=3306
Environment=DB_DATABASE=<REDACTED>
Environment=DB_USERNAME=<REDACTED>
Environment=DB_PASSWORD=<REDACTED>
Environment=DB_DATABASE={{ service_secrets.bookstack.mysql_database }}
Environment=DB_USERNAME={{ service_secrets.bookstack.mysql_user }}
Environment=DB_PASSWORD={{ service_secrets.bookstack.mysql_pw }}
AutoUpdate=registry
Pod=bookstack.pod

View File

@ -7,7 +7,7 @@ Image=docker.io/postgres:14
Volume=/var/vol/gitea/db:/var/lib/postgresql/data:Z
Environment=LANG=en_US.utf8
Environment=PGDATA=/var/lib/postgresql/data/pgdata
Environment=POSTGRES_USER=<REDACTED>
Environment=POSTGRES_PASSWORD=<REDACTED>
Environment=POSTGRES_USER={{ service_secrets.gitea.pg_user }}
Environment=POSTGRES_PASSWORD={{ service_secrets.gitea.pg_pw }}
AutoUpdate=registry
Pod=gitea.pod

View File

@ -9,8 +9,8 @@ Environment=USER_UID=1000
Environment=USER_GID=1000
Environment=GITEA__database__DB_TYPE=postgres
Environment=GITEA__database__DB_HOST=127.0.0.1:5432
Environment=GITEA__database__DB_NAME=<REDACTED>
Environment=GITEA__database__DB_USER=<REDACTED>
Environment=GITEA__database__DB_PASSWD=<REDACTED>
Environment=GITEA__database__DB_NAME={{ service_secrets.gitea.pg_db }}
Environment=GITEA__database__DB_USER={{ service_secrets.gitea.pg_user }}
Environment=GITEA__database__DB_PASSWD={{ service_secrets.gitea.pg_pw }}
AutoUpdate=registry
Pod=gitea.pod

View File

@ -7,7 +7,7 @@ Image=docker.io/postgres:12
Volume=/var/vol/nextcloud/db:/var/lib/postgresql/data:Z
Environment=LANG=en_US.utf8
Environment=PGDATA=/var/lib/postgresql/data/pgdata
Environment=POSTGRES_USER=<REDACTED>
Environment=POSTGRES_PASSWORD=<REDACTED>
Environment=POSTGRES_USER={{ service_secrets.nextcloud.pg_user }}
Environment=POSTGRES_PASSWORD={{ service_secrets.nextcloud.pg_pw }}
AutoUpdate=registry
Pod=nextcloud.pod

View File

@ -9,8 +9,8 @@ Environment=USER_UID=1000
Environment=USER_GID=1000
Environment=PHP_MEMORY_LIMIT=4G
Environment=POSTGRES_HOST=127.0.0.1:5432
Environment=POSTGRES_DB=<REDACTED>
Environment=POSTGRES_USER=<REDACTED>
Environment=POSTGRES_PASSWORD=<REDACTED>
Environment=POSTGRES_DB={{ service_secrets.nextcloud.pg_db }}
Environment=POSTGRES_USER={{ service_secrets.nextcloud.pg_user }}
Environment=POSTGRES_PASSWORD={{ service_secrets.nextcloud.pg_pw }}
AutoUpdate=registry
Pod=nextcloud.pod

View File

@ -6,8 +6,8 @@ ContainerName=paperless-db
Image=docker.io/postgres:17
Volume=/var/vol/paperless/db:/var/lib/postgresql/data:Z
Environment=LANG=en_US.utf8
Environment=POSTGRES_DB=<REDACTED>
Environment=POSTGRES_USER=<REDACTED>
Environment=POSTGRES_PASSWORD=<REDACTED>
Environment=POSTGRES_DB={{ service_secrets.paperless.pg_db }}
Environment=POSTGRES_USER={{ service_secrets.paperless.pg_user }}
Environment=POSTGRES_PASSWORD={{ service_secrets.paperless.pg_pw }}
AutoUpdate=registry
Pod=paperless.pod

View File

@ -9,16 +9,16 @@ Volume=/var/vol/paperless/media:/usr/src/paperless/media:Z
Volume=/var/vol/paperless/export:/usr/src/paperless/export:Z
Volume=/var/vol/paperless/consume:/usr/src/paperless/consume:Z
Environment=PAPERLESS_URL=https://paperless.rohrschacht.de
Environment=PAPERLESS_SECRET_KEY=<REDACTED>
Environment=PAPERLESS_SECRET_KEY={{ service_secrets.paperless.secret_key }}
Environment=PAPERLESS_TIME_ZONE=Europe/Berlin
Environment=PAPERLESS_OCR_LANGUAGE=deu
Environment=PAPERLESS_OCR_LANGUAGES=eng
Environment=PAPERLESS_ADMIN_USER=<REDACTED>
Environment=PAPERLESS_ADMIN_PASSWORD=<REDACTED>
Environment=PAPERLESS_ADMIN_USER={{ service_secrets.paperless.admin_user }}
Environment=PAPERLESS_ADMIN_PASSWORD={{ service_secrets.paperless.admin_pw }}
Environment=PAPERLESS_REDIS=redis://127.0.0.1:6379
Environment=PAPERLESS_DBHOST=127.0.0.1
Environment=PAPERLESS_DBNAME=<REDACTED>
Environment=PAPERLESS_DBUSER=<REDACTED>
Environment=PAPERLESS_DBPASS=<REDACTED>
Environment=PAPERLESS_DBNAME={{ service_secrets.paperless.pg_db }}
Environment=PAPERLESS_DBUSER={{ service_secrets.paperless.pg_user }}
Environment=PAPERLESS_DBPASS={{ service_secrets.paperless.pg_pw }}
AutoUpdate=registry
Pod=paperless.pod

View File

@ -0,0 +1,13 @@
[Unit]
Description=SGNarva Wordpress database
[Container]
ContainerName=sgnarva-db
Image=docker.io/mysql:8
Volume=/var/vol/sgnarva/sgnarvadb:/var/lib/mysql:Z
Environment=MYSQL_ROOT_PASSWORD={{ service_secrets.sgnarva.mysql_root_pw }}
Environment=MYSQL_DATABASE={{ service_secrets.sgnarva.mysql_db }}
Environment=MYSQL_USER={{ service_secrets.sgnarva.mysql_user }}
Environment=MYSQL_PASSWORD={{ service_secrets.sgnarva.mysql_pw }}
AutoUpdate=registry
Pod=sgnarva.pod

View File

@ -0,0 +1,48 @@
---
services:
traefik:
systemd_service_name: "traefik"
wekantesting:
systemd_service_name: "null"
wekan:
systemd_service_name: "null"
gitea:
systemd_service_name: "gitea-pod"
mumble:
systemd_service_name: "mumble"
bitwarden:
systemd_service_name: "bitwarden"
actual:
systemd_service_name: "actual"
nextcloud:
systemd_service_name: "nextcloud-pod"
services_directories:
- db
- data
paperless:
systemd_service_name: "paperless-pod"
services_directories:
- br
- db
- data
- media
- export
- consume
bookstack:
systemd_service_name: "bookstack-pod"
services_directories:
- db
- data
rustdesk:
systemd_service_name: "rustdesk-pod"
services_directories:
- data
languagetool:
systemd_service_name: "languagetool"
service_directories:
- ngrams
sgnarva:
systemd_service_name: "sgnarva-pod"
services_directories:
- sgnarvaweb
- sgnarvadb

View File

@ -1,7 +0,0 @@
---
service_name: "default_service"
systemd_service_name: "default_service"
btrfs_base_path: "/var/vol"
quadlet_template_src: "./templates"
force_systemd_restart: false
service_directories: []

View File

@ -1,19 +0,0 @@
---
- name: Create user and group
include_tasks: create_user.yml
- name: Create Btrfs subvolume
include_tasks: create_btrfs_subvolume.yml
- name: Create service directories
include_tasks: create_service_directories.yml
when: service_directories | length > 0
- name: Enable linger for the user
include_tasks: enable_linger.yml
- name: Copy Quadlet files
include_tasks: copy_quadlet_files.yml
- name: Enable and start main service
include_tasks: enable_service.yml