From dc50af72932ea0643fd2cf07f783560483b24645 Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Wed, 27 Oct 2021 16:46:45 +0200 Subject: Refactoring --- content/docs/adyxax.org/bitwarden/_index.md | 14 -- content/docs/adyxax.org/bitwarden/backups.md | 12 -- content/docs/adyxax.org/bitwarden/install.md | 274 ------------------------- content/docs/adyxax.org/vaultwarden/_index.md | 14 ++ content/docs/adyxax.org/vaultwarden/backups.md | 12 ++ content/docs/adyxax.org/vaultwarden/install.md | 274 +++++++++++++++++++++++++ 6 files changed, 300 insertions(+), 300 deletions(-) delete mode 100644 content/docs/adyxax.org/bitwarden/_index.md delete mode 100644 content/docs/adyxax.org/bitwarden/backups.md delete mode 100644 content/docs/adyxax.org/bitwarden/install.md create mode 100644 content/docs/adyxax.org/vaultwarden/_index.md create mode 100644 content/docs/adyxax.org/vaultwarden/backups.md create mode 100644 content/docs/adyxax.org/vaultwarden/install.md diff --git a/content/docs/adyxax.org/bitwarden/_index.md b/content/docs/adyxax.org/bitwarden/_index.md deleted file mode 100644 index 335789c..0000000 --- a/content/docs/adyxax.org/bitwarden/_index.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "vaultwarden" -description: pass.adyxax.org password management software ---- - -## Introduction - -pass.adyxax.org is a [vaultwarden](https://github.com/dani-garcia/vaultwarden) server (lighter reimplementation of [bitwarden](https://bitwarden.com/)) that has been recommended to me by a friend for some time now. It is the server component of a password management solution. - -## Captain's log - -- 2021-10-12 : Initial setup on myth.adyxax.org's k3s - -## Docs diff --git a/content/docs/adyxax.org/bitwarden/backups.md b/content/docs/adyxax.org/bitwarden/backups.md deleted file mode 100644 index ad3ecfb..0000000 --- a/content/docs/adyxax.org/bitwarden/backups.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "Backups" -description: Backups of pass.adyxax.org ---- - -## Documentation - -Backups are configured with borg on `myth.adyxax.org` to `yen.adyxax.org`. - -There are two jobs : -- a filesystem backup of `/srv/vaultwarden-data` -- a pg_dump of vaultwarden's postgresql database diff --git a/content/docs/adyxax.org/bitwarden/install.md b/content/docs/adyxax.org/bitwarden/install.md deleted file mode 100644 index ecd647f..0000000 --- a/content/docs/adyxax.org/bitwarden/install.md +++ /dev/null @@ -1,274 +0,0 @@ ---- -title: "Installation" -description: Installation notes of vaultwarden on k3s -tags: -- k3s -- kubernetes -- postgresql -- vaultwarden ---- - -## Introduction - -Please refer to [the official website](https://pass.app/) documentation for an up to date installation guide. This page only lists what I had to do at the time to setup pass and adapt it to my particular setup. I updated these instructions after migrating from a traditional hosting to kubernetes. - -## Preparing the postgresql database - -I have a postgresql running in its own namespace from bitnami images. To provision the pass database I : -```sh -export POSTGRES_PASSWORD=$(k get secret -n postgresql postgresql-secrets -o jsonpath="{.data.postgresql-password}"| - base64 --decode) -k run client --rm -ti -n postgresql --image docker.io/bitnami/postgresql:13.4.0-debian-10-r52 \ - --env="PGPASSWORD=$POSTGRES_PASSWORD" --command -- psql --host postgresql -U postgres -CREATE ROLE pass WITH LOGIN PASSWORD 'secret'; -CREATE DATABASE pass WITH OWNER pass TEMPLATE template0 ENCODING UTF8 LC_COLLATE - 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8'; -\c pass -create extension hstore; -``` - -Optionally import a dump of the database by running in another shell : -```sh -k -n postgresql cp pass.sql-20211005 client:/tmp/ -``` - -Then in the psql shell : -```sh -\c pass -\i /tmp/pass.sql-20211005 -``` - -## Kubernetes manifests in terraform - -This app is part of an experiment of mine to migrate stuff from traditional hosting to kubernetes. I first wrote manifests by hand then imported them with terraform. I do not like it and find it too complex/overkill but that is managed this way for now. - -### DNS CNAME - -Since all configuration regarding this application is in terraform, so is the dns : -```hcl -resource "cloudflare_record" "pass-cname" { - zone_id = lookup(data.cloudflare_zones.adyxax-org.zones[0], "id") - name = "pass" - value = "myth.adyxax.org" - type = "CNAME" - proxied = false -} -``` - -### Namespace - -The basic terraform object works for simple things so here it is : -```hcl -resource "kubernetes_namespace" "myth-pass" { - provider = kubernetes.myth - metadata { - name = "pass" - } -} -``` - -### Secret - -Here is the kubernetes secret that tells pass how to connect the database. The password comes from `terraform.tfvars`, you might need to update the service url with the format `..svc.cluster.local` : -```hcl -resource "kubernetes_secret" "myth-pass-secrets" { - provider = kubernetes.myth - metadata { - name = "pass-secrets" - namespace = kubernetes_namespace.myth-pass.id - } - data = { - ADMIN_PASSWORD = var.pass-admin-password - DATABASE_URL = join("", [ "postgres://pass:${var.pass-postgres-password}", - "@postgresql.postgresql.svc.cluster.local/pass?sslmode=disable"]) - } - type = "Opaque" -} -``` - -### Deployment - -I could not write the deployment with the `kubernetes_deployment` terraform ressource, so it is a row manifest which imports a yaml syntax in hcl. It is horrible to look at but works. Change the image tag to the latest stable version of pass before deploying : -```hcl -resource "kubernetes_manifest" "myth-deployment-pass" { - provider = kubernetes.myth - manifest = { - "apiVersion" = "apps/v1" - "kind" = "Deployment" - "metadata" = { - "name" = "pass" - "namespace" = kubernetes_namespace.myth-pass.id - } - "spec" = { - "replicas" = 1 - "selector" = { - "matchLabels" = { - "app" = "pass" - } - } - "strategy" = { - "type" = "RollingUpdate" - "rollingUpdate" = { - "maxSurge" = 1 - "maxUnavailable" = 0 - } - } - "template" = { - "metadata" = { - "labels" = { - "app" = "pass" - } - } - "spec" = { - "containers" = [ - { - "env" = [ - { - "name" = "DATABASE_URL" - "valueFrom" = { - "secretKeyRef" = { - "key" = "DATABASE_URL" - "name" = "pass-secrets" - } - } - }, - { - "name" = "RUN_MIGRATIONS" - "value" = "1" - }, - { - "name" = "ADMIN_USERNAME" - "value" = "admin" - }, - { - "name" = "ADMIN_PASSWORD" - "valueFrom" = { - "secretKeyRef" = { - "key" = "ADMIN_PASSWORD" - "name" = "pass-secrets" - } - } - }, - ] - "image" = "vaultwarden/server:1.23.0" - "livenessProbe" = { - "httpGet" = { - "path" = "/" - "port" = 8080 - } - "initialDelaySeconds" = 5 - "timeoutSeconds" = 5 - } - "name" = "pass" - "ports" = [ - { - "containerPort" = 8080 - }, - ] - "readinessProbe" = { - "httpGet" = { - "path" = "/" - "port" = 8080 - } - "initialDelaySeconds" = 5 - "timeoutSeconds" = 5 - } - "lifecycle" = { - "preStop" = { - "exec" = { - "command" = ["/bin/sh", "-c", "sleep 10"] - } - } - } - }, - ] - "terminationGracePeriodSeconds" = 1 - } - } - } - } -} -``` - -### Service - -```hcl -resource "kubernetes_manifest" "myth-service-pass" { - provider = kubernetes.myth - manifest = { - "apiVersion" = "v1" - "kind" = "Service" - "metadata" = { - "name" = "pass" - "namespace" = kubernetes_namespace.myth-pass.id - } - "spec" = { - "ports" = [ - { - "port" = 80 - "protocol" = "TCP" - "targetPort" = 8080 - }, - ] - "selector" = { - "app" = "pass" - } - "type" = "ClusterIP" - } - } -} -``` - -### Ingress - -```hcl -resource "kubernetes_manifest" "myth-ingress-pass" { - provider = kubernetes.myth - manifest = { - "apiVersion" = "networking.k8s.io/v1" - "kind" = "Ingress" - "metadata" = { - "name" = "pass" - "namespace" = kubernetes_namespace.myth-pass.id - } - "spec" = { - "ingressClassName" = "nginx" - "rules" = [ - { - "host" = "pass.adyxax.org" - "http" = { - "paths" = [ - { - "path" = "/" - "pathType" = "Prefix" - "backend" = { - "service" = { - "name" = "pass" - "port" = { - "number" = 80 - } - } - } - }, - ] - } - }, - ] - "tls" = [ - { - "secretName" = "wildcard-adyxax-org" - }, - ] - } - } -} -``` - -### Certificate - -For now I do not manage my certificates with terraform but manually. Once every two months I run : -```sh -acme.sh --config-home "$HOME/.acme.sh" --server letsencrypt --dns dns_cf --issue -d adyxax.org -d *.adyxax.org --force -kubectl -n pass create secret tls wildcard-adyxax-org --cert=$HOME/.acme.sh/adyxax.org/fullchain.cer \ - --key=$HOME/.acme.sh/adyxax.org/adyxax.org.key -o yaml --save-config --dry-run=client | kubectl apply -f - -``` diff --git a/content/docs/adyxax.org/vaultwarden/_index.md b/content/docs/adyxax.org/vaultwarden/_index.md new file mode 100644 index 0000000..335789c --- /dev/null +++ b/content/docs/adyxax.org/vaultwarden/_index.md @@ -0,0 +1,14 @@ +--- +title: "vaultwarden" +description: pass.adyxax.org password management software +--- + +## Introduction + +pass.adyxax.org is a [vaultwarden](https://github.com/dani-garcia/vaultwarden) server (lighter reimplementation of [bitwarden](https://bitwarden.com/)) that has been recommended to me by a friend for some time now. It is the server component of a password management solution. + +## Captain's log + +- 2021-10-12 : Initial setup on myth.adyxax.org's k3s + +## Docs diff --git a/content/docs/adyxax.org/vaultwarden/backups.md b/content/docs/adyxax.org/vaultwarden/backups.md new file mode 100644 index 0000000..ad3ecfb --- /dev/null +++ b/content/docs/adyxax.org/vaultwarden/backups.md @@ -0,0 +1,12 @@ +--- +title: "Backups" +description: Backups of pass.adyxax.org +--- + +## Documentation + +Backups are configured with borg on `myth.adyxax.org` to `yen.adyxax.org`. + +There are two jobs : +- a filesystem backup of `/srv/vaultwarden-data` +- a pg_dump of vaultwarden's postgresql database diff --git a/content/docs/adyxax.org/vaultwarden/install.md b/content/docs/adyxax.org/vaultwarden/install.md new file mode 100644 index 0000000..ecd647f --- /dev/null +++ b/content/docs/adyxax.org/vaultwarden/install.md @@ -0,0 +1,274 @@ +--- +title: "Installation" +description: Installation notes of vaultwarden on k3s +tags: +- k3s +- kubernetes +- postgresql +- vaultwarden +--- + +## Introduction + +Please refer to [the official website](https://pass.app/) documentation for an up to date installation guide. This page only lists what I had to do at the time to setup pass and adapt it to my particular setup. I updated these instructions after migrating from a traditional hosting to kubernetes. + +## Preparing the postgresql database + +I have a postgresql running in its own namespace from bitnami images. To provision the pass database I : +```sh +export POSTGRES_PASSWORD=$(k get secret -n postgresql postgresql-secrets -o jsonpath="{.data.postgresql-password}"| + base64 --decode) +k run client --rm -ti -n postgresql --image docker.io/bitnami/postgresql:13.4.0-debian-10-r52 \ + --env="PGPASSWORD=$POSTGRES_PASSWORD" --command -- psql --host postgresql -U postgres +CREATE ROLE pass WITH LOGIN PASSWORD 'secret'; +CREATE DATABASE pass WITH OWNER pass TEMPLATE template0 ENCODING UTF8 LC_COLLATE + 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8'; +\c pass +create extension hstore; +``` + +Optionally import a dump of the database by running in another shell : +```sh +k -n postgresql cp pass.sql-20211005 client:/tmp/ +``` + +Then in the psql shell : +```sh +\c pass +\i /tmp/pass.sql-20211005 +``` + +## Kubernetes manifests in terraform + +This app is part of an experiment of mine to migrate stuff from traditional hosting to kubernetes. I first wrote manifests by hand then imported them with terraform. I do not like it and find it too complex/overkill but that is managed this way for now. + +### DNS CNAME + +Since all configuration regarding this application is in terraform, so is the dns : +```hcl +resource "cloudflare_record" "pass-cname" { + zone_id = lookup(data.cloudflare_zones.adyxax-org.zones[0], "id") + name = "pass" + value = "myth.adyxax.org" + type = "CNAME" + proxied = false +} +``` + +### Namespace + +The basic terraform object works for simple things so here it is : +```hcl +resource "kubernetes_namespace" "myth-pass" { + provider = kubernetes.myth + metadata { + name = "pass" + } +} +``` + +### Secret + +Here is the kubernetes secret that tells pass how to connect the database. The password comes from `terraform.tfvars`, you might need to update the service url with the format `..svc.cluster.local` : +```hcl +resource "kubernetes_secret" "myth-pass-secrets" { + provider = kubernetes.myth + metadata { + name = "pass-secrets" + namespace = kubernetes_namespace.myth-pass.id + } + data = { + ADMIN_PASSWORD = var.pass-admin-password + DATABASE_URL = join("", [ "postgres://pass:${var.pass-postgres-password}", + "@postgresql.postgresql.svc.cluster.local/pass?sslmode=disable"]) + } + type = "Opaque" +} +``` + +### Deployment + +I could not write the deployment with the `kubernetes_deployment` terraform ressource, so it is a row manifest which imports a yaml syntax in hcl. It is horrible to look at but works. Change the image tag to the latest stable version of pass before deploying : +```hcl +resource "kubernetes_manifest" "myth-deployment-pass" { + provider = kubernetes.myth + manifest = { + "apiVersion" = "apps/v1" + "kind" = "Deployment" + "metadata" = { + "name" = "pass" + "namespace" = kubernetes_namespace.myth-pass.id + } + "spec" = { + "replicas" = 1 + "selector" = { + "matchLabels" = { + "app" = "pass" + } + } + "strategy" = { + "type" = "RollingUpdate" + "rollingUpdate" = { + "maxSurge" = 1 + "maxUnavailable" = 0 + } + } + "template" = { + "metadata" = { + "labels" = { + "app" = "pass" + } + } + "spec" = { + "containers" = [ + { + "env" = [ + { + "name" = "DATABASE_URL" + "valueFrom" = { + "secretKeyRef" = { + "key" = "DATABASE_URL" + "name" = "pass-secrets" + } + } + }, + { + "name" = "RUN_MIGRATIONS" + "value" = "1" + }, + { + "name" = "ADMIN_USERNAME" + "value" = "admin" + }, + { + "name" = "ADMIN_PASSWORD" + "valueFrom" = { + "secretKeyRef" = { + "key" = "ADMIN_PASSWORD" + "name" = "pass-secrets" + } + } + }, + ] + "image" = "vaultwarden/server:1.23.0" + "livenessProbe" = { + "httpGet" = { + "path" = "/" + "port" = 8080 + } + "initialDelaySeconds" = 5 + "timeoutSeconds" = 5 + } + "name" = "pass" + "ports" = [ + { + "containerPort" = 8080 + }, + ] + "readinessProbe" = { + "httpGet" = { + "path" = "/" + "port" = 8080 + } + "initialDelaySeconds" = 5 + "timeoutSeconds" = 5 + } + "lifecycle" = { + "preStop" = { + "exec" = { + "command" = ["/bin/sh", "-c", "sleep 10"] + } + } + } + }, + ] + "terminationGracePeriodSeconds" = 1 + } + } + } + } +} +``` + +### Service + +```hcl +resource "kubernetes_manifest" "myth-service-pass" { + provider = kubernetes.myth + manifest = { + "apiVersion" = "v1" + "kind" = "Service" + "metadata" = { + "name" = "pass" + "namespace" = kubernetes_namespace.myth-pass.id + } + "spec" = { + "ports" = [ + { + "port" = 80 + "protocol" = "TCP" + "targetPort" = 8080 + }, + ] + "selector" = { + "app" = "pass" + } + "type" = "ClusterIP" + } + } +} +``` + +### Ingress + +```hcl +resource "kubernetes_manifest" "myth-ingress-pass" { + provider = kubernetes.myth + manifest = { + "apiVersion" = "networking.k8s.io/v1" + "kind" = "Ingress" + "metadata" = { + "name" = "pass" + "namespace" = kubernetes_namespace.myth-pass.id + } + "spec" = { + "ingressClassName" = "nginx" + "rules" = [ + { + "host" = "pass.adyxax.org" + "http" = { + "paths" = [ + { + "path" = "/" + "pathType" = "Prefix" + "backend" = { + "service" = { + "name" = "pass" + "port" = { + "number" = 80 + } + } + } + }, + ] + } + }, + ] + "tls" = [ + { + "secretName" = "wildcard-adyxax-org" + }, + ] + } + } +} +``` + +### Certificate + +For now I do not manage my certificates with terraform but manually. Once every two months I run : +```sh +acme.sh --config-home "$HOME/.acme.sh" --server letsencrypt --dns dns_cf --issue -d adyxax.org -d *.adyxax.org --force +kubectl -n pass create secret tls wildcard-adyxax-org --cert=$HOME/.acme.sh/adyxax.org/fullchain.cer \ + --key=$HOME/.acme.sh/adyxax.org/adyxax.org.key -o yaml --save-config --dry-run=client | kubectl apply -f - +``` -- cgit v1.2.3