From 6c0425418e4e7aedc9822c0f96914da7688dbe73 Mon Sep 17 00:00:00 2001 From: Thomas Kleinendorst Date: Fri, 12 Apr 2024 13:34:45 +0200 Subject: [PATCH] Install actual on Raspberry Pi --- playbook.yml | 13 +++-- roles/actual/handlers/main.yml | 6 +++ roles/actual/tasks/main.yml | 47 +++++++++++++++++++ roles/actual/templates/actual.conf.j2 | 25 ++++++++++ roles/actual/vars/main/defaults.yml | 2 + roles/actual/vars/main/vault.yml | 8 ++++ roles/reverse-proxy/handlers/main.yml | 5 ++ roles/reverse-proxy/tasks/main.yml | 8 +++- .../templates/register_certbot_domain.sh.j2 | 3 +- 9 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 roles/actual/handlers/main.yml create mode 100644 roles/actual/tasks/main.yml create mode 100644 roles/actual/templates/actual.conf.j2 create mode 100644 roles/actual/vars/main/defaults.yml create mode 100644 roles/actual/vars/main/vault.yml diff --git a/playbook.yml b/playbook.yml index 75fc844..425654d 100644 --- a/playbook.yml +++ b/playbook.yml @@ -9,13 +9,16 @@ roles: # These roles are disabled after they have being applied once for performance reasons, it should be safe to enable them again. # Notice that this role changes some settings on reruns (on the "Change various sysctl-settings" task), doesn't seem problematic though. - # - role: devsec.hardening.os_hardening - # become: true - # - role: devsec.hardening.ssh_hardening - # become: true - # - role: zsh + - role: devsec.hardening.os_hardening + become: true + - role: devsec.hardening.ssh_hardening + become: true + - role: snapcraft + - role: user - role: pi-hole - role: cloudflare-ddns + - role: reverse-proxy + - role: actual vars: # devsec.hardening.os_hardening vars: os_auth_pw_max_age: 99999 # Effectively disables the setting as mentioned in the docs. diff --git a/roles/actual/handlers/main.yml b/roles/actual/handlers/main.yml new file mode 100644 index 0000000..d78a686 --- /dev/null +++ b/roles/actual/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart Nginx + become: true + ansible.builtin.systemd: + name: nginx.service + state: restarted diff --git a/roles/actual/tasks/main.yml b/roles/actual/tasks/main.yml new file mode 100644 index 0000000..a90afb8 --- /dev/null +++ b/roles/actual/tasks/main.yml @@ -0,0 +1,47 @@ +--- +- name: Install Podman + become: true + ansible.builtin.apt: + name: podman + state: present +- name: Create a new user + ansible.builtin.include_role: + name: user + vars: + username: "{{ actual_user }}" + password: "{{ actual_password }}" +- name: Create a directory for holding actual's (volume) data + become: true + become_user: "{{ actual_user }}" + ansible.builtin.file: + path: "/home/{{ actual_user }}/actual_data" + state: directory + mode: '0700' +# Unfortunatelly I can't set the web password in the container, a user has to manually do this on startup. +- name: Start the Actual container + become: true + become_user: "{{ actual_user }}" + containers.podman.podman_container: + name: actual-server + image: docker.io/actualbudget/actual-server:24.4.0 + restart_policy: on-failure + publish: + - 127.0.0.1:5006:5006 + volumes: + - "/home/{{ actual_user }}/actual_data:/data" + state: started +- name: Install certificate for actual.kleinendorst.info + become: true + ansible.builtin.command: + cmd: register_certbot_domain.sh actual.kleinendorst.info + creates: /etc/letsencrypt/live/actual.kleinendorst.info # The certificate directory +- name: Set Nginx configuration + become: true + ansible.builtin.template: + src: actual.conf.j2 + dest: /etc/nginx/conf.d/actual.conf + mode: '0644' + notify: Restart Nginx +- name: Debug + ansible.builtin.debug: + msg: "Don't forget to manually add a DNS record for actual.kleinendorst.info pointing to: {{ ansible_facts['default_ipv4']['address'] }}." diff --git a/roles/actual/templates/actual.conf.j2 b/roles/actual/templates/actual.conf.j2 new file mode 100644 index 0000000..a9cf1bd --- /dev/null +++ b/roles/actual/templates/actual.conf.j2 @@ -0,0 +1,25 @@ +# Template comes from the actual documentation: https://actualbudget.org/docs/config/reverse-proxies/#nginx +# It was however modified in some ways because the referenced files weren't created. +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name actual.kleinendorst.info; + + client_max_body_size 20M; # The budgets can become quite large and need to be uploaded + + # SSL via Let's Encrypt + ssl_certificate /etc/letsencrypt/live/actual.kleinendorst.info/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/actual.kleinendorst.info/privkey.pem; # managed by Certbot + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + location / { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + + set $upstream_address 127.0.0.1; + set $upstream_port 5006; + set $upstream_proto http; + proxy_pass $upstream_proto://$upstream_address:$upstream_port; + } +} diff --git a/roles/actual/vars/main/defaults.yml b/roles/actual/vars/main/defaults.yml new file mode 100644 index 0000000..cef0cda --- /dev/null +++ b/roles/actual/vars/main/defaults.yml @@ -0,0 +1,2 @@ +--- +actual_user: actual diff --git a/roles/actual/vars/main/vault.yml b/roles/actual/vars/main/vault.yml new file mode 100644 index 0000000..2734add --- /dev/null +++ b/roles/actual/vars/main/vault.yml @@ -0,0 +1,8 @@ +$ANSIBLE_VAULT;1.1;AES256 +33376134646463343235646461303131626139663865333436646535383064383437616231323334 +6162306132343165666134323966363739333638353332620a663034326361383233356639646463 +65386537303530363335363234636464626330343864363162626233613430633430643334396636 +6635653735633730310a343036363136333933653561663839613238336338633061613534326536 +39343563343863643636616130316235316236656531626433613432303561383834333764336534 +35636438613832643433346135623934323964346464383931353539633464333038626561643963 +633839343438623261343239613534393233 diff --git a/roles/reverse-proxy/handlers/main.yml b/roles/reverse-proxy/handlers/main.yml index 9e0275e..98601d3 100644 --- a/roles/reverse-proxy/handlers/main.yml +++ b/roles/reverse-proxy/handlers/main.yml @@ -3,3 +3,8 @@ become: true ansible.builtin.command: cmd: snap set certbot trust-plugin-with-root=ok +- name: Restart Nginx + become: true + ansible.builtin.systemd: + name: nginx.service + state: restarted diff --git a/roles/reverse-proxy/tasks/main.yml b/roles/reverse-proxy/tasks/main.yml index 7f4f479..b152624 100644 --- a/roles/reverse-proxy/tasks/main.yml +++ b/roles/reverse-proxy/tasks/main.yml @@ -19,8 +19,12 @@ ansible.builtin.apt: name: nginx # Creates the "nginx" user as well state: present -# TODO: Remove the default configuration here, we'll keep it for now as an example... -# TODO: Setup Certbot as it's part of the installation... +- name: Remove default configuration + become: true + ansible.builtin.file: + path: /etc/nginx/conf.d/default.conf + state: absent + notify: Restart Nginx # ---------- CERTBOT INSTALLATION ---------- # # See the installation instructions here: https://certbot.eff.org/instructions?ws=nginx&os=debianbuster&tab=wildcard - name: Install Certbot diff --git a/roles/reverse-proxy/templates/register_certbot_domain.sh.j2 b/roles/reverse-proxy/templates/register_certbot_domain.sh.j2 index 3d962d2..25bbdaf 100644 --- a/roles/reverse-proxy/templates/register_certbot_domain.sh.j2 +++ b/roles/reverse-proxy/templates/register_certbot_domain.sh.j2 @@ -1,6 +1,7 @@ #!/bin/bash /snap/bin/certbot certonly \ --dns-cloudflare \ + --dns-cloudflare-propagation-seconds 120 \ --dns-cloudflare-credentials '{{ cloudflare_credential_dir_path }}/{{ cloudflare_credential_filename }}' \ - --agree-tos --test-cert -m {{ administration_email }} \ + --agree-tos -m {{ administration_email }} \ -d $1