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.
96 lines
4.0 KiB
Markdown
96 lines
4.0 KiB
Markdown
# Deploy Workflow
|
|
|
|
Local code → finished image shipped over SSH → container swapped on the host. No
|
|
container registry (see DECISIONS.md D8 for why).
|
|
|
|
## The two channels to the host
|
|
|
|
Both go to the same GCP box; they're used for different steps:
|
|
|
|
- **`podman save … | ssh … podman load`** — ships the image *bytes*. This has to use
|
|
raw `ssh` because it's a pipe into the remote Podman CLI.
|
|
- **`podman --connection gcp-lab …`** — swaps the running container over the existing
|
|
rootless socket, hands-free (no manual SSH). The alias is already configured and set
|
|
as default:
|
|
`ssh://matt@35.203.147.44:22/run/user/1001/podman/podman.sock`.
|
|
|
|
> The socket is under **UID 1001** on this host (the original architecture doc's 1000 is
|
|
> wrong). Using the alias means you never have to think about the UID.
|
|
|
|
## Why build locally
|
|
|
|
The `e2-micro` can't build the Vue multi-stage image reliably (memory). Always build on
|
|
the local workstation and ship the finished image. Never build on the host.
|
|
|
|
## `deploy.sh`
|
|
|
|
Lives at the repo root and is run from there (so the relative `./backend` and
|
|
`./frontend` build contexts resolve). Config block at the top holds host/user/key/alias.
|
|
|
|
Usage:
|
|
|
|
```bash
|
|
./deploy.sh # full cycle: build both, ship both, swap both containers
|
|
VERSION=v2 ./deploy.sh # tag images v2 instead of a timestamp → named rollback point
|
|
./deploy.sh --build --ship --swap # explicit equivalent of the default
|
|
./deploy.sh --restart-caddy # after editing the Caddyfile to add/modify routes
|
|
```
|
|
|
|
With no arguments it runs `build → ship → swap`. `VERSION` defaults to a timestamp; set
|
|
it explicitly to create a named point you can redeploy later.
|
|
|
|
## Steps the script performs
|
|
|
|
1. **build** — `podman build` the backend and frontend images locally.
|
|
2. **ship** — `podman save <img> | ssh -i <key> matt@35.203.147.44 'podman load'` for
|
|
each image.
|
|
3. **swap** — over `--connection gcp-lab`: `rm -f` then `run -d` each container with its
|
|
name and port mapping.
|
|
4. **restart-caddy** (on demand) — `podman --connection gcp-lab restart caddy-proxy`,
|
|
needed only when the Caddyfile changed (e.g. new XSS/traversal routes).
|
|
|
|
## IMPORTANT: keep `swap()` in sync with real run flags
|
|
|
|
The current `swap()` recreates containers with only `--name` and `-p`. It does **not**
|
|
yet reproduce any bind mounts (e.g. the SQLite `demo.db`), config-file mounts, or
|
|
network/DNS-alias flags the real containers depend on. **Before relying on the script,
|
|
confirm the actual `podman run` flags** the current `backend-api` and `frontend-vue`
|
|
were created with and fold them into `swap()`, or a deploy will silently drop them.
|
|
|
|
To inspect what the running containers actually use:
|
|
|
|
```bash
|
|
podman --connection gcp-lab inspect backend-api | jq '.[0].Mounts, .[0].NetworkSettings'
|
|
podman --connection gcp-lab inspect frontend-vue | jq '.[0].Mounts, .[0].NetworkSettings'
|
|
```
|
|
|
|
## Caddy config / cert deploys
|
|
|
|
The Caddyfile and certs live on the host at `~/imperva-proxy/` and are bind-mounted
|
|
read-only into `caddy-proxy`. To change routing:
|
|
|
|
1. Edit `imperva-proxy/Caddyfile` in the repo, copy it to the host `~/imperva-proxy/`.
|
|
2. Validate before restarting so you're not debugging from a crash loop:
|
|
```bash
|
|
podman --connection gcp-lab exec caddy-proxy caddy validate --config /etc/caddy/Caddyfile
|
|
```
|
|
3. `./deploy.sh --restart-caddy`.
|
|
|
|
If the container is already crash-looping and `exec` won't attach, validate against the
|
|
mount with a throwaway container instead:
|
|
|
|
```bash
|
|
podman run --rm -v /home/matt/imperva-proxy/Caddyfile:/etc/caddy/Caddyfile:ro,Z \
|
|
docker.io/library/caddy:2-alpine caddy validate --config /etc/caddy/Caddyfile
|
|
```
|
|
|
|
## Verifying a deploy
|
|
|
|
- Origin health from the host (self-signed, so `-k`):
|
|
```bash
|
|
podman --connection gcp-lab exec caddy-proxy sh -c 'wget -qO- --no-check-certificate https://localhost/ | head'
|
|
```
|
|
(or `curl -vk https://localhost/` directly on the host)
|
|
- Real path end to end: load `https://flytoouter.space/` in a browser — should show
|
|
Imperva's trusted edge cert while the origin serves self-signed to Imperva only.
|