Merge pull request 'password-rotation' (#8) from password-rotation into main
Reviewed-on: #8
This commit is contained in:
commit
8898ee8def
25 changed files with 205 additions and 147 deletions
README.md
doc
infrastructure/backup
package.jsonproject.cljshadow-cljs.ednsrc
main
test
|
@ -52,9 +52,8 @@ Mirrors are:
|
||||||
|
|
||||||
For more details about our repository model see: https://repo.prod.meissa.de/meissa/federate-your-repos
|
For more details about our repository model see: https://repo.prod.meissa.de/meissa/federate-your-repos
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright © 2023, 2024 meissa GmbH
|
Copyright © 2023, 2024, 2025 meissa GmbH
|
||||||
Licensed under the [Apache License, Version 2.0](LICENSE) (the "License")
|
Licensed under the [Apache License, Version 2.0](LICENSE) (the "License")
|
||||||
Pls. find licenses of our subcomponents [here](doc/SUBCOMPONENT_LICENSE)
|
Pls. find licenses of our subcomponents [here](doc/SUBCOMPONENT_LICENSE)
|
|
@ -7,35 +7,67 @@
|
||||||
* Forgejo stores files in `/data/gitea` and `/data/git/repositories`, these files are backed up.
|
* Forgejo stores files in `/data/gitea` and `/data/git/repositories`, these files are backed up.
|
||||||
* The postgres db is also backed up
|
* The postgres db is also backed up
|
||||||
|
|
||||||
## Manual init the restic repository for the first time
|
## Manual backup
|
||||||
|
|
||||||
1. apply backup-and-restore pod:
|
1. Scale down forgejo deployment:
|
||||||
`kubectl -n forgejo scale deployment backup-restore --replicas=1`
|
`kubectl -n forgejo scale deployment forgejo --replicas=0`
|
||||||
2. exec into pod and execute restore pod (press tab to get your exact pod name)
|
2. apply backup-and-restore pod:
|
||||||
`kubectl -n forgejo exec -it backup-restore-... -- /usr/local/bin/init.bb`
|
|
||||||
3. remove backup-and-restore pod:
|
|
||||||
`kubectl -n forgejo scale deployment backup-restore --replicas=0`
|
|
||||||
|
|
||||||
|
|
||||||
## Manual backup the restic repository for the first time
|
|
||||||
|
|
||||||
1. apply backup-and-restore pod:
|
|
||||||
`kubectl -n forgejo scale deployment backup-restore --replicas=1`
|
`kubectl -n forgejo scale deployment backup-restore --replicas=1`
|
||||||
2. exec into pod and execute backup pod (press tab to get your exact pod name)
|
3. exec into pod and execute backup pod (press tab to get your exact pod name)
|
||||||
`kubectl -n forgejo exec -it backup-restore-... -- /usr/local/bin/backup.bb`
|
`kubectl -n forgejo exec -it backup-restore-... -- /usr/local/bin/backup.bb`
|
||||||
3. remove backup-and-restore pod:
|
4. remove backup-and-restore pod:
|
||||||
`kubectl -n forgejo scale deployment backup-restore --replicas=0`
|
`kubectl -n forgejo scale deployment backup-restore --replicas=0`
|
||||||
|
5. Scale up forgejo deployment:
|
||||||
|
`kubectl -n forgejo scale deployment forgejo --replicas=1`
|
||||||
|
|
||||||
## Manual restore
|
## Manual restore
|
||||||
|
|
||||||
1. apply backup-and-restore pod:
|
1. Scale down forgejo deployment:
|
||||||
`kubectl -n forgejo scale deployment backup-restore --replicas=1`
|
|
||||||
2. Scale down forgejo deployment:
|
|
||||||
`kubectl -n forgejo scale deployment forgejo --replicas=0`
|
`kubectl -n forgejo scale deployment forgejo --replicas=0`
|
||||||
|
2. apply backup-and-restore pod:
|
||||||
|
`kubectl -n forgejo scale deployment backup-restore --replicas=1`
|
||||||
3. exec into pod and execute restore pod (press tab to get your exact pod name)
|
3. exec into pod and execute restore pod (press tab to get your exact pod name)
|
||||||
`kubectl -n forgejo exec -it backup-restore-... -- /usr/local/bin/restore.bb`
|
`kubectl -n forgejo exec -it backup-restore-... -- /usr/local/bin/restore.bb`
|
||||||
4. Start forgejo again:
|
4. Start forgejo again:
|
||||||
`kubectl -n forgejo scale deployment forgejo --replicas=1`
|
`kubectl -n forgejo scale deployment forgejo --replicas=1`
|
||||||
5. remove backup-and-restore pod:
|
5. remove backup-and-restore pod:
|
||||||
`kubectl -n forgejo scale deployment backup-restore --replicas=0`
|
`kubectl -n forgejo scale deployment backup-restore --replicas=0`
|
||||||
|
|
||||||
|
## 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 nextcloud scale deployment backup-restore --replicas=1`
|
||||||
|
4. exec into pod and execute restore pod
|
||||||
|
`kubectl -n nextcloud exec -it backup-restore -- change-password.bb`
|
||||||
|
5. Scale backup-restore deployment down:
|
||||||
|
`kubectl -n nextcloud 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
|
||||||
|
```
|
||||||
|
|
8
doc/FirstSteps.md
Normal file
8
doc/FirstSteps.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# First Steps
|
||||||
|
|
||||||
|
## Create admin user
|
||||||
|
|
||||||
|
1. exec into pod and execute restore pod (press tab to get your exact pod name)
|
||||||
|
`kubectl -n forgejo exec -it backup-restore-... -- bash`
|
||||||
|
2. create admin user
|
||||||
|
`su git -c "gitea admin user create --username [login] --password [password] -email "email"--admin"`
|
|
@ -1,4 +1,5 @@
|
||||||
FROM domaindrivenarchitecture/dda-backup:latest
|
FROM domaindrivenarchitecture/dda-backup:5.3.0
|
||||||
|
|
||||||
ADD resources /tmp
|
ADD resources /tmp
|
||||||
RUN /tmp/install.bb
|
RUN /tmp/install.bb
|
||||||
|
RUN init.bb
|
||||||
|
|
|
@ -2,44 +2,27 @@
|
||||||
|
|
||||||
(require
|
(require
|
||||||
'[dda.backup.core :as bc]
|
'[dda.backup.core :as bc]
|
||||||
|
'[dda.backup.config :as cfg]
|
||||||
'[dda.backup.restic :as rc]
|
'[dda.backup.restic :as rc]
|
||||||
'[dda.backup.postgresql :as pg]
|
'[dda.backup.postgresql :as pg]
|
||||||
'[dda.backup.backup :as bak])
|
'[dda.backup.backup :as bak])
|
||||||
|
|
||||||
(def restic-repo {:password-file (bc/env-or-file "RESTIC_PASSWORD_FILE")
|
(def config (cfg/read-config "/usr/local/bin/config.edn"))
|
||||||
:restic-repository (bc/env-or-file "RESTIC_REPOSITORY")})
|
|
||||||
|
|
||||||
(def file-config (merge restic-repo {:backup-path "files"
|
|
||||||
:execution-directory "/var/backups/"
|
|
||||||
:files ["gitea/" "git/repositories/"]}))
|
|
||||||
|
|
||||||
|
|
||||||
(def db-config (merge restic-repo {:backup-path "pg-database"
|
|
||||||
:pg-host (bc/env-or-file "POSTGRES_SERVICE")
|
|
||||||
:pg-port (bc/env-or-file "POSTGRES_PORT")
|
|
||||||
:pg-db (bc/env-or-file "POSTGRES_DB")
|
|
||||||
:pg-user (bc/env-or-file "POSTGRES_USER")
|
|
||||||
:pg-password (bc/env-or-file "POSTGRES_PASSWORD")}))
|
|
||||||
|
|
||||||
(def aws-config {:aws-access-key-id (bc/env-or-file "AWS_ACCESS_KEY_ID")
|
|
||||||
:aws-secret-access-key (bc/env-or-file "AWS_SECRET_ACCESS_KEY")})
|
|
||||||
|
|
||||||
(def dry-run {:dry-run true :debug true})
|
|
||||||
|
|
||||||
(defn prepare!
|
(defn prepare!
|
||||||
[]
|
[]
|
||||||
(bc/create-aws-credentials! aws-config)
|
(bc/create-aws-credentials! (:aws-config config))
|
||||||
(pg/create-pg-pass! db-config))
|
(pg/create-pg-pass! (:db-config config)))
|
||||||
|
|
||||||
(defn restic-repo-init!
|
(defn restic-repo-init!
|
||||||
[]
|
[]
|
||||||
(rc/init! file-config)
|
(rc/init! (:file-config config))
|
||||||
(rc/init! db-config))
|
(rc/init! (:db-config config)))
|
||||||
|
|
||||||
(defn restic-backup!
|
(defn restic-backup!
|
||||||
[]
|
[]
|
||||||
(bak/backup-file! file-config)
|
(bak/backup-file! (:file-config config))
|
||||||
(bak/backup-db! db-config))
|
(bak/backup-db! (:db-config config)))
|
||||||
|
|
||||||
(prepare!)
|
(prepare!)
|
||||||
(restic-repo-init!)
|
(restic-repo-init!)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
{:deps {org.clojure/spec.alpha {:mvn/version "0.4.233"}
|
{:deps {org.clojure/spec.alpha {:mvn/version "0.4.233"}
|
||||||
orchestra/orchestra {:mvn/version "2021.01.01-1"}
|
orchestra/orchestra {:mvn/version "2021.01.01-1"}
|
||||||
|
aero/aero {:mvn/version "1.1.6"}
|
||||||
org.domaindrivenarchitecture/dda-backup {:local/root "/usr/local/lib/dda-backup"}}}
|
org.domaindrivenarchitecture/dda-backup {:local/root "/usr/local/lib/dda-backup"}}}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{:deps {org.clojure/spec.alpha {:mvn/version "0.4.233"}
|
{:deps {org.clojure/spec.alpha {:mvn/version "0.4.233"}
|
||||||
orchestra/orchestra {:mvn/version "2021.01.01-1"}
|
orchestra/orchestra {:mvn/version "2021.01.01-1"}
|
||||||
org.domaindrivenarchitecture/dda-build {:mvn/version "0.1.1-SNAPSHOT"}}}
|
org.domaindrivenarchitecture/dda-build {:mvn/version "0.2.0"}}}
|
||||||
|
|
24
infrastructure/backup/image/resources/change-password.bb
Executable file
24
infrastructure/backup/image/resources/change-password.bb
Executable file
|
@ -0,0 +1,24 @@
|
||||||
|
#!/usr/bin/env bb
|
||||||
|
(require
|
||||||
|
'[dda.backup.core :as bc]
|
||||||
|
'[dda.backup.config :as cfg]
|
||||||
|
'[dda.backup.restic :as rc])
|
||||||
|
|
||||||
|
(def config (cfg/read-config "/usr/local/bin/config.edn"))
|
||||||
|
|
||||||
|
(def file-pw-change-config (merge (:file-config config)
|
||||||
|
{:new-password-file (bc/env-or-file "RESTIC_NEW_PASSWORD_FILE")}))
|
||||||
|
(def db-pw-change-config (merge (:db-config config)
|
||||||
|
{:new-password-file (bc/env-or-file "RESTIC_NEW_PASSWORD_FILE")}))
|
||||||
|
|
||||||
|
(defn prepare!
|
||||||
|
[]
|
||||||
|
(bc/create-aws-credentials! (:aws-config config)))
|
||||||
|
|
||||||
|
(defn change-password!
|
||||||
|
[]
|
||||||
|
(rc/change-password! file-pw-change-config)
|
||||||
|
(rc/change-password! db-pw-change-config))
|
||||||
|
|
||||||
|
(prepare!)
|
||||||
|
(change-password!)
|
|
@ -7,8 +7,11 @@
|
||||||
|
|
||||||
(ub/upgrade-system!)
|
(ub/upgrade-system!)
|
||||||
(in/install! "bb-backup.edn" :target-name "bb.edn" :mod "0400")
|
(in/install! "bb-backup.edn" :target-name "bb.edn" :mod "0400")
|
||||||
|
(in/install! "config.edn" :mod "0440")
|
||||||
|
(in/install! "init.bb")
|
||||||
(in/install! "backup.bb")
|
(in/install! "backup.bb")
|
||||||
(in/install! "restore.bb")
|
(in/install! "restore.bb")
|
||||||
(in/install! "list-snapshots.bb")
|
(in/install! "list-snapshots.bb")
|
||||||
|
(in/install! "change-password.bb")
|
||||||
(in/install! "wait.bb")
|
(in/install! "wait.bb")
|
||||||
(ub/cleanup-container!)
|
(ub/cleanup-container!)
|
|
@ -2,27 +2,19 @@
|
||||||
|
|
||||||
(require
|
(require
|
||||||
'[dda.backup.core :as bc]
|
'[dda.backup.core :as bc]
|
||||||
|
'[dda.backup.config :as cfg]
|
||||||
'[dda.backup.restic :as rc])
|
'[dda.backup.restic :as rc])
|
||||||
|
|
||||||
(def restic-repo {:password-file (bc/env-or-file "RESTIC_PASSWORD_FILE")
|
(def config (cfg/read-config "/usr/local/bin/config.edn"))
|
||||||
:restic-repository (bc/env-or-file "RESTIC_REPOSITORY")})
|
|
||||||
|
|
||||||
(def file-config (merge restic-repo {:backup-path "files"}))
|
|
||||||
|
|
||||||
|
|
||||||
(def db-config (merge restic-repo {:backup-path "pg-database"}))
|
|
||||||
|
|
||||||
(def aws-config {:aws-access-key-id (bc/env-or-file "AWS_ACCESS_KEY_ID")
|
|
||||||
:aws-secret-access-key (bc/env-or-file "AWS_SECRET_ACCESS_KEY")})
|
|
||||||
|
|
||||||
(defn prepare!
|
(defn prepare!
|
||||||
[]
|
[]
|
||||||
(bc/create-aws-credentials! aws-config))
|
(bc/create-aws-credentials! (:aws-config config)))
|
||||||
|
|
||||||
(defn list-snapshots!
|
(defn list-snapshots!
|
||||||
[]
|
[]
|
||||||
(rc/list-snapshots! file-config)
|
(rc/list-snapshots! (:file-config config))
|
||||||
(rc/list-snapshots! db-config))
|
(rc/list-snapshots! (:db-config config)))
|
||||||
|
|
||||||
(prepare!)
|
(prepare!)
|
||||||
(list-snapshots!)
|
(list-snapshots!)
|
||||||
|
|
|
@ -2,34 +2,28 @@
|
||||||
|
|
||||||
(require '[babashka.tasks :as tasks]
|
(require '[babashka.tasks :as tasks]
|
||||||
'[dda.backup.core :as bc]
|
'[dda.backup.core :as bc]
|
||||||
|
'[dda.backup.config :as cfg]
|
||||||
'[dda.backup.postgresql :as pg]
|
'[dda.backup.postgresql :as pg]
|
||||||
'[dda.backup.restore :as rs])
|
'[dda.backup.restore :as rs])
|
||||||
|
|
||||||
(def restic-repo {:password-file (bc/env-or-file "RESTIC_PASSWORD_FILE")
|
(def config (cfg/read-config "/usr/local/bin/config.edn"))
|
||||||
:restic-repository (bc/env-or-file "RESTIC_REPOSITORY")})
|
|
||||||
|
|
||||||
(def file-config (merge restic-repo {:backup-path "files"
|
(def file-config (merge
|
||||||
:restore-target-directory "/var/backups/restore"
|
(:restic-repo config)
|
||||||
:snapshot-id "latest"}))
|
{:backup-path "files"
|
||||||
|
:restore-target-directory "/var/backups/restore"
|
||||||
|
:snapshot-id "latest"}))
|
||||||
|
|
||||||
|
(def db-config (merge (:db-config config)
|
||||||
|
{:snapshot-id "latest"}))
|
||||||
|
|
||||||
(def db-config (merge restic-repo {:backup-path "pg-database"
|
|
||||||
:pg-host (bc/env-or-file "POSTGRES_SERVICE")
|
|
||||||
:pg-port (bc/env-or-file "POSTGRES_PORT")
|
|
||||||
:pg-db (bc/env-or-file "POSTGRES_DB")
|
|
||||||
:pg-user (bc/env-or-file "POSTGRES_USER")
|
|
||||||
:pg-password (bc/env-or-file "POSTGRES_PASSWORD")
|
|
||||||
:snapshot-id "latest"}))
|
|
||||||
|
|
||||||
(def aws-config {:aws-access-key-id (bc/env-or-file "AWS_ACCESS_KEY_ID")
|
|
||||||
:aws-secret-access-key (bc/env-or-file "AWS_SECRET_ACCESS_KEY")})
|
|
||||||
|
|
||||||
(def dry-run {:dry-run true :debug true})
|
(def dry-run {:dry-run true :debug true})
|
||||||
|
|
||||||
(defn prepare!
|
(defn prepare!
|
||||||
[]
|
[]
|
||||||
(pg/create-pg-pass! db-config)
|
(bc/create-aws-credentials! (:aws-config config))
|
||||||
(bc/create-aws-credentials! aws-config))
|
(pg/create-pg-pass! db-config))
|
||||||
|
|
||||||
(defn restic-restore!
|
(defn restic-restore!
|
||||||
[]
|
[]
|
||||||
|
@ -39,8 +33,8 @@
|
||||||
(tasks/shell ["mv" "/var/backups/restore/gitea" "/var/backups/"])
|
(tasks/shell ["mv" "/var/backups/restore/gitea" "/var/backups/"])
|
||||||
(tasks/shell ["mv" "/var/backups/restore/git/repositories" "/var/backups/git/"])
|
(tasks/shell ["mv" "/var/backups/restore/git/repositories" "/var/backups/git/"])
|
||||||
(tasks/shell ["chown" "-R" "1000:1000" "/var/backups"])
|
(tasks/shell ["chown" "-R" "1000:1000" "/var/backups"])
|
||||||
(pg/drop-create-db! (merge db-config {:debug true}))
|
(pg/drop-create-db! db-config)
|
||||||
(rs/restore-db! (merge db-config {:debug true})))
|
(rs/restore-db! db-config))
|
||||||
|
|
||||||
(prepare!)
|
(prepare!)
|
||||||
(restic-restore!)
|
(restic-restore!)
|
||||||
|
|
|
@ -1,27 +1,19 @@
|
||||||
#!/usr/bin/env bb
|
#!/usr/bin/env bb
|
||||||
|
|
||||||
(require
|
(require
|
||||||
'[dda.backup.core :as bc]
|
'[dda.backup.core :as bc]
|
||||||
|
'[dda.backup.config :as cfg]
|
||||||
'[dda.backup.postgresql :as pg])
|
'[dda.backup.postgresql :as pg])
|
||||||
|
|
||||||
|
(def config (cfg/read-config "/usr/local/bin/config.edn"))
|
||||||
(def restic-repo {:password-file (bc/env-or-file "RESTIC_PASSWORD_FILE")
|
|
||||||
:restic-repository (bc/env-or-file "RESTIC_REPOSITORY")})
|
|
||||||
|
|
||||||
(def db-config (merge restic-repo {:backup-path "pg-database"
|
|
||||||
:pg-host (bc/env-or-file "POSTGRES_SERVICE")
|
|
||||||
:pg-port (bc/env-or-file "POSTGRES_PORT")
|
|
||||||
:pg-db (bc/env-or-file "POSTGRES_DB")
|
|
||||||
:pg-user (bc/env-or-file "POSTGRES_USER")
|
|
||||||
:pg-password (bc/env-or-file "POSTGRES_PASSWORD")}))
|
|
||||||
|
|
||||||
(defn prepare!
|
(defn prepare!
|
||||||
[]
|
[]
|
||||||
(pg/create-pg-pass! db-config))
|
(bc/create-aws-credentials! (:aws-config config))
|
||||||
|
(pg/create-pg-pass! (:db-config config)))
|
||||||
|
|
||||||
(defn wait! []
|
(defn wait! []
|
||||||
(while true
|
(while true
|
||||||
(Thread/sleep 1000)))
|
(Thread/sleep 1000)))
|
||||||
|
|
||||||
(prepare!)
|
(prepare!)
|
||||||
(wait!)
|
(wait!)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM c4k-forgejo-backup:latest
|
FROM c4k-forgejo-backup:latest
|
||||||
|
|
||||||
ADD resources /tmp/
|
ADD resources /tmp/
|
||||||
RUN ENV_PASSWORD=env-password FILE_PASSWORD_FILE=/tmp/file_password /tmp/test.bb
|
RUN RESTIC_PASSWORD_FILE=/tmp/file_password RESTIC_NEW_PASSWORD_FILE=/tmp/new_file_password RESTIC_REPOSITORY=/tmp/restic-repo POSTGRES_SERVICE=dummy POSTGRES_PORT=dummy POSTGRES_DB=dummy POSTGRES_USER=dummy POSTGRES_PASSWORD=dummy AWS_ACCESS_KEY_ID=dummy AWS_SECRET_ACCESS_KEY=dummy /tmp/test.bb
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
{:deps {org.clojure/spec.alpha {:mvn/version "0.4.233"}
|
{:deps {org.clojure/spec.alpha {:mvn/version "0.4.233"}
|
||||||
orchestra/orchestra {:mvn/version "2021.01.01-1"}
|
orchestra/orchestra {:mvn/version "2021.01.01-1"}
|
||||||
|
aero/aero {:mvn/version "1.1.6"}
|
||||||
org.domaindrivenarchitecture/dda-backup {:local/root "/usr/local/lib/dda-backup"}}}
|
org.domaindrivenarchitecture/dda-backup {:local/root "/usr/local/lib/dda-backup"}}}
|
||||||
|
|
1
infrastructure/backup/test/resources/file_password
Normal file
1
infrastructure/backup/test/resources/file_password
Normal file
|
@ -0,0 +1 @@
|
||||||
|
oldPassword
|
1
infrastructure/backup/test/resources/new_file_password
Normal file
1
infrastructure/backup/test/resources/new_file_password
Normal file
|
@ -0,0 +1 @@
|
||||||
|
newPassword
|
|
@ -2,61 +2,66 @@
|
||||||
|
|
||||||
(require '[babashka.tasks :as tasks]
|
(require '[babashka.tasks :as tasks]
|
||||||
'[dda.backup.core :as bc]
|
'[dda.backup.core :as bc]
|
||||||
|
'[dda.backup.config :as cfg]
|
||||||
'[dda.backup.restic :as rc]
|
'[dda.backup.restic :as rc]
|
||||||
'[dda.backup.postgresql :as pg]
|
'[dda.backup.postgresql :as pg]
|
||||||
'[dda.backup.backup :as bak]
|
'[dda.backup.backup :as bak]
|
||||||
'[dda.backup.restore :as rs])
|
'[dda.backup.restore :as rs])
|
||||||
|
|
||||||
(def restic-repo {:password-file "restic-pwd"
|
(def config (cfg/read-config "/usr/local/bin/config.edn"))
|
||||||
:restic-repository "restic-repo"})
|
|
||||||
|
|
||||||
(def file-config (merge restic-repo {:backup-path "files"
|
(def file-pw-change-config (merge (:file-config config)
|
||||||
:files ["test-backup"]
|
{:new-password-file (bc/env-or-file "RESTIC_NEW_PASSWORD_FILE")}))
|
||||||
:restore-target-directory "test-restore"}))
|
|
||||||
|
|
||||||
|
(def file-restore-config (merge
|
||||||
(def db-config (merge restic-repo {:backup-path "db"
|
(:restic-repo config)
|
||||||
:pg-db "mydb"
|
{:backup-path "files"
|
||||||
:pg-user "user"
|
:restore-target-directory "/var/backups/restore"
|
||||||
:pg-password "password"}))
|
:snapshot-id "latest"}))
|
||||||
|
|
||||||
(def dry-run {:dry-run true :debug true})
|
|
||||||
|
|
||||||
(defn prepare!
|
(defn prepare!
|
||||||
[]
|
[]
|
||||||
(spit "/tmp/file_password" "file-password")
|
(tasks/shell "mkdir" "-p" "/tmp/restic-repo")
|
||||||
(println (bc/env-or-file "FILE_PASSWORD"))
|
(tasks/shell "mkdir" "-p" "/var/backups/gitea")
|
||||||
(println (bc/env-or-file "ENV_PASSWORD"))
|
(tasks/shell "mkdir" "-p" "/var/backups/git/repositories")
|
||||||
(spit "restic-pwd" "ThePassword")
|
(spit "/var/backups/gitea/file" "I was here")
|
||||||
(tasks/shell "mkdir" "-p" "test-backup")
|
(tasks/shell "mkdir" "-p" "test-restore"))
|
||||||
(spit "test-backup/file" "I was here")
|
|
||||||
(tasks/shell "mkdir" "-p" "test-restore")
|
|
||||||
(pg/create-pg-pass! db-config))
|
|
||||||
|
|
||||||
(defn restic-repo-init!
|
(defn restic-repo-init!
|
||||||
[]
|
[]
|
||||||
(rc/init! file-config)
|
(rc/init! (:file-config config))
|
||||||
(rc/init! (merge db-config dry-run)))
|
(rc/init! (merge (:db-config config)
|
||||||
|
(:dry-run config))))
|
||||||
|
|
||||||
(defn restic-backup!
|
(defn restic-backup!
|
||||||
[]
|
[]
|
||||||
(bak/backup-file! file-config)
|
(bak/backup-file! (:file-config config))
|
||||||
(bak/backup-db! (merge db-config dry-run)))
|
(bak/backup-db! (merge (:db-config config)
|
||||||
|
(:dry-run config))))
|
||||||
|
|
||||||
(defn list-snapshots!
|
(defn list-snapshots!
|
||||||
[]
|
[]
|
||||||
(rc/list-snapshots! file-config)
|
(rc/list-snapshots! (:file-config config))
|
||||||
(rc/list-snapshots! (merge db-config dry-run)))
|
(rc/list-snapshots! (merge (:db-config config)
|
||||||
|
(:dry-run config))))
|
||||||
|
|
||||||
|
|
||||||
(defn restic-restore!
|
(defn restic-restore!
|
||||||
[]
|
[]
|
||||||
(rs/restore-file! file-config)
|
(pg/drop-create-db! (merge (:db-config config)
|
||||||
(pg/drop-create-db! (merge db-config dry-run))
|
(:dry-run config)))
|
||||||
(rs/restore-db! (merge db-config dry-run)))
|
(rs/restore-db! (merge (:db-config config)
|
||||||
|
(:dry-run config)))
|
||||||
|
(rs/restore-file! file-restore-config))
|
||||||
|
|
||||||
|
(defn change-password!
|
||||||
|
[]
|
||||||
|
(println "change-password!")
|
||||||
|
(rc/change-password! file-pw-change-config))
|
||||||
|
|
||||||
(prepare!)
|
(prepare!)
|
||||||
(restic-repo-init!)
|
(restic-repo-init!)
|
||||||
(restic-backup!)
|
(restic-backup!)
|
||||||
(list-snapshots!)
|
(list-snapshots!)
|
||||||
(restic-restore!)
|
(restic-restore!)
|
||||||
|
(change-password!)
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
"js-yaml": "^4.0.0"
|
"js-yaml": "^4.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"shadow-cljs": "^2.11.18",
|
"shadow-cljs": "^2.28.20",
|
||||||
"source-map-support": "^0.5.19"
|
"source-map-support": "^0.5.21"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,9 +3,9 @@
|
||||||
:url "https://domaindrivenarchitecture.org"
|
:url "https://domaindrivenarchitecture.org"
|
||||||
:license {:name "Apache License, Version 2.0"
|
:license {:name "Apache License, Version 2.0"
|
||||||
:url "https://www.apache.org/licenses/LICENSE-2.0.html"}
|
:url "https://www.apache.org/licenses/LICENSE-2.0.html"}
|
||||||
:dependencies [[org.clojure/clojure "1.11.4" :scope "provided"]
|
:dependencies [[org.clojure/clojure "1.12.0" :scope "provided"]
|
||||||
[org.clojure/tools.reader "1.5.0"]
|
[org.clojure/tools.reader "1.5.0"]
|
||||||
[org.domaindrivenarchitecture/c4k-common-clj "8.0.0"]
|
[org.domaindrivenarchitecture/c4k-common-clj "9.0.1"]
|
||||||
[hickory "0.7.1" :exclusions [viebel/codox-klipse-theme]]]
|
[hickory "0.7.1" :exclusions [viebel/codox-klipse-theme]]]
|
||||||
:target-path "target/%s/"
|
:target-path "target/%s/"
|
||||||
:source-paths ["src/main/cljc"
|
:source-paths ["src/main/cljc"
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
:main dda.c4k-forgejo.uberjar
|
:main dda.c4k-forgejo.uberjar
|
||||||
:uberjar-name "c4k-forgejo-standalone.jar"
|
:uberjar-name "c4k-forgejo-standalone.jar"
|
||||||
:dependencies [[org.clojure/tools.cli "1.1.230"]
|
:dependencies [[org.clojure/tools.cli "1.1.230"]
|
||||||
[ch.qos.logback/logback-classic "1.5.7"
|
[ch.qos.logback/logback-classic "1.5.16"
|
||||||
:exclusions [com.sun.mail/javax.mail]]
|
:exclusions [com.sun.mail/javax.mail]]
|
||||||
[org.slf4j/jcl-over-slf4j "2.0.16"]
|
[org.slf4j/jcl-over-slf4j "2.0.16"]
|
||||||
[com.github.clj-easy/graal-build-time "1.0.5"]]}}
|
[com.github.clj-easy/graal-build-time "1.0.5"]]}}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"src/test/cljc"
|
"src/test/cljc"
|
||||||
"src/test/cljs"
|
"src/test/cljs"
|
||||||
"src/test/resources"]
|
"src/test/resources"]
|
||||||
:dependencies [[org.domaindrivenarchitecture/c4k-common-cljs "8.0.0"]
|
:dependencies [[org.domaindrivenarchitecture/c4k-common-cljs "9.0.1"]
|
||||||
[hickory "0.7.1"]]
|
[hickory "0.7.1"]]
|
||||||
:builds {:frontend {:target :browser
|
:builds {:frontend {:target :browser
|
||||||
:modules {:main {:init-fn dda.c4k-forgejo.browser/init}}
|
:modules {:main {:init-fn dda.c4k-forgejo.browser/init}}
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
(ns dda.c4k-forgejo.backup
|
(ns dda.c4k-forgejo.backup
|
||||||
(:require
|
(:require
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
#?(:clj [orchestra.core :refer [defn-spec]]
|
#?(:clj [orchestra.core :refer [defn-spec]]
|
||||||
:cljs [orchestra.core :refer-macros [defn-spec]])
|
:cljs [orchestra.core :refer-macros [defn-spec]])
|
||||||
[dda.c4k-common.yaml :as yaml]
|
[dda.c4k-common.yaml :as yaml]
|
||||||
[dda.c4k-common.base64 :as b64]
|
[dda.c4k-common.base64 :as b64]
|
||||||
[dda.c4k-common.common :as cm]
|
[dda.c4k-common.common :as cm]
|
||||||
[dda.c4k-common.predicate :as p]
|
[dda.c4k-common.predicate :as p]
|
||||||
#?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])))
|
#?(:cljs [dda.c4k-common.macros :refer-macros [inline-resources]])))
|
||||||
|
|
||||||
(s/def ::aws-access-key-id p/bash-env-string?)
|
(s/def ::aws-access-key-id p/bash-env-string?)
|
||||||
(s/def ::aws-secret-access-key p/bash-env-string?)
|
(s/def ::aws-secret-access-key p/bash-env-string?)
|
||||||
(s/def ::restic-password p/bash-env-string?)
|
(s/def ::restic-password p/bash-env-string?)
|
||||||
|
(s/def ::restic-new-password p/bash-env-string?)
|
||||||
(s/def ::restic-repository p/bash-env-string?)
|
(s/def ::restic-repository p/bash-env-string?)
|
||||||
|
|
||||||
(s/def ::config (s/keys :req-un [::restic-repository]))
|
(s/def ::config (s/keys :req-un [::restic-repository]))
|
||||||
|
@ -32,17 +33,20 @@
|
||||||
|
|
||||||
(defn-spec generate-cron p/map-or-seq?
|
(defn-spec generate-cron p/map-or-seq?
|
||||||
[]
|
[]
|
||||||
(yaml/from-string (yaml/load-resource "backup/cron.yaml")))
|
(yaml/from-string (yaml/load-resource "backup/cron.yaml")))
|
||||||
|
|
||||||
(defn-spec generate-backup-restore-deployment p/map-or-seq?
|
(defn-spec generate-backup-restore-deployment p/map-or-seq?
|
||||||
[my-conf ::config]
|
[my-conf ::config]
|
||||||
(yaml/from-string (yaml/load-resource "backup/backup-restore-deployment.yaml")))
|
(yaml/from-string (yaml/load-resource "backup/backup-restore-deployment.yaml")))
|
||||||
|
|
||||||
(defn-spec generate-secret p/map-or-seq?
|
(defn-spec generate-secret p/map-or-seq?
|
||||||
[my-auth ::auth]
|
[auth ::auth]
|
||||||
(let [{:keys [aws-access-key-id aws-secret-access-key restic-password]} my-auth]
|
(let [{:keys [aws-access-key-id aws-secret-access-key
|
||||||
(->
|
restic-password restic-new-password]} auth]
|
||||||
(yaml/from-string (yaml/load-resource "backup/secret.yaml"))
|
(as-> (yaml/from-string (yaml/load-resource "backup/secret.yaml")) res
|
||||||
(cm/replace-key-value :aws-access-key-id (b64/encode aws-access-key-id))
|
(cm/replace-key-value res :aws-access-key-id (b64/encode aws-access-key-id))
|
||||||
(cm/replace-key-value :aws-secret-access-key (b64/encode aws-secret-access-key))
|
(cm/replace-key-value res :aws-secret-access-key (b64/encode aws-secret-access-key))
|
||||||
(cm/replace-key-value :restic-password (b64/encode restic-password)))))
|
(cm/replace-key-value res :restic-password (b64/encode restic-password))
|
||||||
|
(if (contains? auth :restic-new-password)
|
||||||
|
(assoc-in res [:data :restic-new-password] (b64/encode restic-new-password))
|
||||||
|
res))))
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
::forgejo/mailer-user ::forgejo/mailer-pw
|
::forgejo/mailer-user ::forgejo/mailer-pw
|
||||||
::backup/aws-access-key-id ::backup/aws-secret-access-key]
|
::backup/aws-access-key-id ::backup/aws-secret-access-key]
|
||||||
:opt-un [::backup/restic-password
|
:opt-un [::backup/restic-password
|
||||||
|
::backup/restic-new-password
|
||||||
::mon/mon-auth]))
|
::mon/mon-auth]))
|
||||||
|
|
||||||
(defn-spec config-objects p/map-or-seq?
|
(defn-spec config-objects p/map-or-seq?
|
||||||
|
|
|
@ -57,6 +57,8 @@ spec:
|
||||||
key: restic-repository
|
key: restic-repository
|
||||||
- name: RESTIC_PASSWORD_FILE
|
- name: RESTIC_PASSWORD_FILE
|
||||||
value: /var/run/secrets/backup-secrets/restic-password
|
value: /var/run/secrets/backup-secrets/restic-password
|
||||||
|
- name: RESTIC_NEW_PASSWORD_FILE
|
||||||
|
value: /var/run/secrets/backup-secrets/restic-new-password
|
||||||
- name: CERTIFICATE_FILE
|
- name: CERTIFICATE_FILE
|
||||||
value: ""
|
value: ""
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
|
|
|
@ -19,7 +19,20 @@
|
||||||
:restic-password "cmVzdGljLXB3"}}
|
:restic-password "cmVzdGljLXB3"}}
|
||||||
(cut/generate-secret {:aws-access-key-id "aws-id"
|
(cut/generate-secret {:aws-access-key-id "aws-id"
|
||||||
:aws-secret-access-key "aws-secret"
|
:aws-secret-access-key "aws-secret"
|
||||||
:restic-password "restic-pw"}))))
|
:restic-password "restic-pw"})))
|
||||||
|
(is (= {:apiVersion "v1",
|
||||||
|
:kind "Secret",
|
||||||
|
:metadata {:name "backup-secret", :namespace "forgejo"},
|
||||||
|
:type "Opaque",
|
||||||
|
:data
|
||||||
|
{:aws-access-key-id "YXdzLWlk",
|
||||||
|
:aws-secret-access-key "YXdzLXNlY3JldA==",
|
||||||
|
:restic-password "b2xk",
|
||||||
|
:restic-new-password "bmV3"}}
|
||||||
|
(cut/generate-secret {:aws-access-key-id "aws-id"
|
||||||
|
:aws-secret-access-key "aws-secret"
|
||||||
|
:restic-password "old"
|
||||||
|
:restic-new-password "new"}))))
|
||||||
|
|
||||||
(deftest should-generate-backup-config
|
(deftest should-generate-backup-config
|
||||||
(testing "federated"
|
(testing "federated"
|
||||||
|
|
|
@ -4,7 +4,8 @@ mailer-user: ""
|
||||||
mailer-pw: ""
|
mailer-pw: ""
|
||||||
aws-access-key-id: "AWS_KEY_ID"
|
aws-access-key-id: "AWS_KEY_ID"
|
||||||
aws-secret-access-key: "AWS_KEY_SECRET"
|
aws-secret-access-key: "AWS_KEY_SECRET"
|
||||||
restic-password: ""
|
restic-password: "old"
|
||||||
|
restic-new-password: "new"
|
||||||
mon-auth:
|
mon-auth:
|
||||||
grafana-cloud-user: "user"
|
grafana-cloud-user: "user"
|
||||||
grafana-cloud-password: "password"
|
grafana-cloud-password: "password"
|
||||||
|
|
Loading…
Reference in a new issue