#!/bin/bash set -eu echo "=> Starting Docmost setup" # Set up writable client dist directory if [ ! -d "/app/data/client-dist" ]; then echo "=> Setting up writable client dist directory" cp -r /app/client-dist-original /app/data/client-dist chown -R cloudron:cloudron /app/data/client-dist fi # Copy sample .env file for user reference if [ ! -f "/app/data/env.sample" ]; then echo "=> Copying configuration files to /app/data/" cp /app/code/env.sample /app/data/env.sample chown cloudron:cloudron /app/data/env.sample fi # Initialize /app/data if it's empty (first run) if [ ! -f /app/data/.initialized ]; then echo "=> Initializing data directory" mkdir -p /app/data/uploads /app/data/logs chown -R cloudron:cloudron /app/data touch /app/data/.initialized fi # Generate APP_SECRET if not exists if [ ! -f /app/data/app_secret ]; then echo "=> Generating APP_SECRET" openssl rand -hex 32 > /app/data/app_secret chown cloudron:cloudron /app/data/app_secret chmod 600 /app/data/app_secret fi APP_SECRET=$(cat /app/data/app_secret) # Set up environment variables export NODE_ENV=production export APP_URL="${CLOUDRON_APP_ORIGIN}" export APP_SECRET="${APP_SECRET}" export PORT=3001 # Database configuration export DATABASE_URL="${CLOUDRON_POSTGRESQL_URL}" # Redis configuration - parse Cloudron format to standard format echo "=> Configuring Redis..." # Cloudron provides Redis addon with specific environment variables # The CLOUDRON_REDIS_URL is in format: redis://:password@host:port # We need to ensure it's in the correct format for ioredis # Debug: Print the original Redis URL echo "=> Original CLOUDRON_REDIS_URL: ${CLOUDRON_REDIS_URL}" if [ -n "${CLOUDRON_REDIS_URL}" ]; then # Parse the URL components first # Also extract components for individual env vars # Handle both formats: redis://default:password@host and redis://:password@host:port if echo "$CLOUDRON_REDIS_URL" | grep -q "redis://default:"; then # Format: redis://default:password@host REDIS_PASSWORD=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://default:\([^@]*\)@.*|\1|p') REDIS_HOST=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://default:[^@]*@\([^:/]*\).*|\1|p') REDIS_PORT=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://default:[^@]*@[^:]*:\([0-9]*\).*|\1|p') else # Format: redis://:password@host:port REDIS_PASSWORD=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://:\([^@]*\)@.*|\1|p') REDIS_HOST=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://[^@]*@\([^:]*\):.*|\1|p') REDIS_PORT=$(echo "$CLOUDRON_REDIS_URL" | sed -n 's|redis://[^@]*@[^:]*:\([0-9]*\).*|\1|p') fi # Default port if not found if [ -z "$REDIS_PORT" ]; then REDIS_PORT="6379" fi # Export individual components for Docmost export REDIS_HOST="${REDIS_HOST}" export REDIS_PORT="${REDIS_PORT}" export REDIS_PASSWORD="${REDIS_PASSWORD}" export REDIS_DB="0" echo "=> Redis configured: host=${REDIS_HOST}, port=${REDIS_PORT}, has password: $([ -n "$REDIS_PASSWORD" ] && echo "yes" || echo "no")" # Reconstruct the Redis URL in the correct format for ioredis if [ -n "$REDIS_PASSWORD" ]; then export REDIS_URL="redis://:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}" else export REDIS_URL="redis://${REDIS_HOST}:${REDIS_PORT}" fi echo "=> Using Redis URL: ${REDIS_URL}" else echo "=> Error: Redis URL not provided by Cloudron" exit 1 fi # Load custom environment variables if they exist if [ -f "/app/data/.env" ]; then echo "=> Loading custom environment variables from /app/data/.env" # Validate .env file format before sourcing if grep -q "^[[:space:]]*[^#][^=]*=" /app/data/.env 2>/dev/null; then set -a # automatically export all variables if source /app/data/.env 2>/dev/null; then echo "=> Custom .env file loaded successfully" else echo "=> Warning: Error loading .env file, using Cloudron defaults" echo "=> Check /app/data/.env for syntax errors (values with spaces need quotes)" fi set +a # stop automatically exporting else echo "=> Warning: /app/data/.env appears to be empty or invalid, using Cloudron defaults" fi else echo "=> No custom .env file found, using Cloudron defaults" fi # Email configuration - use custom settings if provided, otherwise use Cloudron defaults export MAIL_DRIVER="${MAIL_DRIVER:-smtp}" export SMTP_HOST="${SMTP_HOST:-${CLOUDRON_MAIL_SMTP_SERVER}}" export SMTP_PORT="${SMTP_PORT:-${CLOUDRON_MAIL_SMTP_PORT}}" export SMTP_USERNAME="${SMTP_USERNAME:-${CLOUDRON_MAIL_SMTP_USERNAME}}" export SMTP_PASSWORD="${SMTP_PASSWORD:-${CLOUDRON_MAIL_SMTP_PASSWORD}}" export SMTP_SECURE="${SMTP_SECURE:-false}" export MAIL_FROM_ADDRESS="${MAIL_FROM_ADDRESS:-${CLOUDRON_MAIL_FROM}}" export MAIL_FROM_NAME="${MAIL_FROM_NAME:-Docmost}" # Storage configuration - use custom settings if provided, otherwise use local storage export STORAGE_DRIVER="${STORAGE_DRIVER:-local}" export STORAGE_LOCAL_PATH="${STORAGE_LOCAL_PATH:-/app/data/uploads}" # S3 Storage configuration (only used if STORAGE_DRIVER=s3) export AWS_S3_ACCESS_KEY_ID="${AWS_S3_ACCESS_KEY_ID:-}" export AWS_S3_SECRET_ACCESS_KEY="${AWS_S3_SECRET_ACCESS_KEY:-}" export AWS_S3_REGION="${AWS_S3_REGION:-}" export AWS_S3_BUCKET="${AWS_S3_BUCKET:-}" export AWS_S3_ENDPOINT="${AWS_S3_ENDPOINT:-}" export AWS_S3_FORCE_PATH_STYLE="${AWS_S3_FORCE_PATH_STYLE:-false}" # File upload limits export FILE_UPLOAD_SIZE_LIMIT="${FILE_UPLOAD_SIZE_LIMIT:-50MB}" export FILE_IMPORT_SIZE_LIMIT="${FILE_IMPORT_SIZE_LIMIT:-50MB}" # Application configuration export APP_URL="${APP_URL:-https://${CLOUDRON_APP_DOMAIN}}" export APP_SECRET="${APP_SECRET:-${CLOUDRON_APP_ORIGIN}-$(date +%s)}" export PORT="${PORT:-3001}" export JWT_TOKEN_EXPIRES_IN="${JWT_TOKEN_EXPIRES_IN:-7d}" # Diagrams configuration export DRAWIO_URL="${DRAWIO_URL:-https://embed.diagrams.net}" # Telemetry (disabled by default for privacy) export DISABLE_TELEMETRY="${DISABLE_TELEMETRY:-true}" # Postmark email (alternative to SMTP) export POSTMARK_TOKEN="${POSTMARK_TOKEN:-}" echo "=> Email configuration: ${MAIL_DRIVER} via ${SMTP_HOST}:${SMTP_PORT}" echo "=> Storage configuration: ${STORAGE_DRIVER}" if [ "${STORAGE_DRIVER}" = "s3" ]; then echo "=> S3 storage: ${AWS_S3_BUCKET} in ${AWS_S3_REGION}" fi # Authentication will use built-in email/password system echo "=> Using built-in email/password authentication" # File upload configuration export FILE_UPLOAD_SIZE_LIMIT="50mb" # JWT configuration export JWT_TOKEN_EXPIRES_IN="30d" # Wait for Redis to be available if [ -n "${CLOUDRON_REDIS_URL}" ]; then echo "=> Waiting for Redis to be available..." for i in {1..30}; do if nc -z "${REDIS_HOST}" "${REDIS_PORT}" 2>/dev/null; then echo "=> Redis is available" break fi if [ $i -eq 30 ]; then echo "=> Warning: Redis not reachable after 30 seconds" fi sleep 1 done fi echo "=> Running database migrations" cd /app/code chown -R cloudron:cloudron /app/data # Find the correct prisma binary path PRISMA_BIN="" if [ -f "/app/code/apps/server/node_modules/.bin/prisma" ]; then PRISMA_BIN="/app/code/apps/server/node_modules/.bin/prisma" elif [ -f "/app/code/node_modules/.bin/prisma" ]; then PRISMA_BIN="/app/code/node_modules/.bin/prisma" elif [ -f "/app/code/node_modules/@prisma/cli/build/index.js" ]; then PRISMA_BIN="/usr/bin/node /app/code/node_modules/@prisma/cli/build/index.js" fi if [ -n "$PRISMA_BIN" ]; then echo "=> Found Prisma at: $PRISMA_BIN" cd /app/code/apps/server sudo -u cloudron $PRISMA_BIN migrate deploy || true else echo "=> Warning: Prisma binary not found, skipping migrations" fi # Create nginx temp directories mkdir -p /tmp/nginx_client_temp /tmp/nginx_proxy_temp /tmp/nginx_fastcgi_temp /tmp/nginx_uwsgi_temp /tmp/nginx_scgi_temp chown -R cloudron:cloudron /tmp/nginx_* echo "=> Starting services with supervisor" exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf