bk node and refactor
This commit is contained in:
@@ -124,3 +124,14 @@
|
||||
changed_when: false
|
||||
listen: "notification_restart_mealie"
|
||||
ignore_errors: true # noqa: ignore-errors
|
||||
|
||||
- name: Restart homebox
|
||||
ansible.builtin.systemd:
|
||||
name: "homebox.service"
|
||||
state: "restarted"
|
||||
enabled: true
|
||||
scope: "user"
|
||||
daemon_reload: true
|
||||
changed_when: false
|
||||
listen: "notification_restart_homebox"
|
||||
ignore_errors: true # noqa: ignore-errors
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
---
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/collabora/code"
|
||||
tag: "{{ version['containers']['collabora'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/collabora/collabora.container.j2"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "data/containers/gitea"
|
||||
- "data/containers/gitea/data"
|
||||
- "containers/gitea"
|
||||
- "containers/gitea/ssl"
|
||||
become: true
|
||||
@@ -33,6 +34,13 @@
|
||||
notify: "notification_restart_gitea"
|
||||
no_log: true
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/gitea/gitea"
|
||||
tag: "{{ version['containers']['gitea'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/gitea/gitea.container.j2"
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
- name: Create homebox directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ node['home_path'] }}/{{ item }}"
|
||||
state: "directory"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "data/containers/homebox"
|
||||
- "data/containers/homebox/data"
|
||||
- "containers/homebox"
|
||||
- "containers/homebox/ssl"
|
||||
become: true
|
||||
|
||||
- name: Deploy root certificate
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
{{ hostvars['console']['ca']['root']['crt'] }}
|
||||
dest: "{{ node['home_path'] }}/containers/homebox/ssl/{{ root_cert_filename }}"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0440"
|
||||
become: true
|
||||
notify: "notification_restart_homebox"
|
||||
no_log: true
|
||||
|
||||
- name: Register secret value to podman secret
|
||||
containers.podman.podman_secret:
|
||||
name: "{{ item.name }}"
|
||||
data: "{{ item.value }}"
|
||||
state: "present"
|
||||
force: true
|
||||
loop:
|
||||
- name: "HBOX_AUTH_API_KEY_PEPPER"
|
||||
value: "{{ hostvars['console']['homebox']['api_secret'] }}"
|
||||
- name: "HBOX_DATABASE_PASSWORD"
|
||||
value: "{{ hostvars['console']['postgresql']['password']['homebox'] }}"
|
||||
- name: "HBOX_OIDC_CLIENT_SECRET"
|
||||
value: "{{ hostvars['console']['homebox']['oidc']['secret'] }}"
|
||||
notify: "notification_restart_homebox"
|
||||
no_log: true
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "ghcr.io/sysadminsmedia/homebox"
|
||||
tag: "{{ version['containers']['homebox'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy homebox.container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/homebox/homebox.container.j2"
|
||||
dest: "{{ node['home_path'] }}/.config/containers/systemd/homebox.container"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0644"
|
||||
notify: "notification_restart_homebox"
|
||||
|
||||
- name: Enable homebox.service
|
||||
ansible.builtin.systemd:
|
||||
name: "homebox.service"
|
||||
state: "started"
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
scope: "user"
|
||||
|
||||
- name: Check container archive images
|
||||
ansible.builtin.stat:
|
||||
path: "{{ node['home_path'] }}/archives/containers/ghcr.io_sysadminsmedia_homebox_{{ version['containers']['homebox'] }}.tar"
|
||||
register: container_archive_images
|
||||
|
||||
- name: Save container archive images
|
||||
containers.podman.podman_save:
|
||||
image:
|
||||
- "ghcr.io/sysadminsmedia/homebox:{{ version['containers']['homebox'] }}"
|
||||
dest: "{{ node['home_path'] }}/archives/containers/ghcr.io_sysadminsmedia_homebox_{{ version['containers']['homebox'] }}.tar"
|
||||
format: "oci-archive"
|
||||
force: false
|
||||
when: not container_archive_images.stat.exists
|
||||
|
||||
- name: Fetch container archive images
|
||||
ansible.builtin.fetch:
|
||||
src: "{{ node['home_path'] }}/archives/containers/ghcr.io_sysadminsmedia_homebox_{{ version['containers']['homebox'] }}.tar"
|
||||
dest: "{{ hostvars['console']['node']['data_path'] }}/images/containers/"
|
||||
flat: true
|
||||
@@ -60,6 +60,7 @@
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "data/containers/immich"
|
||||
- "data/containers/immich/data"
|
||||
- "containers/immich"
|
||||
- "containers/immich/ssl"
|
||||
- "containers/immich/ml"
|
||||
@@ -85,6 +86,22 @@
|
||||
notify: "notification_restart_immich"
|
||||
no_log: true
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "{{ item.image }}"
|
||||
tag: "{{ item.tag }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
loop:
|
||||
- name: "immich_ml"
|
||||
image: "ghcr.io/immich-app/immich-machine-learning"
|
||||
tag: "{{ version['containers']['immich'] }}-openvino"
|
||||
- name: "immich"
|
||||
image: "ghcr.io/immich-app/immich-server"
|
||||
tag: "{{ version['containers']['immich'] }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
|
||||
- name: Deploy immich.container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/immich/immich.container.j2"
|
||||
@@ -123,14 +140,17 @@
|
||||
ansible.builtin.stat:
|
||||
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
|
||||
loop:
|
||||
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
|
||||
- name: "redis"
|
||||
image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
|
||||
file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
|
||||
- image: "ghcr.io/immich-app/immich-machine-learning:{{ version['containers']['immich'] }}-openvino"
|
||||
- name: "immich_ml"
|
||||
image: "ghcr.io/immich-app/immich-machine-learning:{{ version['containers']['immich'] }}-openvino"
|
||||
file: "ghcr.io_immich-app_immich-machine-learning_{{ version['containers']['immich'] }}-openvino"
|
||||
- image: "ghcr.io/immich-app/immich-server:{{ version['containers']['immich'] }}"
|
||||
- name: "immich"
|
||||
image: "ghcr.io/immich-app/immich-server:{{ version['containers']['immich'] }}"
|
||||
file: "ghcr.io_immich-app_immich-server_{{ version['containers']['immich'] }}"
|
||||
loop_control:
|
||||
label: "{{ item.file }}"
|
||||
label: "{{ item.name }}"
|
||||
register: container_archive_images
|
||||
|
||||
- name: Save container archive images
|
||||
|
||||
@@ -39,6 +39,13 @@
|
||||
notify: "notification_restart_mealie"
|
||||
no_log: true
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "ghcr.io/mealie-recipes/mealie"
|
||||
tag: "{{ version['containers']['mealie'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy mealie.container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/mealie/mealie.container.j2"
|
||||
|
||||
@@ -29,13 +29,20 @@
|
||||
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&\
|
||||
@{{ services['postgresql']['domain']['internal'] }}.{{ 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: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/neosmemo/memos"
|
||||
tag: "{{ version['containers']['memos'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy memos.container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/memos/memos.container.j2"
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
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_HOST: "{{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}:{{ services['postgresql']['ports']['tcp'] }}"
|
||||
POSTGRES_DB: "nextcloud_db"
|
||||
POSTGRES_USER: "nextcloud"
|
||||
POSTGRES_PASSWORD: "{{ hostvars['console']['postgresql']['password']['nextcloud'] }}"
|
||||
@@ -139,6 +139,13 @@
|
||||
- "upload.ini"
|
||||
notify: "notification_restart_nextcloud"
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/library/nextcloud"
|
||||
tag: "{{ version['containers']['nextcloud'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy nextcloud.container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/nextcloud/nextcloud.container.j2"
|
||||
@@ -179,12 +186,14 @@
|
||||
ansible.builtin.stat:
|
||||
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
|
||||
loop:
|
||||
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
|
||||
- name: "redis"
|
||||
image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
|
||||
file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
|
||||
- image: "docker.io/library/nextcloud:{{ version['containers']['nextcloud'] }}"
|
||||
- name: "nextcloud"
|
||||
image: "docker.io/library/nextcloud:{{ version['containers']['nextcloud'] }}"
|
||||
file: "docker.io_library_nextcloud_{{ version['containers']['nextcloud'] }}"
|
||||
loop_control:
|
||||
label: "{{ item.file }}"
|
||||
label: "{{ item.name }}"
|
||||
register: container_archive_images
|
||||
|
||||
- name: Save container archive images
|
||||
|
||||
@@ -101,6 +101,13 @@
|
||||
notify: "notification_restart_outline"
|
||||
no_log: true
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/outlinewiki/outline"
|
||||
tag: "{{ version['containers']['outline'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy outline.container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/outline/outline.container.j2"
|
||||
@@ -122,12 +129,14 @@
|
||||
ansible.builtin.stat:
|
||||
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
|
||||
loop:
|
||||
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
|
||||
- name: "redis"
|
||||
image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
|
||||
file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
|
||||
- image: "docker.io/outlinewiki/outline:{{ version['containers']['outline'] }}"
|
||||
- name: "outline"
|
||||
image: "docker.io/outlinewiki/outline:{{ version['containers']['outline'] }}"
|
||||
file: "docker.io_outlinewiki_outline_{{ version['containers']['outline'] }}"
|
||||
loop_control:
|
||||
label: "{{ item.file }}"
|
||||
label: "{{ item.name }}"
|
||||
register: container_archive_images
|
||||
|
||||
- name: Save container archive images
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0640"
|
||||
register: "is_paperless_containerfile"
|
||||
notify: "notification_restart_paperless"
|
||||
|
||||
- name: Deploy root certificate
|
||||
ansible.builtin.copy:
|
||||
@@ -87,6 +89,7 @@
|
||||
tag: "{{ version['containers']['paperless'] }}"
|
||||
state: "build"
|
||||
path: "{{ node['home_path'] }}/containers/paperless/build"
|
||||
force: "{{ is_paperless_containerfile.changed }}"
|
||||
|
||||
- name: Prune paperless dangling images
|
||||
containers.podman.podman_prune:
|
||||
@@ -116,7 +119,7 @@
|
||||
"client_id": "paperless",
|
||||
"secret": "{{ hostvars['console']['paperless']['oidc']['secret'] }}",
|
||||
"settings": {
|
||||
"server_url": "https://{{ services['authelia']['domain'] }}.{{ domain['public'] }}/.well-known/openid-configuration",
|
||||
"server_url": "https://{{ services['authelia']['domain']['public'] }}.{{ domain['public'] }}/.well-known/openid-configuration",
|
||||
"token_auth_method": "client_secret_post"
|
||||
}
|
||||
}
|
||||
@@ -147,12 +150,14 @@
|
||||
ansible.builtin.stat:
|
||||
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
|
||||
loop:
|
||||
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
|
||||
- name: "redis"
|
||||
image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
|
||||
file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
|
||||
- image: "{{ domain['internal'] }}/{{ node['name'] }}/paperless-ngx:{{ version['containers']['paperless'] }}"
|
||||
- name: "paperless"
|
||||
image: "{{ domain['internal'] }}/{{ node['name'] }}/paperless-ngx:{{ version['containers']['paperless'] }}"
|
||||
file: "{{ domain['internal'] }}_{{ node['name'] }}_paperless-ngx_{{ version['containers']['paperless'] }}"
|
||||
loop_control:
|
||||
label: "{{ item.file }}"
|
||||
label: "{{ item.name }}"
|
||||
register: container_archive_images
|
||||
|
||||
- name: Save container archive images
|
||||
@@ -161,11 +166,11 @@
|
||||
- "{{ item.item.image }}"
|
||||
dest: "{{ node['home_path'] }}/archives/containers/{{ item.item.file }}.tar"
|
||||
format: "oci-archive"
|
||||
force: false
|
||||
force: "{{ is_paperless_containerfile.changed }}"
|
||||
loop: "{{ container_archive_images.results }}"
|
||||
loop_control:
|
||||
label: "{{ item.item.file }}"
|
||||
when: not item.stat.exists
|
||||
when: not item.stat.exists or (item.item.name == 'paperless' and is_paperless_containerfile.changed)
|
||||
|
||||
- name: Fetch container archive images
|
||||
ansible.builtin.fetch:
|
||||
|
||||
@@ -86,6 +86,13 @@
|
||||
notify: "notification_restart_sure"
|
||||
no_log: true
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "ghcr.io/we-promise/sure"
|
||||
tag: "{{ version['containers']['sure'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy sure.container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/sure/{{ item }}.j2"
|
||||
@@ -113,12 +120,14 @@
|
||||
ansible.builtin.stat:
|
||||
path: "{{ node['home_path'] }}/archives/containers/{{ item.file }}.tar"
|
||||
loop:
|
||||
- image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
|
||||
- name: "redis"
|
||||
image: "docker.io/library/redis:{{ version['containers']['redis'] }}"
|
||||
file: "docker.io_library_redis_{{ version['containers']['redis'] }}"
|
||||
- image: "ghcr.io/we-promise/sure:{{ version['containers']['sure'] }}"
|
||||
- name: "sure"
|
||||
image: "ghcr.io/we-promise/sure:{{ version['containers']['sure'] }}"
|
||||
file: "ghcr.io_we-promise_sure_{{ version['containers']['sure'] }}"
|
||||
loop_control:
|
||||
label: "{{ item.file }}"
|
||||
label: "{{ item.name }}"
|
||||
register: container_archive_images
|
||||
|
||||
- name: Save container archive images
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
mode: "0770"
|
||||
loop:
|
||||
- "data/containers/vaultwarden"
|
||||
- "data/containers/vaultwarden/data"
|
||||
- "containers/vaultwarden"
|
||||
- "containers/vaultwarden/ssl"
|
||||
|
||||
@@ -34,11 +35,18 @@
|
||||
value: "{{ hostvars['console']['vaultwarden']['admin']['hash'] }}"
|
||||
- name: "VW_DATABASE_URL"
|
||||
value: "postgresql://vaultwarden:{{ hostvars['console']['postgresql']['password']['vaultwarden'] | urlencode | replace('/', '%2F') }}\
|
||||
@{{ services['postgresql']['domain'] }}.{{ domain['internal'] }}/vaultwarden_db?sslmode=verify-full&\
|
||||
@{{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}/vaultwarden_db?sslmode=verify-full&\
|
||||
sslrootcert=/etc/ssl/vaultwarden/{{ root_cert_filename }}"
|
||||
notify: "notification_restart_vaultwarden"
|
||||
no_log: true
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/vaultwarden/server"
|
||||
tag: "{{ version['containers']['vaultwarden'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/app/vaultwarden/vaultwarden.container.j2"
|
||||
|
||||
@@ -60,6 +60,13 @@
|
||||
notify: "notification_restart_authelia"
|
||||
no_log: true
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/authelia/authelia"
|
||||
tag: "{{ version['containers']['authelia'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/auth/authelia/authelia.container.j2"
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
- name: Check rclone installation
|
||||
ansible.builtin.shell: |
|
||||
command -v rclone
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
register: "is_rclone_installed"
|
||||
ignore_errors: true
|
||||
|
||||
- name: Install rclone
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- "rclone"
|
||||
state: "present"
|
||||
become: true
|
||||
when: is_rclone_installed.rc != 0
|
||||
|
||||
- name: Create rclone config directory
|
||||
ansible.builtin.file:
|
||||
path: "/etc/secrets/{{ node['uid'] }}/rclone"
|
||||
state: "directory"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "root"
|
||||
mode: "0700"
|
||||
become: true
|
||||
|
||||
- name: Deploy rclone config
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/bk/rclone/config/rclone.config.j2"
|
||||
dest: "/etc/secrets/{{ node['uid'] }}/rclone/rclone.config"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0600"
|
||||
no_log: true
|
||||
|
||||
- name: Deploy rclone backup service files
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/bk/rclone/{{ item }}.j2"
|
||||
dest: "{{ node['home_path'] }}/.config/systemd/user/{{ item }}"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0644"
|
||||
validate: "/usr/bin/systemd-analyze verify %s"
|
||||
loop:
|
||||
- "rclone.service"
|
||||
- "rclone.timer"
|
||||
|
||||
- name: Enable rclone timer
|
||||
ansible.builtin.systemd:
|
||||
name: "rclone.timer"
|
||||
state: "started"
|
||||
enabled: true
|
||||
scope: "user"
|
||||
daemon_reload: true
|
||||
@@ -99,3 +99,14 @@
|
||||
changed_when: false
|
||||
listen: "notification_restart_alloy"
|
||||
ignore_errors: true # noqa: ignore-errors
|
||||
|
||||
- name: Restart kopia server
|
||||
ansible.builtin.systemd:
|
||||
name: "kopia-server.service"
|
||||
state: "restarted"
|
||||
enabled: true
|
||||
scope: "user"
|
||||
daemon_reload: true
|
||||
changed_when: false
|
||||
listen: "notification_restart_kopia_server"
|
||||
ignore_errors: true # noqa: ignore-errors
|
||||
|
||||
+10
-10
@@ -1,16 +1,16 @@
|
||||
---
|
||||
- name: Check app data volume filesystem already exists
|
||||
ansible.builtin.command:
|
||||
cmd: "blkid /dev/{{ vm['data_storage']['name'] }}"
|
||||
register: is_app_data
|
||||
- name: Check data volume filesystem already exists
|
||||
ansible.builtin.command: |
|
||||
blkid /dev/{{ vm['data_storage']['name'] }}
|
||||
register: is_volume
|
||||
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
|
||||
- name: Create ext4 filesystem on data raw
|
||||
ansible.builtin.command: |
|
||||
mkfs.ext4 -F /dev/{{ vm['data_storage']['name'] }}
|
||||
when: is_volume.rc != 0
|
||||
changed_when: true
|
||||
become: true
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0770"
|
||||
|
||||
- name: Mount app data volume
|
||||
- name: Mount data volume
|
||||
ansible.posix.mount:
|
||||
path: "{{ node['home_path'] }}/data"
|
||||
src: "/dev/{{ vm['data_storage']['name'] }}"
|
||||
@@ -31,7 +31,7 @@
|
||||
fstype: "ext4"
|
||||
become: true
|
||||
|
||||
- name: Set app data volume path permissions
|
||||
- name: Set data volume path permissions
|
||||
ansible.builtin.file:
|
||||
path: "{{ node['home_path'] }}/data"
|
||||
state: "directory"
|
||||
@@ -9,8 +9,8 @@
|
||||
become: true
|
||||
|
||||
- name: Deploy timesyncd.conf.d/local-ntp.conf
|
||||
ansible.builtin.copy:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/node/common/timesyncd/local-ntp.conf"
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/node/common/timesyncd/local-ntp.conf.j2"
|
||||
dest: "/etc/systemd/timesyncd.conf.d/local-ntp.conf"
|
||||
owner: "root"
|
||||
group: "systemd-timesync"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
- name: Gather ystem facts (hardware)
|
||||
- name: Gather system facts (hardware)
|
||||
ansible.builtin.setup:
|
||||
gather_subset:
|
||||
- hardware
|
||||
@@ -78,7 +78,7 @@
|
||||
- "{{ node['home_path'] }}"
|
||||
- "{{ node['home_path'] }}/data"
|
||||
become: true
|
||||
when: node['name'] == "app"
|
||||
when: node['name'] in ["bk", "app"]
|
||||
|
||||
- name: Enable alloy service
|
||||
ansible.builtin.systemd:
|
||||
@@ -88,9 +88,16 @@
|
||||
daemon_reload: true
|
||||
become: true
|
||||
|
||||
- name: Check alloy.deb on console
|
||||
delegate_to: "console"
|
||||
ansible.builtin.stat:
|
||||
path: "{{ hostvars['console']['node']['data_path'] }}/bin/alloy-{{ version['packages']['alloy'] }}.deb"
|
||||
register: is_console_alloy_deb
|
||||
|
||||
- name: Fetch deb bin file
|
||||
ansible.builtin.fetch:
|
||||
src: "/var/cache/apt/archives/alloy-{{ version['packages']['alloy'] }}.deb"
|
||||
dest: "{{ hostvars['console']['node']['data_path'] }}/bin/"
|
||||
flat: true
|
||||
when: not is_console_alloy_deb.stat.exists
|
||||
become: true
|
||||
|
||||
@@ -1,5 +1,48 @@
|
||||
---
|
||||
- name: Initialize Caddy services list
|
||||
ansible.builtin.set_fact:
|
||||
caddy_services: []
|
||||
|
||||
# infra, auth, app (vmm, fw has no podman in it)
|
||||
- name: Set Caddy infra services list
|
||||
ansible.builtin.set_fact:
|
||||
caddy_services: >-
|
||||
{{
|
||||
services
|
||||
| dict2items
|
||||
| selectattr('value.dependency.web', 'defined')
|
||||
| selectattr('value.dependency.web', 'in', ['infra-internal', 'infra-public'])
|
||||
| map(attribute='key')
|
||||
| list
|
||||
}}
|
||||
when: node['name'] == 'infra'
|
||||
|
||||
- name: Set Caddy auth services list
|
||||
ansible.builtin.set_fact:
|
||||
caddy_services: >-
|
||||
{{
|
||||
services
|
||||
| dict2items
|
||||
| selectattr('value.dependency.web', 'defined')
|
||||
| selectattr('value.dependency.web', 'in', ['auth-public', 'infra-public', 'app-public'])
|
||||
| map(attribute='key')
|
||||
| list
|
||||
}}
|
||||
when: node['name'] == 'auth'
|
||||
|
||||
- name: Set Caddy app services list
|
||||
ansible.builtin.set_fact:
|
||||
caddy_services: >-
|
||||
{{
|
||||
services
|
||||
| dict2items
|
||||
| selectattr('value.dependency.web', 'defined')
|
||||
| selectattr('value.dependency.web', 'in', ['app-internal', 'app-public'])
|
||||
| map(attribute='key')
|
||||
| list
|
||||
}}
|
||||
when: node['name'] == 'app'
|
||||
|
||||
- name: Create caddy directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ node['home_path'] }}/containers/{{ item }}"
|
||||
@@ -50,6 +93,8 @@
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0640"
|
||||
register: "is_caddy_containerfile"
|
||||
notify: "notification_restart_caddy"
|
||||
|
||||
- name: Deploy root crt for build
|
||||
ansible.builtin.copy:
|
||||
@@ -58,6 +103,8 @@
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0640"
|
||||
register: "is_caddy_root_crt"
|
||||
notify: "notification_restart_caddy"
|
||||
no_log: true
|
||||
|
||||
- name: Build caddy container image
|
||||
@@ -67,6 +114,7 @@
|
||||
tag: "{{ version['containers']['caddy'] }}"
|
||||
state: "build"
|
||||
path: "{{ node['home_path'] }}/containers/caddy/build"
|
||||
force: "{{ is_caddy_root_crt.changed or is_caddy_containerfile.changed }}"
|
||||
|
||||
- name: Prune caddy dangling images
|
||||
containers.podman.podman_prune:
|
||||
@@ -74,7 +122,7 @@
|
||||
|
||||
- name: Deploy caddyfile
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/common/caddy/etc/{{ node['name'] }}/Caddyfile.j2"
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/common/caddy/etc/Caddyfile.j2"
|
||||
dest: "{{ node['home_path'] }}/containers/caddy/etc/Caddyfile"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
@@ -109,8 +157,8 @@
|
||||
- "{{ 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
|
||||
force: "{{ is_caddy_root_crt.changed or is_caddy_containerfile.changed }}"
|
||||
when: not container_archive_images.stat.exists or is_caddy_root_crt.changed or is_caddy_containerfile.changed
|
||||
|
||||
- name: Fetch container archive images
|
||||
ansible.builtin.fetch:
|
||||
|
||||
@@ -120,8 +120,8 @@
|
||||
no_log: true
|
||||
|
||||
- name: Get existing machines list
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli machines list -o json"
|
||||
ansible.builtin.command: |
|
||||
cscli machines list -o json
|
||||
become: true
|
||||
changed_when: false
|
||||
register: "existing_crowdsec_machines_list"
|
||||
@@ -132,27 +132,27 @@
|
||||
|
||||
- name: Set goal machines' name
|
||||
ansible.builtin.set_fact:
|
||||
machines_name: ["fw", "vmm", "infra", "auth", "app"]
|
||||
machines_name: ["fw", "vmm", "bk", "infra", "auth", "app"]
|
||||
no_log: true
|
||||
|
||||
- name: Prune unknown (random) machines
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli machines delete {{ item }}"
|
||||
ansible.builtin.command: |
|
||||
cscli machines delete {{ item }}
|
||||
loop: "{{ existing_machines_name | difference(machines_name) }}"
|
||||
become: true
|
||||
changed_when: true
|
||||
|
||||
- name: Register crowdsec machines to LAPI server
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli machines add {{ item }} --password {{ hostvars['console']['crowdsec']['machine'][item] }} --force -f /dev/null"
|
||||
ansible.builtin.command: |
|
||||
cscli machines add {{ item }} --password {{ hostvars['console']['crowdsec']['machine'][item] }} --force -f /dev/null
|
||||
loop: "{{ machines_name }}"
|
||||
become: true
|
||||
changed_when: false
|
||||
no_log: true
|
||||
|
||||
- name: Get existing bouncers list
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli bouncers list -o json"
|
||||
ansible.builtin.command: |
|
||||
cscli bouncers list -o json
|
||||
become: true
|
||||
register: "existing_crowdsec_bouncers_list"
|
||||
changed_when: false
|
||||
@@ -162,8 +162,8 @@
|
||||
existing_bouncers_name: "{{ existing_crowdsec_bouncers_list.stdout | from_json | map(attribute='name') | list }}"
|
||||
|
||||
- name: Flush bouncers
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli bouncers delete {{ item }}"
|
||||
ansible.builtin.command: |
|
||||
cscli bouncers delete {{ item }}
|
||||
loop: "{{ existing_bouncers_name }}"
|
||||
become: true
|
||||
changed_when: true
|
||||
@@ -173,8 +173,8 @@
|
||||
bouncers_name: ["fw", "caddy"]
|
||||
|
||||
- name: Register Firewall Bouncer to LAPI
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli bouncers add {{ item }}-bouncer -k {{ hostvars['console']['crowdsec']['bouncer'][item] }}"
|
||||
ansible.builtin.command: |
|
||||
cscli bouncers add {{ item }}-bouncer -k {{ hostvars['console']['crowdsec']['bouncer'][item] }}
|
||||
loop: "{{ bouncers_name }}"
|
||||
become: true
|
||||
changed_when: true
|
||||
@@ -185,8 +185,8 @@
|
||||
when: node['name'] in acquisd_list
|
||||
block:
|
||||
- name: Install crowdsec collection
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli collections install {{ item }}"
|
||||
ansible.builtin.command: |
|
||||
cscli collections install {{ item }}
|
||||
loop: "{{ acquisd_list[node['name']]['collection'] }}"
|
||||
become: true
|
||||
changed_when: "'overwrite' not in is_collection_installed.stderr"
|
||||
@@ -196,8 +196,8 @@
|
||||
register: "is_collection_installed"
|
||||
|
||||
- name: Install crowdsec parser
|
||||
ansible.builtin.command:
|
||||
cmd: "cscli parsers install {{ item }}"
|
||||
ansible.builtin.command: |
|
||||
cscli parsers install {{ item }}
|
||||
loop: "{{ acquisd_list[node['name']]['parser'] }}"
|
||||
become: true
|
||||
changed_when: "'overwrite' not in is_parser_installed.stderr"
|
||||
|
||||
@@ -5,50 +5,288 @@
|
||||
- hardware
|
||||
become: true
|
||||
|
||||
- name: Set console kopia
|
||||
when: node['name'] == 'console'
|
||||
- name: Set backup kopia repository server
|
||||
when: node['name'] == "bk"
|
||||
block:
|
||||
- name: Download kopia
|
||||
- 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_{{ 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"
|
||||
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: Install kopia (aarch64)
|
||||
ansible.builtin.apt:
|
||||
deb: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-arm64.deb"
|
||||
state: "present"
|
||||
- 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: Connect console kopia server
|
||||
environment:
|
||||
KOPIA_PASSWORD: "{{ hostvars['console']['kopia']['users']['console'] }}"
|
||||
ansible.builtin.shell: |
|
||||
/usr/bin/kopia repository connect server \
|
||||
--url=https://{{ services['kopia']['domain'] }}.{{ domain['internal'] }}:{{ services['kopia']['ports']['https'] }} \
|
||||
--override-username=console \
|
||||
--override-hostname=console.{{ domain['internal'] }}
|
||||
changed_when: false
|
||||
failed_when: is_kopia_connected.rc != 0
|
||||
register: "is_kopia_connected"
|
||||
- name: Create kopia directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.name }}"
|
||||
state: "directory"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "root"
|
||||
mode: "{{ item.mode }}"
|
||||
loop:
|
||||
- name: "/etc/kopia"
|
||||
mode: "0700"
|
||||
- name: "/etc/kopia/ssl"
|
||||
mode: "0700"
|
||||
- name: "/var/cache/kopia"
|
||||
mode: "0700"
|
||||
become: true
|
||||
no_log: true
|
||||
|
||||
- name: Set infra/app kopia
|
||||
when: node['name'] in ['infra', 'app']
|
||||
- name: Install kopia
|
||||
ansible.builtin.apt:
|
||||
deb: "/var/cache/apt/archives/kopia-{{ version['packages']['kopia'] }}.deb"
|
||||
state: "present"
|
||||
become: true
|
||||
|
||||
- name: Deploy kopia env
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/kopia/kopia.env.j2"
|
||||
dest: "/etc/secrets/{{ node['uid'] }}/kopia.env"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "root"
|
||||
mode: "0400"
|
||||
become: true
|
||||
notify: "notification_restart_kopia_server"
|
||||
no_log: true
|
||||
|
||||
- name: Deploy kopia certificate and key
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
{{ item.value }}
|
||||
dest: "/etc/kopia/ssl/{{ item.name }}"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "{{ item.mode }}"
|
||||
loop:
|
||||
- name: "kopia.crt"
|
||||
value: |
|
||||
{{ hostvars['console']['kopia']['crt'] | trim }}
|
||||
{{ hostvars['console']['ca']['intermediate']['crt'] }}
|
||||
mode: "0440"
|
||||
- name: "kopia.key"
|
||||
value: "{{ hostvars['console']['kopia']['key'] }}"
|
||||
mode: "0400"
|
||||
notify: "notification_restart_kopia_server"
|
||||
no_log: true
|
||||
|
||||
- name: Check repository existance
|
||||
ansible.builtin.stat:
|
||||
path: "{{ node['home_path'] }}/data/kopia/repository"
|
||||
register: "is_kopia_repository"
|
||||
|
||||
- name: Create repository directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ node['home_path'] }}/data/kopia/repository"
|
||||
state: "directory"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0770"
|
||||
when: not is_kopia_repository.stat.exists
|
||||
|
||||
- name: Create kopia repository
|
||||
ansible.builtin.shell: |
|
||||
set -a
|
||||
. /etc/secrets/{{ node['uid'] }}/kopia.env
|
||||
set +a
|
||||
/usr/bin/kopia repository create filesystem \
|
||||
--path="{{ node['home_path'] }}/data/kopia/repository" \
|
||||
--description="ilnmors.internal kopia repository" \
|
||||
--create-only
|
||||
when: not is_kopia_repository.stat.exists
|
||||
changed_when: true
|
||||
register: "is_repository_created"
|
||||
no_log: true
|
||||
|
||||
- name: Connect to kopia repository
|
||||
ansible.builtin.shell: |
|
||||
set -a
|
||||
. /etc/secrets/{{ node['uid'] }}/kopia.env
|
||||
set +a
|
||||
/usr/bin/kopia repository connect filesystem \
|
||||
--path="{{ node['home_path'] }}/data/kopia/repository" \
|
||||
--override-username="il" \
|
||||
--override-hostname="{{ node['name'] }}.{{ domain['internal'] }}" \
|
||||
when:
|
||||
- not is_kopia_repository.stat.exists
|
||||
- is_repository_created.rc == 0
|
||||
changed_when: true
|
||||
register: "is_repository_connected"
|
||||
no_log: true
|
||||
|
||||
- name: Create kopia user
|
||||
ansible.builtin.shell: |
|
||||
set -a
|
||||
. /etc/secrets/{{ node['uid'] }}/kopia.env
|
||||
set +a
|
||||
/usr/bin/kopia server users add \
|
||||
--user-password {{ item.password | quote }} \
|
||||
{{ item.name }}
|
||||
loop:
|
||||
- name: "console@console.ilnmors.internal"
|
||||
password: "{{ hostvars['console']['kopia']['users']['console'] }}"
|
||||
- name: "infra@infra.ilnmors.internal"
|
||||
password: "{{ hostvars['console']['kopia']['users']['infra'] }}"
|
||||
- name: "app@app.ilnmors.internal"
|
||||
password: "{{ hostvars['console']['kopia']['users']['app'] }}"
|
||||
when:
|
||||
- not is_kopia_repository.stat.exists
|
||||
- is_repository_connected.rc == 0
|
||||
changed_when: true
|
||||
register: "is_user_created"
|
||||
no_log: true
|
||||
|
||||
- name: Set kopia console ACL
|
||||
ansible.builtin.shell: |
|
||||
set -a
|
||||
. /etc/secrets/{{ node['uid'] }}/kopia.env
|
||||
set +a
|
||||
/usr/bin/kopia server acl add \
|
||||
--user console@console.ilnmors.internal \
|
||||
--target {{ item }} \
|
||||
--access FULL
|
||||
loop:
|
||||
- "type=snapshot"
|
||||
- "type=policy"
|
||||
- "type=user"
|
||||
- "type=acl"
|
||||
- "type=content"
|
||||
when:
|
||||
- not is_kopia_repository.stat.exists
|
||||
- is_repository_connected.rc == 0
|
||||
changed_when: true
|
||||
no_log: true
|
||||
|
||||
- name: Set kopia infra ACL
|
||||
ansible.builtin.shell: |
|
||||
set -a
|
||||
. /etc/secrets/{{ node['uid'] }}/kopia.env
|
||||
set +a
|
||||
/usr/bin/kopia server acl add \
|
||||
--user infra@infra.ilnmors.internal \
|
||||
--target {{ item.target }} \
|
||||
--access {{ item.access }}
|
||||
loop:
|
||||
- target: "type=snapshot"
|
||||
access: "FULL"
|
||||
- target: "type=policy"
|
||||
access: "READ"
|
||||
- target: "type=policy,username=infra,hostname=infra.ilnmors.internal"
|
||||
access: "FULL"
|
||||
- target: "type=content"
|
||||
access: "APPEND"
|
||||
when:
|
||||
- not is_kopia_repository.stat.exists
|
||||
- is_repository_connected.rc == 0
|
||||
changed_when: true
|
||||
no_log: true
|
||||
|
||||
- name: Set kopia app ACL
|
||||
ansible.builtin.shell: |
|
||||
set -a
|
||||
. /etc/secrets/{{ node['uid'] }}/kopia.env
|
||||
set +a
|
||||
/usr/bin/kopia server acl add \
|
||||
--user app@app.ilnmors.internal \
|
||||
--target {{ item.target }} \
|
||||
--access {{ item.access }}
|
||||
loop:
|
||||
- target: "type=snapshot"
|
||||
access: "FULL"
|
||||
- target: "type=policy"
|
||||
access: "READ"
|
||||
- target: "type=policy,username=app,hostname=app.ilnmors.internal"
|
||||
access: "FULL"
|
||||
- target: "type=content"
|
||||
access: "APPEND"
|
||||
when:
|
||||
- not is_kopia_repository.stat.exists
|
||||
- is_repository_connected.rc == 0
|
||||
changed_when: true
|
||||
no_log: true
|
||||
|
||||
- name: Set kopia policy
|
||||
ansible.builtin.shell: |
|
||||
set -a
|
||||
. /etc/secrets/{{ node['uid'] }}/kopia.env
|
||||
set +a
|
||||
/usr/bin/kopia policy set \
|
||||
{{ item.content }}
|
||||
loop:
|
||||
- content: |
|
||||
--global \
|
||||
--compression=zstd
|
||||
- content: |
|
||||
infra@infra.ilnmors.internal \
|
||||
--compression=zstd \
|
||||
--keep-latest=10 \
|
||||
--keep-hourly=0 \
|
||||
--keep-daily=14 \
|
||||
--keep-weekly=4 \
|
||||
--keep-monthly=6 \
|
||||
--keep-annual=1
|
||||
- content: |
|
||||
app@app.ilnmors.internal \
|
||||
--compression=none \
|
||||
--keep-latest=10 \
|
||||
--keep-hourly=0 \
|
||||
--keep-daily=14 \
|
||||
--keep-weekly=4 \
|
||||
--keep-monthly=6 \
|
||||
--keep-annual=1
|
||||
when:
|
||||
- not is_kopia_repository.stat.exists
|
||||
- is_repository_connected.rc == 0
|
||||
changed_when: true
|
||||
no_log: true
|
||||
|
||||
- name: Set kopia parameters
|
||||
ansible.builtin.shell: |
|
||||
set -a
|
||||
. /etc/secrets/{{ node['uid'] }}/kopia.env
|
||||
set +a
|
||||
/usr/bin/kopia repository set-parameters \
|
||||
--max-pack-size-mb=100
|
||||
when:
|
||||
- not is_kopia_repository.stat.exists
|
||||
- is_repository_connected.rc == 0
|
||||
changed_when: true
|
||||
no_log: true
|
||||
|
||||
- name: Deploy kopia servcer service file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/kopia/kopia-server.service.j2"
|
||||
dest: "{{ node['home_path'] }}/.config/systemd/user/kopia-server.service"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0644"
|
||||
validate: "/usr/bin/systemd-analyze verify %s"
|
||||
become: true
|
||||
|
||||
- name: Enable kopia server service
|
||||
ansible.builtin.systemd:
|
||||
name: "kopia-server.service"
|
||||
state: "started"
|
||||
enabled: true
|
||||
scope: "user"
|
||||
daemon_reload: true
|
||||
|
||||
- name: Set infra/app backup kopia
|
||||
when: node['name'] in ["infra", "app"]
|
||||
block:
|
||||
- name: Set kopia uid
|
||||
ansible.builtin.set_fact:
|
||||
@@ -127,7 +365,7 @@
|
||||
become: true
|
||||
no_log: true
|
||||
|
||||
- name: Deploy kopia service files
|
||||
- name: Deploy kopia backup service files
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/common/kopia/{{ item }}.j2"
|
||||
dest: "/etc/systemd/system/{{ item }}"
|
||||
@@ -140,10 +378,52 @@
|
||||
- "kopia-backup.timer"
|
||||
become: true
|
||||
|
||||
- name: Enable auto kopia rules update
|
||||
- name: Enable Kopia backup timer
|
||||
ansible.builtin.systemd:
|
||||
name: "kopia-backup.timer"
|
||||
state: "started"
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
become: true
|
||||
|
||||
- name: Set console kopia
|
||||
when: node['name'] == "console"
|
||||
block:
|
||||
- name: Download kopia
|
||||
ansible.builtin.get_url:
|
||||
url: "https://github.com/kopia/kopia/releases/download/v{{ version['packages']['kopia'] }}/\
|
||||
kopia_{{ version['packages']['kopia'] }}_linux_{{ item }}.deb"
|
||||
dest: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-{{ item }}.deb"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0600"
|
||||
loop:
|
||||
- "amd64"
|
||||
- "arm64"
|
||||
|
||||
- name: Install kopia (x86_64)
|
||||
ansible.builtin.apt:
|
||||
deb: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-amd64.deb"
|
||||
state: "present"
|
||||
become: true
|
||||
when: ansible_facts['architecture'] == "x86_64"
|
||||
|
||||
- name: Install kopia (aarch64)
|
||||
ansible.builtin.apt:
|
||||
deb: "{{ node['data_path'] }}/bin/kopia-{{ version['packages']['kopia'] }}-arm64.deb"
|
||||
state: "present"
|
||||
become: true
|
||||
when: ansible_facts['architecture'] == "aarch64"
|
||||
|
||||
- name: Connect console kopia server
|
||||
environment:
|
||||
KOPIA_PASSWORD: "{{ hostvars['console']['kopia']['users']['console'] }}"
|
||||
ansible.builtin.shell: |
|
||||
/usr/bin/kopia repository connect server \
|
||||
--url=https://{{ services['kopia']['domain']['internal'] }}.{{ domain['internal'] }}:443 \
|
||||
--override-username=console \
|
||||
--override-hostname=console.{{ domain['internal'] }}
|
||||
changed_when: false
|
||||
failed_when: is_kopia_connected.rc != 0
|
||||
register: "is_kopia_connected"
|
||||
no_log: true
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
environment:
|
||||
SOPS_AGE_KEY: "{{ hostvars['console']['age_key'] }}"
|
||||
ansible.builtin.command: |
|
||||
sops -d --output-type yaml {{ hostvars['console']['node']['config_path'] }}/secrets/secrets.yaml
|
||||
sops -d --output-type yaml "{{ hostvars['console']['node']['config_path'] }}/secrets/secrets.yaml"
|
||||
changed_when: false
|
||||
register: "decrypted_secrets"
|
||||
run_once: true
|
||||
|
||||
@@ -24,16 +24,20 @@
|
||||
notify: "notification_restart_ca"
|
||||
no_log: true
|
||||
|
||||
- name: Deploy ca config files
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/smallstep/step-ca"
|
||||
tag: "{{ version['containers']['step'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy ca config file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ca/config/{{ item }}.j2"
|
||||
dest: "{{ node['home_path'] }}/containers/ca/config/{{ item }}"
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ca/config/ca.json.j2"
|
||||
dest: "{{ node['home_path'] }}/containers/ca/config/ca.json"
|
||||
owner: "{{ services['ca']['subuid'] }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0400"
|
||||
loop:
|
||||
- "ca.json"
|
||||
- "defaults.json"
|
||||
become: true
|
||||
notify: "notification_restart_ca"
|
||||
|
||||
|
||||
@@ -68,6 +68,13 @@
|
||||
become: true
|
||||
notify: "notification_restart_grafana"
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/grafana/grafana"
|
||||
tag: "{{ version['containers']['grafana'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/grafana/grafana.container.j2"
|
||||
|
||||
@@ -46,7 +46,8 @@
|
||||
# urlencode doesn't fix `/` as `%2F`. It needs replace
|
||||
- name: "LLDAP_DATABASE_URL"
|
||||
value: "postgres://ldap:{{ hostvars['console']['postgresql']['password']['ldap'] | urlencode | replace('/', '%2F') }}\
|
||||
@{{ services['postgresql']['domain'] }}.{{ domain['internal'] }}/ldap_db?sslmode=verify-full&sslrootcert=/etc/ssl/ldap/{{ root_cert_filename }}"
|
||||
@{{ services['postgresql']['domain']['internal'] }}.{{ domain['internal'] }}/\
|
||||
ldap_db?sslmode=verify-full&sslrootcert=/etc/ssl/ldap/{{ root_cert_filename }}"
|
||||
- name: "LLDAP_KEY_SEED"
|
||||
value: "{{ hostvars['console']['ldap']['seed_key'] }}"
|
||||
- name: "LLDAP_JWT_SECRET"
|
||||
@@ -93,6 +94,13 @@
|
||||
name: "LLDAP_LDAP_USER_PASSWORD"
|
||||
state: "absent"
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/lldap/lldap"
|
||||
tag: "{{ version['containers']['ldap'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/ldap/ldap.container.j2"
|
||||
|
||||
@@ -48,6 +48,13 @@
|
||||
notify: "notification_restart_loki"
|
||||
no_log: true
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/grafana/loki"
|
||||
tag: "{{ version['containers']['loki'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/loki/loki.container.j2"
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
---
|
||||
- name: Initialize connected services list
|
||||
ansible.builtin.set_fact:
|
||||
connected_services: []
|
||||
|
||||
- name: Set connected services list
|
||||
ansible.builtin.set_fact:
|
||||
connected_services:
|
||||
- "ldap"
|
||||
- "grafana"
|
||||
- "authelia"
|
||||
- "vaultwarden"
|
||||
- "gitea"
|
||||
- "immich"
|
||||
- "paperless"
|
||||
- "nextcloud"
|
||||
- "sure"
|
||||
- "outline"
|
||||
- "memos"
|
||||
- "mealie"
|
||||
connected_services: >-
|
||||
{{
|
||||
services
|
||||
| dict2items
|
||||
| selectattr('value.dependency.db', 'defined')
|
||||
| selectattr('value.dependency.db', 'equalto', 'postgresql')
|
||||
| map(attribute='key')
|
||||
| list
|
||||
}}
|
||||
|
||||
- name: Create postgresql directory
|
||||
ansible.builtin.file:
|
||||
@@ -39,6 +39,8 @@
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0640"
|
||||
register: "is_postgresql_containerfile"
|
||||
notify: "notification_restart_postgresql"
|
||||
|
||||
- name: Build postgresql container image
|
||||
containers.podman.podman_image:
|
||||
@@ -47,6 +49,7 @@
|
||||
tag: "pg{{ version['containers']['postgresql'] }}-vectorchord{{ version['containers']['vectorchord'] }}"
|
||||
state: "build"
|
||||
path: "{{ node['home_path'] }}/containers/postgresql/build"
|
||||
force: "{{ is_postgresql_containerfile.changed }}"
|
||||
|
||||
- name: Prune postgresql dangling images
|
||||
containers.podman.podman_prune:
|
||||
@@ -96,16 +99,33 @@
|
||||
become: true
|
||||
register: "is_postgresql_init"
|
||||
|
||||
- name: Check init directory empty
|
||||
ansible.builtin.find:
|
||||
path: "{{ node['home_path'] }}/containers/postgresql/init/"
|
||||
file_type: "any"
|
||||
patterns:
|
||||
- "*.sql"
|
||||
become: true
|
||||
register: "is_init_dir_empty"
|
||||
|
||||
- name: Check pg_cluster.sql on console
|
||||
delegate_to: "console"
|
||||
ansible.builtin.stat:
|
||||
path: "{{ hostvars['console']['node']['data_path'] }}/sql/postgresql/pg_cluster.sql"
|
||||
register: is_console_pg_cluster_sql
|
||||
|
||||
- name: Prepare initiating DB
|
||||
when:
|
||||
- not is_postgresql_init.stat.exists
|
||||
- is_init_dir_empty.matched == 0
|
||||
- is_console_pg_cluster_sql.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"
|
||||
src: "{{ hostvars['console']['node']['data_path'] }}/sql/postgresql/pg_cluster.sql"
|
||||
dest: "{{ node['home_path'] }}/containers/postgresql/init/00_pg_cluster.sql"
|
||||
owner: "{{ services['postgresql']['subuid'] }}"
|
||||
group: "{{ node['group'] }}"
|
||||
@@ -113,7 +133,7 @@
|
||||
|
||||
- name: Deploy restoring data sql files
|
||||
ansible.builtin.copy:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/postgresql/init/pg_{{ item }}.sql"
|
||||
src: "{{ hostvars['console']['node']['data_path'] }}/sql/postgresql/pg_{{ item }}.sql"
|
||||
dest: "{{ node['home_path'] }}/containers/postgresql/init/{{ '%02d' | format(index_num + 1) }}_pg_{{ item }}.sql"
|
||||
owner: "{{ services['postgresql']['subuid'] }}"
|
||||
group: "{{ node['group'] }}"
|
||||
@@ -192,8 +212,8 @@
|
||||
{{ 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
|
||||
force: "{{ is_postgresql_containerfile.changed }}"
|
||||
when: not container_archive_images.stat.exists or is_postgresql_containerfile.changed
|
||||
|
||||
- name: Fetch container archive images
|
||||
ansible.builtin.fetch:
|
||||
|
||||
@@ -52,6 +52,13 @@
|
||||
notify: "notification_restart_prometheus"
|
||||
no_log: true
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/prom/prometheus"
|
||||
tag: "{{ version['containers']['prometheus'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
- name: Deploy container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/prometheus/prometheus.container.j2"
|
||||
|
||||
@@ -1,4 +1,20 @@
|
||||
---
|
||||
- name: Initialize self-cert services list
|
||||
ansible.builtin.set_fact:
|
||||
cert_services: []
|
||||
|
||||
- name: Set self-cert services list
|
||||
ansible.builtin.set_fact:
|
||||
cert_services: >-
|
||||
{{
|
||||
services
|
||||
| dict2items
|
||||
| selectattr('value.dependency.cert', 'defined')
|
||||
| selectattr('value.dependency.cert', 'equalto', true)
|
||||
| map(attribute='key')
|
||||
| list
|
||||
}}
|
||||
|
||||
- name: Create x509-exporter directory
|
||||
ansible.builtin.file:
|
||||
path: "{{ node['home_path'] }}/containers/{{ item }}"
|
||||
@@ -22,7 +38,7 @@
|
||||
become: true
|
||||
notify: "notification_restart_x509-exporter"
|
||||
|
||||
- name: Deploy certificates
|
||||
- name: Deploy CA certificates
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
{{ item.value }}
|
||||
@@ -35,23 +51,31 @@
|
||||
value: "{{ hostvars['console']['ca']['root']['crt'] }}"
|
||||
- name: "intermediate.crt"
|
||||
value: "{{ hostvars['console']['ca']['intermediate']['crt'] }}"
|
||||
- name: "crowdsec.crt"
|
||||
value: "{{ hostvars['console']['crowdsec']['crt'] }}"
|
||||
- name: "blocky.crt"
|
||||
value: "{{ hostvars['console']['blocky']['crt'] }}"
|
||||
- name: "postgresql.crt"
|
||||
value: "{{ hostvars['console']['postgresql']['crt'] }}"
|
||||
- name: "ldap.crt"
|
||||
value: "{{ hostvars['console']['ldap']['crt'] }}"
|
||||
- name: "prometheus.crt"
|
||||
value: "{{ hostvars['console']['prometheus']['crt'] }}"
|
||||
- name: "loki.crt"
|
||||
value: "{{ hostvars['console']['loki']['crt'] }}"
|
||||
- name: "dsm.crt"
|
||||
value: "{{ hostvars['console']['dsm']['crt'] }}"
|
||||
become: true
|
||||
notify: "notification_restart_x509-exporter"
|
||||
no_log: true
|
||||
|
||||
- name: Deploy leaf certificates
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
{{ hostvars['console'][item]['crt'] }}
|
||||
dest: "{{ node['home_path'] }}/containers/x509-exporter/certs/{{ item }}.crt"
|
||||
owner: "{{ services['x509-exporter']['subuid'] }}"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0440"
|
||||
loop: "{{ cert_services }}"
|
||||
become: true
|
||||
notify: "notification_restart_x509-exporter"
|
||||
no_log: true
|
||||
|
||||
- name: Pull image
|
||||
containers.podman.podman_image:
|
||||
name: "docker.io/enix/x509-certificate-exporter"
|
||||
tag: "{{ version['containers']['x509-exporter'] }}"
|
||||
state: "present"
|
||||
pull: true
|
||||
|
||||
|
||||
- name: Deploy container file
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/containers/infra/x509-exporter/x509-exporter.container.j2"
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
---
|
||||
- name: Check btrfs installation
|
||||
ansible.builtin.shell: |
|
||||
command -v btrfs
|
||||
become: true # btrfs is located in /usr/sbin, which means root permission is needed.
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
register: "is_btrfs_installed"
|
||||
|
||||
- name: Install btrfs
|
||||
ansible.builtin.apt:
|
||||
name: "btrfs-progs"
|
||||
state: "present"
|
||||
become: true
|
||||
when: is_btrfs_installed.rc != 0
|
||||
|
||||
- name: Mount data disk
|
||||
block:
|
||||
- name: Set hard data disk path
|
||||
ansible.builtin.shell: |
|
||||
set -o pipefail
|
||||
ls -1 /dev/disk/by-id/ata-* | \
|
||||
grep -F -e "{{ hardware['disk']['data']['serials'] | join('" -e "') }}" | \
|
||||
grep -vE -- '-part[0-9]+$' | \
|
||||
sort
|
||||
changed_when: false
|
||||
register: "data_disk_path"
|
||||
|
||||
- name: Check vmm_hdd filesystem already exists
|
||||
ansible.builtin.command: |
|
||||
blkid -L {{ hardware['disk']['data']['fs']['label'] }}
|
||||
become: true
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
register: "is_data_disk_fs"
|
||||
|
||||
- name: Check disk number
|
||||
ansible.builtin.fail:
|
||||
msg: "Below 4 disks for RAID10, found {{ data_disk_path.stdout_lines | length }}"
|
||||
when: (data_disk_path.stdout_lines | length) < hardware['disk']['data']['fs']['btrfs']['min_devices']
|
||||
|
||||
- name: Set btrfs raid10 volume
|
||||
ansible.builtin.shell: |
|
||||
mkfs.btrfs -f \
|
||||
-L {{ hardware['disk']['data']['fs']['label'] }} \
|
||||
-d {{ hardware['disk']['data']['fs']['btrfs']['data_profile'] }} \
|
||||
-m {{ hardware['disk']['data']['fs']['btrfs']['metadata_profile'] }} \
|
||||
{{ data_disk_path.stdout_lines | join(' ') }}
|
||||
become: true
|
||||
when:
|
||||
- is_data_disk_fs.rc != 0
|
||||
- (data_disk_path.stdout_lines | length) >= hardware['disk']['data']['fs']['btrfs']['min_devices']
|
||||
changed_when: is_mkfs.rc == 0
|
||||
register: "is_mkfs"
|
||||
|
||||
- name: Create mount volume
|
||||
ansible.builtin.file:
|
||||
path: "{{ hardware['disk']['data']['fs']['mount_point'] }}"
|
||||
state: "directory"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0711"
|
||||
become: true
|
||||
|
||||
- name: Mount btrfs raid10 volume
|
||||
ansible.posix.mount:
|
||||
path: "{{ hardware['disk']['data']['fs']['mount_point'] }}"
|
||||
src: "LABEL={{ hardware['disk']['data']['fs']['label'] }}"
|
||||
state: "mounted"
|
||||
fstype: "{{ hardware['disk']['data']['fs']['type'] }}"
|
||||
opts: "{{ hardware['disk']['data']['fs']['mount_opts'] | join(',') }}"
|
||||
become: true
|
||||
|
||||
- name: Set mounted btrfs volume permissions
|
||||
ansible.builtin.file:
|
||||
path: "{{ hardware['disk']['data']['fs']['mount_point'] }}"
|
||||
state: "directory"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0711"
|
||||
become: true
|
||||
|
||||
- name: Mount backup disk
|
||||
block:
|
||||
- name: Set backup disk path
|
||||
ansible.builtin.shell: |
|
||||
set -o pipefail
|
||||
ls -1 /dev/disk/by-id/ata-* | \
|
||||
grep -F -e "{{ hardware['disk']['backup']['serials'] | join('" -e "') }}" | \
|
||||
grep -vE -- '-part[0-9]+$' | \
|
||||
sort
|
||||
changed_when: false
|
||||
register: "backup_disk_path"
|
||||
|
||||
- name: Check vmm_hdd filesystem already exists
|
||||
ansible.builtin.command: |
|
||||
blkid -L {{ hardware['disk']['backup']['fs']['label'] }}
|
||||
become: true
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
register: "is_backup_disk_fs"
|
||||
|
||||
- name: Set btrfs volume
|
||||
ansible.builtin.shell: |
|
||||
mkfs.btrfs -f \
|
||||
-L {{ hardware['disk']['backup']['fs']['label'] }} \
|
||||
-d {{ hardware['disk']['backup']['fs']['btrfs']['data_profile'] }} \
|
||||
-m {{ hardware['disk']['backup']['fs']['btrfs']['metadata_profile'] }} \
|
||||
{{ backup_disk_path.stdout_lines | join(' ') }}
|
||||
become: true
|
||||
when:
|
||||
- is_backup_disk_fs.rc != 0
|
||||
- (backup_disk_path.stdout_lines | length) >= hardware['disk']['backup']['fs']['btrfs']['min_devices']
|
||||
changed_when: is_mkfs.rc == 0
|
||||
register: "is_mkfs"
|
||||
|
||||
- name: Create mount volume
|
||||
ansible.builtin.file:
|
||||
path: "{{ hardware['disk']['backup']['fs']['mount_point'] }}"
|
||||
state: "directory"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0711"
|
||||
become: true
|
||||
|
||||
- name: Mount btrfs volume
|
||||
ansible.posix.mount:
|
||||
path: "{{ hardware['disk']['backup']['fs']['mount_point'] }}"
|
||||
src: "LABEL={{ hardware['disk']['backup']['fs']['label'] }}"
|
||||
state: "mounted"
|
||||
fstype: "{{ hardware['disk']['backup']['fs']['type'] }}"
|
||||
opts: "{{ hardware['disk']['backup']['fs']['mount_opts'] | join(',') }}"
|
||||
become: true
|
||||
|
||||
- name: Set mounted btrfs volume permissions
|
||||
ansible.builtin.file:
|
||||
path: "{{ hardware['disk']['backup']['fs']['mount_point'] }}"
|
||||
state: "directory"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0711"
|
||||
become: true
|
||||
|
||||
- name: Verify data disk is mounted
|
||||
ansible.builtin.command: |
|
||||
mountpoint -q {{ hardware['disk']['data']['fs']['mount_point'] }}
|
||||
become: true
|
||||
changed_when: false
|
||||
|
||||
- name: Verify backup disk is mounted
|
||||
ansible.builtin.command: |
|
||||
mountpoint -q {{ hardware['disk']['backup']['fs']['mount_point'] }}
|
||||
become: true
|
||||
changed_when: false
|
||||
|
||||
- name: Deploy btrfs scrub service and timer
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/vmm/btrfs/btrfs-scrub-{{ item }}.j2"
|
||||
dest: "/etc/systemd/system/btrfs-scrub-{{ item }}"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0644"
|
||||
loop:
|
||||
- "data.service"
|
||||
- "data.timer"
|
||||
- "backup.service"
|
||||
- "backup.timer"
|
||||
become: true
|
||||
|
||||
- name: Enable auto btrfs scrub
|
||||
ansible.builtin.systemd:
|
||||
name: "btrfs-scrub-{{ item }}.timer"
|
||||
state: "started"
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
loop:
|
||||
- "data"
|
||||
- "backup"
|
||||
become: true
|
||||
@@ -13,7 +13,9 @@
|
||||
loop:
|
||||
- "images"
|
||||
- "seeds"
|
||||
- "data"
|
||||
- "disk"
|
||||
- "disk/data"
|
||||
- "disk/backup"
|
||||
register: "is_libvirt_dir"
|
||||
|
||||
- name: Create libvirt directory
|
||||
@@ -26,7 +28,6 @@
|
||||
loop: "{{ is_libvirt_dir.results }}"
|
||||
when: not item.stat.exists
|
||||
become: true
|
||||
no_log: true
|
||||
|
||||
- name: Set LIBVIRT_DEFAULT_URI
|
||||
ansible.builtin.lineinfile:
|
||||
@@ -74,6 +75,7 @@
|
||||
- "images-pool"
|
||||
- "seeds-pool"
|
||||
- "data-pool"
|
||||
- "backup-pool"
|
||||
|
||||
- name: Start virtual storage pool
|
||||
community.libvirt.virt_pool:
|
||||
@@ -84,6 +86,7 @@
|
||||
- "images-pool"
|
||||
- "seeds-pool"
|
||||
- "data-pool"
|
||||
- "backup-pool"
|
||||
|
||||
- name: Autostart virtual storage pool
|
||||
community.libvirt.virt_pool:
|
||||
@@ -94,3 +97,4 @@
|
||||
- "images-pool"
|
||||
- "seeds-pool"
|
||||
- "data-pool"
|
||||
- "backup-pool"
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
---
|
||||
- name: Check btrfs installation
|
||||
ansible.builtin.shell: |
|
||||
command -v btrfs
|
||||
become: true # btrfs is located in /usr/sbin, which means root permission is needed.
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
register: "is_btrfs_installed"
|
||||
ignore_errors: true
|
||||
|
||||
- name: Install btrfs
|
||||
ansible.builtin.apt:
|
||||
name: "btrfs-progs"
|
||||
state: "present"
|
||||
become: true
|
||||
when: is_btrfs_installed.rc != 0
|
||||
|
||||
- name: Set hard disk path
|
||||
ansible.builtin.shell: |
|
||||
set -o pipefail
|
||||
ls -1 /dev/disk/by-id/ata-* | \
|
||||
grep -F -e "{{ hardware['hdd']['data'].values() | join('" -e "') }}" | \
|
||||
grep -vE -- '-part[0-9]+$' | \
|
||||
sort
|
||||
changed_when: false
|
||||
register: "hdd_path_list"
|
||||
|
||||
- name: Check vmm_hdd filesystem already exists
|
||||
ansible.builtin.command: |
|
||||
blkid -L {{ hardware['btrfs']['label'] }}
|
||||
register: is_vmm_data
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
become: true
|
||||
|
||||
- name: Check disk number
|
||||
ansible.builtin.fail:
|
||||
msg: "Below 4 disks for RAID10, found {{ hdd_path_list.stdout_lines | length }}"
|
||||
when: (hdd_path_list.stdout_lines | length) < 4
|
||||
|
||||
- name: Set btrfs raid10 volume
|
||||
ansible.builtin.shell: |
|
||||
mkfs.btrfs -f \
|
||||
-L {{ hardware['btrfs']['label'] }} \
|
||||
-d {{ hardware['btrfs']['level'] }} \
|
||||
-m {{ hardware['btrfs']['level'] }} \
|
||||
{{ hdd_path_list.stdout_lines | join(' ') }}
|
||||
become: true
|
||||
when:
|
||||
- is_vmm_data.rc != 0
|
||||
- (hdd_path_list.stdout_lines | length) >= 4
|
||||
changed_when: is_mkfs.rc == 0
|
||||
register: "is_mkfs"
|
||||
|
||||
- name: Create mount volume
|
||||
ansible.builtin.file:
|
||||
path: "{{ hardware['btrfs']['mount_point'] }}"
|
||||
state: "directory"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0711"
|
||||
become: true
|
||||
|
||||
- name: Mount btrfs raid10 volume
|
||||
ansible.posix.mount:
|
||||
path: "{{ hardware['btrfs']['mount_point'] }}"
|
||||
src: "LABEL={{ hardware['btrfs']['label'] }}"
|
||||
state: "mounted"
|
||||
fstype: "btrfs"
|
||||
opts: "defaults,noatime,nodatacow,degraded,nofail"
|
||||
become: true
|
||||
|
||||
- name: Set mounted btrfs volume permissions
|
||||
ansible.builtin.file:
|
||||
path: "{{ hardware['btrfs']['mount_point'] }}"
|
||||
state: "directory"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0711"
|
||||
become: true
|
||||
|
||||
- name: Deploy btrfs scrub service and timer
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/vmm/btrfs/{{ item }}.j2"
|
||||
dest: "/etc/systemd/system/{{ item }}"
|
||||
owner: "root"
|
||||
group: "root"
|
||||
mode: "0644"
|
||||
loop:
|
||||
- "btrfs-scrub.service"
|
||||
- "btrfs-scrub.timer"
|
||||
become: true
|
||||
|
||||
- name: Enable auto btrfs scrub
|
||||
ansible.builtin.systemd:
|
||||
name: "btrfs-scrub.timer"
|
||||
state: "started"
|
||||
enabled: true
|
||||
daemon_reload: true
|
||||
become: true
|
||||
@@ -49,8 +49,7 @@
|
||||
register: "is_seediso"
|
||||
|
||||
- name: Create seed.iso
|
||||
ansible.builtin.shell:
|
||||
cmd: |
|
||||
ansible.builtin.shell: |
|
||||
cloud-localds -N {{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/network-config \
|
||||
{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/seed.iso \
|
||||
{{ hostvars['console']['node']['data_path'] }}/images/seeds/{{ target_vm }}/user-data \
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
become: true
|
||||
|
||||
- name: Check deployed cloud-init file info
|
||||
ansible.builtin.command:
|
||||
cmd: "qemu-img info {{ node['libvirt_path'] }}/images/{{ target_vm }}.qcow2 --output json"
|
||||
ansible.builtin.command: |
|
||||
qemu-img info {{ node['libvirt_path'] }}/images/{{ target_vm }}.qcow2 --output json
|
||||
changed_when: false
|
||||
failed_when:
|
||||
- deployed_cloudfile_info.rc != 0
|
||||
@@ -37,29 +37,29 @@
|
||||
register: "deployed_cloudfile_info"
|
||||
|
||||
- name: Resize deployed cloud-init file
|
||||
ansible.builtin.command:
|
||||
cmd: "qemu-img resize {{ node['libvirt_path'] }}/images/{{ target_vm }}.qcow2 {{ hostvars[target_vm]['vm']['storage'] }}G"
|
||||
ansible.builtin.command: |
|
||||
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
|
||||
- name: Check bk/app raw image
|
||||
ansible.builtin.stat:
|
||||
path: "{{ hardware['btrfs']['mount_point'] }}/{{ target_vm }}.raw"
|
||||
path: "{{ hardware['disk'][hostvars[target_vm]['vm']['data_storage']['pool']]['fs']['mount_point'] }}/{{ target_vm }}.raw"
|
||||
get_checksum: false
|
||||
get_mime: false
|
||||
get_attributes: false
|
||||
when: target_vm == "app"
|
||||
when: target_vm in ["bk", "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"
|
||||
- name: Create bk/app raw image
|
||||
ansible.builtin.command: |
|
||||
qemu-img create -f raw {{ hardware['disk'][hostvars[target_vm]['vm']['data_storage']['pool']]['fs']['mount_point'] }}/{{ target_vm }}.raw \
|
||||
{{ hostvars[target_vm]['vm']['data_storage']['size'] }}T
|
||||
become: true
|
||||
when:
|
||||
- target_vm == "app"
|
||||
- target_vm in ["bk", "app"]
|
||||
- not is_app_data.stat.exists
|
||||
changed_when: true
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
command: define
|
||||
|
||||
- name: Deploy VM systemd file
|
||||
ansible.builtin.copy:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/vmm/libvirt/services/{{ target_vm }}.service"
|
||||
ansible.builtin.template:
|
||||
src: "{{ hostvars['console']['node']['config_path'] }}/services/systemd/vmm/libvirt/services/{{ target_vm }}.service.j2"
|
||||
dest: "{{ node['home_path'] }}/.config/systemd/user/{{ target_vm }}.service"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "svadmins"
|
||||
group: "{{ node['group'] }}"
|
||||
mode: "0400"
|
||||
|
||||
- name: Register VM service
|
||||
|
||||
Reference in New Issue
Block a user