Files
probo/contrib/lima/provision.sh
2026-04-29 12:48:43 +04:00

253 lines
7.9 KiB
Bash
Executable File

#!/bin/bash
# Copyright (c) 2025, 2026 Probo Inc.
# SPDX-License-Identifier: ISC
set -euo pipefail
# Read Lima user from cidata (values are unquoted so we cannot source the file
# directly — LIMA_CIDATA_COMMENT may contain spaces).
LIMA_CIDATA_USER="$(sed -n 's/^LIMA_CIDATA_USER=//p' /mnt/lima-cidata/lima.env)"
export LIMA_CIDATA_USER
export DEBIAN_FRONTEND=noninteractive
GO_VERSION="1.26.1"
NODE_MAJOR=24
NPM_VERSION="11.8.0"
GOTESTSUM_VERSION="v1.13.0"
GOLANGCI_LINT_VERSION="v2.11.3"
GOW_VERSION="v0.0.0-20260225145757-ff0f6779ab4c"
MKCERT_VERSION="v1.4.4"
apt-get update -qq
apt-get install -y -qq \
build-essential \
git \
curl \
jq \
parallel \
ca-certificates \
gnupg \
lsb-release \
unzip
if ! command -v docker &>/dev/null; then
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
| tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update -qq
apt-get install -y -qq \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
systemctl enable --now docker
fi
usermod -aG docker "${LIMA_CIDATA_USER:-lima}" 2>/dev/null || true
if [ ! -d "/usr/local/go" ] || ! /usr/local/go/bin/go version | grep -q "go${GO_VERSION}"; then
rm -rf /usr/local/go
ARCH=$(dpkg --print-architecture)
curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${ARCH}.tar.gz" \
| tar -C /usr/local -xzf -
fi
cat > /etc/profile.d/go.sh << 'GOEOF'
export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"
GOEOF
chmod +x /etc/profile.d/go.sh
export PATH="/usr/local/go/bin:$PATH"
export HOME="${HOME:-/root}"
GOBIN=/usr/local/bin /usr/local/go/bin/go install "gotest.tools/gotestsum@${GOTESTSUM_VERSION}"
GOBIN=/usr/local/bin /usr/local/go/bin/go install "github.com/golangci/golangci-lint/v2/cmd/golangci-lint@${GOLANGCI_LINT_VERSION}"
GOBIN=/usr/local/bin /usr/local/go/bin/go install "github.com/mitranim/gow@${GOW_VERSION}"
if ! command -v node &>/dev/null || ! node --version | grep -q "v${NODE_MAJOR}"; then
curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | bash -
apt-get install -y -qq nodejs
fi
npm install -g "npm@${NPM_VERSION}"
if ! command -v mkcert &>/dev/null; then
GOBIN=/usr/local/bin /usr/local/go/bin/go install "filippo.io/mkcert@${MKCERT_VERSION}"
fi
mkcert -install 2>/dev/null || true
LIMA_USER="${LIMA_CIDATA_USER:-lima}"
LIMA_HOME=$(eval echo "~${LIMA_USER}")
mkdir -p /root/.parallel "${LIMA_HOME}/.parallel"
touch /root/.parallel/will-cite "${LIMA_HOME}/.parallel/will-cite"
chown -R "${LIMA_USER}:${LIMA_USER}" "${LIMA_HOME}/.parallel"
# Generate sandbox-specific probod config and frontend .env files
VM_IP=$(ip -4 -j addr show dev lima0 | jq -r '.[0].addr_info[0].local')
su - "${LIMA_USER}" -c "export PATH=/usr/local/go/bin:\$HOME/go/bin:\$PATH && cd /workspace && make bin/probod-bootstrap"
make -C /workspace compose/pebble/certs/rootCA.pem compose/keycloak/probo-realm.json
mkdir -p /etc/probod
OAUTH2_SIGNING_KEY_PATH=/etc/probod/oauth2-signing-key.pem
if [ ! -f "${OAUTH2_SIGNING_KEY_PATH}" ]; then
openssl genrsa -out "${OAUTH2_SIGNING_KEY_PATH}" 2048
chmod 600 "${OAUTH2_SIGNING_KEY_PATH}"
fi
# Load developer-specific overrides (not committed to repo).
if [ -f /workspace/.sandbox.env ]; then
set -a
. /workspace/.sandbox.env
set +a
fi
PROBOD_BASE_URL="http://${VM_IP}:8080" \
AUTH_COOKIE_DOMAIN="${VM_IP}" \
AUTH_COOKIE_SECURE=false \
AUTH_COOKIE_SECRET="this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes" \
AUTH_PASSWORD_PEPPER="this-is-a-secure-pepper-for-password-hashing-at-least-32-bytes" \
PROBOD_ENCRYPTION_KEY="thisisnotasecretAAAAAAAAAAAAAAAAAAAAAAAAAAA=" \
OAUTH2_SERVER_SIGNING_KEY="$(cat "${OAUTH2_SIGNING_KEY_PATH}")" \
API_CORS_ALLOWED_ORIGINS="http://${VM_IP}:8080,http://${VM_IP}:5173,http://${VM_IP}:5174" \
AWS_ENDPOINT="http://127.0.0.1:8333" \
AWS_ACCESS_KEY_ID="probod" \
AWS_SECRET_ACCESS_KEY="thisisnotasecret" \
AWS_USE_PATH_STYLE=true \
ACME_DIRECTORY="https://127.0.0.1:14000/dir" \
ACME_EMAIL="admin@getprobo.com" \
ACME_KEY_TYPE="EC256" \
ACME_ROOT_CA="$(cat /workspace/compose/pebble/certs/rootCA.pem)" \
/workspace/bin/probod-bootstrap -output /etc/probod/config.yml
# probod runs as ${LIMA_USER} but bootstrap writes config.yml as root with 0600
# because it contains secrets. Transfer ownership so probod can read it.
chown "${LIMA_USER}:${LIMA_USER}" /etc/probod/config.yml "${OAUTH2_SIGNING_KEY_PATH}"
# Populate VM-local node_modules with Linux-native binaries (esbuild, etc.).
# The host's node_modules is macOS; `probo-node-modules.service` bind-mounts an
# empty tree over /workspace/node_modules, and we install into it once here so
# `make build` and the dev servers can run without cross-platform mismatches.
if [ -z "$(ls -A /var/lib/probo/node_modules 2>/dev/null)" ]; then
su - "${LIMA_USER}" -c "cd /workspace && npm ci"
fi
# Generate go and ts files for probod and apps, and create embedded files for probod
make -C /workspace generate WITH_APPS=1
make -C /workspace embed
echo "VITE_API_URL=http://${VM_IP}:8080" > /workspace/apps/console/.env
echo "VITE_API_URL=http://${VM_IP}:8080" > /workspace/apps/trust/.env
# Bind-mount VM-local node_modules over the shared workspace to avoid
# platform conflicts between macOS host and Linux VM native binaries.
cat > /etc/systemd/system/probo-node-modules.service << EOF
[Unit]
Description=Bind-mount VM-local node_modules over workspace
DefaultDependencies=no
Before=probo-console.service probo-trust.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/bin/mkdir -p /var/lib/probo/node_modules /workspace/node_modules
ExecStart=/bin/mount --bind /var/lib/probo/node_modules /workspace/node_modules
ExecStartPost=/bin/chown ${LIMA_USER}:${LIMA_USER} /var/lib/probo/node_modules
[Install]
WantedBy=multi-user.target
EOF
# Install systemd services for the sandbox
cat > /etc/systemd/system/probo-stack.service << EOF
[Unit]
Description=Probo Docker Compose Stack
Requires=docker.service
After=docker.service
[Service]
Type=simple
User=root
WorkingDirectory=/workspace
ExecStart=/usr/bin/docker compose -f compose.yaml up
ExecStop=/usr/bin/docker compose -f compose.yaml down
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
cat > /etc/systemd/system/probod.service << EOF
[Unit]
Description=Probo API Server
Requires=probo-stack.service
After=probo-stack.service
[Service]
Type=simple
User=${LIMA_USER}
WorkingDirectory=/workspace
ExecStart=/usr/local/bin/gow -r=false run ./cmd/probod -cfg-file /etc/probod/config.yml -format pretty
Restart=on-failure
RestartSec=3s
Environment=PATH=/usr/local/go/bin:/usr/local/bin:/usr/bin:/bin
[Install]
WantedBy=multi-user.target
EOF
cat > /etc/systemd/system/probo-console.service << EOF
[Unit]
Description=Probo Console Dev Server
Requires=probo-node-modules.service
After=probod.service probo-node-modules.service
[Service]
Type=simple
User=${LIMA_USER}
WorkingDirectory=/workspace
ExecStart=/usr/bin/npm --workspace @probo/console run dev -- --host 0.0.0.0
Restart=on-failure
RestartSec=3s
[Install]
WantedBy=multi-user.target
EOF
cat > /etc/systemd/system/probo-trust.service << EOF
[Unit]
Description=Probo Trust Dev Server
Requires=probo-node-modules.service
After=probod.service probo-node-modules.service
[Service]
Type=simple
User=${LIMA_USER}
WorkingDirectory=/workspace
ExecStart=/usr/bin/npm --workspace @probo/trust run dev -- --host 0.0.0.0
Restart=on-failure
RestartSec=3s
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now probo-node-modules.service
systemctl enable --now probo-stack.service
systemctl enable probod.service probo-console.service probo-trust.service