migrate bootstrap.sh from bw to bws, update docs

This commit is contained in:
2026-03-18 19:04:22 -04:00
parent 00ab7d1b8d
commit ef7fe7677c
5 changed files with 92 additions and 55 deletions
+21 -9
View File
@@ -21,18 +21,30 @@ A separate server running the Gitea instance. Provides:
- Gitea Actions CI/CD (runner registered at site level) - Gitea Actions CI/CD (runner registered at site level)
- Organization-level secrets and variables shared across repos - Organization-level secrets and variables shared across repos
### Bitwarden (cloud) ### Bitwarden Secrets Manager (cloud)
Bitwarden free tier is used as the secret store. Stores: Secrets are stored in Bitwarden Secrets Manager (free tier, project: `hantim`).
The `bws` CLI fetches secrets using machine account access tokens.
- `hantim-ci-registry-push` -- Gitea API token for registry access (Secure Note) - `hantim-ci-registry-push` -- Gitea API token for registry access
- `hantim-server-deploy` -- deploy user SSH key pair (SSH Key) - `hantim-deploy-ssh-private-key` -- deploy user SSH private key
- `hantim-new-app-script` -- Gitea API token for creating repos (Secure Note) - `hantim-deploy-ssh-public-key` -- deploy user SSH public key
- `hantim-vultr-api-key` -- Vultr API key for DNS management (Secure Note) - `hantim-new-app-script` -- Gitea API token for creating repos
- `argento-garage` -- Garage rpc_secret, argento_node_id, S3 keys (Secure Note) - `hantim-vultr-api-key` -- Vultr API key for DNS management
The Bitwarden CLI (`bw`) is used in `bootstrap.sh` (on the server) and Machine accounts:
`new-app.sh` (on dev machines) to fetch secrets at runtime. - `hantim-server` -- used by `bootstrap.sh` and `configure.sh` on the server
(access token at `/etc/bws-token`)
- `hantim-ci` -- reserved for future CI use
### Gitea secrets
Workflow secrets stored in the `hantim` Gitea org. These duplicate some
Bitwarden secrets for direct use in CI workflows without installing `bws`:
- `DEPLOY_SSH_KEY` -- deploy SSH private key
- `CI_REGISTRY_TOKEN` -- Gitea registry token
- `DEPLOY_HOST` -- server IP (variable, not secret)
## Repos ## Repos
+10 -6
View File
@@ -31,12 +31,16 @@ Actions workflows.
## Secrets ## Secrets
Stored in Bitwarden (free tier), fetched via `bw` CLI: Bitwarden Secrets Manager (project: `hantim`, fetched via `bws` CLI):
- `hantim-ci-registry-push` -- Secure Note (Gitea registry token) - `hantim-ci-registry-push` -- Gitea registry token (used by bootstrap.sh)
- `hantim-server-deploy` -- SSH Key (deploy user key pair) - `hantim-deploy-ssh-private-key` -- deploy user SSH private key (used by new-app.sh)
- `hantim-new-app-script` -- Secure Note (Gitea API token for creating repos) - `hantim-deploy-ssh-public-key` -- deploy user SSH public key (used by bootstrap.sh)
- `hantim-vultr-api-key` -- Secure Note (Vultr API key for DNS management) - `hantim-new-app-script` -- Gitea API token for creating repos (used by new-app.sh)
- `argento-garage` -- Secure Note (Garage rpc_secret, argento_node_id, S3 keys) - `hantim-vultr-api-key` -- Vultr API key for DNS management (used by new-app.sh)
Machine accounts:
- `hantim-server` -- access token stored at `/etc/bws-token` on hantim
- `hantim-ci` -- access token stored as Gitea secret (reserved for future use)
Gitea org-level (`hantim`) secrets/variables: Gitea org-level (`hantim`) secrets/variables:
- `DEPLOY_HOST` -- Variable (server IP) - `DEPLOY_HOST` -- Variable (server IP)
+20 -20
View File
@@ -38,12 +38,13 @@ bash /opt/hantim/scripts/bootstrap.sh
`bootstrap.sh` runs once manually. It: `bootstrap.sh` runs once manually. It:
1. Installs system dependencies (jq, certbot, Node.js 20, Docker) 1. Installs system dependencies (jq, certbot, unzip, Docker)
2. Installs and authenticates the Bitwarden CLI 2. Installs the `bws` CLI (Bitwarden Secrets Manager)
3. Fetches the Docker registry token and deploy SSH public key from Bitwarden 3. Prompts for a Bitwarden Secrets Manager access token (saved to `/etc/bws-token`)
4. Logs into the Gitea Docker registry 4. Fetches the Docker registry token and deploy SSH public key via `bws`
5. Creates the `deploy` user with restricted SSH access and sudo 5. Logs into the Gitea Docker registry
6. Runs `configure.sh` (firewall, certbot, start services) 6. Creates the `deploy` user with restricted SSH access and sudo
7. Runs `configure.sh` (firewall, certbot, start services)
`configure.sh` is idempotent and CI-safe. It: `configure.sh` is idempotent and CI-safe. It:
@@ -51,8 +52,9 @@ bash /opt/hantim/scripts/bootstrap.sh
2. Sets up certbot and issues SSL certificates for all configured domains 2. Sets up certbot and issues SSL certificates for all configured domains
3. Starts all services (nginx first, then all apps) 3. Starts all services (nginx first, then all apps)
**Prerequisites**: DNS for all configured domains must point to the server **Prerequisites**:
before running bootstrap. - DNS for all configured domains must point to the server
- Bitwarden Secrets Manager access token for the `hantim-server` machine account
## Adding a new app ## Adding a new app
@@ -100,24 +102,22 @@ Run the same three commands as provisioning. `bootstrap.sh` is idempotent:
## Secrets ## Secrets
The following are stored in Bitwarden and fetched automatically by `bootstrap.sh`: Bitwarden Secrets Manager (project: `hantim`, fetched via `bws` CLI on the server):
| Bitwarden item | Type | Purpose | | Secret | Purpose | Used by |
|---|---|---| |---|---|---|
| `hantim-ci-registry-push` | Secure Note | Gitea token for Docker registry | | `hantim-ci-registry-push` | Gitea token for Docker registry | `bootstrap.sh` |
| `hantim-server-deploy` | SSH Key | Deploy user's SSH key | | `hantim-deploy-ssh-public-key` | Deploy user's SSH public key | `bootstrap.sh` |
| `hantim-deploy-ssh-private-key` | Deploy user's SSH private key | `new-app.sh` |
| `hantim-new-app-script` | Gitea API token for creating repos | `new-app.sh` |
| `hantim-vultr-api-key` | Vultr API key for DNS management | `new-app.sh` |
The following are configured in the `hantim` Gitea org settings: Machine accounts: `hantim-server` (token at `/etc/bws-token`), `hantim-ci` (reserved).
Gitea org-level (`hantim`) secrets/variables:
| Name | Type | Purpose | | Name | Type | Purpose |
|---|---|---| |---|---|---|
| `DEPLOY_HOST` | Variable | Server IP or hostname | | `DEPLOY_HOST` | Variable | Server IP or hostname |
| `DEPLOY_SSH_KEY` | Secret | SSH private key for the deploy user | | `DEPLOY_SSH_KEY` | Secret | SSH private key for the deploy user |
| `CI_REGISTRY_TOKEN` | Secret | Gitea token for Docker registry login | | `CI_REGISTRY_TOKEN` | Secret | Gitea token for Docker registry login |
The following are stored in Bitwarden and used by `new-app.sh`:
| Bitwarden item | Type | Purpose |
|---|---|---|
| `hantim-new-app-script` | Secure Note | Gitea API token for creating repos |
| `hantim-vultr-api-key` | Secure Note | Vultr API key for DNS management |
+4 -3
View File
@@ -11,8 +11,9 @@ bash /opt/hantim/scripts/bootstrap.sh
``` ```
**What happens:** **What happens:**
- Installs all dependencies (jq, certbot, Node.js 20, Docker, bw CLI) - Installs all dependencies (jq, certbot, unzip, Docker)
- Fetches secrets from Bitwarden (registry token, deploy SSH key) - Installs `bws` CLI, prompts for Bitwarden Secrets Manager access token
- Fetches registry token and deploy SSH public key via `bws`
- Logs into Docker registry - Logs into Docker registry
- Creates deploy user with restricted SSH + sudo - Creates deploy user with restricted SSH + sudo
- Runs `configure.sh`: - Runs `configure.sh`:
@@ -22,7 +23,7 @@ bash /opt/hantim/scripts/bootstrap.sh
**Prerequisites:** **Prerequisites:**
- DNS for all configured domains must point to the server - DNS for all configured domains must point to the server
- Bitwarden vault must contain: `hantim-ci-registry-push`, `hantim-server-deploy` - Bitwarden Secrets Manager access token for the `hantim-server` machine account
- Docker images must exist in the Gitea registry (or apps will start on next push) - Docker images must exist in the Gitea registry (or apps will start on next push)
## 2. Restore from backup ## 2. Restore from backup
+37 -17
View File
@@ -10,8 +10,16 @@ set -euo pipefail
# 2. git clone https://git.timothykim.net/hantim/hantim-server.git /opt/hantim # 2. git clone https://git.timothykim.net/hantim/hantim-server.git /opt/hantim
# 3. bash /opt/hantim/scripts/bootstrap.sh # 3. bash /opt/hantim/scripts/bootstrap.sh
# #
# Prerequisites:
# - Bitwarden Secrets Manager access token for the hantim-server machine account
REPO_DIR="/opt/hantim" REPO_DIR="/opt/hantim"
BWS_TOKEN_FILE="/etc/bws-token"
BWS_VERSION="2.0.0"
# Secret IDs (Bitwarden Secrets Manager)
SECRET_REGISTRY_TOKEN="43f4a77d-7bb4-49ad-8044-b411016c5c6e"
SECRET_DEPLOY_PUBKEY="945760dd-90e2-46e5-98ad-b411016e3f3b"
# --- Prerequisites --- # --- Prerequisites ---
@@ -32,29 +40,41 @@ echo "==> Upgrading system packages..."
dnf upgrade -y dnf upgrade -y
echo "==> Installing dependencies..." echo "==> Installing dependencies..."
dnf install -y jq epel-release dnf install -y jq epel-release unzip
dnf install -y certbot dnf install -y certbot
dnf module reset -y nodejs
dnf module install -y nodejs:20/common
BW_CLI="$(npm config get prefix)/bin/bw" # --- Install bws CLI ---
if [ ! -x "$BW_CLI" ]; then
echo "==> Installing Bitwarden CLI..." if ! command -v bws &>/dev/null; then
npm install -g @bitwarden/cli echo "==> Installing Bitwarden Secrets Manager CLI..."
curl -sL "https://github.com/bitwarden/sdk-sm/releases/download/bws-v${BWS_VERSION}/bws-x86_64-unknown-linux-gnu-${BWS_VERSION}.zip" -o /tmp/bws.zip
unzip -o /tmp/bws.zip -d /usr/local/bin
chmod +x /usr/local/bin/bws
rm /tmp/bws.zip
fi fi
# --- Fetch secrets from Bitwarden --- # --- Set up access token ---
echo "==> Fetching secrets from Bitwarden..." if [ ! -f "$BWS_TOKEN_FILE" ]; then
echo " Log in to Bitwarden when prompted." echo "==> Bitwarden Secrets Manager access token required."
if "$BW_CLI" status 2>/dev/null | grep -q '"status":"unauthenticated"'; then echo " Generate one for the hantim-server machine account at:"
"$BW_CLI" login echo " https://vault.bitwarden.com/#/sm/machine-accounts"
read -rp " Paste access token: " BWS_TOKEN
if [ -z "$BWS_TOKEN" ]; then
echo "ERROR: Access token cannot be empty."
exit 1
fi fi
BW_SESSION=$("$BW_CLI" unlock --raw) echo "$BWS_TOKEN" > "$BWS_TOKEN_FILE"
"$BW_CLI" sync --session "$BW_SESSION" chmod 600 "$BWS_TOKEN_FILE"
REGISTRY_TOKEN=$("$BW_CLI" get notes hantim-ci-registry-push --session "$BW_SESSION") fi
DEPLOY_PUBKEY=$("$BW_CLI" get item hantim-server-deploy --session "$BW_SESSION" | jq -r '.sshKey.publicKey') export BWS_ACCESS_TOKEN
"$BW_CLI" lock BWS_ACCESS_TOKEN=$(cat "$BWS_TOKEN_FILE")
# --- Fetch secrets ---
echo "==> Fetching secrets from Bitwarden Secrets Manager..."
REGISTRY_TOKEN=$(bws secret get "$SECRET_REGISTRY_TOKEN" | jq -r .value)
DEPLOY_PUBKEY=$(bws secret get "$SECRET_DEPLOY_PUBKEY" | jq -r .value)
# --- Install Docker --- # --- Install Docker ---