Files
Momento/scripts/deploy.sh
Sepehr Ramezani f3b58b32fd
Some checks failed
Deploy to Production / Deploy to 192.168.1.190 (push) Has been cancelled
ci: add deploy script and simplify CI/CD workflow
- scripts/deploy.sh: automated deployment with interactive env setup
  (--env-only, --build, --full)
- Supports OpenRouter, OpenAI, Ollama, DeepSeek providers
- Auto-generates NEXTAUTH_SECRET and postgres password
- Waits for healthchecks, initializes DB, shows status
- CI/CD workflow simplified to call deploy.sh --build

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-21 22:55:15 +02:00

296 lines
8.2 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# ============================================================
# Memento - Deploy Script
# ============================================================
# Usage: ./scripts/deploy.sh [--env-only | --build | --full]
#
# --env-only : Generate .env.docker interactively
# --build : Build and start containers (default)
# --full : env + build + first-time setup
# ============================================================
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
ENV_FILE="$PROJECT_DIR/.env.docker"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; }
# -----------------------------------------------------------
# Generate .env.docker
# -----------------------------------------------------------
generate_env() {
if [ -f "$ENV_FILE" ]; then
warn "$ENV_FILE already exists."
read -rp "Overwrite? [y/N] " confirm
[[ "$confirm" != "y" && "$confirm" != "Y" ]] && return 0
fi
info "Generating $ENV_FILE ..."
# Auto-generate NEXTAUTH_SECRET
local secret
secret=$(openssl rand -base64 32 2>/dev/null || head -c 32 /dev/urandom | base64)
# Auto-generate secure postgres password
local pg_pass
pg_pass=$(openssl rand -hex 16 2>/dev/null || head -c 16 /dev/urandom | hexdump -v -e '/1 "%02x"')
# Ask for URL
local url="http://192.168.1.190"
read -rp "NEXTAUTH_URL [$url]: " input_url
[ -n "$input_url" ] && url="$input_url"
# Ask for AI provider
echo ""
echo "AI Provider:"
echo " 1) OpenRouter (recommended, works out of the box)"
echo " 2) Ollama (requires ollama container)"
echo " 3) OpenAI"
echo " 4) DeepSeek"
echo " 5) Skip AI configuration"
read -rp "Choice [1]: " ai_choice
ai_choice="${ai_choice:-1}"
local ai_tags_provider="openrouter"
local ai_tags_model="google/gemma-3-27b-it"
local ai_embed_provider="openrouter"
local ai_embed_model="text-embedding-3-small"
local ai_chat_provider="openrouter"
local ai_chat_model="google/gemma-3-27b-it"
local custom_api_key=""
local custom_base_url=""
case "$ai_choice" in
1)
read -rp "OpenRouter API Key: " custom_api_key
[ -z "$custom_api_key" ] && error "API key is required"
custom_base_url="https://openrouter.ai/api/v1"
;;
2)
ai_tags_provider="ollama"
ai_tags_model="granite4:latest"
ai_embed_provider="ollama"
ai_embed_model="embeddinggemma:latest"
ai_chat_provider="ollama"
ai_chat_model="granite4:latest"
custom_base_url="http://ollama:11434"
;;
3)
ai_tags_provider="openai"
ai_tags_model="gpt-4o-mini"
ai_embed_provider="openai"
ai_embed_model="text-embedding-3-small"
ai_chat_provider="openai"
ai_chat_model="gpt-4o-mini"
read -rp "OpenAI API Key: " custom_api_key
[ -z "$custom_api_key" ] && error "API key is required"
;;
4)
ai_tags_provider="deepseek"
ai_tags_model="deepseek-chat"
ai_embed_provider="openrouter"
ai_embed_model="text-embedding-3-small"
ai_chat_provider="deepseek"
ai_chat_model="deepseek-chat"
read -rp "DeepSeek API Key: " custom_api_key
[ -z "$custom_api_key" ] && error "API key is required"
custom_base_url="https://api.deepseek.com/v1"
;;
5)
info "Skipping AI configuration"
;;
*)
error "Invalid choice"
;;
esac
# Ask for email provider
echo ""
echo "Email provider:"
echo " 1) Resend"
echo " 2) SMTP"
echo " 3) Skip"
read -rp "Choice [3]: " email_choice
email_choice="${email_choice:-3}"
local resend_key=""
local smtp_config=""
case "$email_choice" in
1)
read -rp "Resend API Key: " resend_key
;;
2)
local smtp_host smtp_port smtp_user smtp_pass smtp_from
read -rp "SMTP Host: " smtp_host
read -rp "SMTP Port [587]: " smtp_port; smtp_port="${smtp_port:-587}"
read -rp "SMTP User: " smtp_user
read -rp "SMTP Password: " smtp_pass
read -rp "SMTP From: " smtp_from
smtp_config="SMTP_HOST=\"$smtp_host\"
SMTP_PORT=\"$smtp_port\"
SMTP_USER=\"$smtp_user\"
SMTP_PASS=\"$smtp_pass\"
SMTP_FROM=\"$smtp_from\""
;;
esac
# Write .env.docker
cat > "$ENV_FILE" << ENVEOF
# =============================================================================
# Memento - Docker Environment (auto-generated)
# =============================================================================
NEXTAUTH_URL="${url}"
NEXTAUTH_SECRET="${secret}"
ALLOW_REGISTRATION="true"
# PostgreSQL
POSTGRES_PORT=5432
POSTGRES_DB=memento
POSTGRES_USER=memento
POSTGRES_PASSWORD="${pg_pass}"
# MCP Server
MCP_MODE="sse"
MCP_PORT="3001"
# AI - Tags
AI_PROVIDER_TAGS=${ai_tags_provider}
AI_MODEL_TAGS="${ai_tags_model}"
# AI - Embeddings
AI_PROVIDER_EMBEDDING=${ai_embed_provider}
AI_MODEL_EMBEDDING="${ai_embed_model}"
# AI - Chat
AI_PROVIDER_CHAT=${ai_chat_provider}
AI_MODEL_CHAT="${ai_chat_model}"
ENVEOF
# Add API key config if applicable
if [ -n "$custom_api_key" ]; then
case "$ai_choice" in
1)
echo "CUSTOM_OPENAI_API_KEY=\"${custom_api_key}\"" >> "$ENV_FILE"
echo "CUSTOM_OPENAI_BASE_URL=\"${custom_base_url}\"" >> "$ENV_FILE"
;;
3)
echo "OPENAI_API_KEY=\"${custom_api_key}\"" >> "$ENV_FILE"
;;
4)
echo "CUSTOM_OPENAI_API_KEY=\"${custom_api_key}\"" >> "$ENV_FILE"
echo "CUSTOM_OPENAI_BASE_URL=\"${custom_base_url}\"" >> "$ENV_FILE"
;;
esac
fi
# Add Ollama URL if using ollama
if [ "$ai_choice" = "2" ]; then
echo "OLLAMA_BASE_URL=\"http://ollama:11434\"" >> "$ENV_FILE"
fi
# Add email config
if [ -n "$resend_key" ]; then
echo "RESEND_API_KEY=\"${resend_key}\"" >> "$ENV_FILE"
fi
if [ -n "$smtp_config" ]; then
echo "" >> "$ENV_FILE"
echo "$smtp_config" >> "$ENV_FILE"
fi
ok "$ENV_FILE created"
echo ""
info "Contents:"
grep -v "KEY\|PASSWORD\|SECRET" "$ENV_FILE" | sed 's/^/ /'
echo " (sensitive values hidden)"
}
# -----------------------------------------------------------
# Build and deploy
# -----------------------------------------------------------
deploy() {
[ -f "$ENV_FILE" ] || error "$ENV_FILE not found. Run with --env-only first."
cd "$PROJECT_DIR"
info "Pulling latest code..."
git pull origin main 2>/dev/null || warn "Could not pull (maybe already up to date or no git)"
info "Building containers..."
docker compose build --parallel 2>&1
info "Starting containers..."
docker compose up -d 2>&1
info "Waiting for healthchecks..."
local retries=0
local max_retries=30
while [ $retries -lt $max_retries ]; do
local unhealthy
unhealthy=$(docker compose ps --format '{{.Status}}' 2>/dev/null | grep -c -v "healthy\|Up" || true)
if [ "$unhealthy" -eq 0 ]; then
break
fi
retries=$((retries + 1))
sleep 2
printf "."
done
echo ""
info "Initializing database..."
docker compose exec memento-note npx prisma db push --skip-generate 2>/dev/null || \
warn "DB push failed (may already be synced)"
echo ""
echo "=========================================="
docker compose ps
echo "=========================================="
echo ""
ok "Deploy complete!"
info "App: $(grep NEXTAUTH_URL "$ENV_FILE" | cut -d= -f2 | tr -d '"')"
# Show admin setup hint if first time
local user_count
user_count=$(docker compose exec -T postgres psql -U memento -d memento -t -c 'SELECT COUNT(*) FROM "User"' 2>/dev/null | tr -d ' ' || echo "0")
if [ "$user_count" = "0" ]; then
echo ""
warn "No users found. Register at $(grep NEXTAUTH_URL "$ENV_FILE" | cut -d= -f2 | tr -d '"')/register"
warn "Then run: docker compose exec memento-note npx tsx scripts/grant-all-admins.ts"
fi
}
# -----------------------------------------------------------
# Main
# -----------------------------------------------------------
ACTION="${1:---build}"
case "$ACTION" in
--env-only)
generate_env
;;
--build)
deploy
;;
--full)
generate_env
echo ""
deploy
;;
*)
echo "Usage: $0 [--env-only | --build | --full]"
exit 1
;;
esac