This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

tangled-infra / deploy / bootstrap.sh
7.1 kB 179 lines
1#!/usr/bin/env bash 2# bootstrap.sh — provision a fresh ubuntu-24.04 box as a tangled.org knot + spindle host. 3# rendered by terraform's templatefile() with values substituted at apply time. 4# idempotent-ish: re-runs are safe but not the primary path. for re-provisioning use `just redeploy`. 5 6set -euo pipefail 7 8OWNER_DID="${owner_did}" 9KNOT_HOSTNAME="${knot_hostname}" 10SPINDLE_HOSTNAME="${spindle_hostname}" 11TANGLED_CORE_TAG="${tangled_core_tag}" 12ADMIN_EMAIL="${admin_email}" 13 14GO_VERSION="1.23.4" 15SOURCE_DIR="/opt/tangled-source" 16 17echo ">>> bootstrap starting at $(date -Iseconds)" 18echo ">>> owner DID: $${OWNER_DID}" 19echo ">>> knot hostname: $${KNOT_HOSTNAME}" 20echo ">>> spindle hostname: $${SPINDLE_HOSTNAME}" 21echo ">>> tangled core tag: $${TANGLED_CORE_TAG}" 22 23# --------------------------------------------------------------------------- 24# docker (required by spindle to spawn step containers) 25# --------------------------------------------------------------------------- 26echo ">>> installing docker" 27install -m 0755 -d /etc/apt/keyrings 28# --batch --yes makes gpg overwrite existing keyring silently (so re-runs work). 29curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ 30 | gpg --batch --yes --dearmor -o /etc/apt/keyrings/docker.gpg 31chmod a+r /etc/apt/keyrings/docker.gpg 32 33. /etc/os-release 34echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $${VERSION_CODENAME} stable" \ 35 > /etc/apt/sources.list.d/docker.list 36 37apt-get update 38apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 39systemctl enable --now docker 40 41# --------------------------------------------------------------------------- 42# go toolchain (to build knot + spindle from source) 43# --------------------------------------------------------------------------- 44echo ">>> installing go $${GO_VERSION}" 45ARCH=$(dpkg --print-architecture) 46case "$${ARCH}" in 47 amd64) GO_ARCH="amd64" ;; 48 arm64) GO_ARCH="arm64" ;; 49 *) echo "unsupported arch: $${ARCH}" >&2; exit 1 ;; 50esac 51curl -fsSL "https://go.dev/dl/go$${GO_VERSION}.linux-$${GO_ARCH}.tar.gz" \ 52 | tar -C /usr/local -xz 53ln -sf /usr/local/go/bin/go /usr/local/bin/go 54ln -sf /usr/local/go/bin/gofmt /usr/local/bin/gofmt 55 56# --------------------------------------------------------------------------- 57# build knot + spindle from @tangled.org/core 58# --------------------------------------------------------------------------- 59echo ">>> cloning tangled core @ $${TANGLED_CORE_TAG}" 60mkdir -p /opt 61# canonical clone URL — verified working via direct probe. 62# retry with backoff to ride out transient knot/appview hiccups. 63CLONE_URL="https://tangled.org/tangled.org/core" 64clone_with_retry() { 65 local attempt 66 for attempt in 1 2 3 4 5; do 67 if [ ! -d "$${SOURCE_DIR}/.git" ]; then 68 if git clone --depth 1 --branch "$${TANGLED_CORE_TAG}" "$${CLONE_URL}" "$${SOURCE_DIR}"; then 69 return 0 70 fi 71 rm -rf "$${SOURCE_DIR}" 72 else 73 if git -C "$${SOURCE_DIR}" fetch --tags && git -C "$${SOURCE_DIR}" checkout "$${TANGLED_CORE_TAG}"; then 74 return 0 75 fi 76 fi 77 echo ">>> clone attempt $${attempt} failed, sleeping $((attempt * 10))s..." 78 sleep $((attempt * 10)) 79 done 80 return 1 81} 82clone_with_retry 83 84echo ">>> building knot" 85cd "$${SOURCE_DIR}" 86CGO_ENABLED=1 go build -o /usr/local/bin/knot ./cmd/knot 87chown root:root /usr/local/bin/knot 88chmod 0755 /usr/local/bin/knot 89 90echo ">>> building spindle" 91CGO_ENABLED=1 go build -o /usr/local/bin/spindle ./cmd/spindle 92chown root:root /usr/local/bin/spindle 93chmod 0755 /usr/local/bin/spindle 94 95# --------------------------------------------------------------------------- 96# knot: git user, env file, repo dir, sshd AuthorizedKeysCommand 97# --------------------------------------------------------------------------- 98echo ">>> setting up knot (git user, env, sshd)" 99if ! id -u git >/dev/null 2>&1; then 100 adduser --disabled-password --gecos "" git 101fi 102 103mkdir -p /home/git/repositories 104chown -R git:git /home/git 105 106cat > /home/git/.knot.env <<EOF 107KNOT_REPO_SCAN_PATH=/home/git/repositories 108KNOT_SERVER_HOSTNAME=$${KNOT_HOSTNAME} 109APPVIEW_ENDPOINT=https://tangled.org 110KNOT_SERVER_OWNER=$${OWNER_DID} 111KNOT_SERVER_INTERNAL_LISTEN_ADDR=127.0.0.1:5444 112KNOT_SERVER_LISTEN_ADDR=127.0.0.1:5555 113KNOT_SERVER_DB_PATH=/home/git/knotserver.db 114EOF 115chown git:git /home/git/.knot.env 116chmod 0640 /home/git/.knot.env 117 118# sshd: AuthorizedKeysCommand for git user — defers to knot for key lookup 119cat > /etc/ssh/sshd_config.d/knot.conf <<'EOF' 120Match User git 121 AuthorizedKeysCommand /usr/local/bin/knot keys -o authorized-keys -git-dir /home/git/repositories 122 AuthorizedKeysCommandUser nobody 123EOF 124systemctl reload ssh 125 126# install + start knot systemd unit 127install -m 0644 /opt/tangled-infra/knot.service /etc/systemd/system/knot.service 128systemctl daemon-reload 129systemctl enable --now knot.service 130 131# --------------------------------------------------------------------------- 132# spindle: spindle user (in docker group), env file, data + log dirs 133# --------------------------------------------------------------------------- 134echo ">>> setting up spindle (user, env, dirs)" 135if ! id -u spindle >/dev/null 2>&1; then 136 adduser --system --group --home /var/lib/spindle --shell /usr/sbin/nologin spindle 137fi 138usermod -aG docker spindle 139 140mkdir -p /var/lib/spindle /var/log/spindle /etc/spindle 141chown -R spindle:spindle /var/lib/spindle /var/log/spindle 142 143cat > /etc/spindle/env <<EOF 144SPINDLE_SERVER_HOSTNAME=$${SPINDLE_HOSTNAME} 145SPINDLE_SERVER_OWNER=$${OWNER_DID} 146SPINDLE_SERVER_LISTEN_ADDR=127.0.0.1:6555 147SPINDLE_SERVER_DB_PATH=/var/lib/spindle/spindle.db 148SPINDLE_PIPELINES_LOG_DIR=/var/log/spindle 149EOF 150chown spindle:spindle /etc/spindle/env 151chmod 0640 /etc/spindle/env 152 153install -m 0644 /opt/tangled-infra/spindle.service /etc/systemd/system/spindle.service 154systemctl daemon-reload 155systemctl enable --now spindle.service 156 157# --------------------------------------------------------------------------- 158# caddy: reverse proxy with letsencrypt for both hostnames 159# --------------------------------------------------------------------------- 160echo ">>> installing caddy" 161curl -fsSL "https://dl.cloudsmith.io/public/caddy/stable/gpg.key" \ 162 | gpg --batch --yes --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg 163curl -fsSL "https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt" \ 164 > /etc/apt/sources.list.d/caddy-stable.list 165apt-get update 166apt-get install -y caddy 167 168install -m 0644 /opt/tangled-infra/Caddyfile /etc/caddy/Caddyfile 169systemctl enable --now caddy 170systemctl reload caddy 171 172# --------------------------------------------------------------------------- 173# done 174# --------------------------------------------------------------------------- 175echo ">>> bootstrap complete at $(date -Iseconds)" 176echo ">>> next steps:" 177echo " 1. point DNS A records for $${KNOT_HOSTNAME} and $${SPINDLE_HOSTNAME} at this server" 178echo " 2. verify the knot at https://tangled.org/settings/knots" 179echo " 3. verify the spindle at https://tangled.org/settings/spindles"