Compare commits

...

21 commits
1.2.0 ... main

Author SHA1 Message Date
0d8339cfa7 bump version to: 1.2.7-SNAPSHOT 2025-01-31 08:59:10 +01:00
031a75bba2 release: 1.2.6 2025-01-31 08:59:09 +01:00
a0fafe6f5c update picture 2025-01-30 17:32:47 +01:00
9d538e39d9 bump version to: 1.2.6-SNAPSHOT 2025-01-30 16:36:43 +01:00
b434cf7e1f release: 1.2.5 2025-01-30 16:36:43 +01:00
5e8acf075e cleanup lables & add global generation test 2025-01-30 16:24:17 +01:00
a2fc8d5ab6 fix duplicated ns 2025-01-30 13:58:45 +01:00
ca770fb93d fix js 2025-01-30 13:38:27 +01:00
46c49a3317 Merge branch 'main' of ssh://repo.prod.meissa.de:2222/meissa/c4k-taiga 2025-01-24 15:06:40 +01:00
64f8f80da1 moved backup process 2025-01-24 15:05:29 +01:00
2bcf68760b bump version to: 1.2.5-SNAPSHOT 2025-01-20 10:05:09 +01:00
46ca21c227 release: 1.2.4 2025-01-20 10:05:08 +01:00
2b932a8e60 bump version to: 1.2.4-SNAPSHOT 2025-01-17 16:29:59 +01:00
95465a3649 release: 1.2.3 2025-01-17 16:29:59 +01:00
860659aa6a add the missing config.edn 2025-01-17 16:26:09 +01:00
17fe23e965 bump version to: 1.2.3-SNAPSHOT 2025-01-17 16:21:39 +01:00
2122809cb4 release: 1.2.2 2025-01-17 16:21:39 +01:00
8439b20b42 bump version to: 1.2.2-SNAPSHOT 2025-01-15 13:08:03 +01:00
7d44d390f5 release: 1.2.1 2025-01-15 13:08:02 +01:00
1cc181662e fix backup & restore script 2025-01-15 13:04:37 +01:00
0b7e7991ce bump version to: 1.2.1-SNAPSHOT 2025-01-15 09:55:43 +01:00
32 changed files with 1887 additions and 153 deletions

5
.gitignore vendored
View file

@ -27,8 +27,7 @@ public/js/
*.iml
.idea/
auth.edn
config.edn
build-and-move-frontend.sh
website.yaml
.envrc

View file

@ -1,77 +1,9 @@
# Backup Architecture details
![](backup.svg)
Use process documented at https://repo.prod.meissa.de/meissa/dda-backup/src/branch/main/docs/Backup.md
* we use restic to produce small & encrypted backups
* backup is scheduled at `schedule: "10 23 * * *"`
* Cloud stores files on `/var/jira`, these files are backuped. If you create a jira xml backup located in /var/jira this file will also be backed up.
* postgres db is backed up as pgdump
Parameters are:
## Manual backup
1. Scale gateway and front deployment down:
`kubectl -n taiga scale deployment taiga-gateway-deployment --replicas=0`
`kubectl -n taiga scale deployment taiga-front-deployment --replicas=0`
2. Scale backup-restore deployment up:
`kubectl -n taiga scale deployment backup-restore --replicas=1`
3. exec into pod and execute restore pod
`kubectl -n taiga exec -it backup-restore -- backup.bb`
4. Scale backup-restore deployment down:
`kubectl -n taiga scale deployment backup-restore --replicas=0`
1. Scale gateway and front deployment up:
`kubectl -n taiga scale deployment taiga-gateway-deployment --replicas=1`
`kubectl -n taiga scale deployment taiga-front-deployment --replicas=1`
## Manual restore
1. Scale gateway and front deployment down:
`kubectl -n taiga scale deployment taiga-gateway-deployment --replicas=0`
`kubectl -n taiga scale deployment taiga-front-deployment --replicas=0`
2. Scale backup-restore deployment up:
`kubectl -n taiga scale deployment backup-restore --replicas=1`
3. exec into pod and execute restore pod
`kubectl -n taiga exec -it backup-restore -- restore.bb`
4. Scale backup-restore deployment down:
`kubectl -n taiga scale deployment backup-restore --replicas=0`
5. Scale gateway and front deployment up:
`kubectl -n taiga scale deployment taiga-gateway-deployment --replicas=1`
`kubectl -n taiga scale deployment taiga-front-deployment --replicas=1`
## Change Password
1. Check restic-new-password env is set in backup deployment
```
kind: Deployment
metadata:
name: backup-restore
spec:
spec:
containers:
- name: backup-app
env:
- name: RESTIC_NEW_PASSWORD_FILE
value: /var/run/secrets/backup-secrets/restic-new-password
```
2. Add restic-new-password to secret
```
kind: Secret
metadata:
name: backup-secret
data:
restic-password: old
restic-new-password: new
```
3. Scale backup-restore deployment up:
`kubectl -n taiga scale deployment backup-restore --replicas=1`
4. exec into pod and execute restore pod
`kubectl -n taiga exec -it backup-restore -- change-password.bb`
5. Scale backup-restore deployment down:
`kubectl -n taiga scale deployment backup-restore --replicas=0`
6. Replace restic-password with restic-new-password in secret
```
kind: Secret
metadata:
name: backup-secret
data:
restic-password: new
```
1. **deployment-name**: taiga-front-deployment, taiga-gateway-deployment
2. **deployment-namespace**: taiga

Binary file not shown.

Before

(image error) Size: 53 KiB

After

(image error) Size: 157 KiB

View file

@ -6,7 +6,7 @@ from ddadevops import *
name = "c4k-taiga"
MODULE = "backup"
PROJECT_ROOT_PATH = "../.."
version = "1.2.0"
version = "1.2.7-dev"
@init

View file

@ -1,6 +1,5 @@
#!/usr/bin/env bb
(require
'[babashka.tasks :as t]
'[dda.backup.core :as bc]
'[dda.backup.config :as cfg]
'[dda.backup.restic :as rc]
@ -25,8 +24,6 @@
(bak/backup-file! (:file-config config))
(bak/backup-db! (:db-config config)))
(t/shell "start-maintenance.sh")
(prepare!)
(restic-repo-init!)
(restic-backup!)
(t/shell "end-maintenance.sh")

View file

@ -0,0 +1,24 @@
{:restic-repo {:password-file #env-or-file "RESTIC_PASSWORD_FILE"
:restic-repository #env-or-file "RESTIC_REPOSITORY"}
:file-config #merge [#ref [:restic-repo]
{:backup-path "files"
:execution-directory "/media"
:files ["."]}]
:file-restore-config #merge [#ref [:restic-repo]
{:backup-path "files"
:restore-target-directory "/media/"
:clean-up-elements ["user"]}]
:db-config #merge [#ref [:restic-repo] {:backup-path "pg-database"
:pg-host #env-or-file "POSTGRES_SERVICE"
:pg-port #env-or-file "POSTGRES_PORT"
:pg-db #env-or-file "POSTGRES_DB"
:pg-user #env-or-file "POSTGRES_USER"
:pg-password #env-or-file "POSTGRES_PASSWORD"}]
:aws-config {:aws-access-key-id #env-or-file "AWS_ACCESS_KEY_ID"
:aws-secret-access-key #env-or-file "AWS_SECRET_ACCESS_KEY"}
:dry-run {:dry-run true :debug true}}

View file

@ -18,7 +18,6 @@
(pg/drop-create-db! (:db-config config))
(rs/restore-db! (:db-config config))
(rs/restore-file! (:file-restore-config config))
(t/shell "mv /var/backups/restore/* /media")
(t/shell "chown -R 999:999 /media"))
(prepare!)

1772
out.yml Normal file

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
"name": "c4k-taiga",
"description": "Generate c4k yaml for a taiga project management deployment.",
"author": "meissa GmbH",
"version": "1.2.0",
"version": "1.2.7-SNAPSHOT",
"homepage": "https://gitlab.com/domaindrivenarchitecture/c4k-taiga#readme",
"repository": "https://www.npmjs.com/package/c4k-taiga",
"license": "APACHE2",

View file

@ -1,4 +1,4 @@
(defproject org.domaindrivenarchitecture/c4k-taiga "1.2.0"
(defproject org.domaindrivenarchitecture/c4k-taiga "1.2.7-SNAPSHOT"
:description "taiga c4k-installation package"
:url "https://domaindrivenarchitecture.org"
:license {:name "Apache License, Version 2.0"

View file

@ -9,7 +9,7 @@
"c4k-taiga"
core/config?
core/auth?
core/defaults
core/config-defaults
core/config-objects
core/auth-objects
cmd-args))

View file

@ -12,16 +12,16 @@
[dda.c4k-common.postgres :as postgres]
[dda.c4k-common.namespace :as ns]))
(def defaults {:namespace "taiga"
:issuer "staging"
:storage-class-name "local-path"
:pv-storage-size-gb "5"
:storage-media-size "5"
:storage-static-size "5"
:storage-async-rabbitmq-size "5"
:storage-events-rabbitmq-size "5"
:public-register-enabled "false"
:enable-telemetry "false"})
(def config-defaults {:namespace "taiga"
:issuer "staging"
:storage-class-name "local-path"
:pv-storage-size-gb "5"
:storage-media-size "5"
:storage-static-size "5"
:storage-async-rabbitmq-size "5"
:storage-events-rabbitmq-size "5"
:public-register-enabled "false"
:enable-telemetry "false"})
(def config? (s/merge
::backup/config
@ -54,7 +54,7 @@
(defn-spec config-objects cp/map-or-seq?
[config config?]
(let [resolved-config (merge defaults config)]
(let [resolved-config (merge config-defaults config)]
(cm/concat-vec
(map yaml/to-string
(filter
@ -97,7 +97,7 @@
(defn-spec auth-objects cp/map-or-seq?
[config config?
auth auth?]
(let [resolved-config (merge defaults config)]
(let [resolved-config (merge config-defaults config)]
(cm/concat-vec
(map yaml/to-string
(filter

View file

@ -12,35 +12,39 @@
(cm/concat-vec
(br/generate-group
"config"
(br/generate-text-area "config" "Your config.edn:" "{:fqdn \"cloud.your.domain\"
:issuer \"staging\"
:restic-repository \"s3://yourbucket/your-repo\"
:mon-cfg {:cluster-name \"cloud\"
:cluster-stage \"test\"
:cloud-url \"https://prometheus-prod-01-eu-west-0.grafana.net/api/prom/push\"}}"
"5"))
(br/generate-text-area
"config" "Your config.edn:"
"{:fqdn \"taiga.your.domain\"
:issuer \"staging\"
:restic-repository \"s3://yourbucket/your-repo\"
:mon-cfg {:cluster-name \"taiga\"
:cluster-stage \"test\"
:grafana-cloud-url \"https://prometheus-prod-01-eu-west-0.grafana.net/api/prom/push\"}}"
"6"))
(br/generate-group
"auth"
(br/generate-text-area "auth" "Your auth.edn:" "{:postgres-db-user \"taiga\"
:postgres-db-password \"db-password\"
:mailer-user \"mail[at]example.com\"
:mailer-pw \"change-me\"
:django-superuser-username \"admin\"
:django-superuser-password \"change-me\"
:django-superuser-email \"mail[at]example.com\"
:rabbitmq-user \"user\"
:rabbitmq-pw \"change-me\"
:rabbitmq-erlang-cookie \"change-me\"
:taiga-secret-key \"change-me\"
:aws-access-key-id \"aws-id\"
:aws-secret-access-key \"aws-secret\"
:restic-password \"restic-password\"}
:mon-auth {:grafana-cloud-user \"your-user-id\"
:grafana-cloud-password \"your-cloud-password\"}"
"5"))
(br/generate-text-area
"auth" "Your auth.edn:"
"{:postgres-db-user \"taiga\"
:postgres-db-password \"db-password\"
:mailer-user \"mail[at]example.com\"
:mailer-pw \"change-me\"
:django-superuser-username \"admin\"
:django-superuser-password \"change-me\"
:django-superuser-email \"mail[at]example.com\"
:rabbitmq-user \"user\"
:rabbitmq-pw \"change-me\"
:rabbitmq-erlang-cookie \"change-me\"
:taiga-secret-key \"change-me\"
:aws-access-key-id \"aws-id\"
:aws-secret-access-key \"aws-secret\"
:restic-password \"restic-password\"
:mon-auth {:grafana-cloud-user \"your-user-id\"
:grafana-cloud-password \"your-cloud-password\"}}"
"16"))
[(br/generate-br)]
(br/generate-button "generate-button" "Generate c4k yaml")))]
(br/generate-output "c4k-taiga-output" "Your c4k deployment.yaml:" "15")))
(br/generate-output "c4k-taiga-output" "Your c4k deployment.yaml:" "25")))
(defn generate-content-div
[]
@ -66,12 +70,12 @@
#(do (validate-all!)
(-> (cm/generate-cm
(br/get-content-from-element "config" :deserializer edn/read-string)
(br/get-content-from-element "auth" :deserializer edn/read-string)
core/config-defaults
core/config-objects
core/auth-objects
false
false)
(br/get-content-from-element "auth" :deserializer edn/read-string)
core/config-defaults
core/config-objects
core/auth-objects
false
false)
(br/set-output!)))))
(add-validate-listener "config")
(add-validate-listener "authr"))
(add-validate-listener "auth"))

View file

@ -15,7 +15,7 @@ spec:
labels:
app: backup-restore
app.kubernetes.io/name: backup-restore
app.kubernetes.io/part-of: taiga
app.kubernetes.io/part-of: c4k-taiga
spec:
containers:
- image: domaindrivenarchitecture/c4k-taiga-backup

View file

@ -5,6 +5,6 @@ metadata:
namespace: taiga
labels:
app.kubernetes.io/name: backup
app.kubernetes.io/part-of: taiga
app.kubernetes.io/part-of: c4k-taiga
data:
restic-repository: restic-repository

View file

@ -4,7 +4,7 @@ metadata:
name: taiga-backup
namespace: taiga
labels:
app.kubernetes.part-of: taiga
app.kubernetes.part-of: c4k-taiga
spec:
schedule: "10 23 * * *"
successfulJobsHistoryLimit: 1

View file

@ -48,7 +48,6 @@ spec:
configMapKeyRef:
name: taiga-configmap
key: RABBITMQ_DEFAULT_VHOST
volumes:
- name: taiga-async-rabbitmq-data
persistentVolumeClaim:

View file

@ -6,7 +6,6 @@ metadata:
labels:
app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-async-rabbitmq
namespace: taiga
spec:
type: ClusterIP
selector:

View file

@ -6,7 +6,6 @@ metadata:
labels:
app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-async
namespace: taiga
spec:
type: ClusterIP
selector:

View file

@ -3,6 +3,8 @@ kind: ConfigMap
metadata:
name: taiga-configmap
namespace: taiga
labels:
app.kubernetes.part-of: c4k-taiga
data:
# These environment variables will be used by taiga-back and taiga-async.
# Database settings handled in deployment

View file

@ -48,7 +48,6 @@ spec:
secretKeyRef:
name: taiga-secret
key: RABBITMQ_PASS
volumes:
- name: taiga-events-rabbitmq-data
persistentVolumeClaim:

View file

@ -6,7 +6,6 @@ metadata:
labels:
app.kubernetes.part-of: c4k-taiga
app.kubernetes.io/component: taiga-events-rabbitmq
namespace: taiga
spec:
type: ClusterIP
selector:

View file

@ -3,6 +3,8 @@ kind: ConfigMap
metadata:
name: taiga-gateway-configmap
namespace: taiga
labels:
app.kubernetes.part-of: c4k-taiga
data:
default.conf: |
server {

View file

@ -34,7 +34,6 @@ spec:
- name: taiga-media
mountPath: /taiga/media
readOnly: false
volumes:
- name: taiga-gateway-configmap
configMap:

View file

@ -4,8 +4,7 @@ metadata:
name: taiga-media-data
namespace: taiga
labels:
app: taiga
app.kubernetes.part-of: taiga
app.kubernetes.part-of: c4k-taiga
spec:
storageClassName: REPLACEME
accessModes:

View file

@ -4,8 +4,7 @@ metadata:
name: taiga-static-data
namespace: taiga
labels:
app: taiga
app.kubernetes.part-of: taiga
app.kubernetes.part-of: c4k-taiga
spec:
storageClassName: REPLACEME
accessModes:

View file

@ -4,8 +4,7 @@ metadata:
name: taiga-async-rabbitmq-data
namespace: taiga
labels:
app: taiga
app.kubernetes.part-of: taiga
app.kubernetes.part-of: c4k-taiga
spec:
storageClassName: REPLACEME
accessModes:

View file

@ -4,8 +4,7 @@ metadata:
name: taiga-events-rabbitmq-data
namespace: taiga
labels:
app: taiga
app.kubernetes.part-of: taiga
app.kubernetes.part-of: c4k-taiga
spec:
storageClassName: REPLACEME
accessModes:

View file

@ -4,7 +4,7 @@ metadata:
name: taiga-secret
namespace: taiga
labels:
app.kubernetes.part-of: taiga
app.kubernetes.part-of: c4k-taiga
data:
# Taiga settings
TAIGA_SECRET_KEY: TAIGA_SECRET_KEY

View file

@ -15,7 +15,7 @@
:metadata {:name "backup-config"
:namespace "taiga"
:labels {:app.kubernetes.io/name "backup"
:app.kubernetes.io/part-of "taiga"}}
:app.kubernetes.io/part-of "c4k-taiga"}}
:data
{:restic-repository "s3:restic-repository"}}
(cut/generate-config {:restic-repository "s3:restic-repository"}))))

View file

@ -14,3 +14,14 @@
(deftest validate-valid-resources
(is (s/valid? cut/config? (yaml/load-as-edn "taiga-test/valid-config.yaml")))
(is (s/valid? cut/auth? (yaml/load-as-edn "taiga-test/valid-auth.yaml"))))
(deftest test-whole-generation
(is (= 49
(count
(cut/config-objects
(yaml/load-as-edn "taiga-test/valid-config.yaml")))))
(is (= 4
(count
(cut/auth-objects
(yaml/load-as-edn "taiga-test/valid-config.yaml")
(yaml/load-as-edn "taiga-test/valid-auth.yaml"))))))

View file

@ -20,7 +20,9 @@
(deftest should-generate-configmap
(is (= {:apiVersion "v1",
:kind "ConfigMap",
:metadata {:name "taiga-configmap", :namespace "taiga"},
:metadata
{:name "taiga-configmap", :namespace "taiga"
:labels {:app.kubernetes.part-of "c4k-taiga"}},
:data
{:ENABLE_TELEMETRY "false",
:TAIGA_SITES_SCHEME "https",
@ -43,7 +45,7 @@
:metadata
{:name "taiga-media-data",
:namespace "taiga"
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
:labels {:app.kubernetes.part-of "c4k-taiga"}},
:spec
{:storageClassName "local-path",
:accessModes ["ReadWriteOnce"],
@ -54,7 +56,7 @@
:metadata
{:name "taiga-static-data",
:namespace "taiga"
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
:labels {:app.kubernetes.part-of "c4k-taiga"}},
:spec
{:storageClassName "local-path",
:accessModes ["ReadWriteOnce"],
@ -67,7 +69,7 @@
:metadata
{:name "taiga-async-rabbitmq-data",
:namespace "taiga"
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
:labels {:app.kubernetes.part-of "c4k-taiga"}},
:spec
{:storageClassName "local-path",
:accessModes ["ReadWriteOnce"],
@ -80,7 +82,7 @@
:metadata
{:name "taiga-events-rabbitmq-data",
:namespace "taiga"
:labels {:app "taiga", :app.kubernetes.part-of "taiga"}},
:labels {:app.kubernetes.part-of "c4k-taiga"}},
:spec
{:storageClassName "local-path",
:accessModes ["ReadWriteOnce"],
@ -91,7 +93,7 @@
(is (= {:apiVersion "v1",
:kind "Secret",
:metadata
{:name "taiga-secret", :namespace "taiga" :labels {:app.kubernetes.part-of "taiga"}},
{:name "taiga-secret", :namespace "taiga" :labels {:app.kubernetes.part-of "c4k-taiga"}},
:data
{:TAIGA_SECRET_KEY "c29tZS1rZXk=",
:EMAIL_HOST_USER "bWFpbGVyLXVzZXI=",