diff options
-rw-r--r-- | content/blog/ansible/vaultwarden.md | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/content/blog/ansible/vaultwarden.md b/content/blog/ansible/vaultwarden.md new file mode 100644 index 0000000..a6bc0ea --- /dev/null +++ b/content/blog/ansible/vaultwarden.md @@ -0,0 +1,172 @@ +--- +title: 'Migrating vaultwarden from nixos to Debian' +description: 'How I am deploying vaultwarden with ansible' +date: '2024-12-31' +tags: +- ansible +- vaultwarden +--- + +## Introduction + +I am migrating several services from a NixOS server (dalinar.adyxax.org) to a Debian server (lore.adyxax.org). Here is how I performed the operation for my self hosted [vaultwarden](https://github.com/dani-garcia/vaultwarden). + +## Ansible role + +### Meta + +The `meta/main.yaml` contains the role dependencies: + +``` yaml +--- +dependencies: + - role: 'borg' + - role: 'nginx' + - role: 'podman' + - role: 'postgresql' +``` + +### Tasks + +The `tasks/main.yaml` just creates a data directory and fetches the admin secret token from a terraform state. All the heavy lifting is then done by calling other roles: + +``` yaml +--- +- name: 'Make vaultwarden data directory' + file: + path: '/srv/vaultwarden' + owner: 'root' + group: 'root' + mode: '0750' + state: 'directory' + +- include_role: + name: 'postgresql' + tasks_from: 'database' + vars: + postgresql: + name: 'vaultwarden' + +- name: 'Load the tofu state to read the database encryption key' + include_vars: + file: '../tofu/04-apps/terraform.tfstate' # TODO use my http backend instead + name: 'tofu_state_vaultwarden' + +- set_fact: + vaultwarden_argon2_token: "{{ tofu_state_vaultwarden | json_query(\"resources[?type=='random_password'&&name=='vaultwarden_argon2_token'].instances[0].attributes.result\") }}" + +- include_role: + name: 'podman' + tasks_from: 'container' + vars: + container: + name: 'vaultwarden' + env_vars: + - name: 'ADMIN_TOKEN' + value: "'{{ vaultwarden_argon2_token[0] }}'" + - name: 'DATABASE_MAX_CONNS' + value: '2' + - name: 'DATABASE_URL' + value: 'postgres://vaultwarden:{{ ansible_local.postgresql_vaultwarden.password }}@10.88.0.1/vaultwarden?sslmode=disable' + image: '{{ versions.vaultwarden.image }}:{{ versions.vaultwarden.tag }}' + publishs: + - container_port: '80' + host_port: '8083' + ip: '127.0.0.1' + volumes: + - dest: '/data' + src: '/srv/vaultwarden' + +- include_role: + name: 'nginx' + tasks_from: 'vhost' + vars: + vhost: + name: 'vaultwarden' + path: 'roles/vaultwarden/files/nginx-vhost.conf' + +- include_role: + name: 'borg' + tasks_from: 'client' + vars: + client: + jobs: + - name: 'data' + paths: + - '/srv/vaultwarden' + - name: 'postgres' + command_to_pipe: "su - postgres -c '/usr/bin/pg_dump -b -c -C -d vaultwarden'" + name: 'vaultwarden' + server: '{{ vaultwarden.borg }}' +``` + +### Files + +There is only the nginx vhost file, fairly straightforward: + +``` nginx +############################################################################### +# \_o< WARNING : This file is being managed by ansible! >o_/ # +# ~~~~ ~~~~ # +############################################################################### + +server { + listen 80; + listen [::]:80; + server_name pass.adyxax.org; + location / { + return 308 https://$server_name$request_uri; + } +} + +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name pass.adyxax.org; + + location / { + proxy_pass http://127.0.0.1:8083; + } + ssl_certificate adyxax.org.fullchain; + ssl_certificate_key adyxax.org.key; +} +``` + +## Migration process + +The first step is to deploy this new configuration to the server: + +``` shell +make run limit=lore.adyxax.org tags=vaultwarden +``` + +After that I manually backup the vaultwarden data with: + +``` shell +ssh root@dalinar.adyxax.org systemctl stop podman-vaultwarden +ssh root@dalinar.adyxax.org /run/current-system/sw/bin/pg_dump -b -c -C -h localhost -U vaultwarden -d vaultwarden > /tmp/vaultwarden.sql +ssh root@dalinar.adyxax.org tar czf /tmp/vaultwarden.tar.gz /srv/vaultwarden/ +``` + +I retrieve then migrate these backups with: +``` shell +scp root@dalinar.adyxax.org:/tmp/vaultwarden.{sql,tar.gz} . +ssh root@dalinar.adyxax.org rm vaultwarden.{sql,tar.gz} +scp vaultwarden.{sql,tar.gz} root@lore.adyxax.org: +rm vaultwarden.{sql,tar.gz} +``` + +On the new server, restoring the backup is done with: +``` shell +ssh root@lore.adyxax.org systemctl stop podman-vaultwarden +ssh root@lore.adyxax.org "cat vaultwarden.sql | su - postgres -c 'psql'" +ssh root@lore.adyxax.org tar -xzf vaultwarden.tar.gz -C /srv/vaultwarden/ +ssh root@lore.adyxax.org rm vaultwarden.{sql,tar.gz} +ssh root@lore.adyxax.org systemctl start podman-vaultwarden +``` + +I then test the new server by setting the record in my `/etc/hosts` file. Since it all works well, I rollback my change to `/etc/hosts` and update the DNS record using OpenTofu. + +## Conclusion + +I did all this in early October and performed several vaultwarden upgrades since then. It all works well! |