#!/bin/sh # Copyright (C) 2026 Doan Luu Duc Tai # # 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 . 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"