Update Cloudron app configuration and setup

This commit is contained in:
Andreas Düren 2025-03-16 22:17:41 +01:00
parent 05a0b42b8e
commit 65e88f4408
4 changed files with 374 additions and 100 deletions

View File

@ -8,8 +8,8 @@
"tagline": "Open Source End-to-End Encrypted Photos & Authentication", "tagline": "Open Source End-to-End Encrypted Photos & Authentication",
"upstreamVersion": "1.0.0", "upstreamVersion": "1.0.0",
"version": "1.0.0", "version": "1.0.0",
"healthCheckPath": "/", "healthCheckPath": "/healthcheck",
"httpPort": 8080, "httpPort": 3080,
"memoryLimit": 1073741824, "memoryLimit": 1073741824,
"addons": { "addons": {
"localstorage": {}, "localstorage": {},
@ -18,6 +18,12 @@
"supportsDisplayName": true "supportsDisplayName": true
} }
}, },
"checklist": {
"create-permanent-admin": {
"message": "Required: S3 Storage Configuration!"
}
},
"icon": "file://logo.png", "icon": "file://logo.png",
"tags": [ "tags": [
"photos", "photos",

View File

@ -12,8 +12,10 @@ RUN apt-get update && apt-get install -y git && \
RUN corepack enable RUN corepack enable
# Set environment variables for web app build # Set environment variables for web app build
# Will be overridden at runtime with the actual server endpoint # Use "/api" as the endpoint which will be replaced at runtime with the full URL
ENV NEXT_PUBLIC_ENTE_ENDPOINT="https://localhost:8080" ENV NEXT_PUBLIC_ENTE_ENDPOINT="/api"
# Add a note for clarity
RUN echo "Building with NEXT_PUBLIC_ENTE_ENDPOINT=/api, will be replaced at runtime with full URL"
# Debugging the repository structure # Debugging the repository structure
RUN find . -type d -maxdepth 3 | sort RUN find . -type d -maxdepth 3 | sort
@ -78,8 +80,14 @@ FROM cloudron/base:5.0.0@sha256:04fd70dbd8ad6149c19de39e35718e024417c3e01dc9c663
# Install necessary packages (excluding golang as we'll install it manually) # Install necessary packages (excluding golang as we'll install it manually)
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y curl git nodejs npm libsodium23 libsodium-dev pkg-config nginx && \ apt-get install -y curl git nodejs npm libsodium23 libsodium-dev pkg-config postgresql-client && \
npm install -g yarn serve && \ npm install -g yarn serve && \
# Install Caddy instead of NGINX
apt-get install -y debian-keyring debian-archive-keyring apt-transport-https && \
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg && \
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list && \
apt-get update && \
apt-get install -y caddy && \
apt-get clean && apt-get autoremove && \ apt-get clean && apt-get autoremove && \
rm -rf /var/cache/apt /var/lib/apt/lists rm -rf /var/cache/apt /var/lib/apt/lists
@ -103,6 +111,17 @@ RUN git clone --depth=1 https://github.com/ente-io/ente.git . && \
cp -r server/go.mod server/go.sum /app/data/go/ && \ cp -r server/go.mod server/go.sum /app/data/go/ && \
chmod 777 /app/data/go/go.mod /app/data/go/go.sum chmod 777 /app/data/go/go.mod /app/data/go/go.sum
# Pre-download Go dependencies
RUN cd server && \
export GOMODCACHE="/app/data/go/pkg/mod" && \
export GOFLAGS="-modfile=/app/data/go/go.mod -mod=mod" && \
export GOTOOLCHAIN=local && \
export GO111MODULE=on && \
export GOSUMDB=off && \
mkdir -p /app/data/go/pkg/mod && \
chmod -R 777 /app/data/go && \
go mod download
# Set Go environment variables # Set Go environment variables
ENV GOTOOLCHAIN=local ENV GOTOOLCHAIN=local
ENV GO111MODULE=on ENV GO111MODULE=on
@ -127,8 +146,8 @@ RUN chmod +x /app/pkg/start.sh
# Create NGINX directories # Create NGINX directories
RUN mkdir -p /etc/nginx/sites-available /etc/nginx/sites-enabled RUN mkdir -p /etc/nginx/sites-available /etc/nginx/sites-enabled
# Expose the web port (Cloudron expects port 8080) # Expose the web port (Cloudron expects port 3080 now)
EXPOSE 8080 EXPOSE 3080
# Start the application # Start the application
CMD ["/app/pkg/start.sh"] CMD ["/app/pkg/start.sh"]

View File

@ -10,6 +10,28 @@ This repository contains the Cloudron packaging for [Ente](https://ente.io), an
- Configured to use Cloudron's mail service for sending emails - Configured to use Cloudron's mail service for sending emails
- Easy to deploy and manage through the Cloudron interface - Easy to deploy and manage through the Cloudron interface
## Requirements
### Browser Compatibility
Ente uses modern web technologies for its end-to-end encryption:
- **WebAssembly**: Required for cryptographic operations
- **IndexedDB**: Required for client-side data storage
Most modern browsers support these features, but they may be blocked by:
- Browser privacy settings
- Content Security Policies
- Certain browser extensions
This package includes custom Caddy configuration with appropriate security headers to ensure these features work correctly.
### S3-Compatible Storage
Ente requires an S3-compatible object storage service. You can use:
- Cloudron's built-in object storage
- External services like AWS S3, Wasabi, or MinIO
## Building and Installing ## Building and Installing
### Option 1: Build and Install Manually ### Option 1: Build and Install Manually
@ -53,6 +75,14 @@ The app is configured automatically using Cloudron's environment variables for:
- SMTP mail service - SMTP mail service
- App origin URL - App origin URL
### Additional Configuration
The package includes several enhancements to ensure proper functionality:
1. **Security Headers**: Custom Content-Security-Policy headers that allow WebAssembly and IndexedDB
2. **API Configuration**: Dynamic runtime configuration to ensure the frontend connects to the correct API endpoint
3. **CORS Headers**: Proper CORS configuration for API access
## Usage ## Usage
### Web Client ### Web Client
@ -77,6 +107,12 @@ cloudron update --app ente.yourdomain.com
## Troubleshooting ## Troubleshooting
### Common Issues
1. **"Failed to fetch" errors**: Check if your browser is blocking API requests to your domain
2. **WebAssembly errors**: Ensure your browser supports and allows WebAssembly (try using Chrome or Firefox)
3. **IndexedDB errors**: Make sure your browser allows IndexedDB (not in private/incognito mode)
For issues specific to the Cloudron packaging, please open an issue in this repository. For issues specific to the Cloudron packaging, please open an issue in this repository.
For issues with Ente itself, please refer to the [main Ente repository](https://github.com/ente-io/ente). For issues with Ente itself, please refer to the [main Ente repository](https://github.com/ente-io/ente).

391
start.sh
View File

@ -1,14 +1,14 @@
#!/bin/bash #!/bin/bash
# Better signal handling - forward signals to child processes # Better signal handling - forward signals to child processes
trap 'kill -TERM $SERVER_PID; kill -TERM $NGINX_PID; exit' TERM INT trap 'kill -TERM $SERVER_PID; kill -TERM $CADDY_PID; exit' TERM INT
set -eu set -eu
echo "==> Starting Ente Cloudron app..." echo "==> Starting Ente Cloudron app..."
# Create necessary directories # Create necessary directories
mkdir -p /app/data/config /app/data/storage /app/data/nginx/tmp /app/data/go /app/data/logs /run/nginx mkdir -p /app/data/config /app/data/storage /app/data/caddy /app/data/go /app/data/logs
# Add comment about Cloudron filesystem limitations # Add comment about Cloudron filesystem limitations
echo "==> NOTE: Running in Cloudron environment with limited write access" echo "==> NOTE: Running in Cloudron environment with limited write access"
@ -164,82 +164,135 @@ sed -i 's|s3.are_local_buckets: true|s3.are_local_buckets: false|g' /app/data/co
# Install or verify required packages # Install or verify required packages
echo "==> Checking for required packages" echo "==> Checking for required packages"
if ! command -v nginx &> /dev/null; then if ! command -v caddy &> /dev/null; then
echo "==> Installing NGINX" echo "==> Installing Caddy"
apt-get update && apt-get install -y nginx apt-get update && apt-get install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list
apt-get update && apt-get install -y caddy
fi fi
# Set up NGINX to serve the web apps and proxy to the Museum server # Set up Caddy to serve the web apps and proxy to the Museum server
echo "==> Setting up NGINX for web apps and API" echo "==> Setting up Caddy for web apps and API"
# Create a custom NGINX configuration in the writable data directory # Create a custom Caddy configuration in the writable data directory
cat > /app/data/nginx/ente.conf <<EOT mkdir -p /app/data/caddy
worker_processes 1; cat > /app/data/caddy/Caddyfile <<EOT
error_log stderr; {
daemon off; admin off
pid /app/data/nginx/nginx.pid; auto_https off
log {
events { output file /app/data/caddy/caddy.log
worker_connections 1024; format console
}
} }
http { :3080 {
include /etc/nginx/mime.types; log {
default_type application/octet-stream; output file /app/data/caddy/access.log
access_log /dev/stdout combined; format console
sendfile on; }
keepalive_timeout 65;
# Define temp file paths # Add security headers to enable WebAssembly and IndexedDB
client_body_temp_path /app/data/nginx/tmp; header {
proxy_temp_path /app/data/nginx/tmp; # Security headers
fastcgi_temp_path /app/data/nginx/tmp; Strict-Transport-Security "max-age=31536000; includeSubDomains"
uwsgi_temp_path /app/data/nginx/tmp; X-Content-Type-Options "nosniff"
scgi_temp_path /app/data/nginx/tmp; X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
server { # Content Security Policy that allows WebAssembly
listen 8080; Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ${CLOUDRON_APP_ORIGIN} https://*.${CLOUDRON_APP_DOMAIN}; worker-src 'self' blob:;"
# Photos app - root path # CORS headers for API access
location / { Access-Control-Allow-Origin "*"
root /app/web/photos; Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
try_files \$uri \$uri/ /index.html; Access-Control-Allow-Headers "Content-Type, Authorization"
Access-Control-Allow-Credentials "true"
}
# For debugging - public access to the config.js
handle /debug/config.js {
root * /app/data/caddy/public
file_server
}
# Create a special handler for index.html files to inject our config
@indexhtml {
path_regexp index .*\/index\.html$
}
# Handle the direct window variable configuration better
handle @indexhtml {
# Inject a non-defer, early-loading script that defines ENTE_CONFIG
respond_early_hints {
link "</config.js>; rel=preload; as=script"
} }
header Content-Type "text/html; charset=utf-8"
# Accounts app replace_response_headers Content-Length ""
location /accounts/ { rewrite_early * {
alias /app/web/accounts/; # This injects the script into the head section of any index.html
try_files \$uri \$uri/ /accounts/index.html; r </head> <script>window.ENTE_CONFIG = { API_URL: "${CLOUDRON_APP_ORIGIN}/api" };</script></head>
} }
}
# Auth app # Configuration available via JavaScript
location /auth/ { handle /config.js {
alias /app/web/auth/; header Content-Type "application/javascript"
try_files \$uri \$uri/ /auth/index.html; respond "window.ENTE_CONFIG = { API_URL: '${CLOUDRON_APP_ORIGIN}/api' }; console.log('Ente config loaded with API_URL:', window.ENTE_CONFIG.API_URL);"
} }
# Cast app # Photos app - root path
location /cast/ { handle /photos* {
alias /app/web/cast/; uri strip_prefix /photos
try_files \$uri \$uri/ /cast/index.html; root * /app/web/photos
} try_files {path} /index.html
file_server
}
# API endpoints - proxy to Museum server # Accounts app
location /api/ { handle /accounts/* {
proxy_pass http://localhost:8000; uri strip_prefix /accounts
proxy_http_version 1.1; root * /app/web/accounts
proxy_set_header Upgrade \$http_upgrade; try_files {path} /index.html
proxy_set_header Connection 'upgrade'; file_server
proxy_set_header Host \$host; }
proxy_cache_bypass \$http_upgrade;
access_log /dev/stdout; # Auth app
error_log /dev/stderr debug; handle /auth/* {
} uri strip_prefix /auth
root * /app/web/auth
try_files {path} /index.html
file_server
}
# Cast app
handle /cast/* {
uri strip_prefix /cast
root * /app/web/cast
try_files {path} /index.html
file_server
}
# API endpoints - proxy to Museum server
handle /api/* {
reverse_proxy localhost:8080
}
# Health check endpoint for Cloudron
handle /healthcheck {
respond "OK" 200
}
# Default to photos app
handle {
root * /app/web/photos
try_files {path} /index.html
file_server
} }
} }
EOT EOT
echo "==> Caddy configuration created at /app/data/caddy/Caddyfile"
echo "==> Custom NGINX configuration created at /app/data/nginx/ente.conf"
# Looking for Museum (Go server component) # Looking for Museum (Go server component)
echo "==> Looking for Museum (Go server component)" echo "==> Looking for Museum (Go server component)"
@ -363,21 +416,60 @@ if [ ! -f "/app/data/go/go.mod" ] && [ -f "$SERVER_DIR/go.mod" ]; then
chmod 666 /app/data/go/go.mod /app/data/go/go.sum || echo "==> Warning: Could not set permissions" chmod 666 /app/data/go/go.mod /app/data/go/go.sum || echo "==> Warning: Could not set permissions"
fi fi
# Create proper directories with correct permissions
mkdir -p /app/data/go/cache /app/data/go/pkg/mod /app/data/go/bin
chmod -R 777 /app/data/go
chown -R cloudron:cloudron /app/data/go
# Override version requirements and force module mode # Override version requirements and force module mode
export GOFLAGS="-modfile=/app/data/go/go.mod -mod=mod -modcacherw" export GOFLAGS="-modfile=/app/data/go/go.mod -mod=mod -modcacherw"
# Create a temporary directory for Go module cache and build in writable area # Create a temporary directory for Go module cache and build in writable area
export GOCACHE=/app/data/go/cache export GOCACHE=/app/data/go/cache
export GOMODCACHE=/app/data/go/modcache export GOMODCACHE=/app/data/go/pkg/mod
mkdir -p $GOCACHE $GOMODCACHE mkdir -p $GOCACHE $GOMODCACHE
echo "==> Set up Go environment in writable directories" echo "==> Set up Go environment in writable directories"
# Set up more verbose logging for API debugging # Set up more verbose logging for API debugging
export ENTE_LOG_LEVEL=debug export ENTE_LOG_LEVEL=debug
# Test if API endpoint is reachable # Start Caddy first before the Museum server to ensure port 3080 is available for health checks
echo "==> Testing API connectivity" echo "==> Setting up Caddy before starting the Museum server"
curl -v http://localhost:8000/api/health || echo "API not yet available, this is normal during startup" echo "==> Caddy will be listening on port 3080"
echo "==> Testing if port 3080 is already in use"
if netstat -tuln | grep -q ":3080 "; then
echo "==> WARNING: Port 3080 is already in use, Caddy may fail to start"
netstat -tuln | grep ":3080 "
else
echo "==> Port 3080 is available"
fi
# Only set permissions on the Caddy directory, not the web directory which is read-only
mkdir -p /app/data/caddy/logs
chmod -R 755 /app/data/caddy
chown -R cloudron:cloudron /app/data/caddy
# Start Caddy
echo "==> Starting Caddy"
caddy run --config /app/data/caddy/Caddyfile --adapter caddyfile &
CADDY_PID=$!
echo "==> Caddy started with PID $CADDY_PID"
# Check if Caddy started successfully
sleep 2
if ! ps -p $CADDY_PID > /dev/null; then
echo "==> ERROR: Caddy failed to start"
echo "==> Any logs available:"
if [ -f "/app/data/caddy/caddy.log" ]; then
cat /app/data/caddy/caddy.log
else
echo "No Caddy logs available yet"
fi
else
echo "==> Caddy is running properly on port 3080"
echo "==> Testing Caddy connectivity"
curl -v http://localhost:3080/healthcheck || echo "==> Failed to connect to Caddy"
fi
# Determine available memory and set limits accordingly # Determine available memory and set limits accordingly
if [[ -f /sys/fs/cgroup/cgroup.controllers ]]; then # cgroup v2 if [[ -f /sys/fs/cgroup/cgroup.controllers ]]; then # cgroup v2
@ -395,9 +487,66 @@ export ENTE_DB_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD}"
export ENTE_DB_HOST="${CLOUDRON_POSTGRESQL_HOST}" export ENTE_DB_HOST="${CLOUDRON_POSTGRESQL_HOST}"
export ENTE_DB_PORT="${CLOUDRON_POSTGRESQL_PORT}" export ENTE_DB_PORT="${CLOUDRON_POSTGRESQL_PORT}"
export ENTE_DB_NAME="${CLOUDRON_POSTGRESQL_DATABASE}" export ENTE_DB_NAME="${CLOUDRON_POSTGRESQL_DATABASE}"
export ENTE_DB_SSLMODE="require" export ENTE_DB_SSLMODE="disable"
export CONFIG_PATH="/app/data/config/config.yaml" 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 # Additional environment variables
export REMOTE_STORAGE_ENDPOINT="${S3_ENDPOINT}" export REMOTE_STORAGE_ENDPOINT="${S3_ENDPOINT}"
export REMOTE_STORAGE_REGION="${S3_REGION}" export REMOTE_STORAGE_REGION="${S3_REGION}"
@ -408,21 +557,61 @@ export REMOTE_STORAGE_PREFIX="${S3_PREFIX:-ente/}"
# Change ownership to cloudron user # Change ownership to cloudron user
chown -R cloudron:cloudron /app/data chown -R cloudron:cloudron /app/data
chown -R cloudron:cloudron /run/nginx
# Start Museum server on port 8000 (different from the NGINX port 8080) # Start Museum server on port 8080 for compatibility with the Caddy configuration
echo "==> Starting Museum server" echo "==> Starting Museum server"
# Modify environment variables for frontend # Modify environment variables for frontend
echo "==> Setting up environment variables for frontend" echo "==> Setting up environment variables for frontend"
# For web frontend, these aren't changing # Set frontend endpoint to the proper origin
export NEXT_PUBLIC_ENTE_ENDPOINT="${CLOUDRON_APP_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 <<EOT
// Direct configuration file for Ente web apps
window.ENTE_CONFIG = {
API_URL: "${CLOUDRON_APP_ORIGIN}/api"
};
// Log configuration loaded
console.log("Ente config loaded with API_URL:", window.ENTE_CONFIG.API_URL);
EOT
# 2. JSON format
cat > /app/data/runtime/config.json <<EOT
{
"API_URL": "${CLOUDRON_APP_ORIGIN}/api"
}
EOT
# 3. Environment variable format
cat > /app/data/runtime/env.js <<EOT
// Environment variables in JavaScript
window.process = window.process || {};
window.process.env = window.process.env || {};
window.process.env.NEXT_PUBLIC_ENTE_ENDPOINT = "${CLOUDRON_APP_ORIGIN}/api";
EOT
# Copy them to the Caddy public directory
mkdir -p /app/data/caddy/public
cp /app/data/runtime/config.js /app/data/caddy/public/
cp /app/data/runtime/config.json /app/data/caddy/public/
cp /app/data/runtime/env.js /app/data/caddy/public/
# Print the content of the config file for debugging
echo "==> Generated config.js content:"
cat /app/data/runtime/config.js
# First check for pre-built Museum binary # First check for pre-built Museum binary
if find "$SERVER_DIR" -name "museum" -type f -executable | grep -q .; then if find "$SERVER_DIR" -name "museum" -type f -executable | grep -q .; then
MUSEUM_BIN=$(find "$SERVER_DIR" -name "museum" -type f -executable | head -1) MUSEUM_BIN=$(find "$SERVER_DIR" -name "museum" -type f -executable | head -1)
echo "==> Found Museum binary at $MUSEUM_BIN" echo "==> Found Museum binary at $MUSEUM_BIN"
/usr/local/bin/gosu cloudron:cloudron "$MUSEUM_BIN" --port 8000 \ /usr/local/bin/gosu cloudron:cloudron "$MUSEUM_BIN" --port 8080 \
--storage.s3.endpoint="${S3_ENDPOINT}" \ --storage.s3.endpoint="${S3_ENDPOINT}" \
--storage.s3.region="${S3_REGION}" \ --storage.s3.region="${S3_REGION}" \
--storage.s3.bucket="${S3_BUCKET}" \ --storage.s3.bucket="${S3_BUCKET}" \
@ -433,7 +622,7 @@ if find "$SERVER_DIR" -name "museum" -type f -executable | grep -q .; then
--storage.s3.areLocalBuckets=false \ --storage.s3.areLocalBuckets=false \
--storage.type="s3" \ --storage.type="s3" \
--config.path="/app/data/config/museum.yaml" \ --config.path="/app/data/config/museum.yaml" \
--database.sslmode="require" > /app/data/logs/museum-server.log 2>&1 & --database.sslmode="disable" > /app/data/logs/museum-server.log 2>&1 &
SERVER_PID=$! SERVER_PID=$!
echo "==> Museum server started with PID $SERVER_PID" echo "==> Museum server started with PID $SERVER_PID"
# Next check for cmd/museum directory pattern # Next check for cmd/museum directory pattern
@ -451,7 +640,8 @@ elif [ -d "$SERVER_DIR/cmd/museum" ]; then
if [[ "${S3_ENDPOINT}" == *"wasabi"* ]]; then if [[ "${S3_ENDPOINT}" == *"wasabi"* ]]; then
echo "==> Detected Wasabi S3 endpoint, adjusting settings" echo "==> Detected Wasabi S3 endpoint, adjusting settings"
echo "==> Adding -mod=mod to go run to ignore version mismatch" echo "==> Adding -mod=mod to go run to ignore version mismatch"
/usr/local/bin/gosu cloudron:cloudron go run -mod=mod cmd/museum/main.go --port 8000 \ 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.endpoint="${S3_ENDPOINT}" \
--storage.s3.region="${S3_REGION}" \ --storage.s3.region="${S3_REGION}" \
--storage.s3.bucket="${S3_BUCKET}" \ --storage.s3.bucket="${S3_BUCKET}" \
@ -462,10 +652,11 @@ elif [ -d "$SERVER_DIR/cmd/museum" ]; then
--storage.s3.areLocalBuckets=false \ --storage.s3.areLocalBuckets=false \
--storage.type="s3" \ --storage.type="s3" \
--config.path="/app/data/config/museum.yaml" \ --config.path="/app/data/config/museum.yaml" \
--database.sslmode="require" \ --database.sslmode="disable" \
--log.level=debug > /app/data/logs/museum-server.log 2>&1 & --log.level=debug > /app/data/logs/museum-server.log 2>&1 &
else else
/usr/local/bin/gosu cloudron:cloudron go run -mod=mod cmd/museum/main.go --port 8000 \ 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.endpoint="${S3_ENDPOINT}" \
--storage.s3.region="${S3_REGION}" \ --storage.s3.region="${S3_REGION}" \
--storage.s3.bucket="${S3_BUCKET}" \ --storage.s3.bucket="${S3_BUCKET}" \
@ -476,7 +667,7 @@ elif [ -d "$SERVER_DIR/cmd/museum" ]; then
--storage.s3.areLocalBuckets=false \ --storage.s3.areLocalBuckets=false \
--storage.type="s3" \ --storage.type="s3" \
--config.path="/app/data/config/museum.yaml" \ --config.path="/app/data/config/museum.yaml" \
--database.sslmode="require" \ --database.sslmode="disable" \
--log.level=debug > /app/data/logs/museum-server.log 2>&1 & --log.level=debug > /app/data/logs/museum-server.log 2>&1 &
fi fi
SERVER_PID=$! SERVER_PID=$!
@ -491,7 +682,7 @@ elif [ -d "$SERVER_DIR/cmd/museum" ]; then
RETRY_COUNT=0 RETRY_COUNT=0
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
echo "==> Testing API connection (attempt $((RETRY_COUNT+1))/$MAX_RETRIES)" echo "==> Testing API connection (attempt $((RETRY_COUNT+1))/$MAX_RETRIES)"
if curl -s http://localhost:8000/api/health > /dev/null; then if curl -s http://localhost:8080/api/health > /dev/null; then
echo "==> API is now responding" echo "==> API is now responding"
break break
else else
@ -527,7 +718,8 @@ else
export GOTOOLCHAIN=local export GOTOOLCHAIN=local
echo "==> Running main.go with Go" echo "==> Running main.go with Go"
/usr/local/bin/gosu cloudron:cloudron go run -mod=mod main.go --port 8000 \ 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.endpoint="${S3_ENDPOINT}" \
--storage.s3.region="${S3_REGION}" \ --storage.s3.region="${S3_REGION}" \
--storage.s3.bucket="${S3_BUCKET}" \ --storage.s3.bucket="${S3_BUCKET}" \
@ -538,6 +730,7 @@ else
--storage.s3.areLocalBuckets=false \ --storage.s3.areLocalBuckets=false \
--storage.type="s3" \ --storage.type="s3" \
--config.path="/app/data/config/museum.yaml" \ --config.path="/app/data/config/museum.yaml" \
--database.sslmode="disable" \
--log.level=debug > /app/data/logs/museum-server.log 2>&1 & --log.level=debug > /app/data/logs/museum-server.log 2>&1 &
SERVER_PID=$! SERVER_PID=$!
echo "==> Museum server started with PID $SERVER_PID" echo "==> Museum server started with PID $SERVER_PID"
@ -592,10 +785,10 @@ func main() {
}) })
// Start the server // Start the server
log.Println("Starting mock server on port 8000") log.Println("Starting mock server on port 8080")
// Start in a goroutine to prevent blocking // Start in a goroutine to prevent blocking
server := &http.Server{Addr: ":8000"} server := &http.Server{Addr: ":8080"}
go func() { go func() {
if err := server.ListenAndServe(); err != nil { if err := server.ListenAndServe(); err != nil {
log.Fatalf("Server error: %v", err) log.Fatalf("Server error: %v", err)
@ -612,15 +805,35 @@ EOT
echo "==> Mock server started with PID $SERVER_PID to show error message" echo "==> Mock server started with PID $SERVER_PID to show error message"
fi fi
# Serve the static web apps in the foreground using our custom nginx config echo "==> Testing health check endpoint directly"
echo "==> Running NGINX in the foreground with custom configuration" curl -v http://localhost:3080/healthcheck
nginx -c /app/data/nginx/ente.conf &
NGINX_PID=$!
echo "==> NGINX started with PID $NGINX_PID"
echo "==> Ente is now running!" echo "==> Ente is now running!"
echo "==> Museum server: PID $SERVER_PID" echo "==> Museum server: PID $SERVER_PID"
echo "==> NGINX: PID $NGINX_PID" echo "==> Caddy: PID $CADDY_PID"
# Wait for the processes to finish (or be terminated) # Function to inject the config.js script tag into index.html files
wait inject_config_script() {
echo "==> Attempting to inject config.js script tag into index.html files"
# List of web app directories
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"
# Try to modify in place without creating a backup
sed -i 's|</head>|<script>window.ENTE_CONFIG = { API_URL: "'"${CLOUDRON_APP_ORIGIN}"'/api" };</script></head>|' "$app_dir/index.html" || echo "==> Cannot modify $app_dir/index.html - read-only file system"
else
echo "==> Skipping $app_dir - index.html not found"
fi
done
}
# Try to inject the config script but don't worry if it fails
inject_config_script || echo "==> NOTE: Could not inject configuration directly into HTML files"
# Wait for child processes to exit
wait $SERVER_PID
wait $CADDY_PID