diff --git a/deploy/README.md b/deploy/README.md index 33c5da7..a544dc4 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -44,11 +44,18 @@ Everything is overridable from the environment: | `SERVICE_USER` | `lembas` | system account to run as | | `HOME_DIR` | `/home/lembas` | that account's home | | `PREFIX` | `/srv/lembas` | install root (bind mount of `HOME_DIR`) | -| `REPO_URL` | this checkout's `origin` | so a fork deploys itself | +| `REPO_URL` | this checkout's `origin` | so a fork deploys itself. **Must be https** — see below | | `LEMBAS_BRANCH` | `main` | branch to fetch, and what the `edge` channel follows | | `LEMBAS_CHANNEL` | `stable` | `stable` follows release tags, `edge` follows the branch tip | | `INSTALL_UPDATE_HELPER` | `0` | `1` lets the web interface deploy that branch as root | +**The deployment fetches over HTTPS, on purpose.** The service user has no SSH +key and should not have one: a credential that can push to the repository, +sitting on a box, to do a read-only job. If you push over SSH your checkout's +`origin` is an `ssh://` URL, which is the one thing that cannot work here — so +the installer refuses it and names the fix rather than letting the clone fail +with `Permission denied (publickey)` from an account you were not thinking about. + ## Channels | | follows | for | diff --git a/deploy/install.sh b/deploy/install.sh index 956de11..04f9b73 100755 --- a/deploy/install.sh +++ b/deploy/install.sh @@ -48,6 +48,23 @@ if [[ -z "$REPO_URL" ]]; then exit 1 fi +# The deployment clones as the service user, which has no SSH key and should not +# have one: a credential that can push to the repository, sitting on a box, to +# do a read-only job. Whoever runs this usually has an ssh:// origin because +# *they* push over SSH, so the default inherited from their checkout is the one +# thing that cannot work here. +# +# The clone would fail loudly anyway. Saying so first turns "Permission denied +# (publickey)" from the service user into a sentence that names the fix. +if [[ "$REPO_URL" == ssh://* || "$REPO_URL" == git@* ]]; then + echo "== repository ==" >&2 + echo " $REPO_URL is an SSH URL, and $SERVICE_USER has no key." >&2 + echo " Set an https URL, which is what a deployment should fetch over:" >&2 + echo " REPO_URL=https://host/owner/repo.git $0" >&2 + echo " (Or give $SERVICE_USER a read-only deploy key and re-run.)" >&2 + exit 1 +fi + echo "== plan ==" echo " host : https://$SITE_HOST -> 127.0.0.1:$APP_PORT" echo " user : $SERVICE_USER ($HOME_DIR)" diff --git a/deploy/update.sh b/deploy/update.sh index cb8728d..38a8d08 100755 --- a/deploy/update.sh +++ b/deploy/update.sh @@ -41,8 +41,13 @@ git_as fetch --quiet --tags --force origin "$BRANCH" # onto a release candidate on the strength of a hyphen. target="origin/$BRANCH" if [[ "$CHANNEL" == "stable" ]]; then + # `|| true` is load-bearing under `set -euo pipefail`, and for two reasons: + # grep exits 1 when nothing matches -- which is every host until the first + # release is tagged -- and `head -1` closing the pipe early can hand grep a + # SIGPIPE. Either kills the script mid-update, after the fetch and before the + # reset, leaving the checkout fetched and unmoved with no error printed. newest=$(git_as tag --list --sort=-v:refname \ - | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | head -1) + | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | head -1 || true) if [[ -n "$newest" ]]; then target="$newest" else