Loading start.sh +322 −110 Original line number Diff line number Diff line #!/bin/bash # Better signal handling - forward signals to child processes trap 'kill -TERM $SERVER_PID; kill -TERM $CADDY_PID; exit' TERM INT trap 'kill -TERM $SERVER_PID; kill -TERM $PUBLIC_SERVER_PID; kill -TERM $CADDY_PID; exit' TERM INT set -eu Loading Loading @@ -231,6 +231,7 @@ mkdir -p /app/data/caddy # Define ports CADDY_PORT=3080 API_PORT=8080 PUBLIC_ALBUMS_PORT=8081 # New port for public albums service # Check if ports are available echo "==> Checking port availability" Loading @@ -246,6 +247,12 @@ else echo "==> Port $API_PORT is available for API server" fi if lsof -i:$PUBLIC_ALBUMS_PORT > /dev/null 2>&1; then echo "==> WARNING: Port $PUBLIC_ALBUMS_PORT is already in use" else echo "==> Port $PUBLIC_ALBUMS_PORT is available for Public Albums server" fi # 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) Loading Loading @@ -343,11 +350,15 @@ if [ -d "$SERVER_DIR/cmd/museum" ]; then if [ -f "$MAIN_GO" ]; then echo "==> Patching main.go to force correct database host" # Create a backup of the original file cp "$MAIN_GO" "${MAIN_GO}.orig" # Create writable directory for patched files mkdir -p /app/data/patched # Copy the file to a writable location before patching cp "$MAIN_GO" "/app/data/patched/main.go" WRITABLE_MAIN_GO="/app/data/patched/main.go" # Look for setupDatabase function and patch it DB_SETUP_LINE=$(grep -n "func setupDatabase" "$MAIN_GO" | cut -d: -f1) DB_SETUP_LINE=$(grep -n "func setupDatabase" "$WRITABLE_MAIN_GO" | cut -d: -f1) if [ -n "$DB_SETUP_LINE" ]; then echo "==> Found setupDatabase function at line $DB_SETUP_LINE" Loading @@ -356,25 +367,24 @@ if [ -d "$SERVER_DIR/cmd/museum" ]; then sed -i "${DB_SETUP_LINE}a\\ \\tlog.Printf(\"Forcing database host to %s\", \"${CLOUDRON_POSTGRESQL_HOST}\")\\ \\tos.Setenv(\"PGHOST\", \"${CLOUDRON_POSTGRESQL_HOST}\")\\ \\tos.Setenv(\"PGHOSTADDR\", \"${CLOUDRON_POSTGRESQL_HOST}\")" "$MAIN_GO" \\tos.Setenv(\"PGHOSTADDR\", \"${CLOUDRON_POSTGRESQL_HOST}\")" "$WRITABLE_MAIN_GO" echo "==> Patched setupDatabase function" fi # If there's a connection string being built, patch that too CONN_STR_LINE=$(grep -n "postgres://" "$MAIN_GO" | head -1 | cut -d: -f1) CONN_STR_LINE=$(grep -n "postgres://" "$WRITABLE_MAIN_GO" | head -1 | cut -d: -f1) if [ -n "$CONN_STR_LINE" ]; then echo "==> Found connection string at line $CONN_STR_LINE" # Backup again just to be safe cp "$MAIN_GO" "${MAIN_GO}.conn_patch" # Replace localhost or [::1] with the actual host sed -i "s/localhost/${CLOUDRON_POSTGRESQL_HOST}/g" "$MAIN_GO" sed -i "s/\[::1\]/${CLOUDRON_POSTGRESQL_HOST}/g" "$MAIN_GO" sed -i "s/localhost/${CLOUDRON_POSTGRESQL_HOST}/g" "$WRITABLE_MAIN_GO" sed -i "s/\[::1\]/${CLOUDRON_POSTGRESQL_HOST}/g" "$WRITABLE_MAIN_GO" echo "==> Patched connection string" fi echo "==> Will use patched version at runtime" fi fi Loading Loading @@ -423,103 +433,8 @@ else echo "==> Skipping migration state check: cmd/museum not found" fi # Set up Caddy web server echo "==> Setting up Caddy web server" # Create a Caddyfile for serving web apps and reverse proxy to API cat > /app/data/caddy/Caddyfile <<EOT # Global settings { admin off auto_https off http_port $CADDY_PORT https_port 0 } # Main site configuration :$CADDY_PORT { # Basic logging log { level INFO output file /app/data/logs/caddy.log } # Root path serves the photos app handle / { root * /app/web/photos try_files {path} /index.html file_server } # Accounts app handle /accounts/* { root * /app/web/accounts uri strip_prefix /accounts try_files {path} /index.html file_server } # Auth app handle /auth/* { root * /app/web/auth uri strip_prefix /auth try_files {path} /index.html file_server } # Cast app handle /cast/* { root * /app/web/cast uri strip_prefix /cast try_files {path} /index.html file_server } # API proxy handle /api/* { uri strip_prefix /api reverse_proxy localhost:$API_PORT } # Health check endpoints handle /health { respond "OK" } handle /healthcheck { respond "OK" } handle /api/health { uri strip_prefix /api reverse_proxy localhost:$API_PORT } # Configuration scripts handle /config.js { respond " // Direct configuration for Ente window.ENTE_CONFIG = { API_URL: '${API_ENDPOINT}' }; // Next.js environment variables window.process = window.process || {}; window.process.env = window.process.env || {}; window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = '${API_ENDPOINT}'; console.log('Ente config loaded - API_URL:', window.ENTE_CONFIG.API_URL); " 200 { Content-Type "application/javascript" } } } EOT echo "==> Created Caddy config at /app/data/caddy/Caddyfile" # Start the Museum server with proper environment variables echo "==> Starting Museum server" echo "==> Starting main Museum server" cd "$SERVER_DIR" # Check if there's a pre-built binary Loading Loading @@ -560,8 +475,17 @@ CLOUDRON_POSTGRESQL_PORT="${CLOUDRON_POSTGRESQL_PORT}" \ CLOUDRON_POSTGRESQL_USERNAME="${CLOUDRON_POSTGRESQL_USERNAME}" \ CLOUDRON_POSTGRESQL_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}" \ CLOUDRON_POSTGRESQL_DATABASE="${CLOUDRON_POSTGRESQL_DATABASE}" \ go run -ldflags "-X 'github.com/lib/pq.defaulthost=${MUSEUM_DB_HOST}'" overrides/db_override.go cmd/museum/main.go serve EOF # Check if we have a patched main.go to use if [ -f "/app/data/patched/main.go" ]; then echo "Using patched main.go from writable location" echo "go run -ldflags \"-X 'github.com/lib/pq.defaulthost=${MUSEUM_DB_HOST}'\" overrides/db_override.go /app/data/patched/main.go serve" >> /tmp/run_server.sh else echo "Using original main.go from read-only location" echo "go run -ldflags \"-X 'github.com/lib/pq.defaulthost=${MUSEUM_DB_HOST}'\" overrides/db_override.go cmd/museum/main.go serve" >> /tmp/run_server.sh fi chmod +x /tmp/run_server.sh /usr/local/bin/gosu cloudron:cloudron env \ Loading Loading @@ -672,7 +596,7 @@ 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 if curl -s --max-time 2 --fail http://0.0.0.0:$API_PORT/health > /dev/null; then echo "==> API is responding on port $API_PORT" break else Loading @@ -687,6 +611,264 @@ for i in {1..5}; do fi done # Start the Public Albums Museum server (second instance) echo "==> Starting Public Albums Museum server" # Create configuration for public albums instance mkdir -p /app/data/config/public cp /app/data/config/museum.yaml /app/data/config/public/museum.yaml if [ -n "$MUSEUM_BIN" ]; then echo "==> Starting Public Albums Museum from binary: $MUSEUM_BIN" MUSEUM_CONFIG="/app/data/config/public/museum.yaml" $MUSEUM_BIN serve --port $PUBLIC_ALBUMS_PORT > /app/data/logs/public_museum.log 2>&1 & PUBLIC_SERVER_PID=$! elif [ -d "$SERVER_DIR/cmd/museum" ]; then echo "==> Starting Public Albums Museum from source" # Create a startup script cat > /tmp/run_public_server.sh <<EOF #!/bin/bash cd "$SERVER_DIR" && \ PGHOST="${CLOUDRON_POSTGRESQL_HOST}" \ PGPORT="${CLOUDRON_POSTGRESQL_PORT}" \ PGUSER="${CLOUDRON_POSTGRESQL_USERNAME}" \ PGPASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}" \ PGDATABASE="${CLOUDRON_POSTGRESQL_DATABASE}" \ PGSSLMODE="disable" \ ENTE_PG_HOST="${MUSEUM_DB_HOST}" \ ENTE_PG_PORT="${MUSEUM_DB_PORT}" \ ENTE_PG_USER="${MUSEUM_DB_USER}" \ ENTE_PG_PASSWORD="${MUSEUM_DB_PASSWORD}" \ ENTE_PG_DATABASE="${MUSEUM_DB_NAME}" \ ENTE_PG_DSN="postgres://${MUSEUM_DB_USER}:${MUSEUM_DB_PASSWORD}@${MUSEUM_DB_HOST}:${MUSEUM_DB_PORT}/${MUSEUM_DB_NAME}?sslmode=disable&host=${MUSEUM_DB_HOST}" \ CLOUDRON_POSTGRESQL_HOST="${CLOUDRON_POSTGRESQL_HOST}" \ CLOUDRON_POSTGRESQL_PORT="${CLOUDRON_POSTGRESQL_PORT}" \ CLOUDRON_POSTGRESQL_USERNAME="${CLOUDRON_POSTGRESQL_USERNAME}" \ CLOUDRON_POSTGRESQL_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}" \ CLOUDRON_POSTGRESQL_DATABASE="${CLOUDRON_POSTGRESQL_DATABASE}" \ EOF # Check if we have a patched main.go to use if [ -f "/app/data/patched/main.go" ]; then echo "Using patched main.go from writable location" echo "go run -ldflags \"-X 'github.com/lib/pq.defaulthost=${MUSEUM_DB_HOST}'\" overrides/db_override.go /app/data/patched/main.go serve --port $PUBLIC_ALBUMS_PORT" >> /tmp/run_public_server.sh else echo "Using original main.go from read-only location" echo "go run -ldflags \"-X 'github.com/lib/pq.defaulthost=${MUSEUM_DB_HOST}'\" overrides/db_override.go cmd/museum/main.go serve --port $PUBLIC_ALBUMS_PORT" >> /tmp/run_public_server.sh fi chmod +x /tmp/run_public_server.sh /usr/local/bin/gosu cloudron:cloudron env \ GOCACHE="$GOCACHE" \ GOMODCACHE="$GOMODCACHE" \ GO111MODULE=on \ GOFLAGS="$GOFLAGS" \ MUSEUM_CONFIG="/app/data/config/public/museum.yaml" \ MUSEUM_DB_HOST="$MUSEUM_DB_HOST" \ MUSEUM_DB_PORT="$MUSEUM_DB_PORT" \ MUSEUM_DB_USER="$MUSEUM_DB_USER" \ MUSEUM_DB_PASSWORD="$MUSEUM_DB_PASSWORD" \ MUSEUM_DB_NAME="$MUSEUM_DB_NAME" \ ENTE_PG_DSN="postgres://${MUSEUM_DB_USER}:${MUSEUM_DB_PASSWORD}@${MUSEUM_DB_HOST}:${MUSEUM_DB_PORT}/${MUSEUM_DB_NAME}?sslmode=disable" \ ENTE_PG_HOST="$MUSEUM_DB_HOST" \ ENTE_PG_PORT="$MUSEUM_DB_PORT" \ ENTE_PG_USER="$MUSEUM_DB_USER" \ ENTE_PG_PASSWORD="$MUSEUM_DB_PASSWORD" \ ENTE_PG_DATABASE="$MUSEUM_DB_NAME" \ PGHOST="$PGHOST" \ PGPORT="$PGPORT" \ PGUSER="$PGUSER" \ PGPASSWORD="$PGPASSWORD" \ PGDATABASE="$PGDATABASE" \ PGSSLMODE="$PGSSLMODE" \ ENTE_LOG_LEVEL=debug \ bash /tmp/run_public_server.sh > /app/data/logs/public_museum.log 2>&1 & PUBLIC_SERVER_PID=$! else echo "==> ERROR: Museum server not found for public albums" echo "==> Starting a mock public albums server" # Create a temporary directory for a simple Go server mkdir -p /tmp/mock-public-server cat > /tmp/mock-public-server/main.go.template <<EOT package main import ( "fmt" "log" "net/http" "os" "time" ) func main() { // Log environment variables log.Println("Starting mock Public Albums API server") log.Println("Running on port: PORT_NUMBER") // Add a health endpoint http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") fmt.Fprint(w, `{"status":"ok","message":"Mock Public Albums server running","time":"` + time.Now().String() + `"}`) }) // Handle all other requests http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { log.Printf("Public Albums: Received request for %s via %s", r.URL.Path, r.Method) w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `{"status":"mock","service":"public_albums","endpoint":"%s","method":"%s","time":"%s"}`, r.URL.Path, r.Method, time.Now().String()) }) // Start the server log.Printf("Starting mock Public Albums server on port PORT_NUMBER\n") if err := http.ListenAndServe(":PORT_NUMBER", nil); err != nil { log.Fatalf("Failed to start Public Albums server: %v", err) } } EOT # Replace the port placeholder with the actual port number sed "s/PORT_NUMBER/$PUBLIC_ALBUMS_PORT/g" /tmp/mock-public-server/main.go.template > /tmp/mock-public-server/main.go # Run the mock server with environment variables cd /tmp/mock-public-server go run main.go > /app/data/logs/public_museum.log 2>&1 & PUBLIC_SERVER_PID=$! echo "==> Mock Public Albums server started with PID $PUBLIC_SERVER_PID" fi echo "==> Public Albums server started with PID $PUBLIC_SERVER_PID" # Test if Public Albums API is responding echo "==> Testing Public Albums API connectivity" for i in {1..5}; do if curl -s --max-time 2 --fail http://0.0.0.0:$PUBLIC_ALBUMS_PORT/health > /dev/null; then echo "==> Public Albums API is responding on port $PUBLIC_ALBUMS_PORT" break else if [ $i -eq 5 ]; then echo "==> WARNING: Public Albums API is not responding after several attempts" echo "==> Last 20 lines of public_museum.log:" tail -20 /app/data/logs/public_museum.log || echo "==> No public_museum.log available" else echo "==> Attempt $i: Waiting for Public Albums API to start... (2 seconds)" sleep 2 fi fi done # Set up Caddy web server echo "==> Setting up Caddy web server" # Create a Caddyfile for serving web apps and reverse proxy to API cat > /app/data/caddy/Caddyfile <<EOT # Global settings { admin off auto_https off http_port $CADDY_PORT https_port 0 } # Main site configuration :$CADDY_PORT { # Basic logging log { level INFO output file /app/data/logs/caddy.log } # Root path serves the photos app handle / { root * /app/web/photos try_files {path} /index.html file_server } # Accounts app handle /accounts/* { root * /app/web/accounts uri strip_prefix /accounts try_files {path} /index.html file_server } # Auth app handle /auth/* { root * /app/web/auth uri strip_prefix /auth try_files {path} /index.html file_server } # Cast app handle /cast/* { root * /app/web/cast uri strip_prefix /cast try_files {path} /index.html file_server } # Main API proxy handle /api/* { uri strip_prefix /api reverse_proxy 0.0.0.0:$API_PORT } # Public albums API proxy handle /public/* { uri strip_prefix /public reverse_proxy 0.0.0.0:$PUBLIC_ALBUMS_PORT } # Health check endpoints handle /health { respond "OK" } handle /healthcheck { respond "OK" } handle /api/health { uri strip_prefix /api reverse_proxy 0.0.0.0:$API_PORT } handle /public/health { uri strip_prefix /public reverse_proxy 0.0.0.0:$PUBLIC_ALBUMS_PORT } # Configuration scripts handle /config.js { respond " // Direct configuration for Ente window.ENTE_CONFIG = { API_URL: '${API_ENDPOINT}', PUBLIC_ALBUMS_URL: '${CLOUDRON_APP_ORIGIN}/public' }; // Next.js environment variables window.process = window.process || {}; window.process.env = window.process.env || {}; window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = '${API_ENDPOINT}'; window.process.env.NEXT_PUBLIC_ENTE_PUBLIC_ALBUMS_ENDPOINT = '${CLOUDRON_APP_ORIGIN}/public'; console.log('Ente config loaded - API_URL:', window.ENTE_CONFIG.API_URL); console.log('Ente config loaded - PUBLIC_ALBUMS_URL:', window.ENTE_CONFIG.PUBLIC_ALBUMS_URL); " 200 { Content-Type "application/javascript" } } } EOT echo "==> Created Caddy config at /app/data/caddy/Caddyfile" # Start Caddy server echo "==> Starting Caddy server" caddy start --config /app/data/caddy/Caddyfile --adapter caddyfile & Loading @@ -699,7 +881,7 @@ sleep 2 # Test Caddy connectivity echo "==> Testing Caddy connectivity" for i in {1..5}; do if curl -s --max-time 2 --fail http://localhost:$CADDY_PORT/health > /dev/null; then if curl -s --max-time 2 --fail http://0.0.0.0:$CADDY_PORT/health > /dev/null; then echo "==> Caddy is responding on port $CADDY_PORT" break else Loading @@ -716,9 +898,39 @@ done echo "==> Application is now running" echo "==> Access your Ente instance at: $CLOUDRON_APP_ORIGIN" # Check communication between frontend and backend services echo "==> Checking communication between frontend and backend services" echo "==> Testing main API communication" MAIN_API_TEST=$(curl -s --max-time 2 http://0.0.0.0:$CADDY_PORT/api/health) if [ $? -eq 0 ]; then echo "==> Main API communication via frontend is working" else echo "==> WARNING: Main API communication via frontend is NOT working" echo "==> Response: $MAIN_API_TEST" fi echo "==> Testing public albums API communication" PUBLIC_API_TEST=$(curl -s --max-time 2 http://0.0.0.0:$CADDY_PORT/public/health) if [ $? -eq 0 ]; then echo "==> Public Albums API communication via frontend is working" else echo "==> WARNING: Public Albums API communication via frontend is NOT working" echo "==> Response: $PUBLIC_API_TEST" fi echo "==> Testing frontend config.js" CONFIG_JS_TEST=$(curl -s --max-time 2 http://0.0.0.0:$CADDY_PORT/config.js) if [[ "$CONFIG_JS_TEST" == *"API_URL"* && "$CONFIG_JS_TEST" == *"PUBLIC_ALBUMS_URL"* ]]; then echo "==> Frontend configuration is properly loaded" else echo "==> WARNING: Frontend configuration is not properly loaded" echo "==> Response: $CONFIG_JS_TEST" fi 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 $PUBLIC_SERVER_PID wait $CADDY_PID # Create a new go file to inject into the build that overrides the database connection Loading Loading
start.sh +322 −110 Original line number Diff line number Diff line #!/bin/bash # Better signal handling - forward signals to child processes trap 'kill -TERM $SERVER_PID; kill -TERM $CADDY_PID; exit' TERM INT trap 'kill -TERM $SERVER_PID; kill -TERM $PUBLIC_SERVER_PID; kill -TERM $CADDY_PID; exit' TERM INT set -eu Loading Loading @@ -231,6 +231,7 @@ mkdir -p /app/data/caddy # Define ports CADDY_PORT=3080 API_PORT=8080 PUBLIC_ALBUMS_PORT=8081 # New port for public albums service # Check if ports are available echo "==> Checking port availability" Loading @@ -246,6 +247,12 @@ else echo "==> Port $API_PORT is available for API server" fi if lsof -i:$PUBLIC_ALBUMS_PORT > /dev/null 2>&1; then echo "==> WARNING: Port $PUBLIC_ALBUMS_PORT is already in use" else echo "==> Port $PUBLIC_ALBUMS_PORT is available for Public Albums server" fi # 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) Loading Loading @@ -343,11 +350,15 @@ if [ -d "$SERVER_DIR/cmd/museum" ]; then if [ -f "$MAIN_GO" ]; then echo "==> Patching main.go to force correct database host" # Create a backup of the original file cp "$MAIN_GO" "${MAIN_GO}.orig" # Create writable directory for patched files mkdir -p /app/data/patched # Copy the file to a writable location before patching cp "$MAIN_GO" "/app/data/patched/main.go" WRITABLE_MAIN_GO="/app/data/patched/main.go" # Look for setupDatabase function and patch it DB_SETUP_LINE=$(grep -n "func setupDatabase" "$MAIN_GO" | cut -d: -f1) DB_SETUP_LINE=$(grep -n "func setupDatabase" "$WRITABLE_MAIN_GO" | cut -d: -f1) if [ -n "$DB_SETUP_LINE" ]; then echo "==> Found setupDatabase function at line $DB_SETUP_LINE" Loading @@ -356,25 +367,24 @@ if [ -d "$SERVER_DIR/cmd/museum" ]; then sed -i "${DB_SETUP_LINE}a\\ \\tlog.Printf(\"Forcing database host to %s\", \"${CLOUDRON_POSTGRESQL_HOST}\")\\ \\tos.Setenv(\"PGHOST\", \"${CLOUDRON_POSTGRESQL_HOST}\")\\ \\tos.Setenv(\"PGHOSTADDR\", \"${CLOUDRON_POSTGRESQL_HOST}\")" "$MAIN_GO" \\tos.Setenv(\"PGHOSTADDR\", \"${CLOUDRON_POSTGRESQL_HOST}\")" "$WRITABLE_MAIN_GO" echo "==> Patched setupDatabase function" fi # If there's a connection string being built, patch that too CONN_STR_LINE=$(grep -n "postgres://" "$MAIN_GO" | head -1 | cut -d: -f1) CONN_STR_LINE=$(grep -n "postgres://" "$WRITABLE_MAIN_GO" | head -1 | cut -d: -f1) if [ -n "$CONN_STR_LINE" ]; then echo "==> Found connection string at line $CONN_STR_LINE" # Backup again just to be safe cp "$MAIN_GO" "${MAIN_GO}.conn_patch" # Replace localhost or [::1] with the actual host sed -i "s/localhost/${CLOUDRON_POSTGRESQL_HOST}/g" "$MAIN_GO" sed -i "s/\[::1\]/${CLOUDRON_POSTGRESQL_HOST}/g" "$MAIN_GO" sed -i "s/localhost/${CLOUDRON_POSTGRESQL_HOST}/g" "$WRITABLE_MAIN_GO" sed -i "s/\[::1\]/${CLOUDRON_POSTGRESQL_HOST}/g" "$WRITABLE_MAIN_GO" echo "==> Patched connection string" fi echo "==> Will use patched version at runtime" fi fi Loading Loading @@ -423,103 +433,8 @@ else echo "==> Skipping migration state check: cmd/museum not found" fi # Set up Caddy web server echo "==> Setting up Caddy web server" # Create a Caddyfile for serving web apps and reverse proxy to API cat > /app/data/caddy/Caddyfile <<EOT # Global settings { admin off auto_https off http_port $CADDY_PORT https_port 0 } # Main site configuration :$CADDY_PORT { # Basic logging log { level INFO output file /app/data/logs/caddy.log } # Root path serves the photos app handle / { root * /app/web/photos try_files {path} /index.html file_server } # Accounts app handle /accounts/* { root * /app/web/accounts uri strip_prefix /accounts try_files {path} /index.html file_server } # Auth app handle /auth/* { root * /app/web/auth uri strip_prefix /auth try_files {path} /index.html file_server } # Cast app handle /cast/* { root * /app/web/cast uri strip_prefix /cast try_files {path} /index.html file_server } # API proxy handle /api/* { uri strip_prefix /api reverse_proxy localhost:$API_PORT } # Health check endpoints handle /health { respond "OK" } handle /healthcheck { respond "OK" } handle /api/health { uri strip_prefix /api reverse_proxy localhost:$API_PORT } # Configuration scripts handle /config.js { respond " // Direct configuration for Ente window.ENTE_CONFIG = { API_URL: '${API_ENDPOINT}' }; // Next.js environment variables window.process = window.process || {}; window.process.env = window.process.env || {}; window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = '${API_ENDPOINT}'; console.log('Ente config loaded - API_URL:', window.ENTE_CONFIG.API_URL); " 200 { Content-Type "application/javascript" } } } EOT echo "==> Created Caddy config at /app/data/caddy/Caddyfile" # Start the Museum server with proper environment variables echo "==> Starting Museum server" echo "==> Starting main Museum server" cd "$SERVER_DIR" # Check if there's a pre-built binary Loading Loading @@ -560,8 +475,17 @@ CLOUDRON_POSTGRESQL_PORT="${CLOUDRON_POSTGRESQL_PORT}" \ CLOUDRON_POSTGRESQL_USERNAME="${CLOUDRON_POSTGRESQL_USERNAME}" \ CLOUDRON_POSTGRESQL_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}" \ CLOUDRON_POSTGRESQL_DATABASE="${CLOUDRON_POSTGRESQL_DATABASE}" \ go run -ldflags "-X 'github.com/lib/pq.defaulthost=${MUSEUM_DB_HOST}'" overrides/db_override.go cmd/museum/main.go serve EOF # Check if we have a patched main.go to use if [ -f "/app/data/patched/main.go" ]; then echo "Using patched main.go from writable location" echo "go run -ldflags \"-X 'github.com/lib/pq.defaulthost=${MUSEUM_DB_HOST}'\" overrides/db_override.go /app/data/patched/main.go serve" >> /tmp/run_server.sh else echo "Using original main.go from read-only location" echo "go run -ldflags \"-X 'github.com/lib/pq.defaulthost=${MUSEUM_DB_HOST}'\" overrides/db_override.go cmd/museum/main.go serve" >> /tmp/run_server.sh fi chmod +x /tmp/run_server.sh /usr/local/bin/gosu cloudron:cloudron env \ Loading Loading @@ -672,7 +596,7 @@ 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 if curl -s --max-time 2 --fail http://0.0.0.0:$API_PORT/health > /dev/null; then echo "==> API is responding on port $API_PORT" break else Loading @@ -687,6 +611,264 @@ for i in {1..5}; do fi done # Start the Public Albums Museum server (second instance) echo "==> Starting Public Albums Museum server" # Create configuration for public albums instance mkdir -p /app/data/config/public cp /app/data/config/museum.yaml /app/data/config/public/museum.yaml if [ -n "$MUSEUM_BIN" ]; then echo "==> Starting Public Albums Museum from binary: $MUSEUM_BIN" MUSEUM_CONFIG="/app/data/config/public/museum.yaml" $MUSEUM_BIN serve --port $PUBLIC_ALBUMS_PORT > /app/data/logs/public_museum.log 2>&1 & PUBLIC_SERVER_PID=$! elif [ -d "$SERVER_DIR/cmd/museum" ]; then echo "==> Starting Public Albums Museum from source" # Create a startup script cat > /tmp/run_public_server.sh <<EOF #!/bin/bash cd "$SERVER_DIR" && \ PGHOST="${CLOUDRON_POSTGRESQL_HOST}" \ PGPORT="${CLOUDRON_POSTGRESQL_PORT}" \ PGUSER="${CLOUDRON_POSTGRESQL_USERNAME}" \ PGPASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}" \ PGDATABASE="${CLOUDRON_POSTGRESQL_DATABASE}" \ PGSSLMODE="disable" \ ENTE_PG_HOST="${MUSEUM_DB_HOST}" \ ENTE_PG_PORT="${MUSEUM_DB_PORT}" \ ENTE_PG_USER="${MUSEUM_DB_USER}" \ ENTE_PG_PASSWORD="${MUSEUM_DB_PASSWORD}" \ ENTE_PG_DATABASE="${MUSEUM_DB_NAME}" \ ENTE_PG_DSN="postgres://${MUSEUM_DB_USER}:${MUSEUM_DB_PASSWORD}@${MUSEUM_DB_HOST}:${MUSEUM_DB_PORT}/${MUSEUM_DB_NAME}?sslmode=disable&host=${MUSEUM_DB_HOST}" \ CLOUDRON_POSTGRESQL_HOST="${CLOUDRON_POSTGRESQL_HOST}" \ CLOUDRON_POSTGRESQL_PORT="${CLOUDRON_POSTGRESQL_PORT}" \ CLOUDRON_POSTGRESQL_USERNAME="${CLOUDRON_POSTGRESQL_USERNAME}" \ CLOUDRON_POSTGRESQL_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}" \ CLOUDRON_POSTGRESQL_DATABASE="${CLOUDRON_POSTGRESQL_DATABASE}" \ EOF # Check if we have a patched main.go to use if [ -f "/app/data/patched/main.go" ]; then echo "Using patched main.go from writable location" echo "go run -ldflags \"-X 'github.com/lib/pq.defaulthost=${MUSEUM_DB_HOST}'\" overrides/db_override.go /app/data/patched/main.go serve --port $PUBLIC_ALBUMS_PORT" >> /tmp/run_public_server.sh else echo "Using original main.go from read-only location" echo "go run -ldflags \"-X 'github.com/lib/pq.defaulthost=${MUSEUM_DB_HOST}'\" overrides/db_override.go cmd/museum/main.go serve --port $PUBLIC_ALBUMS_PORT" >> /tmp/run_public_server.sh fi chmod +x /tmp/run_public_server.sh /usr/local/bin/gosu cloudron:cloudron env \ GOCACHE="$GOCACHE" \ GOMODCACHE="$GOMODCACHE" \ GO111MODULE=on \ GOFLAGS="$GOFLAGS" \ MUSEUM_CONFIG="/app/data/config/public/museum.yaml" \ MUSEUM_DB_HOST="$MUSEUM_DB_HOST" \ MUSEUM_DB_PORT="$MUSEUM_DB_PORT" \ MUSEUM_DB_USER="$MUSEUM_DB_USER" \ MUSEUM_DB_PASSWORD="$MUSEUM_DB_PASSWORD" \ MUSEUM_DB_NAME="$MUSEUM_DB_NAME" \ ENTE_PG_DSN="postgres://${MUSEUM_DB_USER}:${MUSEUM_DB_PASSWORD}@${MUSEUM_DB_HOST}:${MUSEUM_DB_PORT}/${MUSEUM_DB_NAME}?sslmode=disable" \ ENTE_PG_HOST="$MUSEUM_DB_HOST" \ ENTE_PG_PORT="$MUSEUM_DB_PORT" \ ENTE_PG_USER="$MUSEUM_DB_USER" \ ENTE_PG_PASSWORD="$MUSEUM_DB_PASSWORD" \ ENTE_PG_DATABASE="$MUSEUM_DB_NAME" \ PGHOST="$PGHOST" \ PGPORT="$PGPORT" \ PGUSER="$PGUSER" \ PGPASSWORD="$PGPASSWORD" \ PGDATABASE="$PGDATABASE" \ PGSSLMODE="$PGSSLMODE" \ ENTE_LOG_LEVEL=debug \ bash /tmp/run_public_server.sh > /app/data/logs/public_museum.log 2>&1 & PUBLIC_SERVER_PID=$! else echo "==> ERROR: Museum server not found for public albums" echo "==> Starting a mock public albums server" # Create a temporary directory for a simple Go server mkdir -p /tmp/mock-public-server cat > /tmp/mock-public-server/main.go.template <<EOT package main import ( "fmt" "log" "net/http" "os" "time" ) func main() { // Log environment variables log.Println("Starting mock Public Albums API server") log.Println("Running on port: PORT_NUMBER") // Add a health endpoint http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") fmt.Fprint(w, `{"status":"ok","message":"Mock Public Albums server running","time":"` + time.Now().String() + `"}`) }) // Handle all other requests http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { log.Printf("Public Albums: Received request for %s via %s", r.URL.Path, r.Method) w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `{"status":"mock","service":"public_albums","endpoint":"%s","method":"%s","time":"%s"}`, r.URL.Path, r.Method, time.Now().String()) }) // Start the server log.Printf("Starting mock Public Albums server on port PORT_NUMBER\n") if err := http.ListenAndServe(":PORT_NUMBER", nil); err != nil { log.Fatalf("Failed to start Public Albums server: %v", err) } } EOT # Replace the port placeholder with the actual port number sed "s/PORT_NUMBER/$PUBLIC_ALBUMS_PORT/g" /tmp/mock-public-server/main.go.template > /tmp/mock-public-server/main.go # Run the mock server with environment variables cd /tmp/mock-public-server go run main.go > /app/data/logs/public_museum.log 2>&1 & PUBLIC_SERVER_PID=$! echo "==> Mock Public Albums server started with PID $PUBLIC_SERVER_PID" fi echo "==> Public Albums server started with PID $PUBLIC_SERVER_PID" # Test if Public Albums API is responding echo "==> Testing Public Albums API connectivity" for i in {1..5}; do if curl -s --max-time 2 --fail http://0.0.0.0:$PUBLIC_ALBUMS_PORT/health > /dev/null; then echo "==> Public Albums API is responding on port $PUBLIC_ALBUMS_PORT" break else if [ $i -eq 5 ]; then echo "==> WARNING: Public Albums API is not responding after several attempts" echo "==> Last 20 lines of public_museum.log:" tail -20 /app/data/logs/public_museum.log || echo "==> No public_museum.log available" else echo "==> Attempt $i: Waiting for Public Albums API to start... (2 seconds)" sleep 2 fi fi done # Set up Caddy web server echo "==> Setting up Caddy web server" # Create a Caddyfile for serving web apps and reverse proxy to API cat > /app/data/caddy/Caddyfile <<EOT # Global settings { admin off auto_https off http_port $CADDY_PORT https_port 0 } # Main site configuration :$CADDY_PORT { # Basic logging log { level INFO output file /app/data/logs/caddy.log } # Root path serves the photos app handle / { root * /app/web/photos try_files {path} /index.html file_server } # Accounts app handle /accounts/* { root * /app/web/accounts uri strip_prefix /accounts try_files {path} /index.html file_server } # Auth app handle /auth/* { root * /app/web/auth uri strip_prefix /auth try_files {path} /index.html file_server } # Cast app handle /cast/* { root * /app/web/cast uri strip_prefix /cast try_files {path} /index.html file_server } # Main API proxy handle /api/* { uri strip_prefix /api reverse_proxy 0.0.0.0:$API_PORT } # Public albums API proxy handle /public/* { uri strip_prefix /public reverse_proxy 0.0.0.0:$PUBLIC_ALBUMS_PORT } # Health check endpoints handle /health { respond "OK" } handle /healthcheck { respond "OK" } handle /api/health { uri strip_prefix /api reverse_proxy 0.0.0.0:$API_PORT } handle /public/health { uri strip_prefix /public reverse_proxy 0.0.0.0:$PUBLIC_ALBUMS_PORT } # Configuration scripts handle /config.js { respond " // Direct configuration for Ente window.ENTE_CONFIG = { API_URL: '${API_ENDPOINT}', PUBLIC_ALBUMS_URL: '${CLOUDRON_APP_ORIGIN}/public' }; // Next.js environment variables window.process = window.process || {}; window.process.env = window.process.env || {}; window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = '${API_ENDPOINT}'; window.process.env.NEXT_PUBLIC_ENTE_PUBLIC_ALBUMS_ENDPOINT = '${CLOUDRON_APP_ORIGIN}/public'; console.log('Ente config loaded - API_URL:', window.ENTE_CONFIG.API_URL); console.log('Ente config loaded - PUBLIC_ALBUMS_URL:', window.ENTE_CONFIG.PUBLIC_ALBUMS_URL); " 200 { Content-Type "application/javascript" } } } EOT echo "==> Created Caddy config at /app/data/caddy/Caddyfile" # Start Caddy server echo "==> Starting Caddy server" caddy start --config /app/data/caddy/Caddyfile --adapter caddyfile & Loading @@ -699,7 +881,7 @@ sleep 2 # Test Caddy connectivity echo "==> Testing Caddy connectivity" for i in {1..5}; do if curl -s --max-time 2 --fail http://localhost:$CADDY_PORT/health > /dev/null; then if curl -s --max-time 2 --fail http://0.0.0.0:$CADDY_PORT/health > /dev/null; then echo "==> Caddy is responding on port $CADDY_PORT" break else Loading @@ -716,9 +898,39 @@ done echo "==> Application is now running" echo "==> Access your Ente instance at: $CLOUDRON_APP_ORIGIN" # Check communication between frontend and backend services echo "==> Checking communication between frontend and backend services" echo "==> Testing main API communication" MAIN_API_TEST=$(curl -s --max-time 2 http://0.0.0.0:$CADDY_PORT/api/health) if [ $? -eq 0 ]; then echo "==> Main API communication via frontend is working" else echo "==> WARNING: Main API communication via frontend is NOT working" echo "==> Response: $MAIN_API_TEST" fi echo "==> Testing public albums API communication" PUBLIC_API_TEST=$(curl -s --max-time 2 http://0.0.0.0:$CADDY_PORT/public/health) if [ $? -eq 0 ]; then echo "==> Public Albums API communication via frontend is working" else echo "==> WARNING: Public Albums API communication via frontend is NOT working" echo "==> Response: $PUBLIC_API_TEST" fi echo "==> Testing frontend config.js" CONFIG_JS_TEST=$(curl -s --max-time 2 http://0.0.0.0:$CADDY_PORT/config.js) if [[ "$CONFIG_JS_TEST" == *"API_URL"* && "$CONFIG_JS_TEST" == *"PUBLIC_ALBUMS_URL"* ]]; then echo "==> Frontend configuration is properly loaded" else echo "==> WARNING: Frontend configuration is not properly loaded" echo "==> Response: $CONFIG_JS_TEST" fi 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 $PUBLIC_SERVER_PID wait $CADDY_PID # Create a new go file to inject into the build that overrides the database connection Loading