#!/usr/bin/env bash # Siftlode self-host installer (Linux/macOS). Generates secrets into .env, starts the stack from # the prebuilt image, and prints the first-run setup-wizard URL. Re-running is safe: an existing # .env is left untouched. Requires Docker (with the compose plugin) and openssl. set -euo pipefail COMPOSE="docker compose -f docker-compose.selfhost.yml" PORT="${HTTP_PORT:-8080}" if [ -f .env ]; then echo ".env already exists — leaving it untouched (delete it to re-generate)." else printf "Public URL where this instance will be reached [http://localhost:%s]: " "$PORT" read -r URL URL="${URL:-http://localhost:$PORT}" URL="${URL%/}" # Secrets — openssl only, no Python needed. The Fernet key is urlsafe base64 of 32 bytes. SECRET_KEY="$(openssl rand -hex 32)" TOKEN_ENCRYPTION_KEY="$(openssl rand -base64 32 | tr '+/' '-_')" POSTGRES_PASSWORD="$(openssl rand -hex 16)" cat > .env <). # DOWNLOAD_HOST_PATH=/mnt/media/youtube EOF chmod 600 .env echo "Wrote .env (secrets generated)." fi echo "Pulling and starting Siftlode…" $COMPOSE pull $COMPOSE up -d echo "Waiting for the app to come up…" for _ in $(seq 1 30); do curl -fsS -o /dev/null "http://localhost:$PORT/healthz" 2>/dev/null && break sleep 2 done echo echo "===================================================================" echo " Siftlode is up. Open the first-run setup wizard at:" URL_LINE="$($COMPOSE logs api 2>/dev/null | grep -o 'http[s]*://[^ ]*setup?token=[A-Za-z0-9_-]*' | tail -1)" if [ -n "$URL_LINE" ]; then echo " $URL_LINE" else echo " (not found yet — run: $COMPOSE logs api | grep 'setup?token=')" fi echo "==================================================================="