Flight-booking app scaffolded from the source running on the GCP host, plus the four-screen frontend and three OWASP attack endpoints (SQLi, reflected XSS, path traversal) built and locally verified against a live uvicorn/vite dev pair. Includes deploy.sh (local build -> ship over ssh -> swap on host) and docs/ carried over from the handoff.
124 lines
3.9 KiB
Bash
Executable File
124 lines
3.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Local build -> ship over ssh -> swap on host. No container registry (see docs/DECISIONS.md D8).
|
|
#
|
|
# Run this from a real terminal on your workstation (NOT inside a sandboxed
|
|
# coding-agent shell) with the `gcp-lab` podman connection already configured:
|
|
#
|
|
# podman system connection add gcp-lab \
|
|
# --identity ~/.ssh/google_compute_engine \
|
|
# ssh://matt@35.203.147.44:22/run/user/1001/podman/podman.sock
|
|
#
|
|
# Usage:
|
|
# ./deploy.sh # build both, ship both, swap both containers
|
|
# VERSION=v2 ./deploy.sh # tag images v2 instead of a timestamp
|
|
# ./deploy.sh --build --ship --swap # explicit equivalent of the default
|
|
# ./deploy.sh --restart-caddy # after editing imperva-proxy/Caddyfile
|
|
|
|
set -euo pipefail
|
|
|
|
# --- config -------------------------------------------------------------
|
|
HOST="35.203.147.44"
|
|
HOST_USER="matt"
|
|
SSH_KEY="$HOME/.ssh/google_compute_engine"
|
|
CONNECTION="gcp-lab"
|
|
VERSION="${VERSION:-$(date +%Y%m%d%H%M%S)}"
|
|
REMOTE_PROXY_DIR="/home/matt/imperva-proxy"
|
|
|
|
BACKEND_IMAGE="backend-api"
|
|
FRONTEND_IMAGE="frontend-vue"
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
cd "$SCRIPT_DIR"
|
|
|
|
# --- steps ----------------------------------------------------------------
|
|
|
|
do_build() {
|
|
echo "==> Building ${BACKEND_IMAGE}:${VERSION}"
|
|
podman build -t "${BACKEND_IMAGE}:${VERSION}" -t "${BACKEND_IMAGE}:latest" ./backend
|
|
|
|
echo "==> Building ${FRONTEND_IMAGE}:${VERSION}"
|
|
podman build -t "${FRONTEND_IMAGE}:${VERSION}" -t "${FRONTEND_IMAGE}:latest" ./frontend
|
|
}
|
|
|
|
do_ship() {
|
|
echo "==> Shipping ${BACKEND_IMAGE}:${VERSION} over ssh"
|
|
podman save "${BACKEND_IMAGE}:${VERSION}" | ssh -i "$SSH_KEY" "${HOST_USER}@${HOST}" podman load
|
|
|
|
echo "==> Shipping ${FRONTEND_IMAGE}:${VERSION} over ssh"
|
|
podman save "${FRONTEND_IMAGE}:${VERSION}" | ssh -i "$SSH_KEY" "${HOST_USER}@${HOST}" podman load
|
|
}
|
|
|
|
do_swap() {
|
|
echo "==> Swapping backend-api container"
|
|
podman --connection "$CONNECTION" rm -f backend-api >/dev/null 2>&1 || true
|
|
podman --connection "$CONNECTION" run -d \
|
|
--name backend-api \
|
|
--restart always \
|
|
-p 8000:8000 \
|
|
"${BACKEND_IMAGE}:${VERSION}"
|
|
|
|
echo "==> Swapping frontend-vue container"
|
|
podman --connection "$CONNECTION" rm -f frontend-vue >/dev/null 2>&1 || true
|
|
podman --connection "$CONNECTION" run -d \
|
|
--name frontend-vue \
|
|
--restart always \
|
|
-p 8080:8080 \
|
|
"${FRONTEND_IMAGE}:${VERSION}"
|
|
}
|
|
|
|
do_restart_caddy() {
|
|
echo "==> Copying Caddyfile to host"
|
|
scp -i "$SSH_KEY" ./imperva-proxy/Caddyfile "${HOST_USER}@${HOST}:${REMOTE_PROXY_DIR}/Caddyfile"
|
|
|
|
echo "==> Validating Caddyfile on host"
|
|
podman --connection "$CONNECTION" exec caddy-proxy caddy validate --config /etc/caddy/Caddyfile
|
|
|
|
echo "==> Restarting caddy-proxy"
|
|
podman --connection "$CONNECTION" restart caddy-proxy
|
|
}
|
|
|
|
check_connection() {
|
|
if ! podman system connection list --format '{{.Name}}' 2>/dev/null | grep -qx "$CONNECTION"; then
|
|
echo "error: podman connection '${CONNECTION}' is not configured." >&2
|
|
echo " podman system connection add ${CONNECTION} --identity ${SSH_KEY} ssh://${HOST_USER}@${HOST}:22/run/user/1001/podman/podman.sock" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# --- arg parsing ------------------------------------------------------
|
|
|
|
RUN_BUILD=false
|
|
RUN_SHIP=false
|
|
RUN_SWAP=false
|
|
RUN_RESTART_CADDY=false
|
|
|
|
if [ "$#" -eq 0 ]; then
|
|
RUN_BUILD=true
|
|
RUN_SHIP=true
|
|
RUN_SWAP=true
|
|
else
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--build) RUN_BUILD=true ;;
|
|
--ship) RUN_SHIP=true ;;
|
|
--swap) RUN_SWAP=true ;;
|
|
--restart-caddy) RUN_RESTART_CADDY=true ;;
|
|
*)
|
|
echo "unknown flag: $arg" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
|
|
if [ "$RUN_SHIP" = true ] || [ "$RUN_SWAP" = true ] || [ "$RUN_RESTART_CADDY" = true ]; then
|
|
check_connection
|
|
fi
|
|
|
|
[ "$RUN_BUILD" = true ] && do_build
|
|
[ "$RUN_SHIP" = true ] && do_ship
|
|
[ "$RUN_SWAP" = true ] && do_swap
|
|
[ "$RUN_RESTART_CADDY" = true ] && do_restart_caddy
|
|
|
|
echo "==> Done (version: ${VERSION})"
|