#!/bin/bash ## Bootstrap the local dev environment. ## Run after `docker compose -f docker-compose.dev.yaml up -d` set -euo pipefail HOMESERVER="http://localhost:8008" USERNAME="sol" PASSWORD="soldevpassword" SERVER_NAME="sunbeam.local" echo "Waiting for Tuwunel..." until curl -sf "$HOMESERVER/_matrix/client/versions" > /dev/null 2>&1; do sleep 1 done echo "Tuwunel is ready." echo "Registering @sol:$SERVER_NAME..." RESPONSE=$(curl -s -X POST "$HOMESERVER/_matrix/client/v3/register" \ -H "Content-Type: application/json" \ -d "{ \"username\": \"$USERNAME\", \"password\": \"$PASSWORD\", \"auth\": {\"type\": \"m.login.dummy\"} }") ACCESS_TOKEN=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin).get('access_token',''))" 2>/dev/null || true) DEVICE_ID=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin).get('device_id',''))" 2>/dev/null || true) if [ -z "$ACCESS_TOKEN" ]; then echo "Registration failed (user may already exist). Trying login..." RESPONSE=$(curl -s -X POST "$HOMESERVER/_matrix/client/v3/login" \ -H "Content-Type: application/json" \ -d "{ \"type\": \"m.login.password\", \"identifier\": {\"type\": \"m.id.user\", \"user\": \"$USERNAME\"}, \"password\": \"$PASSWORD\" }") ACCESS_TOKEN=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])") DEVICE_ID=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['device_id'])") fi # ── Matrix: create integration test room ───────────────────────────────── echo "" echo "Creating integration test room..." ROOM_RESPONSE=$(curl -sf -X POST "$HOMESERVER/_matrix/client/v3/createRoom" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"Integration Test Room","room_alias_name":"integration-test","visibility":"private"}' 2>/dev/null || echo '{}') ROOM_ID=$(echo "$ROOM_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin).get('room_id',''))" 2>/dev/null || echo "") if [ -z "$ROOM_ID" ]; then # Room alias might already exist — resolve it ROOM_ID=$(curl -sf "$HOMESERVER/_matrix/client/v3/directory/room/%23integration-test:$SERVER_NAME" \ -H "Authorization: Bearer $ACCESS_TOKEN" 2>/dev/null \ | python3 -c "import sys,json; print(json.load(sys.stdin).get('room_id',''))" 2>/dev/null || echo "") fi if [ -n "$ROOM_ID" ]; then echo " Room: $ROOM_ID" # Send a bootstrap message curl -sf -X PUT "$HOMESERVER/_matrix/client/v3/rooms/$ROOM_ID/send/m.room.message/bootstrap-$(date +%s)" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"msgtype":"m.text","body":"Integration test bootstrap message"}' \ > /dev/null 2>&1 && echo " ✓ bootstrap message sent" || echo " – message send failed" else echo " – Failed to create/find room" fi # ── OpenBao: seed KV secrets engine ────────────────────────────────────── OPENBAO="http://localhost:8200" VAULT_TOKEN="dev-root-token" echo "" echo "Waiting for OpenBao..." until curl -sf "$OPENBAO/v1/sys/health" >/dev/null 2>&1; do sleep 1 done echo "OpenBao is ready." # Write a test secret for integration tests echo "Seeding OpenBao KV..." curl -sf -X POST "$OPENBAO/v1/secret/data/sol-test" \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"data":{"key":"test-secret-value","note":"seeded by bootstrap.sh"}}' \ > /dev/null 2>&1 && echo " ✓ secret/sol-test" || echo " – sol-test (already exists or failed)" # Write a test token path curl -sf -X POST "$OPENBAO/v1/secret/data/sol-tokens/testuser/gitea" \ -H "X-Vault-Token: $VAULT_TOKEN" \ -H "Content-Type: application/json" \ -d '{"data":{"token":"test-gitea-pat-12345","token_type":"pat","refresh_token":"","expires_at":""}}' \ > /dev/null 2>&1 && echo " ✓ secret/sol-tokens/testuser/gitea" || echo " – token (already exists or failed)" # ── Kratos: seed test identities ──────────────────────────────────────── KRATOS_ADMIN="http://localhost:4434" echo "" echo "Waiting for Kratos..." until curl -sf "$KRATOS_ADMIN/admin/health/ready" >/dev/null 2>&1; do sleep 1 done echo "Kratos is ready." echo "Seeding Kratos identities..." curl -sf -X POST "$KRATOS_ADMIN/admin/identities" \ -H "Content-Type: application/json" \ -d '{"schema_id":"default","traits":{"email":"sienna@sunbeam.local","name":{"first":"Sienna","last":"V"}}}' \ > /dev/null 2>&1 && echo " ✓ sienna@sunbeam.local" || echo " – sienna (already exists or failed)" curl -sf -X POST "$KRATOS_ADMIN/admin/identities" \ -H "Content-Type: application/json" \ -d '{"schema_id":"default","traits":{"email":"lonni@sunbeam.local","name":{"first":"Lonni","last":"B"}}}' \ > /dev/null 2>&1 && echo " ✓ lonni@sunbeam.local" || echo " – lonni (already exists or failed)" curl -sf -X POST "$KRATOS_ADMIN/admin/identities" \ -H "Content-Type: application/json" \ -d '{"schema_id":"default","traits":{"email":"amber@sunbeam.local","name":{"first":"Amber","last":"K"}}}' \ > /dev/null 2>&1 && echo " ✓ amber@sunbeam.local" || echo " – amber (already exists or failed)" # ── Summary ───────────────────────────────────────────────────────────── echo "" echo "Add these to your .env or export them:" echo "" echo "export SOL_MATRIX_ACCESS_TOKEN=\"$ACCESS_TOKEN\"" echo "export SOL_MATRIX_DEVICE_ID=\"$DEVICE_ID\"" echo "" echo "Services:" echo " Tuwunel: $HOMESERVER" echo " OpenBao: $OPENBAO (token: $VAULT_TOKEN)" echo " Kratos: $KRATOS_ADMIN" if [ -n "$ROOM_ID" ]; then echo " Test room: $ROOM_ID" fi echo "" echo "Then restart Sol: docker compose -f docker-compose.dev.yaml restart sol"