anvilsign in

collin/anvil

1#!/usr/bin/env bash
2# (Re)start the anvil container on hagrid from an ALREADY-LOADED image.
3#
4# Build and ship the image first with deploy/build.sh on a capable machine
5# (the VPS can't compile it). This script only runs docker — no build — so it's
6# safe on the low-RAM box. Standalone: needs only docker + the loaded image.
7set -euo pipefail
8
9IMAGE="${ANVIL_IMAGE:-anvil:latest}"
10NETWORK="${ANVIL_NETWORK:-hagrid}"
11SSH_PORT="${ANVIL_SSH_PORT:-22}"
12# Publish SSH on the droplet's DEFAULT public IPv4 only. The reserved IP
13# (137.184.249.48) is reached via the anchor IP 10.15.0.6, where the host's
14# own sshd listens — binding a specific IP here keeps the two off each other.
15SSH_BIND_IP="${ANVIL_SSH_BIND_IP:-165.232.162.167}"
16DOCKER_SOCK="${ANVIL_DOCKER_SOCK:-/var/run/docker.sock}"
17
18# The CI runner drives Docker via the host socket. Mount it in, and add the
19# socket's group to the non-root `anvil` user so it can actually open it.
20# NOTE: socket access = root-equivalent on the host. We accept this because
21# anvil is a single-tenant, owner-operated forge; CI only runs code the owner
22# pushed. Do not expose this instance to untrusted users.
23SOCK_GID="$(stat -c '%g' "$DOCKER_SOCK")"
24
25# Single sign-on's client secret, if this instance uses one (docs/oidc.md).
26#
27# Read from a file on the host by default, because deploy/deploy.sh pipes this
28# script over ssh (`ssh host 'bash -s' < run.sh`) and no environment travels
29# with it — an env var alone would silently vanish on exactly the path that
30# matters. ANVIL_OIDC_CLIENT_SECRET still wins when running this by hand.
31#
32# Passed only when non-empty: an empty value would override the baked config
33# with "no secret" and turn a confidential client into a public one.
34OIDC_SECRET_FILE="${ANVIL_OIDC_SECRET_FILE:-$HOME/.config/anvil/oidc-client-secret}"
35OIDC_SECRET="${ANVIL_OIDC_CLIENT_SECRET:-}"
36if [[ -z "$OIDC_SECRET" && -r "$OIDC_SECRET_FILE" ]]; then
37 OIDC_SECRET="$(tr -d '[:space:]' <"$OIDC_SECRET_FILE")"
38fi
39
40OIDC_ENV=()
41if [[ -n "$OIDC_SECRET" ]]; then
42 OIDC_ENV=(-e "ANVIL_OIDC_CLIENT_SECRET=${OIDC_SECRET}")
43 echo "==> single sign-on: client secret loaded"
44else
45 echo "==> single sign-on: no client secret found (${OIDC_SECRET_FILE})"
46fi
47
48docker rm -f anvil 2>/dev/null || true
49docker run -d \
50 --name anvil \
51 --network "$NETWORK" \
52 --restart unless-stopped \
53 -p "${SSH_BIND_IP}:${SSH_PORT}:2222" \
54 -v anvil-data:/data \
55 -v "${DOCKER_SOCK}:/var/run/docker.sock" \
56 --group-add "$SOCK_GID" \
57 -v "$(cd "$(dirname "$0")" && pwd)/anvil.toml:/etc/anvil/anvil.toml:ro" \
58 "${OIDC_ENV[@]}" \
59 "$IMAGE"
60
61echo "==> anvil (re)started from $IMAGE (web: anvil:3000 via Caddy, ssh: ${SSH_BIND_IP}:${SSH_PORT}, docker.sock gid ${SOCK_GID})"