summaryrefslogtreecommitdiff
path: root/infra/guix/bundle.sh
diff options
context:
space:
mode:
Diffstat (limited to 'infra/guix/bundle.sh')
-rw-r--r--infra/guix/bundle.sh56
1 files changed, 56 insertions, 0 deletions
diff --git a/infra/guix/bundle.sh b/infra/guix/bundle.sh
new file mode 100644
index 0000000..c6d5bb0
--- /dev/null
+++ b/infra/guix/bundle.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+# Copyright (C) 2026 Doan Luu Duc Tai <doan@luuduct.ai>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+set -eu
+umask 077
+[ "$#" = 3 ] || { echo 'Usage: sh infra/guix/bundle.sh BACKUP.tar.gz.gpg RELEASE.tar.gz OUTPUT.tar.gz' >&2; exit 1; }
+[ -f "$1" ] || { echo 'Encrypted backup missing.' >&2; exit 1; }
+case "$1" in *.tar.gz.gpg) ;; *) echo 'Requires an encrypted stack backup.' >&2; exit 1 ;; esac
+[ -f "$2" ] || { echo 'Trusted release missing.' >&2; exit 1; }
+case "$2" in *.tar.gz) ;; *) echo 'Requires a trusted public release archive.' >&2; exit 1 ;; esac
+case "$3" in *.tar.gz) ;; *) echo 'Output must end in .tar.gz.' >&2; exit 1 ;; esac
+[ ! -e "$3" ] || { echo 'Output already exists.' >&2; exit 1; }
+STAGE=$(mktemp -d "$(dirname -- "$3")/.recovery.XXXXXX")
+trap 'rm -rf -- "$STAGE"' EXIT HUP INT TERM
+tar -xOf "$2" stack/bin/stack > "$STAGE/verify"
+chmod 700 "$STAGE/verify"
+"$STAGE/verify" restore --release "$2" "$STAGE/release"
+RELEASE="$STAGE/release"
+[ ! -e "$RELEASE/.env" ] && [ ! -e "$RELEASE/var/data" ] || {
+ echo 'Release contains private application state; refusing plaintext publication.' >&2; exit 1;
+}
+for FILE in bin/stack bin/guix-runtime.tar.gz bin/guix-channels.scm \
+ bin/chat/server bin/chat/crypto.wasm bin/chat/SOURCE.tar.gz infra/services.toml \
+ infra/guix/bootstrap.sh infra/guix/restore.sh infra/guix/run.sh \
+ infra/guix/containers.conf var/image-lock.json var/images.tar LICENSE; do
+ [ -f "$RELEASE/$FILE" ] || { echo "Release missing $FILE; build a complete release first." >&2; exit 1; }
+done
+mkdir "$STAGE/stack-recovery"
+cp -- "$1" "$STAGE/stack-recovery/backup.tar.gz.gpg"
+cp -- "$2" "$STAGE/stack-recovery/release.tar.gz"
+cp -- "$RELEASE/bin/stack" "$STAGE/stack-recovery/stack"
+cp -- "$RELEASE/bin/guix-runtime.tar.gz" "$STAGE/stack-recovery/runtime.tar.gz"
+cp -- "$RELEASE/bin/guix-channels.scm" "$STAGE/stack-recovery/channels.scm"
+cp -- "$RELEASE/infra/guix/restore.sh" "$STAGE/stack-recovery/restore"
+cp -- "$RELEASE/infra/guix/bootstrap.sh" "$STAGE/stack-recovery/bootstrap"
+cp -- "$RELEASE/infra/guix/run.sh" "$STAGE/stack-recovery/run"
+cp -- "$RELEASE/infra/guix/containers.conf" "$STAGE/stack-recovery/containers.conf"
+cp -- "$RELEASE/LICENSE" "$STAGE/stack-recovery/LICENSE"
+chmod 700 "$STAGE/stack-recovery/restore" "$STAGE/stack-recovery/bootstrap" "$STAGE/stack-recovery/run" "$STAGE/stack-recovery/stack"
+(cd "$STAGE/stack-recovery" && sha256sum backup.tar.gz.gpg release.tar.gz stack runtime.tar.gz channels.scm restore bootstrap run containers.conf LICENSE > SHA256SUMS)
+tar -czf "$STAGE/bundle.tar.gz" -C "$STAGE" stack-recovery
+ln -- "$STAGE/bundle.tar.gz" "$3"
+printf 'Recovery bundle: %s\n' "$3"