From 942dd6b8761ceefb1eee55ab68559176dd35807f Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Fri, 17 Jan 2025 23:10:02 +0100 Subject: [PATCH] actual: add config --- hosts.ini | 3 + nas.yml | 6 ++ roles/actual-web/meta/main.yml | 3 + roles/actual-web/tasks/main.yml | 9 +++ .../actual-web/templates/actual.Caddyfile.j2 | 3 + roles/actual/files/actual.data.backup.sh | 12 ++++ roles/actual/files/actual.service | 13 ++++ roles/actual/files/compose.yml | 8 +++ roles/actual/handlers/main.yml | 5 ++ roles/actual/tasks/main.yml | 68 +++++++++++++++++++ web.yml | 8 ++- 11 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 roles/actual-web/meta/main.yml create mode 100644 roles/actual-web/tasks/main.yml create mode 100644 roles/actual-web/templates/actual.Caddyfile.j2 create mode 100644 roles/actual/files/actual.data.backup.sh create mode 100644 roles/actual/files/actual.service create mode 100644 roles/actual/files/compose.yml create mode 100644 roles/actual/handlers/main.yml create mode 100644 roles/actual/tasks/main.yml diff --git a/hosts.ini b/hosts.ini index 06902bf..dad11aa 100644 --- a/hosts.ini +++ b/hosts.ini @@ -44,3 +44,6 @@ [calathea] 192.168.0.2 static_ip=192.168.0.2 + +[actual] +192.168.0.3 static_ip=192.168.0.3 diff --git a/nas.yml b/nas.yml index 44d1e1a..251f022 100644 --- a/nas.yml +++ b/nas.yml @@ -94,3 +94,9 @@ roles: - syncthing tags: syncthing + +- hosts: nas + become: yes + roles: + - actual + tags: actual diff --git a/roles/actual-web/meta/main.yml b/roles/actual-web/meta/main.yml new file mode 100644 index 0000000..1dbd0f6 --- /dev/null +++ b/roles/actual-web/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - role: caddy diff --git a/roles/actual-web/tasks/main.yml b/roles/actual-web/tasks/main.yml new file mode 100644 index 0000000..2e7c5c9 --- /dev/null +++ b/roles/actual-web/tasks/main.yml @@ -0,0 +1,9 @@ +--- +- name: Ensure Caddyfile is present + template: + src: 'actual.Caddyfile.j2' + dest: '/etc/caddy/actual.Caddyfile' + owner: root + group: root + mode: '0644' + notify: caddy-reload diff --git a/roles/actual-web/templates/actual.Caddyfile.j2 b/roles/actual-web/templates/actual.Caddyfile.j2 new file mode 100644 index 0000000..18b6197 --- /dev/null +++ b/roles/actual-web/templates/actual.Caddyfile.j2 @@ -0,0 +1,3 @@ +actual.roosens.me { + reverse_proxy {{ hostvars[groups['actual'][0]].static_ip }}:8014 +} diff --git a/roles/actual/files/actual.data.backup.sh b/roles/actual/files/actual.data.backup.sh new file mode 100644 index 0000000..93c162a --- /dev/null +++ b/roles/actual/files/actual.data.backup.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +data_dir='/mnt/data1/actual/data' +snapshot_dir="${data_dir}.snapshot" + +# Read-only snapshot for atomic backup +btrfs subvolume snapshot -r "$data_dir" "$snapshot_dir" || exit $? + +/usr/local/bin/restic backup "$snapshot_dir" + +# Always remove snapshot subvolume, even if restic fails +btrfs subvolume delete "$snapshot_dir" diff --git a/roles/actual/files/actual.service b/roles/actual/files/actual.service new file mode 100644 index 0000000..e63f047 --- /dev/null +++ b/roles/actual/files/actual.service @@ -0,0 +1,13 @@ +[Unit] +Description=A local-first personal finance app +After=docker.service +Requires=docker.service + +[Service] +Type=exec +WorkingDirectory=/etc/actual +ExecStart=/usr/bin/docker compose up +ExecStop=/usr/bin/docker compose down + +[Install] +WantedBy=multi-user.target diff --git a/roles/actual/files/compose.yml b/roles/actual/files/compose.yml new file mode 100644 index 0000000..a114fc6 --- /dev/null +++ b/roles/actual/files/compose.yml @@ -0,0 +1,8 @@ +services: + app: + image: 'actualbudget/actual-server:latest-alpine' + + ports: + - '8014:5006' + volumes: + - '/mnt/data1/actual/data:/data' diff --git a/roles/actual/handlers/main.yml b/roles/actual/handlers/main.yml new file mode 100644 index 0000000..88e6a07 --- /dev/null +++ b/roles/actual/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: 'restart actual' + ansible.builtin.service: + name: 'actual' + state: 'restarted' diff --git a/roles/actual/tasks/main.yml b/roles/actual/tasks/main.yml new file mode 100644 index 0000000..e6dbc54 --- /dev/null +++ b/roles/actual/tasks/main.yml @@ -0,0 +1,68 @@ +--- +- name: Ensure data directory is present + ansible.builtin.file: + path: '/mnt/data1/actual' + state: directory + mode: '0755' + owner: 'root' + group: 'root' + +- name: Ensure data subvolumes are present + community.general.btrfs_subvolume: + name: '/actual/{{ item }}' + loop: + - 'data' + +- name: Ensure subvolume permissions are correct + ansible.builtin.file: + path: "/mnt/data1/actual/{{ item }}" + state: directory + mode: '0755' + owner: '1001' + group: '1001' + loop: + - 'data' + +- name: Ensure configuration directory is present + ansible.builtin.file: + path: '/etc/actual' + state: directory + mode: '0755' + +- name: Ensure compose file is present + ansible.builtin.copy: + src: 'compose.yml' + dest: '/etc/actual/compose.yml' + mode: '0644' + owner: 'root' + group: 'root' + notify: 'restart actual' + +- name: Ensure backup scripts are present + ansible.builtin.copy: + src: "actual.{{ item }}.backup.sh" + dest: "/etc/backups/actual.{{ item }}.backup.sh" + owner: 'root' + group: 'root' + mode: '0644' + loop: + - 'data' + +- name: Ensure service file is present + ansible.builtin.copy: + src: 'actual.service' + dest: '/lib/systemd/system/actual.service' + owner: 'root' + group: 'root' + mode: '0644' + register: res + +- name: systemd-reload + ansible.builtin.systemd_service: + daemon_reload: true + when: 'res.changed' + +- name: Ensure actual service is enabled + ansible.builtin.service: + name: 'actual' + enabled: true diff --git a/web.yml b/web.yml index 1320aac..d0c0954 100644 --- a/web.yml +++ b/web.yml @@ -1,4 +1,4 @@ ---- + - hosts: web become: yes roles: @@ -70,3 +70,9 @@ roles: - calathea-web tags: calathea + +- hosts: web + become: yes + roles: + - actual-web + tags: actual