diff options
Diffstat (limited to 'infra/guix/bundle.sh')
| -rw-r--r-- | infra/guix/bundle.sh | 56 |
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" |
