#!/bin/bash set -euo pipefail APP_CODE_DIR=${APP_CODE_DIR:-/app/code} APP_DATA_DIR=${APP_DATA_DIR:-/app/data} APP_RUNTIME_DIR=${APP_RUNTIME_DIR:-/run/affine} APP_TMP_DIR=${APP_TMP_DIR:-/tmp/data} APP_BUILD_DIR=${APP_BUILD_DIR:-/app/code/affine} AFFINE_HOME=/home/cloudron/.affine export APP_CODE_DIR APP_DATA_DIR APP_RUNTIME_DIR APP_TMP_DIR APP_BUILD_DIR log() { printf '[%s] %s\n' "$(date --iso-8601=seconds)" "$*" } require_env() { local var_name="$1" if [ -z "${!var_name:-}" ]; then echo "Environment variable ${var_name} is not set" >&2 exit 1 fi } prepare_data_dirs() { log "Preparing persistent directories" mkdir -p "$APP_DATA_DIR/config" "$APP_DATA_DIR/storage" "$APP_DATA_DIR/logs" "$APP_RUNTIME_DIR" "$AFFINE_HOME" if [ ! -f "$APP_DATA_DIR/config/config.json" ]; then log "Seeding default configuration" cp "$APP_TMP_DIR/config/config.json" "$APP_DATA_DIR/config/config.json" fi local storage_contents="" if [ -d "$APP_DATA_DIR/storage" ]; then storage_contents=$(ls -A "$APP_DATA_DIR/storage" 2>/dev/null || true) fi if [ ! -d "$APP_DATA_DIR/storage" ] || [ -z "$storage_contents" ]; then cp -a "$APP_TMP_DIR/storage/." "$APP_DATA_DIR/storage/" 2>/dev/null || true fi rm -rf "$AFFINE_HOME/config" "$AFFINE_HOME/storage" ln -sf "$APP_DATA_DIR/config" "$AFFINE_HOME/config" ln -sf "$APP_DATA_DIR/storage" "$AFFINE_HOME/storage" chown -R cloudron:cloudron "$APP_DATA_DIR" "$APP_RUNTIME_DIR" /home/cloudron } configure_database() { require_env CLOUDRON_POSTGRESQL_URL local db_url="$CLOUDRON_POSTGRESQL_URL" if [[ "$db_url" == postgres://* ]]; then db_url="postgresql://${db_url#postgres://}" fi export DATABASE_URL="$db_url" log "Configured PostgreSQL endpoint" } configure_redis() { require_env CLOUDRON_REDIS_URL local redis_info redis_info=$(python3 - <<'PY' import os from urllib.parse import urlparse url = os.environ.get('CLOUDRON_REDIS_URL') if not url: raise SystemExit('redis url missing') parsed = urlparse(url) host = parsed.hostname or 'localhost' port = parsed.port or 6379 password = parsed.password or '' db = (parsed.path or '/0').lstrip('/') or '0' print(f"{host}\n{port}\n{password}\n{db}") PY ) IFS=$'\n' read -r host port password db <<<"$redis_info" export REDIS_SERVER_HOST="$host" export REDIS_SERVER_PORT="$port" export REDIS_SERVER_PASSWORD="$password" export REDIS_URL="$CLOUDRON_REDIS_URL" export REDIS_SERVER_URL="$CLOUDRON_REDIS_URL" log "Configured Redis endpoint" } configure_mail() { if [ -z "${CLOUDRON_MAIL_SMTP_SERVER:-}" ]; then log "Cloudron mail addon not configured, skipping SMTP setup" return fi export MAILER_HOST="$CLOUDRON_MAIL_SMTP_SERVER" export MAILER_PORT="${CLOUDRON_MAIL_SMTP_PORT:-587}" export MAILER_USER="${CLOUDRON_MAIL_SMTP_USERNAME:-}" export MAILER_PASSWORD="${CLOUDRON_MAIL_SMTP_PASSWORD:-}" export MAILER_SENDER="${CLOUDRON_MAIL_FROM:-AFFiNE }" export MAILER_SERVERNAME="${MAILER_SERVERNAME:-AFFiNE Server}" log "Configured SMTP relay" } configure_server_metadata() { if [ -n "${CLOUDRON_APP_ORIGIN:-}" ]; then export AFFINE_SERVER_EXTERNAL_URL="$CLOUDRON_APP_ORIGIN" local host host=$(python3 - <