summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVoid Agent <void@jayrup.hermes>2026-07-31 18:52:14 +0100
committerVoid Agent <void@jayrup.hermes>2026-07-31 18:52:14 +0100
commit2885861a92691b8200a9b9a520179d079fbb2c37 (patch)
tree8042f7caca1ac657e86bfc6912f528ba197da2ea
parentea040cf5dadf682e8d7cec581a61baaa7302479b (diff)
harden deploy: strict mode, mktemp build dirs, pinned quarto digest, no fixed /tmp paths
-rwxr-xr-xdeploy-docker.sh15
-rwxr-xr-xdeploy.sh21
-rwxr-xr-xhooks/post-receive6
3 files changed, 30 insertions, 12 deletions
diff --git a/deploy-docker.sh b/deploy-docker.sh
index ce6f4d0..69ccdce 100755
--- a/deploy-docker.sh
+++ b/deploy-docker.sh
@@ -3,8 +3,8 @@
# post-receive hook always uses the deploy logic that matches the pushed tree.
#
# Designed to run ON MERU (docker-only machine) from a git archive snapshot:
-# git archive HEAD | tar -x -C /tmp/build && bash /tmp/build/deploy-docker.sh /tmp/build <sha>
-# Quarto runs inside the official quarto/quarto container; rsync ships
+# git archive HEAD | tar -x -C "$BUILD_DIR" && bash "$BUILD_DIR/deploy-docker.sh" "$BUILD_DIR" <sha>
+# Quarto runs inside the pinned devxygmbh/alpine-quarto container; rsync ships
# public/ to nandi (jayrup.me).
#
# Usage: deploy-docker.sh <build-dir> <short-sha>
@@ -14,7 +14,9 @@ BUILD_DIR="${1:?usage: deploy-docker.sh <build-dir> <short-sha>}"
SHORT_SHA="${2:?missing short sha}"
cd "$BUILD_DIR"
-QUARTO_IMAGE="${QUARTO_IMAGE:-devxygmbh/alpine-quarto:latest}"
+# Pinned digest — update deliberately (docker pull devxygmbh/alpine-quarto:latest
+# then replace the sha256:).
+QUARTO_IMAGE="${QUARTO_IMAGE:-devxygmbh/alpine-quarto@sha256:0c0d785139b467ab75c053bc24463d2450cbf928ca8ece8d9a20dedba9568fa9}"
# Fallback if meru can't reach jayrup.me (IPv6): DEPLOY_HOST=jayrup@100.94.131.98
DEPLOY_HOST="${DEPLOY_HOST:-jayrup.me}"
RUN_UID="$(id -u)"
@@ -22,7 +24,8 @@ RUN_GID="$(id -g)"
# Render script runs INSIDE the container (one container spin, both passes).
# HOME=/tmp so quarto's cache is writable by the unprivileged uid.
-cat > /tmp/homepage-render.sh <<'RENDER_EOF'
+# Written into the private build dir (not /tmp) per review finding.
+cat > "$BUILD_DIR/homepage-render.sh" <<'RENDER_EOF'
#!/usr/bin/env bash
set -euo pipefail
cd /site
@@ -34,7 +37,7 @@ find . -name "*.qmd" -not -path "./.*" -not -path "./public/*" | while read -r f
quarto render "$file" --to plain --output "${base_name}.txt" --output-dir "public/$rel_dir"
done
RENDER_EOF
-chmod +x /tmp/homepage-render.sh
+chmod +x "$BUILD_DIR/homepage-render.sh"
echo ">> rendering with $QUARTO_IMAGE (commit $SHORT_SHA)"
# --entrypoint /bin/bash overrides whatever entrypoint the image declares
@@ -43,7 +46,7 @@ docker run --rm \
-u "$RUN_UID:$RUN_GID" \
-e HOME=/tmp \
-v "$BUILD_DIR":/site \
- -v /tmp/homepage-render.sh:/render.sh:ro \
+ -v "$BUILD_DIR/homepage-render.sh":/render.sh:ro \
-w /site \
"$QUARTO_IMAGE" /render.sh
diff --git a/deploy.sh b/deploy.sh
index 67402ff..5fa8abf 100755
--- a/deploy.sh
+++ b/deploy.sh
@@ -1,7 +1,18 @@
#!/usr/bin/env bash
+# deploy.sh — local native-quarto build + deploy for jayrup.me.
+# For machines with quarto installed natively (e.g. Arch laptop / voidlaptop).
+# The Docker-based path is deploy-docker.sh (used by meru's post-receive hook).
+#
+# Strict mode: a failed render exits BEFORE rsync --delete can touch the VPS.
+set -euo pipefail
-# 1. Clear the old garbage
-rm -rf public/
+# 1. Render into a fresh temp dir so a partial build never gets deployed
+BUILD_DIR="$(mktemp -d /tmp/homepage-local.XXXXXX)"
+trap 'rm -rf "$BUILD_DIR"' EXIT
+cd "$BUILD_DIR"
+git archive --format=tar --output=tree.tar HEAD
+tar xf tree.tar
+rm tree.tar
# 2. Render the whole website (HTML)
# This creates the directories and index.html files correctly
@@ -14,7 +25,7 @@ find . -name "*.qmd" -not -path "./.*" -not -path "./public/*" | while read -r f
rel_dir=$(dirname "${file#./}")
# Get the filename without extension (e.g., index)
base_name=$(basename "$file" .qmd)
-
+
# Render to plain text directly into the correct public sub-directory
quarto render "$file" --to plain --output "${base_name}.txt" --output-dir "public/$rel_dir"
done
@@ -28,6 +39,10 @@ cp cv/index.txt public/cv.txt
cp assets/dissertation.pdf public/dissertation.pdf
cp assets/public_key public/public_key
+# 6. Deploy marker
+printf 'deployed %s commit %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$(git rev-parse --short HEAD)" > public/last-deploy.txt
+
echo "Pushing to vps"
+# Only reached if all renders succeeded (set -e)
rsync -avz --delete public/ jayrup.me:~/homepage/public/
diff --git a/hooks/post-receive b/hooks/post-receive
index 378e777..8096848 100755
--- a/hooks/post-receive
+++ b/hooks/post-receive
@@ -19,9 +19,9 @@ exec > >(tee -a "$LOG") 2>&1
echo "=== post-receive $(date -u +%Y-%m-%dT%H:%M:%SZ) ==="
BARE_DIR="$(cd "$(dirname "$0")/.." && pwd)"
-BUILD_DIR="/tmp/homepage-build"
-rm -rf "$BUILD_DIR"
-mkdir -p "$BUILD_DIR"
+# Private runtime dir — no fixed /tmp paths, cleaned up on exit
+BUILD_DIR="$(mktemp -d /tmp/homepage-build.XXXXXX)"
+trap 'rm -rf "$BUILD_DIR"' EXIT
DEPLOYED=0
while read oldrev newrev ref; do