Working restic restore from snapshot id on boot.
This commit is contained in:
3
Makefile
3
Makefile
@@ -110,6 +110,7 @@ all-apps/nassella/lldap-config/lldap_config.toml \
|
|||||||
all-apps/ghost/.compose-env \
|
all-apps/ghost/.compose-env \
|
||||||
restic-env \
|
restic-env \
|
||||||
restic-password \
|
restic-password \
|
||||||
|
restic-restore.sh \
|
||||||
all-apps/.env \
|
all-apps/.env \
|
||||||
$(config_dir)ssh-keys
|
$(config_dir)ssh-keys
|
||||||
cat cl.yaml | docker run --rm --volume $(config_dir)/ssh-keys:/pwd/ssh-keys --volume ${PWD}:/pwd --workdir /pwd -i quay.io/coreos/butane:latest -d /pwd > ignition.json
|
cat cl.yaml | docker run --rm --volume $(config_dir)/ssh-keys:/pwd/ssh-keys --volume ${PWD}:/pwd --workdir /pwd -i quay.io/coreos/butane:latest -d /pwd > ignition.json
|
||||||
@@ -146,7 +147,7 @@ restic-snapshots: $(apps_config) restic-password
|
|||||||
.PHONY: archive
|
.PHONY: archive
|
||||||
archive:
|
archive:
|
||||||
tar -cf nassella-latest.tar all-apps cl.yaml init-restic.sh main.tf make-caddyfile.sh Makefile \
|
tar -cf nassella-latest.tar all-apps cl.yaml init-restic.sh main.tf make-caddyfile.sh Makefile \
|
||||||
make-generated.sh make-nextcloud-env.sh make-ghost-env.sh make-restic-generated.sh make-restic-password.sh restic-snapshots.sh copy-apps.sh \
|
make-generated.sh make-nextcloud-env.sh make-ghost-env.sh make-restic-generated.sh make-restic-password.sh restic-snapshots.sh copy-apps.sh restic-restore.sh \
|
||||||
make-nassella-authelia-config.sh make-nassella-lldap-config.sh .terraform.lock.hcl
|
make-nassella-authelia-config.sh make-nassella-lldap-config.sh .terraform.lock.hcl
|
||||||
cp nassella-latest.tar src/
|
cp nassella-latest.tar src/
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Main App
|
Description=Main App
|
||||||
After=docker.service
|
After=restic-restore.service
|
||||||
Requires=docker.service
|
Requires=docker.service restic-restore.service
|
||||||
[Service]
|
[Service]
|
||||||
TimeoutStartSec=0
|
TimeoutStartSec=0
|
||||||
ExecStart=/bin/bash -c '/usr/bin/docker compose -f /app/docker-compose.yaml $(find /app -mindepth 2 -maxdepth 2 -type f -name docker-compose.yaml -exec echo -f {} \;) up'
|
ExecStart=/bin/bash -c '/usr/bin/docker compose -f /app/docker-compose.yaml $(find /app -mindepth 2 -maxdepth 2 -type f -name docker-compose.yaml -exec echo -f {} \;) up'
|
||||||
|
|||||||
29
cl.yaml
29
cl.yaml
@@ -19,6 +19,21 @@ systemd:
|
|||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
RequiredBy=local-fs.target
|
RequiredBy=local-fs.target
|
||||||
|
- name: restic-restore.service
|
||||||
|
enabled: true
|
||||||
|
contents: |
|
||||||
|
[Unit]
|
||||||
|
Description=Run once on first boot, if needed, to restore a backup
|
||||||
|
After=docker.service
|
||||||
|
Requires=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
EnvironmentFile=/restic-env
|
||||||
|
ExecStart=/restic-restore.sh
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
- name: app.service
|
- name: app.service
|
||||||
enabled: true
|
enabled: true
|
||||||
contents_local: app/app.service
|
contents_local: app/app.service
|
||||||
@@ -31,7 +46,7 @@ systemd:
|
|||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
EnvironmentFile=/restic-env
|
EnvironmentFile=/restic-env
|
||||||
ExecStart=/usr/bin/bash -c "docker run --rm --volume /nassella:/nassella --volume /restic-password:/restic-password -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} -i restic/restic:0.18.0 backup --verbose --repo s3:${BACKBLAZE_BUCKET_URL} --password-file /restic-password /nassella"
|
ExecStart=/usr/bin/bash -c "docker run --rm --volume /nassella:/nassella --volume /restic-password:/restic-password -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} -i restic/restic:0.18.0 backup --verbose --repo s3:${BACKBLAZE_BUCKET_URL} --password-file /restic-password --tag daily_automatic /nassella"
|
||||||
ExecStopPost=systemctl start app.service
|
ExecStopPost=systemctl start app.service
|
||||||
|
|
||||||
- name: restic-backup.timer
|
- name: restic-backup.timer
|
||||||
@@ -91,8 +106,20 @@ storage:
|
|||||||
contents:
|
contents:
|
||||||
local: restic-password
|
local: restic-password
|
||||||
- path: /restic-env
|
- path: /restic-env
|
||||||
|
overwrite: true
|
||||||
contents:
|
contents:
|
||||||
local: restic-env
|
local: restic-env
|
||||||
|
- path: /restic-restore.sh
|
||||||
|
mode: 0755
|
||||||
|
contents:
|
||||||
|
local: restic-restore.sh
|
||||||
|
- path: /etc/ssh/sshd_config.d/custom.conf
|
||||||
|
overwrite: true
|
||||||
|
mode: 0600
|
||||||
|
contents:
|
||||||
|
inline: |
|
||||||
|
PermitRootLogin no
|
||||||
|
AllowUsers core
|
||||||
### docker-compose sysext
|
### docker-compose sysext
|
||||||
### https://flatcar.github.io/sysext-bakery/docker_compose/
|
### https://flatcar.github.io/sysext-bakery/docker_compose/
|
||||||
- path: /opt/extensions/docker-compose/docker-compose-2.34.0-x86-64.raw
|
- path: /opt/extensions/docker-compose/docker-compose-2.34.0-x86-64.raw
|
||||||
|
|||||||
@@ -7,3 +7,7 @@ set -e
|
|||||||
echo "AWS_ACCESS_KEY_ID=\"$BACKBLAZE_KEY_ID\""
|
echo "AWS_ACCESS_KEY_ID=\"$BACKBLAZE_KEY_ID\""
|
||||||
echo "AWS_SECRET_ACCESS_KEY=\"$BACKBLAZE_APPLICATION_KEY\""
|
echo "AWS_SECRET_ACCESS_KEY=\"$BACKBLAZE_APPLICATION_KEY\""
|
||||||
echo "BACKBLAZE_BUCKET_URL=\"$BACKBLAZE_BUCKET_URL\""
|
echo "BACKBLAZE_BUCKET_URL=\"$BACKBLAZE_BUCKET_URL\""
|
||||||
|
|
||||||
|
if [ -n "$RESTIC_SNAPSHOT_ID" ]; then
|
||||||
|
echo "RESTIC_SNAPSHOT_ID=\"$RESTIC_SNAPSHOT_ID\""
|
||||||
|
fi
|
||||||
|
|||||||
8
restic-restore.sh
Normal file
8
restic-restore.sh
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
MARKER=/var/lib/firstboot.done
|
||||||
|
|
||||||
|
if [ ! -f "$MARKER" ] && [ -n "$RESTIC_SNAPSHOT_ID" ]; then
|
||||||
|
docker run --rm --volume /nassella:/nassella --volume /restic-password:/restic-password -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} -i restic/restic:0.18.0 restore "$RESTIC_SNAPSHOT_ID" --verbose --repo s3:${BACKBLAZE_BUCKET_URL} --password-file /restic-password --target /
|
||||||
|
fi
|
||||||
|
|
||||||
|
touch "$MARKER"
|
||||||
@@ -1304,6 +1304,7 @@ chmod -R 777 /opt/keys")))
|
|||||||
(get-most-recent-deployment-status db (session-user-id) instance-id)))))))
|
(get-most-recent-deployment-status db (session-user-id) instance-id)))))))
|
||||||
(when (not (or (eq? status 'queued) (eq? status 'in-progress)))
|
(when (not (or (eq? status 'queued) (eq? status 'in-progress)))
|
||||||
(let* ((instance-id (alist-ref "id" (current-params) equal?))
|
(let* ((instance-id (alist-ref "id" (current-params) equal?))
|
||||||
|
(restic-snapshot-id (alist-ref 'restic-snapshot-id (current-params)))
|
||||||
(results
|
(results
|
||||||
(with-db/transaction
|
(with-db/transaction
|
||||||
(lambda (db)
|
(lambda (db)
|
||||||
@@ -1372,7 +1373,8 @@ chmod -R 777 /opt/keys")))
|
|||||||
("BACKBLAZE_KEY_ID" . ,(alist-ref 'backblaze-key-id service-config))
|
("BACKBLAZE_KEY_ID" . ,(alist-ref 'backblaze-key-id service-config))
|
||||||
("BACKBLAZE_APPLICATION_KEY" . ,(alist-ref 'backblaze-application-key service-config))
|
("BACKBLAZE_APPLICATION_KEY" . ,(alist-ref 'backblaze-application-key service-config))
|
||||||
("BACKBLAZE_BUCKET_URL" . ,(alist-ref 'backblaze-bucket-url service-config))
|
("BACKBLAZE_BUCKET_URL" . ,(alist-ref 'backblaze-bucket-url service-config))
|
||||||
("RESTIC_PASSWORD" . ,restic-password)))))
|
("RESTIC_PASSWORD" . ,restic-password)
|
||||||
|
,@(if (and restic-snapshot-id (not (string=? restic-snapshot-id ""))) `(("RESTIC_SNAPSHOT_ID" . ,restic-snapshot-id)) '())))))
|
||||||
(with-output-to-file (string-append dir "/config/production.tfvars")
|
(with-output-to-file (string-append dir "/config/production.tfvars")
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(map (lambda (e)
|
(map (lambda (e)
|
||||||
@@ -1526,7 +1528,8 @@ chmod -R 777 /opt/keys")))
|
|||||||
,(alist-ref 'instance-id instance)))
|
,(alist-ref 'instance-id instance)))
|
||||||
"Modify Setup"))
|
"Modify Setup"))
|
||||||
(li "Upgrade Now (pending automatic upgrades scheduled for: )")
|
(li "Upgrade Now (pending automatic upgrades scheduled for: )")
|
||||||
(li "Manage Backups")
|
(li (a (@ (href "/backups/" ,(alist-ref 'instance-id instance)))
|
||||||
|
"Manage Backups"))
|
||||||
(li (a (@ (href "/destroy/" ,(alist-ref 'instance-id instance)))
|
(li (a (@ (href "/destroy/" ,(alist-ref 'instance-id instance)))
|
||||||
"Destroy - deletes data and configuration (confirmation required)"))
|
"Destroy - deletes data and configuration (confirmation required)"))
|
||||||
(li (a (@ (href "/reset/" ,(alist-ref 'instance-id instance)))
|
(li (a (@ (href "/reset/" ,(alist-ref 'instance-id instance)))
|
||||||
@@ -1744,6 +1747,27 @@ chmod -R 777 /opt/keys")))
|
|||||||
,output)))
|
,output)))
|
||||||
)))))
|
)))))
|
||||||
|
|
||||||
|
(get/widgets
|
||||||
|
("/backups/:id")
|
||||||
|
(let* ((instance-id (alist-ref "id" (current-params) equal?))
|
||||||
|
;; (res (with-db/transaction
|
||||||
|
;; (lambda (db)
|
||||||
|
;; `((status . ,(get-most-recent-deployment-status db (session-user-id) instance-id))
|
||||||
|
;; (progress . ,(get-most-recent-deployment-progress db (session-user-id) instance-id))))))
|
||||||
|
)
|
||||||
|
`(App
|
||||||
|
(Main-Container
|
||||||
|
(VStack
|
||||||
|
(h1 "Backups")
|
||||||
|
(a (@ (href "/")) "Create Snapshot") ;; TODO
|
||||||
|
(table
|
||||||
|
(thead
|
||||||
|
(tr (th "Time") (th "Size") (th "Tag") (th "*")))
|
||||||
|
(tbody
|
||||||
|
(tr (td "2026-04-22 22:24:41") (td "139.742 MiB") (td "") (td (a (@ (href "/")) "Restore")))
|
||||||
|
(tr (td "2026-04-21 12:01:03") (td "139.742 MiB") (td "before upgrade") (td (a (@ (href "/")) "Restore")))
|
||||||
|
(tr (td "2026-04-21 22:24:41") (td "129.742 MiB") (td "") (td (a (@ (href "/")) "Restore"))))))))))
|
||||||
|
|
||||||
(schematra-install)
|
(schematra-install)
|
||||||
|
|
||||||
))
|
))
|
||||||
|
|||||||
Reference in New Issue
Block a user