From 56fb5716b530b7e47428def20e538a51e588bbcf Mon Sep 17 00:00:00 2001 From: il Date: Sun, 23 Aug 2026 21:55:12 +0900 Subject: [PATCH] 2026-AUG-23 --- ansible/inventory/group_vars/all.yaml | 21 +- ansible/playbooks/app/site.yaml | 8 - ansible/playbooks/infra/site.yaml | 8 + ansible/roles/app/handlers/main.yaml | 11 - ansible/roles/infra/handlers/main.yaml | 12 ++ .../infra/tasks/services/set_mariadb.yaml | 197 ++++++++++++++++++ .../infra/tasks/services/set_postgresql.yaml | 2 +- config/node/infra/nftables.conf.j2 | 2 +- config/secrets/secrets.yaml | 21 +- .../app/tandoor/tandoor.container.j2 | 3 + .../auth/authelia/config/authelia.yaml.j2 | 22 -- .../infra/mariadb/config/mariadb.cnf.j2 | 39 ++++ .../infra/mariadb/mariadb.container.j2 | 37 ++++ .../services/mariadb-data-backup@.service | 26 +++ .../services/mariadb-data-backup@.timer | 17 ++ .../archives/services/app/memos/authelia.yaml | 27 +++ .../services/app/memos/group_vars.yaml | 16 ++ .../services}/app/memos/memos.container.j2 | 0 .../services/app/memos/secret.example.yaml | 8 + 19 files changed, 412 insertions(+), 65 deletions(-) create mode 100644 ansible/roles/infra/tasks/services/set_mariadb.yaml create mode 100644 config/services/containers/infra/mariadb/config/mariadb.cnf.j2 create mode 100644 config/services/containers/infra/mariadb/mariadb.container.j2 create mode 100644 config/services/containers/infra/mariadb/services/mariadb-data-backup@.service create mode 100644 config/services/containers/infra/mariadb/services/mariadb-data-backup@.timer create mode 100644 docs/archives/services/app/memos/authelia.yaml create mode 100644 docs/archives/services/app/memos/group_vars.yaml rename {config/services/containers => docs/archives/services}/app/memos/memos.container.j2 (100%) create mode 100644 docs/archives/services/app/memos/secret.example.yaml diff --git a/ansible/inventory/group_vars/all.yaml b/ansible/inventory/group_vars/all.yaml index 0cd3979..36fb6b9 100644 --- a/ansible/inventory/group_vars/all.yaml +++ b/ansible/inventory/group_vars/all.yaml @@ -76,6 +76,14 @@ services: subuid: "100998" dependency: cert: true + mariadb: + domain: + internal: "mariadb" + ports: + tcp: "3306" # mariadb db connection port + subuid: "100998" + dependency: + cert: true ldap: domain: internal: "ldap" @@ -251,16 +259,6 @@ services: dependency: web: "app-public" db: "postgresql" - memos: - domain: - public: "memos" - internal: "memos.app" - ports: - http: "3005" - subuid: "110000" - dependency: - web: "app-public" - db: "postgresql" sure: domain: public: "sure" @@ -336,6 +334,8 @@ version: ca: "0.30.2" ## Postgresql postgresql: "18.4" + ## Mariadb + mariadb: "12.3.2" ### For immich - https://github.com/immich-app/base-images/blob/main/postgres/versions.yaml vectorchord: "1.1.1" ## lldap @@ -357,7 +357,6 @@ version: collabora: "26.04.3.1.1" sure: "0.7.3" outline: "1.9.2" - memos: "0.30.0" mealie: "v3.22.0" homebox: "0.26.2" homepage: "v2.0.0" diff --git a/ansible/playbooks/app/site.yaml b/ansible/playbooks/app/site.yaml index 294d847..41c54c7 100644 --- a/ansible/playbooks/app/site.yaml +++ b/ansible/playbooks/app/site.yaml @@ -234,14 +234,6 @@ 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" diff --git a/ansible/playbooks/infra/site.yaml b/ansible/playbooks/infra/site.yaml index 154ffb3..d2c8da7 100644 --- a/ansible/playbooks/infra/site.yaml +++ b/ansible/playbooks/infra/site.yaml @@ -162,6 +162,14 @@ tags: ["site", "postgresql"] tags: ["site", "postgresql"] + - name: Set mariadb + ansible.builtin.include_role: + name: "infra" + tasks_from: "services/set_mariadb" + apply: + tags: ["site", "mariadb"] + tags: ["site", "mariadb"] + - name: Set caddy ansible.builtin.include_role: name: "common" diff --git a/ansible/roles/app/handlers/main.yaml b/ansible/roles/app/handlers/main.yaml index 3904286..576eeb8 100644 --- a/ansible/roles/app/handlers/main.yaml +++ b/ansible/roles/app/handlers/main.yaml @@ -92,17 +92,6 @@ 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" diff --git a/ansible/roles/infra/handlers/main.yaml b/ansible/roles/infra/handlers/main.yaml index 3cf5c55..b024616 100644 --- a/ansible/roles/infra/handlers/main.yaml +++ b/ansible/roles/infra/handlers/main.yaml @@ -30,6 +30,18 @@ listen: "notification_restart_postgresql" ignore_errors: true # noqa: ignore-errors +- name: Restart mariadb + ansible.builtin.systemd: + name: "mariadb.service" + state: "restarted" + enabled: true + daemon_reload: true + scope: "user" + when: is_mariadb_init_marker.stat.exists + changed_when: false + listen: "notification_restart_mariadb" + ignore_errors: true # noqa: ignore-errors + - name: Restart ldap ansible.builtin.systemd: name: "ldap.service" diff --git a/ansible/roles/infra/tasks/services/set_mariadb.yaml b/ansible/roles/infra/tasks/services/set_mariadb.yaml new file mode 100644 index 0000000..f8a406a --- /dev/null +++ b/ansible/roles/infra/tasks/services/set_mariadb.yaml @@ -0,0 +1,197 @@ +--- +- name: Initialize connected services list + ansible.builtin.set_fact: + connected_services: [] + +- name: Set connected services list + ansible.builtin.set_fact: + connected_services: >- + {{ + services + | dict2items + | selectattr('value.dependency.db', 'defined') + | selectattr('value.dependency.db', 'equalto', 'mariadb') + | map(attribute='key') + | list + }} + +- name: Create mariadb directory + ansible.builtin.file: + path: "{{ node['home_path'] }}/{{ item }}" + state: "directory" + owner: "{{ services['mariadb']['subuid'] }}" + group: "{{ node['group'] }}" + mode: "0770" + loop: + - "data/containers/mariadb/" + - "data/containers/mariadb/backups" + - "data/containers/mariadb/backups/sql" + - "containers/mariadb" + - "containers/mariadb/data" + - "containers/mariadb/config" + - "containers/mariadb/ssl" + - "containers/mariadb/init" + become: true + +- name: Check mariadb .init marker + ansible.builtin.stat: + path: "{{ node['home_path'] }}/containers/mariadb/.init" + register: "is_mariadb_init_marker" + +- name: Pull image + containers.podman.podman_image: + name: "docker.io/library/mariadb" + tag: "{{ version['containers']['mariadb'] }}" + state: "present" + pull: true + +- name: Deploy mariadb configuration files + ansible.builtin.template: + src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/mariadb/config/mariadb.cnf.j2" + dest: "{{ node['home_path'] }}/containers/mariadb/config/mariadb.cnf" + owner: "{{ services['mariadb']['subuid'] }}" + group: "{{ node['group'] }}" + mode: "0600" + become: true + notify: "notification_restart_mariadb" + no_log: true + +- name: Deploy mariadb certificate and key + ansible.builtin.copy: + content: | + {{ item.value }} + dest: "{{ node['home_path'] }}/containers/mariadb/ssl/{{ item.name }}" + owner: "{{ services['mariadb']['subuid'] }}" + group: "{{ node['group'] }}" + mode: "{{ item.mode }}" + loop: + - name: "{{ root_cert_filename }}" + value: "{{ hostvars['console']['ca']['root']['crt'] }}" + mode: "0440" + - name: "mariadb.crt" + value: | + {{ hostvars['console']['mariadb']['crt'] | trim }} + {{ hostvars['console']['ca']['intermediate']['crt'] }} + mode: "0440" + - name: "mariadb.key" + value: "{{ hostvars['console']['mariadb']['key'] }}" + mode: "0400" + become: true + notify: "notification_restart_mariadb" + no_log: true + +- name: Initiating mariadb + when: not is_mariadb_init_marker.stat.exists + block: + - name: Check initiating SQL files + ansible.builtin.find: + path: "{{ node['home_path'] }}/data/containers/mariadb/backups/sql/" + file_type: "file" + patterns: + - "mariadb_*.sql" + hidden: true + recurse: false + become: true + register: "mariadb_init_sql_files" + + - name: Set initiating SQL file lists + ansible.builtin.set_fact: + mariadb_init_sql_file_list: >- + {{ + mariadb_init_sql_files.files + | map(attribute='path') + | map('basename') + | map('regex_replace', '^mariadb_', '') + | map('regex_replace', '[.]sql$', '') + | list + }} + + - name: Fail on invalid initiating SQL file set + ansible.builtin.fail: + when: + - mariadb_init_sql_files.matched > 0 + - ((connected_services) + | symmetric_difference(mariadb_init_sql_file_list) + | length) > 0 + + - name: Remote copy the initiating SQL + ansible.builtin.copy: + src: "{{ node['home_path'] }}/data/containers/mariadb/backups/sql/mariadb_{{ item }}.sql" + remote_src: true + dest: "{{ node['home_path'] }}/containers/mariadb/init/{{ '%02d' | format(index_num) }}_mariadb_{{ item }}.sql" + owner: "{{ services['mariadb']['subuid'] }}" + group: "{{ node['group'] }}" + mode: "0600" + loop: "{{ connected_services }}" + loop_control: + index_var: index_num + become: true + when: + - ((connected_services) + | symmetric_difference(mariadb_init_sql_file_list) + | length) == 0 + +- name: Deploy container file + ansible.builtin.template: + src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/mariadb/mariadb.container.j2" + dest: "{{ node['home_path'] }}/.config/containers/systemd/mariadb.container" + owner: "{{ ansible_user }}" + group: "{{ node['group'] }}" + mode: "0644" + notify: "notification_restart_mariadb" + +- name: Deploy backup service files + ansible.builtin.copy: + src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/mariadb/services/{{ item }}" + dest: "{{ node['home_path'] }}/.config/systemd/user/{{ item }}" + owner: "{{ ansible_user }}" + group: "{{ node['group'] }}" + mode: "0644" + loop: + - "mariadb-data-backup@.service" + - "mariadb-data-backup@.timer" + +- name: Enable mariadb + ansible.builtin.systemd: + name: "mariadb.service" + state: "started" + enabled: true + daemon_reload: true + scope: "user" + +- name: Enable data backup timer + ansible.builtin.systemd: + name: "mariadb-data-backup@{{ item }}.timer" + state: "started" + enabled: true + daemon_reload: true + scope: "user" + loop: "{{ connected_services }}" + +- name: Create .init file + ansible.builtin.file: + path: "{{ node['home_path'] }}/containers/mariadb/.init" + state: "touch" + mode: "0644" + owner: "{{ ansible_user }}" + group: "{{ node['group'] }}" + when: not is_mariadb_init_marker.stat.exists + +- name: Check container archive images + ansible.builtin.stat: + path: "{{ node['home_path'] }}/archives/containers/docker.io_library_mariadb_{{ version['containers']['mariadb'] }}" + register: container_archive_images + +- name: Save container archive images + containers.podman.podman_save: + image: + - "docker.io/library/mariadb:{{ version['containers']['mariadb'] }}" + dest: "{{ node['home_path'] }}/archives/containers/docker.io_library_mariadb_{{ version['containers']['mariadb'] }}" + format: "oci-archive" + when: not container_archive_images.stat.exists + +- name: Fetch container archive images + ansible.builtin.fetch: + src: "{{ node['home_path'] }}/archives/containers/docker.io_library_mariadb_{{ version['containers']['mariadb'] }}" + dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/" + flat: true diff --git a/ansible/roles/infra/tasks/services/set_postgresql.yaml b/ansible/roles/infra/tasks/services/set_postgresql.yaml index 7c0d669..1fd7b4c 100644 --- a/ansible/roles/infra/tasks/services/set_postgresql.yaml +++ b/ansible/roles/infra/tasks/services/set_postgresql.yaml @@ -122,7 +122,7 @@ | map(attribute='path') | map('basename') | map('regex_replace', '^pg_', '') - | map('regex_replace', '\\.sql$', '') + | map('regex_replace', '[.]sql$', '') | list }} diff --git a/config/node/infra/nftables.conf.j2 b/config/node/infra/nftables.conf.j2 index d7926ea..b98a5aa 100644 --- a/config/node/infra/nftables.conf.j2 +++ b/config/node/infra/nftables.conf.j2 @@ -8,7 +8,7 @@ define NET6_SERVER = {{ hostvars['fw']['network']['subnet']['ipv6']['server'] }} define HOSTS4_CONSOLE = { {{ hostvars['fw']['network']['console']['ipv4'] | dict2items | rejectattr('key', 'equalto', 'reverse') | map(attribute='value') | join(', ')}} } define HOSTS6_CONSOLE = { {{ hostvars['fw']['network']['console']['ipv6'] | dict2items | rejectattr('key', 'equalto', 'reverse') | map(attribute='value') | join(', ')}} } define PORTS_SSH = 22 -define PORTS_DB = 5432 +define PORTS_DB = { 5432, 3306 } define PORTS_CA = {{ services['ca']['ports']['https'] }} define PORTS_LDAPS = 636 define PORTS_LDAPS_FORWARD = {{ services['ldap']['ports']['ldaps'] }} diff --git a/config/secrets/secrets.yaml b/config/secrets/secrets.yaml index a342881..1a06f82 100644 --- a/config/secrets/secrets.yaml +++ b/config/secrets/secrets.yaml @@ -135,7 +135,6 @@ postgresql: 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] homebox: ENC[AES256_GCM,data:EhNnltOBwLai5vEMt7Dih5Ug6h3ojrdbwhq4Vr0tg/p/0nqI9L7O/Le0B4w=,iv:14oyl916t0inr+W/lztQCjYiSQ0vIIwC9NmbezDuvvY=,tag:IiXZd3NU+dUvDrHpxJXFew==,type:str] mastodon: ENC[AES256_GCM,data:hq1ETBK9iUI7kWFO+9pZwMQMbmyLExGk7/VzBwDdLFbzptXL2KEi6oYRCS0=,iv:hF1C8lsnP2i3LxDIuOA6op4qKXQKjJ7gqznDst7hVAU=,tag:maR7Jvsv3DJGrO77EzmBDA==,type:str] @@ -145,6 +144,14 @@ postgresql: #ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment] # # +#ENC[AES256_GCM,data:n2lt/VhdDjqfcwYN5OUjTg==,iv:QidjK4AzjisEzaDmXhYZKWyx/BrHOsgGcxxcirQOlQo=,tag:0ViayyRFg5E3kQ5vPgV5fA==,type:comment] +mariadb: + key: ENC[AES256_GCM,data:JsEzdgp0RdLRuZ6vfOugPGjz5+tBlpZpWhFOSkKSbEeUCU9D/IkAFUcZGwCBR4XBl2cOx8uszCryi6Cxm2L1fT+x6N9auMiM07W0A34kT5PMT3w+n+wQx48Ss0fZRH1kfH2tg8G4J5ASvl0dylGnuv1aIGFsmD+6Ygj+F2AFef6Y/+Sje24QKeyISU9+2tsfTNoRAH9ECxdIk2cI14ayQbISaTlBhlzciL/bzvRqqtz6KoB2HYj2YX5EK/zVRpBwkssbMsGR/LMepUWyg2hic78gc+UGK9FAkfCd1ctFQyUgsck=,iv:dSvRa+wdKPXhz+SI+69eT/YDAIoWMTcouZJQHgRIdRU=,tag:pEz/doDqhB+hnDMRMS5CqQ==,type:str] + crt: ENC[AES256_GCM,data:D9/6WbvHwaetFQY/MQMq7F3Oprz8aiY2B6urDCXhwqDD1ipqDaVT/g3Q87LsauCJiwaflCcTms7I0ulQIHUyiqHUrDmE+yxzeEIAwFHVaxr34FURnGHLKFPlKvvBcLC28WjWIYbdaNbfjtZTORZwiLVqZgNoM91rFJDDbTlo+a4OBip40nk8/UPv5NGIApGzJlcc3UZevGsbEeu5g12KfbfaW7mMnor5my7zsvUQclNdWFyOlCUmWDHjHvjwWSPom9AlTnDVoGnePdigfeEEbz19kxGGjL+li48buskbnXPTR8/4G9OHT+yiQtszNq9mZTxyTXRagzpIzYQjBK4/Ww+lLOHgaKG4awrSR2Y8NLZfPsbaJVWg+XvkI9E9s1LfXs/hBsRD6f26joFzXVQpZgzuWqrwSBtnP3LY10KygxVN+kbLHCxIxohM6SH/rM5eMRGftZlPQMZTIxzirjF7YZcdtvRFtd8BYmksYaEuQ6PnFroh7xv9M/5GDaEpkkQngiRkxrXfHaExjOBZvgtUV2R+7Tzd5odu8Rj7nfZOySlPy0qifVODSFbIKYN0HVqYur0PxLZD10xzx1PfwBWvnR1U0QzTVbbxGD2vDPf9SJEuREcWsOwNzM9snuuR7S3uzDX28MwvyAeALYz7PWhC6jEhgUyEShuzAn7BNsJySgPrRcgrP5s5fQU3Fkjfg/s8DYXFxFCRELT0pNf7TjFsW/tevxonlhzAbGXMnNiB3vwHyh/dPLQA8Lq0MDsLPWuiDy+cuoq9k22hIOJOrmnoEIEqErp2W5VAliFYBj6QKav/f+2XxK4iNA/vcZcFdp5w4tC8h3GNVXHVmJrgPT0wkajOE1UBgHwTxns0EJtUTGNDY4B8kdKHONDqFscq+1WCHah69Dq1UD1rOQDeSlfyso+N5w0f2GsxPmGnROXWLxm+VMQfe4PQPdSrrRcW,iv:LuX8l49se20frOc6qIBopqn99DRFzi2o9BfHqfL+CBg=,tag:sq8Wei7DZJPgPMSK1IlJSw==,type:str] + password: "" +#ENC[AES256_GCM,data:ODXFUxxxdQ==,iv:s9zJVx6wo6x517tbNvC+FZ0dFzqbjqeLI6rXBq72hQA=,tag:bXoV2I3LbpmQyddJrtS3Qg==,type:comment] +# +# #ENC[AES256_GCM,data:VuOcF5INAvCNDvXhcAc=,iv:zdTFTKaII606RjjDJbdUyv8jGba8abL7lJNTsPH5C74=,tag:cYSefZHKIuvHmAzoxierQg==,type:comment] ldap: key: ENC[AES256_GCM,data:PwQ/AtsQbbM454iM0wpUjGRfxyxNY5lGDARv/XOdk0yMCHRsf9qHKaW37EwcqNe+MVTJH+sx8lHDdxRYF1gO1yj6kasEIbMeo9cIaGQHvey5dYdber/qUkcjuAXyhSZGSUXI3PR1CuAsiqNUEruh/eKyDZAvHTTY0Rc5jk4HLFzPqqBjBOMkA6VQXJ2I+v4s8W0T8/JEQ5l6avwYbaaInIIY+uPV+sY0mBczAuaHLyeA3V7VQNTxQ9lUgdfH/TpgBn9EBH2wWqIGk2zQ6XmVrmOarCo/+JqwLQVEyY5TTrNuBto=,iv:iYzoRXjH8NjPnX5nBhU2gTQXOekXMirjTGhmpGt3YAs=,tag:IxwtGNXx1i54Jnhn1aZx3w==,type:str] @@ -280,14 +287,6 @@ outline: #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: @@ -377,7 +376,7 @@ sops: k+uyWPPi+enFkVaceSwMFrA66uaWWrwAj11sXEB7yzvGFPrnAGezjQ== -----END AGE ENCRYPTED FILE----- recipient: age120wuwcmsm845ztsvsz46pswj5je53uc2n35vadklrfqudu6cxuusxetk7y - lastmodified: "2026-08-21T05:32:45Z" - mac: ENC[AES256_GCM,data:VED6JYuDQlmXl6buMuPEkF4LRbVL8RmlQhNYguHRvrUEbAYZn4iB5bUCoZuLhklsBc5b9Y+Xzgd4Gixk0puS85K2FxQ1jXazq/pVvKl3UPn3XFbqhXFtwLxq1Rqj1iY69E+pgiI31/pflcGwmJbzOFNO8SZ2jMTrH690P3XsCAM=,iv:6HR/+VC2Or+RMMdrHD7r6sp4oUR4g/MsNudg+J7iPe0=,tag:DrH6lcpptXn1OOucxfzK/g==,type:str] + lastmodified: "2026-08-23T12:15:15Z" + mac: ENC[AES256_GCM,data:EKc4Ifpl/NIaPJ/QqGc3Bw+KDMtiZpi7dK1Um/axitORcdOCR0gfTAbtuaFp88Ss9hpHu1+hJYL3yYihELZz+7MDyiydSAC7QdGPeARwWa4XlCap//K7+W5Wpu+SRC8H/IE6jejuCF2LwsrnXYMssAlujLSXI65JIaOIrgn9nT8=,iv:iuQcoJdacW9OTRP05C25/BKaiqRUjEQl8ZhPKQavzIs=,tag:GDDJFqWOso34QN5oIwWung==,type:str] unencrypted_suffix: _unencrypted version: 3.13.2 diff --git a/config/services/containers/app/tandoor/tandoor.container.j2 b/config/services/containers/app/tandoor/tandoor.container.j2 index 813ae66..0de075f 100644 --- a/config/services/containers/app/tandoor/tandoor.container.j2 +++ b/config/services/containers/app/tandoor/tandoor.container.j2 @@ -22,6 +22,9 @@ Environment="ALLOWED_HOSTS={{ services['tandoor']['domain']['public'] }}.{{ doma Environment="CSRF_TRUSTED_ORIGINS=https://{{ services['tandoor']['domain']['public'] }}.{{ domain['public'] }}" # auth Caddy -> app Caddy -> Tandoor built-in nginx Environment="ALLAUTH_TRUSTED_PROXY_COUNT=3" +# Set Django gunicorn worker as 1, and threads as 2 +Environment="GUNICORN_WORKERS=1" +Environment="GUNICORN_THREADS=2" # Secrets Secret=TANDOOR_SECRET_KEY,type=env,target=SECRET_KEY diff --git a/config/services/containers/auth/authelia/config/authelia.yaml.j2 b/config/services/containers/auth/authelia/config/authelia.yaml.j2 index a9cec0c..466f2b3 100644 --- a/config/services/containers/auth/authelia/config/authelia.yaml.j2 +++ b/config/services/containers/auth/authelia/config/authelia.yaml.j2 @@ -252,28 +252,6 @@ identity_providers: access_token_signed_response_alg: 'none' userinfo_signed_response_alg: 'none' token_endpoint_auth_method: 'client_secret_post' - # https://www.authelia.com/integration/openid-connect/clients/memos/ - - client_id: 'memos' - client_name: 'Memos' - consent_mode: 'implicit' - client_secret: '{{ hostvars['console']['memos']['oidc']['hash'] }}' - public: false - authorization_policy: 'one_factor' - require_pkce: false - pkce_challenge_method: '' - redirect_uris: - - 'https://{{ services['memos']['domain']['public'] }}.{{ domain['public'] }}/auth/callback' - scopes: - - 'openid' - - 'profile' - - 'email' - response_types: - - 'code' - grant_types: - - 'authorization_code' - access_token_signed_response_alg: 'none' - userinfo_signed_response_alg: 'none' - token_endpoint_auth_method: 'client_secret_post' # https://www.authelia.com/integration/openid-connect/clients/mealie/ - client_id: 'mealie' client_name: 'Mealie' diff --git a/config/services/containers/infra/mariadb/config/mariadb.cnf.j2 b/config/services/containers/infra/mariadb/config/mariadb.cnf.j2 new file mode 100644 index 0000000..f9d823c --- /dev/null +++ b/config/services/containers/infra/mariadb/config/mariadb.cnf.j2 @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# CUSTOMIZED OPTIONS +#------------------------------------------------------------------------------ +[mariadb] + +# Listen address +bind-address = 0.0.0.0 + +# Max connections +max_connections = 250 + +# Listen port +port = {{ services['mariadb']['ports']['tcp'] }} + +# SSL +ssl-ca = /etc/ssl/mariadb/{{ root_cert_filename }} +ssl-cert = /etc/ssl/mariadb/mariadb.crt +ssl-key = /etc/ssl/mariadb/mariadb.key +ssl-cipher = HIGH:!aNULL:!MD5 +require_secure_transport = ON + +# InnoDB +innodb_buffer_pool_size = 512M +innodb_log_file_size = 5G +innodb_flush_log_at_trx_commit = 1 + +# Temporary memory +tmp_table_size = 16M +max_heap_table_size = 16M + +# IO +innodb_io_capacity = 200 + +# SSD +innodb_flush_neighbors = 0 + +[client] +protocol=socket +skip-ssl diff --git a/config/services/containers/infra/mariadb/mariadb.container.j2 b/config/services/containers/infra/mariadb/mariadb.container.j2 new file mode 100644 index 0000000..c4f9947 --- /dev/null +++ b/config/services/containers/infra/mariadb/mariadb.container.j2 @@ -0,0 +1,37 @@ +[Quadlet] +DefaultDependencies=false + +[Unit] +Description=MariaDB + +After=network-online.target +Wants=network-online.target + +[Container] +Image=docker.io/library/mariadb:{{ version['containers']['mariadb'] }} + +ContainerName=mariadb +HostName=mariadb + +PublishPort={{ services['mariadb']['ports']['tcp'] }}:3306/tcp + +Volume=%h/containers/mariadb/data:/var/lib/mysql:rw +Volume=%h/containers/mariadb/config:/etc/mysql/conf.d/:ro +Volume=%h/containers/mariadb/ssl:/etc/ssl/mariadb:ro +Volume=%h/containers/mariadb/init:/docker-entrypoint-initdb.d/:ro +Volume=%h/data/containers/mariadb/backups:/backups:rw + +# General +Environment="TZ={{ timezone }}" + +# root is only available in container (localhost) +Environment="MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=1" +Environment="MARIADB_ROOT_HOST=localhost" + +[Service] +Restart=always +RestartSec=10s +TimeoutStopSec=120 + +[Install] +WantedBy=default.target diff --git a/config/services/containers/infra/mariadb/services/mariadb-data-backup@.service b/config/services/containers/infra/mariadb/services/mariadb-data-backup@.service new file mode 100644 index 0000000..513a93f --- /dev/null +++ b/config/services/containers/infra/mariadb/services/mariadb-data-backup@.service @@ -0,0 +1,26 @@ +[Unit] +Description=MariaDB Data %i Backup Service +After=mariadb.service +BindsTo=mariadb.service + +[Service] +Type=oneshot + +# logging +StandardOutput=journal +StandardError=journal + +ExecStartPre=/usr/bin/podman exec mariadb sh -c "mkdir -p /backups/%i && chown mysql:root /backups/%i && chmod 770 /backups/%i" +ExecStartPre=/usr/bin/podman exec mariadb sh -c "mkdir -p /backups/sql && chown mysql:root /backups/sql && chmod 770 /backups/sql" + +# Run the script +## User SQL +ExecStart=/usr/bin/podman exec -u mysql mariadb sh -c 'mariadb -uroot -N -B -e \"SHOW CREATE USER \'%i\'@\'%%\';\" | sed "s/$/;/" > /backups/%i/mariadb_%i_$(date "+%%Y-%%m-%%d").sql' +## Database SQL +ExecStart=/usr/bin/podman exec -u mysql mariadb sh -c 'mariadb-dump -uroot --single-transaction --routines --events --triggers --databases %i_db >> /backups/%i/mariadb_%i_$(date "+%%Y-%%m-%%d").sql' +## Grant SQL +ExecStart=/usr/bin/podman exec -u mysql mariadb sh -c 'mariadb -uroot -N -B -e \"SHOW GRANTS FOR \'%i\'@\'%%\';\" | sed "s/$/;/" >> /backups/%i/mariadb_%i_$(date "+%%Y-%%m-%%d").sql' +ExecStart=/usr/bin/podman exec -u mysql mariadb sh -c 'cp -a /backups/%i/mariadb_%i_$(date "+%%Y-%%m-%%d").sql /backups/sql/mariadb_%i.sql' +ExecStart=/usr/bin/podman exec -u mysql mariadb sh -c "find /backups/%i -maxdepth 1 -type f -name 'mariadb_%i_*.sql' -mtime +7 -delete" +ExecStart=/usr/bin/podman exec mariadb sh -c "chown -R mysql:root /backups/%i && chmod 660 /backups/%i/*" +ExecStart=/usr/bin/podman exec mariadb sh -c "chown -R mysql:root /backups/sql && chmod 660 /backups/sql/mariadb_%i.sql" diff --git a/config/services/containers/infra/mariadb/services/mariadb-data-backup@.timer b/config/services/containers/infra/mariadb/services/mariadb-data-backup@.timer new file mode 100644 index 0000000..d73af5b --- /dev/null +++ b/config/services/containers/infra/mariadb/services/mariadb-data-backup@.timer @@ -0,0 +1,17 @@ +[Unit] +Description=Run %i Data Backup service every day + +[Timer] +# Execute service after 1 min on booting +OnBootSec=1min + +# Execute service every day 00:00 +OnCalendar=*-*-* 00:00:00 +# Random time to postpone the timer +RandomizedDelaySec=15min + +# When timer is activated, Service also starts. +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/docs/archives/services/app/memos/authelia.yaml b/docs/archives/services/app/memos/authelia.yaml new file mode 100644 index 0000000..aab052a --- /dev/null +++ b/docs/archives/services/app/memos/authelia.yaml @@ -0,0 +1,27 @@ +--- +identity_providers: + oidc: + clients: + # https://www.authelia.com/integration/openid-connect/clients/memos/ + - client_id: 'memos' + client_name: 'Memos' + consent_mode: 'implicit' + client_secret: 'hash' + public: false + authorization_policy: 'one_factor' + require_pkce: false + pkce_challenge_method: '' + redirect_uris: + - 'https://memos.example.com/auth/callback' + scopes: + - 'openid' + - 'profile' + - 'email' + response_types: + - 'code' + grant_types: + - 'authorization_code' + access_token_signed_response_alg: 'none' + userinfo_signed_response_alg: 'none' + token_endpoint_auth_method: 'client_secret_post' + \ No newline at end of file diff --git a/docs/archives/services/app/memos/group_vars.yaml b/docs/archives/services/app/memos/group_vars.yaml new file mode 100644 index 0000000..5b3f2a5 --- /dev/null +++ b/docs/archives/services/app/memos/group_vars.yaml @@ -0,0 +1,16 @@ +--- +services: + memos: + domain: + public: "" + internal: "" + ports: + http: "3005" + subuid: "110000" + dependency: + web: "app-public" + db: "postgresql" + +version: + containers: + memos: "0.30.0" diff --git a/config/services/containers/app/memos/memos.container.j2 b/docs/archives/services/app/memos/memos.container.j2 similarity index 100% rename from config/services/containers/app/memos/memos.container.j2 rename to docs/archives/services/app/memos/memos.container.j2 diff --git a/docs/archives/services/app/memos/secret.example.yaml b/docs/archives/services/app/memos/secret.example.yaml new file mode 100644 index 0000000..41d8b24 --- /dev/null +++ b/docs/archives/services/app/memos/secret.example.yaml @@ -0,0 +1,8 @@ +--- +postgresql: + password: + memos: "" +memos: + oidc: + secret: "" + hash: ""