#!/bin/sh set -e # Ensure data directory exists mkdir -p /app/data # Handle custom CA certificates if [ -d "/app/certs" ] && [ "$(ls -A /app/certs/*.crt 2>/dev/null)" ]; then echo "Custom CA certificates found, configuring Node.js to use them..." # Combine all CA certificates into a bundle for Node.js CA_BUNDLE="/app/certs/ca-bundle.crt" > "$CA_BUNDLE" for cert in /app/certs/*.crt; do if [ -f "$cert" ]; then echo "Adding certificate: $(basename "$cert")" cat "$cert" >> "$CA_BUNDLE" echo "" >> "$CA_BUNDLE" # Add newline between certificates fi done # Set Node.js to use the custom CA bundle export NODE_EXTRA_CA_CERTS="$CA_BUNDLE" echo "NODE_EXTRA_CA_CERTS set to: $NODE_EXTRA_CA_CERTS" # For Bun compatibility, also set the CA bundle in system location if writable if [ -f "/etc/ssl/certs/ca-certificates.crt" ] && [ -w "/etc/ssl/certs/" ]; then echo "Appending custom certificates to system CA bundle..." cat "$CA_BUNDLE" >> /etc/ssl/certs/ca-certificates.crt fi else echo "No custom CA certificates found in /app/certs" fi # Check if system CA bundle is mounted and use it (only if not already set) if [ -z "$NODE_EXTRA_CA_CERTS" ] && [ -f "/etc/ssl/certs/ca-certificates.crt" ] && [ ! -L "/etc/ssl/certs/ca-certificates.crt" ]; then # Check if it's a mounted file (not the default symlink) if [ "$(stat -c '%d' /etc/ssl/certs/ca-certificates.crt 2>/dev/null)" != "$(stat -c '%d' / 2>/dev/null)" ] || \ [ "$(stat -f '%d' /etc/ssl/certs/ca-certificates.crt 2>/dev/null)" != "$(stat -f '%d' / 2>/dev/null)" ]; then echo "System CA bundle mounted, configuring Node.js to use it..." export NODE_EXTRA_CA_CERTS="/etc/ssl/certs/ca-certificates.crt" echo "NODE_EXTRA_CA_CERTS set to: $NODE_EXTRA_CA_CERTS" fi fi # Optional: If GITEA_SKIP_TLS_VERIFY is set, configure accordingly if [ "$GITEA_SKIP_TLS_VERIFY" = "true" ]; then echo "Warning: GITEA_SKIP_TLS_VERIFY is set to true. This is insecure!" export NODE_TLS_REJECT_UNAUTHORIZED=0 fi # Generate a secure BETTER_AUTH_SECRET if one isn't provided or is using the default value BETTER_AUTH_SECRET_FILE="/app/data/.better_auth_secret" JWT_SECRET_FILE="/app/data/.jwt_secret" # Old file for backward compatibility if [ "$BETTER_AUTH_SECRET" = "your-secret-key-change-this-in-production" ] || [ -z "$BETTER_AUTH_SECRET" ]; then # Check if we have a previously generated secret if [ -f "$BETTER_AUTH_SECRET_FILE" ]; then echo "Using previously generated BETTER_AUTH_SECRET" export BETTER_AUTH_SECRET=$(cat "$BETTER_AUTH_SECRET_FILE") # Check for old JWT_SECRET file for backward compatibility elif [ -f "$JWT_SECRET_FILE" ]; then echo "Migrating from old JWT_SECRET to BETTER_AUTH_SECRET" export BETTER_AUTH_SECRET=$(cat "$JWT_SECRET_FILE") # Save to new file echo "$BETTER_AUTH_SECRET" > "$BETTER_AUTH_SECRET_FILE" chmod 600 "$BETTER_AUTH_SECRET_FILE" # Optionally remove old file after successful migration rm -f "$JWT_SECRET_FILE" else echo "Generating a secure random BETTER_AUTH_SECRET" # Try to generate a secure random string using OpenSSL if command -v openssl >/dev/null 2>&1; then GENERATED_SECRET=$(openssl rand -hex 32) else # Fallback to using /dev/urandom if openssl is not available echo "OpenSSL not found, using fallback method for random generation" GENERATED_SECRET=$(head -c 32 /dev/urandom | sha256sum | cut -d' ' -f1) fi export BETTER_AUTH_SECRET="$GENERATED_SECRET" # Save the secret to a file for persistence across container restarts echo "$GENERATED_SECRET" > "$BETTER_AUTH_SECRET_FILE" chmod 600 "$BETTER_AUTH_SECRET_FILE" fi echo "BETTER_AUTH_SECRET has been set to a secure random value" fi # Generate a secure ENCRYPTION_SECRET if one isn't provided ENCRYPTION_SECRET_FILE="/app/data/.encryption_secret" if [ -z "$ENCRYPTION_SECRET" ]; then # Check if we have a previously generated secret if [ -f "$ENCRYPTION_SECRET_FILE" ]; then echo "Using previously generated ENCRYPTION_SECRET" export ENCRYPTION_SECRET=$(cat "$ENCRYPTION_SECRET_FILE") else echo "Generating a secure random ENCRYPTION_SECRET" # Generate a 48-character secret for encryption if command -v openssl >/dev/null 2>&1; then GENERATED_ENCRYPTION_SECRET=$(openssl rand -base64 36) else # Fallback to using /dev/urandom if openssl is not available echo "OpenSSL not found, using fallback method for encryption secret generation" GENERATED_ENCRYPTION_SECRET=$(head -c 36 /dev/urandom | base64 | tr -d '\n' | head -c 48) fi export ENCRYPTION_SECRET="$GENERATED_ENCRYPTION_SECRET" # Save the secret to a file for persistence across container restarts echo "$GENERATED_ENCRYPTION_SECRET" > "$ENCRYPTION_SECRET_FILE" chmod 600 "$ENCRYPTION_SECRET_FILE" fi echo "ENCRYPTION_SECRET has been set to a secure random value" fi # Skip dependency installation entirely for pre-built images # Dependencies are already installed during the Docker build process # Initialize the database if it doesn't exist # Note: Drizzle migrations will be run automatically when the app starts (see src/lib/db/index.ts) if [ ! -f "/app/data/gitea-mirror.db" ]; then echo "Database not found. It will be created and initialized via Drizzle migrations on first app startup..." # Create empty database file so migrations can run touch /app/data/gitea-mirror.db else echo "Database already exists, Drizzle will check for pending migrations on startup..." fi # Extract version from package.json and set as environment variable if [ -f "package.json" ]; then export npm_package_version=$(grep -o '"version": *"[^"]*"' package.json | cut -d'"' -f4) echo "Setting application version: $npm_package_version" fi # Initialize configuration from environment variables if provided echo "Checking for environment configuration..." if [ -f "dist/scripts/startup-env-config.js" ]; then echo "Loading configuration from environment variables..." bun dist/scripts/startup-env-config.js ENV_CONFIG_EXIT_CODE=$? elif [ -f "scripts/startup-env-config.ts" ]; then echo "Loading configuration from environment variables..." bun scripts/startup-env-config.ts ENV_CONFIG_EXIT_CODE=$? else echo "Environment configuration script not found. Skipping." ENV_CONFIG_EXIT_CODE=0 fi # Log environment config result if [ $ENV_CONFIG_EXIT_CODE -eq 0 ]; then echo "✅ Environment configuration loaded successfully" else echo "⚠️ Environment configuration loading completed with warnings" fi # Run startup recovery to handle any interrupted jobs echo "Running startup recovery..." if [ -f "dist/scripts/startup-recovery.js" ]; then echo "Running startup recovery using compiled script..." bun dist/scripts/startup-recovery.js --timeout=30000 RECOVERY_EXIT_CODE=$? elif [ -f "scripts/startup-recovery.ts" ]; then echo "Running startup recovery using TypeScript script..." bun scripts/startup-recovery.ts --timeout=30000 RECOVERY_EXIT_CODE=$? else echo "Warning: Startup recovery script not found. Skipping recovery." RECOVERY_EXIT_CODE=0 fi # Log recovery result if [ $RECOVERY_EXIT_CODE -eq 0 ]; then echo "✅ Startup recovery completed successfully" elif [ $RECOVERY_EXIT_CODE -eq 1 ]; then echo "⚠️ Startup recovery completed with warnings" else echo "❌ Startup recovery failed with exit code $RECOVERY_EXIT_CODE" fi # Run repository status repair to fix any inconsistent mirroring states echo "Running repository status repair..." if [ -f "dist/scripts/repair-mirrored-repos.js" ]; then echo "Running repository repair using compiled script..." bun dist/scripts/repair-mirrored-repos.js --startup REPAIR_EXIT_CODE=$? elif [ -f "scripts/repair-mirrored-repos.ts" ]; then echo "Running repository repair using TypeScript script..." bun scripts/repair-mirrored-repos.ts --startup REPAIR_EXIT_CODE=$? else echo "Warning: Repository repair script not found. Skipping repair." REPAIR_EXIT_CODE=0 fi # Log repair result if [ $REPAIR_EXIT_CODE -eq 0 ]; then echo "✅ Repository status repair completed successfully" else echo "⚠️ Repository status repair completed with warnings (exit code $REPAIR_EXIT_CODE)" fi # Function to handle shutdown signals shutdown_handler() { echo "🛑 Received shutdown signal, forwarding to application..." if [ ! -z "$APP_PID" ]; then kill -TERM "$APP_PID" wait "$APP_PID" fi exit 0 } # Set up signal handlers trap 'shutdown_handler' TERM INT HUP # Start the application echo "Starting Gitea Mirror..." bun ./dist/server/entry.mjs & APP_PID=$! # Wait for the application to finish wait "$APP_PID"