From 956d39fca5e733d4ccd84d13203893dc5ad17a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20D=C3=BCren?= Date: Sun, 16 Mar 2025 23:11:53 +0100 Subject: [PATCH] Complete rewrite of Ente Cloudron app startup script with proper SERVER_DIR detection --- start.sh | 1185 +++++++++++++++++++++--------------------------------- 1 file changed, 450 insertions(+), 735 deletions(-) diff --git a/start.sh b/start.sh index 90b754e..9d48d2d 100644 --- a/start.sh +++ b/start.sh @@ -14,6 +14,22 @@ mkdir -p /app/data/config /app/data/storage /app/data/caddy /app/data/go /app/da echo "==> NOTE: Running in Cloudron environment with limited write access" echo "==> Writable directories: /app/data, /tmp, /run" +# Define the server directory +SERVER_DIR="/app/code/server" +if [ ! -d "$SERVER_DIR" ]; then + if [ -d "/app/code/museum" ]; then + SERVER_DIR="/app/code/museum" + else + # Look for main.go in likely places + SERVER_DIR=$(dirname $(find /app/code -name "main.go" -path "*/server*" -o -path "*/museum*" | head -1)) + if [ ! -d "$SERVER_DIR" ]; then + echo "==> WARNING: Could not find server directory, using /app/code as fallback" + SERVER_DIR="/app/code" + fi + fi +fi +echo "==> Using server directory: $SERVER_DIR" + # One-time initialization tracking if [[ ! -f /app/data/.initialized ]]; then echo "==> Fresh installation, setting up data directory..." @@ -216,728 +232,11 @@ export REACT_APP_ENTE_ENDPOINT=$API_ENDPOINT export VUE_APP_ENTE_ENDPOINT=$API_ENDPOINT echo "==> Set environment variables for web apps" -# Create directory for direct modifications +# Create directory for configuration files +mkdir -p /app/data/public mkdir -p /app/data/scripts -# Create a script that will directly define the ENTE_CONFIG global in window -cat > /app/data/scripts/ente-config.js < Setting up direct runtime configuration" - -# Global API endpoint -API_ENDPOINT="${CLOUDRON_APP_ORIGIN}/api" -echo "==> Setting API endpoint to $API_ENDPOINT" - -# Create runtime configuration files -mkdir -p /app/data/runtime -echo "==> Creating runtime configuration files" - -# Create a config script -cat > /app/data/runtime/config.js < Attempting to directly modify web app HTML files" -WEB_APPS=("/app/web/photos" "/app/web/accounts" "/app/web/auth" "/app/web/cast") - -for app_dir in "${WEB_APPS[@]}"; do - if [ -f "$app_dir/index.html" ]; then - echo "==> Processing $app_dir/index.html" - - # Create a backup copy in our data directory - mkdir -p "/app/data/original/$(basename $app_dir)" - cp "$app_dir/index.html" "/app/data/original/$(basename $app_dir)/index.html" - - # Create a modified version of the file in our data directory - mkdir -p "/app/data/modified/$(basename $app_dir)" - cp "$app_dir/index.html" "/app/data/modified/$(basename $app_dir)/index.html" - - # Insert our configuration script into the head section - sed -i 's|||' "/app/data/modified/$(basename $app_dir)/index.html" - - # Try to replace the original file (may fail if read-only) - if cp "/app/data/modified/$(basename $app_dir)/index.html" "$app_dir/index.html" 2>/dev/null; then - echo "==> Successfully modified $app_dir/index.html" - else - echo "==> Could not modify $app_dir/index.html (read-only filesystem)" - fi - else - echo "==> Skipping $app_dir - index.html not found" - fi -done - -# Second approach: Create a modified copy that Caddy will serve -mkdir -p /app/data/public -cp /app/data/runtime/config.js /app/data/public/ -echo "==> Created public configuration script" - -# Create a loading page for each app with configuration -for app_name in "photos" "accounts" "auth" "cast"; do - cat > "/app/data/public/${app_name}-config.html" < - - - - Loading ${app_name} - - - - -

Loading ${app_name}...

-

If you are not redirected automatically, click here.

-

Debug Information

- - -EOT -done - -# Create root index.html that loads config and redirects -cat > /app/data/public/index.html < - - - - Ente - - - - -

Loading Ente...

-

You will be redirected automatically.

-

Debug Information

- - -EOT - -echo "==> Created special root index.html with configuration" - -# Check port availability before starting services -echo "==> Checking port availability" -CADDY_PORT=3080 -API_PORT=8080 - -# Check if ports are already in use -if lsof -i:$CADDY_PORT > /dev/null 2>&1; then - echo "==> WARNING: Port $CADDY_PORT is already in use" - echo "===> Process using port $CADDY_PORT:" - lsof -i:$CADDY_PORT -else - echo "==> Port $CADDY_PORT is available for Caddy" -fi - -if lsof -i:$API_PORT > /dev/null 2>&1; then - echo "==> WARNING: Port $API_PORT is already in use" - echo "===> Process using port $API_PORT:" - lsof -i:$API_PORT -else - echo "==> Port $API_PORT is available for API server" -fi - -# Set up Caddy -echo "==> Setting up Caddy server for web apps" -mkdir -p /app/data/caddy/public -cat > /app/data/caddy/Caddyfile < Caddy configuration created at /app/data/caddy/Caddyfile" - -# Start Caddy first before the Museum server to ensure port 3080 is available for health checks -echo "==> Setting up Caddy before starting the Museum server" -echo "==> Caddy will be listening on port $CADDY_PORT" - -# Only set permissions on the Caddy directory, not the web directory which is read-only -mkdir -p /app/data/caddy -chmod -R 777 /app/data/caddy -chown -R cloudron:cloudron /app/data/caddy - -# Start Caddy server -echo "==> Starting Caddy server..." -caddy run --config /app/data/caddy/Caddyfile --adapter caddyfile & -CADDY_PID=$! -echo "==> Caddy started with PID $CADDY_PID" - -# Wait a moment for Caddy to start -sleep 2 - -# Test Caddy connectivity -echo "==> Testing Caddy connectivity on port $CADDY_PORT" -for i in {1..5}; do - if curl -s --max-time 2 --head --fail http://localhost:$CADDY_PORT/health > /dev/null; then - echo "==> Caddy is running properly on port $CADDY_PORT" - break - else - if [ $i -eq 5 ]; then - echo "==> Failed to connect to Caddy on port $CADDY_PORT after multiple attempts" - echo "==> Last 20 lines of Caddy log:" - tail -20 /app/data/caddy/caddy.log || echo "==> No Caddy log available" - echo "==> Network ports in use:" - netstat -tuln || echo "==> netstat command not available" - echo "==> Processes listening on ports:" - lsof -i -P -n | grep LISTEN || echo "==> lsof command not available" - else - echo "==> Attempt $i: Waiting for Caddy to start... (1 second)" - sleep 1 - fi - fi -done - -# Determine available memory and set limits accordingly -if [[ -f /sys/fs/cgroup/cgroup.controllers ]]; then # cgroup v2 - memory_limit=$(cat /sys/fs/cgroup/memory.max) - [[ "${memory_limit}" == "max" ]] && memory_limit=$(( 2 * 1024 * 1024 * 1024 )) # "max" really means unlimited -else - memory_limit=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes) # this is the RAM. we have equal amount of swap -fi -memory_mb=$((memory_limit/1024/1024)) -echo "==> Available memory: ${memory_mb}MB" - -# Set up database environment variables and ensure proper SSL config -export ENTE_DB_USER="${CLOUDRON_POSTGRESQL_USERNAME}" -export ENTE_DB_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}" -export ENTE_DB_HOST="${CLOUDRON_POSTGRESQL_HOST}" -export ENTE_DB_PORT="${CLOUDRON_POSTGRESQL_PORT}" -export ENTE_DB_NAME="${CLOUDRON_POSTGRESQL_DATABASE}" -export ENTE_DB_SSLMODE="disable" -export CONFIG_PATH="/app/data/config/config.yaml" - -# Check database connectivity -echo "==> Checking database connectivity" -MAX_RETRIES=5 -RETRY_COUNT=0 -while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do - if PGPASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}" psql -h "${CLOUDRON_POSTGRESQL_HOST}" -p "${CLOUDRON_POSTGRESQL_PORT}" \ - -U "${CLOUDRON_POSTGRESQL_USERNAME}" -d "${CLOUDRON_POSTGRESQL_DATABASE}" -c "SELECT 1" > /dev/null 2>&1; then - echo "==> Successfully connected to database" - break - else - echo "==> Failed to connect to database (attempt $((RETRY_COUNT+1))/$MAX_RETRIES)" - RETRY_COUNT=$((RETRY_COUNT+1)) - sleep 5 - fi -done - -if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then - echo "==> ERROR: Could not connect to database after $MAX_RETRIES attempts" - echo "==> Database connection details:" - echo "Host: ${CLOUDRON_POSTGRESQL_HOST}" - echo "Port: ${CLOUDRON_POSTGRESQL_PORT}" - echo "User: ${CLOUDRON_POSTGRESQL_USERNAME}" - echo "Database: ${CLOUDRON_POSTGRESQL_DATABASE}" - exit 1 -fi - -# Fix database migration state if needed -echo "==> Checking database migration state" -if [ -d "$SERVER_DIR/cmd/museum" ]; then - echo "==> Attempting to fix dirty migration state" - cd "$SERVER_DIR" - - # Create migrations log directory - mkdir -p /app/data/logs/migrations - - echo "==> Forcing migration version to 25" - if /usr/local/bin/gosu cloudron:cloudron env GOCACHE=/app/data/go/cache GOMODCACHE=/app/data/go/pkg/mod \ - go run -modfile=/app/data/go/go.mod -mod=mod cmd/museum/main.go migrate force 25 \ - > /app/data/logs/migrations/force.log 2>&1; then - echo "==> Successfully forced migration version" - else - echo "==> Failed to force migration version. Check /app/data/logs/migrations/force.log for details" - cat /app/data/logs/migrations/force.log - fi - - echo "==> Running clean migrations" - if /usr/local/bin/gosu cloudron:cloudron env GOCACHE=/app/data/go/cache GOMODCACHE=/app/data/go/pkg/mod \ - go run -modfile=/app/data/go/go.mod -mod=mod cmd/museum/main.go migrate up \ - > /app/data/logs/migrations/up.log 2>&1; then - echo "==> Successfully ran migrations" - else - echo "==> Failed to run migrations. Check /app/data/logs/migrations/up.log for details" - cat /app/data/logs/migrations/up.log - echo "==> WARNING: Database migrations failed. The application may not work correctly." - fi -fi - -# Additional environment variables -export REMOTE_STORAGE_ENDPOINT="${S3_ENDPOINT}" -export REMOTE_STORAGE_REGION="${S3_REGION}" -export REMOTE_STORAGE_BUCKET="${S3_BUCKET}" -export REMOTE_STORAGE_ACCESS_KEY="${S3_ACCESS_KEY}" -export REMOTE_STORAGE_SECRET_KEY="${S3_SECRET_KEY}" -export REMOTE_STORAGE_PREFIX="${S3_PREFIX:-}" - -# Change ownership to cloudron user -chown -R cloudron:cloudron /app/data - -# Start Museum server on port 8080 for compatibility with the Caddy configuration -echo "==> Starting Museum server" - -# Modify environment variables for frontend -echo "==> Setting up environment variables for frontend" -# Set frontend endpoint to the proper origin -export NEXT_PUBLIC_ENTE_ENDPOINT="${CLOUDRON_APP_ORIGIN}/api" -echo "==> NEXT_PUBLIC_ENTE_ENDPOINT set to ${NEXT_PUBLIC_ENTE_ENDPOINT}" - -# Also create a direct config in multiple formats to ensure it's properly loaded -echo "==> Creating runtime configuration for the web apps in multiple formats" -mkdir -p /app/data/runtime - -# 1. Standard config.js -cat > /app/data/runtime/config.js < /app/data/runtime/config.json < /app/data/runtime/env.js < Generated config.js content:" -cat /app/data/runtime/config.js - -# First check for pre-built Museum binary -if find "$SERVER_DIR" -name "museum" -type f -executable | grep -q .; then - MUSEUM_BIN=$(find "$SERVER_DIR" -name "museum" -type f -executable | head -1) - echo "==> Found Museum binary at $MUSEUM_BIN" - /usr/local/bin/gosu cloudron:cloudron "$MUSEUM_BIN" --port 8080 \ - --storage.s3.endpoint="${S3_ENDPOINT}" \ - --storage.s3.region="${S3_REGION}" \ - --storage.s3.bucket="${S3_BUCKET}" \ - --storage.s3.accessKey="${S3_ACCESS_KEY}" \ - --storage.s3.secretKey="${S3_SECRET_KEY}" \ - --storage.s3.prefix="${S3_PREFIX:-}" \ - --storage.s3.forcePathStyle=true \ - --storage.s3.areLocalBuckets=false \ - --storage.type="s3" \ - --config.path="/app/data/config/museum.yaml" \ - --database.sslmode="disable" > /app/data/logs/museum-server.log 2>&1 & - SERVER_PID=$! - echo "==> Museum server started with PID $SERVER_PID" -# Next check for cmd/museum directory pattern -elif [ -d "$SERVER_DIR/cmd/museum" ]; then - echo "==> Found Museum source in cmd/museum, running with go run" - cd "$SERVER_DIR" - - # Set environment variables for compatibility - echo "==> Setting Go environment variables for compatibility" - export GOFLAGS="-modfile=/app/data/go/go.mod -mod=mod -modcacherw" - # Use local toolchain to avoid downloading required version - export GOTOOLCHAIN=local - - # Launch the server with S3 configuration - echo "==> Starting Museum server with S3 configuration" - cd "$SERVER_DIR" && \ - /usr/local/bin/gosu cloudron:cloudron env GOCACHE=/app/data/go/cache GOMODCACHE=/app/data/go/pkg/mod PORT=8080 GIN_MODE=release go run -modfile=/app/data/go/go.mod -mod=mod cmd/museum/main.go --port 8080 \ - --storage.s3.endpoint="${S3_ENDPOINT}" \ - --storage.s3.region="${S3_REGION}" \ - --storage.s3.bucket="${S3_BUCKET}" \ - --storage.s3.accessKey="${S3_ACCESS_KEY}" \ - --storage.s3.secretKey="${S3_SECRET_KEY}" \ - --storage.s3.prefix="${S3_PREFIX:-}" \ - --storage.s3.forcePathStyle=true \ - --storage.s3.areLocalBuckets=false \ - --storage.type="s3" \ - --config.path="/app/data/config/museum.yaml" \ - --database.sslmode="disable" \ - --log.level=debug > /app/data/logs/museum-server.log 2>&1 & - SERVER_PID=$! - echo "==> Museum server started with PID $SERVER_PID" - - # Wait for the server to start - echo "==> Waiting for Museum server to start..." - sleep 5 - - # Test if API is responding - MAX_RETRIES=5 - RETRY_COUNT=0 - while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do - echo "==> Testing API connection (attempt $((RETRY_COUNT+1))/$MAX_RETRIES)" - if curl -s http://localhost:8080/api/health > /dev/null; then - echo "==> API is now responding" - break - else - echo "==> API not responding yet, waiting..." - RETRY_COUNT=$((RETRY_COUNT+1)) - sleep 5 - # Print recent log output - echo "==> Recent server log output:" - tail -n 20 /app/data/logs/museum-server.log || echo "==> No logs available yet" - fi - done - - if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then - echo "==> WARNING: API server did not respond after multiple attempts" - echo "==> Checking server logs:" - ps -p $SERVER_PID >/dev/null || echo "==> ERROR: Server process is not running!" - tail -n 50 /app/data/logs/museum-server.log || echo "==> No logs available" - fi - -# Next try to find any main.go for the Museum -else - # Fallback approach - find main.go files - MAIN_FILES=$(find "$SERVER_DIR" -name "main.go" | grep -v "test" || echo "") - if [ -n "$MAIN_FILES" ]; then - MAIN_FILE=$(echo "$MAIN_FILES" | head -1) - MAIN_DIR=$(dirname "$MAIN_FILE") - echo "==> Using main.go file at $MAIN_FILE" - cd "$MAIN_DIR" - - # Instead of trying to modify go.mod, set environment variables for compatibility - echo "==> Setting Go environment variables for compatibility" - export GOFLAGS="-modfile=/app/data/go/go.mod -mod=mod -modcacherw" - export GOTOOLCHAIN=local - - echo "==> Running main.go with Go" - cd "$MAIN_DIR" && \ - /usr/local/bin/gosu cloudron:cloudron env GOCACHE=/app/data/go/cache GOMODCACHE=/app/data/go/pkg/mod PORT=8080 GIN_MODE=release go run -modfile=/app/data/go/go.mod -mod=mod main.go --port 8080 \ - --storage.s3.endpoint="${S3_ENDPOINT}" \ - --storage.s3.region="${S3_REGION}" \ - --storage.s3.bucket="${S3_BUCKET}" \ - --storage.s3.accessKey="${S3_ACCESS_KEY}" \ - --storage.s3.secretKey="${S3_SECRET_KEY}" \ - --storage.s3.prefix="${S3_PREFIX:-}" \ - --storage.s3.forcePathStyle=true \ - --storage.s3.areLocalBuckets=false \ - --storage.type="s3" \ - --config.path="/app/data/config/museum.yaml" \ - --database.sslmode="disable" \ - --log.level=debug > /app/data/logs/museum-server.log 2>&1 & - SERVER_PID=$! - echo "==> Museum server started with PID $SERVER_PID" - - # Check if the server process is actually running after a brief pause - sleep 2 - if ! ps -p $SERVER_PID > /dev/null; then - echo "==> WARNING: Server process exited immediately" - echo "==> Recent server log output:" - tail -n 50 /app/data/logs/museum-server.log || echo "==> No logs available yet" - echo "==> Falling back to mock server" - SERVER_PID="" - fi - else - echo "==> ERROR: Could not find Museum binary or main.go source file" - echo "==> Available Go files:" - find "$SERVER_DIR" -name "*.go" | sort - - SERVER_PID="" - fi -fi - -# If server didn't start successfully, use mock server -if [ -z "$SERVER_PID" ] || ! ps -p $SERVER_PID > /dev/null; then - echo "==> Starting mock server as fallback" - # Last resort - create a temporary Go HTTP server that returns a meaningful error - mkdir -p /tmp/mock-server - cat > /tmp/mock-server/main.go < Mock server started with PID $SERVER_PID to show error message" -fi - -echo "==> Testing health check endpoint directly" -curl -v http://localhost:3080/healthcheck - -echo "==> Ente is now running!" -echo "==> Museum server: PID $SERVER_PID" -echo "==> Caddy: PID $CADDY_PID" - -# Wait for child processes to exit -wait $SERVER_PID -wait $CADDY_PID - -# Create a special root index.html that loads the config and redirects -cat > /app/data/public/index.html < - - - - Ente - - - - -

Loading Ente...

-

You will be redirected automatically.

-

Debug Information

- - -EOT - -echo "==> Created special root index.html with configuration" - -# Create debug script for frontend -mkdir -p /app/data/public -mkdir -p /app/data/debug - -echo "==> Creating debug scripts" +# Create a debugging script cat > /app/data/public/debug.js < /app/data/public/debug.js < /app/data/debug/debug_env.js < /app/data/public/config.js < /app/data/public/debug.html < @@ -1056,17 +367,17 @@ cat > /app/data/public/debug.html < // Define configuration globally window.ENTE_CONFIG = { - API_URL: "${CLOUDRON_APP_ORIGIN}/api" + API_URL: "${API_ENDPOINT}" }; // Set environment variables for Next.js apps window.process = window.process || {}; window.process.env = window.process.env || {}; - window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = "${CLOUDRON_APP_ORIGIN}/api"; + window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = "${API_ENDPOINT}"; // Store in localStorage localStorage.setItem('ENTE_CONFIG', JSON.stringify(window.ENTE_CONFIG)); - localStorage.setItem('NEXT_PUBLIC_ENTE_ENDPOINT', "${CLOUDRON_APP_ORIGIN}/api"); + localStorage.setItem('NEXT_PUBLIC_ENTE_ENDPOINT', "${API_ENDPOINT}"); // Display configuration document.getElementById('config-info').textContent = @@ -1104,4 +415,408 @@ cat > /app/data/public/debug.html < -EOT \ No newline at end of file +EOT + +# Create a simple app that loads the config and redirects to the main app +cat > /app/data/public/index.html < + + + + Ente + + + + + +

Loading Ente...

+

You will be redirected automatically.

+

Debug Information

+ + +EOT + +# Set up Caddy +echo "==> Setting up Caddy server" +mkdir -p /app/data/caddy +chmod -R 777 /app/data/caddy + +# Define ports +CADDY_PORT=3080 +API_PORT=8080 + +# Check if ports are available +echo "==> Checking port availability" +if lsof -i:$CADDY_PORT > /dev/null 2>&1; then + echo "==> WARNING: Port $CADDY_PORT is already in use" +else + echo "==> Port $CADDY_PORT is available for Caddy" +fi + +if lsof -i:$API_PORT > /dev/null 2>&1; then + echo "==> WARNING: Port $API_PORT is already in use" +else + echo "==> Port $API_PORT is available for API server" +fi + +# Create the Caddyfile +cat > /app/data/caddy/Caddyfile < Created Caddyfile at /app/data/caddy/Caddyfile" + +# Create injected HTML files for each app +for app_name in "photos" "accounts" "auth" "cast"; do + # Create an injected HTML file that loads the config + cat > "/app/data/public/${app_name}-injected.html" < + + + + Ente ${app_name^} + + + + + +
+

Loading Ente ${app_name^}...

+

Please wait while the application initializes.

+
+ + +EOT +done + +echo "==> Created injected HTML files for all apps" + +# Start Caddy +echo "==> Starting Caddy on port $CADDY_PORT" +caddy run --config /app/data/caddy/Caddyfile --adapter caddyfile & +CADDY_PID=$! +echo "==> Caddy started with PID $CADDY_PID" + +# Wait for Caddy to start +sleep 2 + +# Test Caddy connectivity +echo "==> Testing Caddy connectivity" +for i in {1..5}; do + if curl -s --max-time 2 --head --fail http://localhost:$CADDY_PORT/health > /dev/null; then + echo "==> Caddy is running properly on port $CADDY_PORT" + break + else + if [ $i -eq 5 ]; then + echo "==> Failed to connect to Caddy after multiple attempts" + echo "==> Last 20 lines of Caddy log:" + tail -20 /app/data/caddy/caddy.log || echo "==> No Caddy log available" + echo "==> Network ports in use:" + netstat -tuln || echo "==> netstat command not available" + else + echo "==> Attempt $i: Waiting for Caddy to start... (1 second)" + sleep 1 + fi + fi +done + +# Determine available memory and set limits accordingly +if [[ -f /sys/fs/cgroup/cgroup.controllers ]]; then # cgroup v2 + memory_limit=$(cat /sys/fs/cgroup/memory.max) + if [[ "$memory_limit" != "max" ]]; then + MEMORY_MB=$((memory_limit / 1024 / 1024)) + else + MEMORY_MB=$(free -m | awk '/^Mem:/{print $2}') + fi +else # cgroup v1 + if [ -f /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then + memory_limit=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes) + MEMORY_MB=$((memory_limit / 1024 / 1024)) + else + MEMORY_MB=$(free -m | awk '/^Mem:/{print $2}') + fi +fi + +echo "==> Available memory: ${MEMORY_MB}MB" + +# Test database connectivity +echo "==> Checking database connectivity" +PGPASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}" psql -h ${CLOUDRON_POSTGRESQL_HOST} -p ${CLOUDRON_POSTGRESQL_PORT} -U ${CLOUDRON_POSTGRESQL_USERNAME} -d ${CLOUDRON_POSTGRESQL_DATABASE} -c "SELECT 1" > /dev/null + +if [ $? -ne 0 ]; then + echo "==> ERROR: Failed to connect to database" + echo "Host: ${CLOUDRON_POSTGRESQL_HOST}" + echo "Port: ${CLOUDRON_POSTGRESQL_PORT}" + echo "User: ${CLOUDRON_POSTGRESQL_USERNAME}" + echo "Database: ${CLOUDRON_POSTGRESQL_DATABASE}" + exit 1 +fi +echo "==> Successfully connected to database" + +# Fix database migration state if needed +echo "==> Checking database migration state" +if [ -d "$SERVER_DIR/cmd/museum" ]; then + echo "==> Attempting to fix dirty migration state" + cd "$SERVER_DIR" + + # Create migrations log directory + mkdir -p /app/data/logs/migrations + + echo "==> Forcing migration version to 25" + if /usr/local/bin/gosu cloudron:cloudron env GOCACHE=/app/data/go/cache GOMODCACHE=/app/data/go/pkg/mod \ + go run cmd/museum/main.go db force 25 > /app/data/logs/migrations/force.log 2>&1; then + echo "==> Successfully forced migration version" + else + echo "==> WARNING: Could not force migration version" + echo "==> Migration force log:" + cat /app/data/logs/migrations/force.log + fi +else + echo "==> Skipping migration state check: cmd/museum not found" +fi + +# Start the Museum server +echo "==> Starting Museum server" +cd "$SERVER_DIR" + +# Set necessary environment variables +export MUSEUM_CONFIG="/app/data/config/museum.yaml" +export MUSEUM_DB_HOST="${CLOUDRON_POSTGRESQL_HOST}" +export MUSEUM_DB_PORT="${CLOUDRON_POSTGRESQL_PORT}" +export MUSEUM_DB_USER="${CLOUDRON_POSTGRESQL_USERNAME}" +export MUSEUM_DB_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}" +export MUSEUM_DB_NAME="${CLOUDRON_POSTGRESQL_DATABASE}" +export ENTE_LOG_LEVEL=debug + +# Check if there's a pre-built binary +MUSEUM_BIN="" +if [ -f "$SERVER_DIR/bin/museum" ] && [ -x "$SERVER_DIR/bin/museum" ]; then + echo "==> Found Museum binary at $SERVER_DIR/bin/museum" + MUSEUM_BIN="$SERVER_DIR/bin/museum" +elif [ -f "/app/data/go/bin/museum" ] && [ -x "/app/data/go/bin/museum" ]; then + echo "==> Found Museum binary at /app/data/go/bin/museum" + MUSEUM_BIN="/app/data/go/bin/museum" +fi + +# Start server +if [ -n "$MUSEUM_BIN" ]; then + echo "==> Starting Museum from binary: $MUSEUM_BIN" + $MUSEUM_BIN serve > /app/data/logs/museum.log 2>&1 & + SERVER_PID=$! +elif [ -d "$SERVER_DIR/cmd/museum" ]; then + echo "==> Starting Museum from source" + /usr/local/bin/gosu cloudron:cloudron env GOCACHE=/app/data/go/cache GOMODCACHE=/app/data/go/pkg/mod \ + go run cmd/museum/main.go serve > /app/data/logs/museum.log 2>&1 & + SERVER_PID=$! +else + echo "==> ERROR: Museum server not found" + echo "==> Starting a mock server" + + # Create a simple mock server using netcat + while true; do + echo -e "HTTP/1.1 503 Service Unavailable\nContent-Type: application/json\n\n{\"error\":\"Museum server not available\"}" | nc -l -p $API_PORT + done & + SERVER_PID=$! + + echo "==> Mock server started with PID $SERVER_PID" +fi + +echo "==> Server started with PID $SERVER_PID" + +# Test if API is responding +echo "==> Testing API connectivity" +for i in {1..5}; do + if curl -s --max-time 2 --fail http://localhost:$API_PORT/health > /dev/null; then + echo "==> API is responding on port $API_PORT" + break + else + if [ $i -eq 5 ]; then + echo "==> WARNING: API is not responding after several attempts" + echo "==> Last 20 lines of museum.log:" + tail -20 /app/data/logs/museum.log || echo "==> No museum.log available" + else + echo "==> Attempt $i: Waiting for API to start... (2 seconds)" + sleep 2 + fi + fi +done + +echo "==> Application is now running" +echo "==> Access your Ente instance at: $CLOUDRON_APP_ORIGIN" +echo "==> To view debug information, visit: $CLOUDRON_APP_ORIGIN/debug" + +echo "==> Entering wait state - press Ctrl+C to stop" +# Wait for all background processes to complete (or for user to interrupt) +wait $SERVER_PID +wait $CADDY_PID \ No newline at end of file