#!/usr/bin/env bashio # shellcheck shell=bash set -euo pipefail MINIO_USER="$(bashio::config 'MINIO_ROOT_USER')" MINIO_PASS="$(bashio::config 'MINIO_ROOT_PASSWORD')" S3_BUCKET="b2-eu-cen" export ENTE_S3_ARE_LOCAL_BUCKETS=true export ENTE_S3_B2_EU_CEN_KEY="$MINIO_USER" export ENTE_S3_B2_EU_CEN_SECRET="$MINIO_PASS" export ENTE_S3_B2_EU_CEN_ENDPOINT="http://192.168.178.23:$(bashio::addon.port "3200")" export ENTE_S3_B2_EU_CEN_REGION=eu-central-2 export ENTE_S3_B2_EU_CEN_BUCKET="$S3_BUCKET" ############################################ # Paths & constants ############################################ CFG=/config/museum.yaml PGDATA=/config/postgres # Internal Postgres always bound here DB_HOST_INTERNAL=127.0.0.1 DB_PORT_INTERNAL=5432 ############################################ # Read add‑on options ############################################ DB_NAME="$(bashio::config 'DB_DATABASE_NAME' || echo ente_db)" DB_USER="$(bashio::config 'DB_USERNAME' || echo pguser)" DB_PASS="$(bashio::config 'DB_PASSWORD' || echo ente)" # External DB opts (may be blank) DB_HOST_EXT="$(bashio::config 'DB_HOSTNAME' || echo '')" DB_PORT_EXT="$(bashio::config 'DB_PORT' || echo '')" USE_EXTERNAL_DB=false if bashio::config.true 'USE_EXTERNAL_DB'; then USE_EXTERNAL_DB=true bashio::log.warning "USE_EXTERNAL_DB enabled: will connect to external Postgres." else bashio::log.info "Using internal Postgres." fi DISABLE_WEB_UI=false if bashio::config.true 'DISABLE_WEB_UI'; then DISABLE_WEB_UI=true fi # Active DB connection target (may be overridden below) if $USE_EXTERNAL_DB; then DB_HOST="$DB_HOST_EXT" DB_PORT="$DB_PORT_EXT" else DB_HOST="$DB_HOST_INTERNAL" DB_PORT="$DB_PORT_INTERNAL" fi ############################################ # Ensure persistent dirs ############################################ mkdir -p /config/ente/custom-logs \ /config/data \ /config/minio-data \ "$PGDATA" \ /config/scripts/compose ############################################ # Locate binaries ############################################ INITDB="$(command -v initdb || echo /usr/bin/initdb)" POSTGRES_BIN="$(command -v postgres || echo /usr/bin/postgres)" MINIO_BIN="/usr/local/bin/minio" MC_BIN="/usr/local/bin/mc" MUSEUM_BIN="$(command -v museum || true)" [ -z "$MUSEUM_BIN" ] && [ -x /app/museum ] && MUSEUM_BIN=/app/museum [ -z "$MUSEUM_BIN" ] && [ -x /museum ] && MUSEUM_BIN=/museum [ -z "$MUSEUM_BIN" ] && MUSEUM_BIN=museum # fallback in PATH ############################################ # Config generation ############################################ create_config() { bashio::log.info "Generating new museum config at $CFG" _rand_b64() { head -c "$1" /dev/urandom | base64 | tr -d '\n'; } _rand_b64url() { head -c "$1" /dev/urandom | base64 | tr '+/' '-_' | tr -d '\n'; } cat > "$CFG" << EOF key: encryption: $(_rand_b64 32) hash: $(_rand_b64 64) jwt: secret: $(_rand_b64url 32) db: host: ${DB_HOST_INTERNAL} port: ${DB_PORT_INTERNAL} name: ${DB_NAME} user: ${DB_USER} password: ${DB_PASS} s3: are_local_buckets: true ${S3_BUCKET}: key: ${MINIO_USER} secret: ${MINIO_PASS} endpoint: ${ENTE_S3_B2_EU_CEN_ENDPOINT} region: ${ENTE_S3_B2_EU_CEN_REGION} bucket: ${S3_BUCKET} EOF } ############################################ # Postgres ############################################ start_postgres() { if $USE_EXTERNAL_DB; then bashio::log.info "External DB in use; not starting internal Postgres." return 0 fi mkdir -p /run/postgresql chown postgres:postgres /run/postgresql chmod 775 /run/postgresql chown -R postgres:postgres "$PGDATA" chmod 0700 "$PGDATA" if [[ ! -s "$PGDATA/PG_VERSION" ]]; then bashio::log.info "Initializing Postgres data directory..." su - postgres -c "$INITDB -D $PGDATA" fi bashio::log.info "Starting Postgres (${DB_HOST_INTERNAL}:${DB_PORT_INTERNAL})..." su - postgres -c "$POSTGRES_BIN -D $PGDATA -c listen_addresses='127.0.0.1'" & PG_PID=$! } wait_postgres_ready() { local host port if $USE_EXTERNAL_DB; then host="$DB_HOST_EXT" port="$DB_PORT_EXT" bashio::log.info "Waiting for EXTERNAL Postgres at ${host}:${port}..." else host="$DB_HOST_INTERNAL" port="$DB_PORT_INTERNAL" bashio::log.info "Waiting for internal Postgres..." fi until pg_isready -q -h "$host" -p "$port"; do sleep 1; done bashio::log.info "Postgres reachable." } bootstrap_internal_db() { if $USE_EXTERNAL_DB; then return 0 fi bashio::log.info "Ensuring role & database exist..." local esc_pass="${DB_PASS//\'/\'\'}" # role if ! psql -v ON_ERROR_STOP=1 -h "$DB_HOST_INTERNAL" -p "$DB_PORT_INTERNAL" -U postgres -tAc \ "SELECT 1 FROM pg_roles WHERE rolname = '${DB_USER}'" | grep -q 1; then psql -v ON_ERROR_STOP=1 -h "$DB_HOST_INTERNAL" -p "$DB_PORT_INTERNAL" -U postgres \ -c "CREATE ROLE \"${DB_USER}\" LOGIN PASSWORD '${esc_pass}';" else psql -v ON_ERROR_STOP=1 -h "$DB_HOST_INTERNAL" -p "$DB_PORT_INTERNAL" -U postgres \ -c "ALTER ROLE \"${DB_USER}\" PASSWORD '${esc_pass}';" fi # db if ! psql -v ON_ERROR_STOP=1 -h "$DB_HOST_INTERNAL" -p "$DB_PORT_INTERNAL" -U postgres -tAc \ "SELECT 1 FROM pg_database WHERE datname = '${DB_NAME}'" | grep -q 1; then psql -v ON_ERROR_STOP=1 -h "$DB_HOST_INTERNAL" -p "$DB_PORT_INTERNAL" -U postgres \ -c "CREATE DATABASE \"${DB_NAME}\" OWNER \"${DB_USER}\";" else psql -v ON_ERROR_STOP=1 -h "$DB_HOST_INTERNAL" -p "$DB_PORT_INTERNAL" -U postgres \ -c "ALTER DATABASE \"${DB_NAME}\" OWNER TO \"${DB_USER}\";" fi } ############################################ # MinIO ############################################ start_minio() { bashio::log.info "Starting MinIO (:3200)..." mkdir -p /config/minio-data "$MINIO_BIN" server /config/minio-data --address ":3200" & MINIO_PID=$! } wait_minio_ready_and_bucket() { bashio::log.info "Waiting for MinIO API..." until "$MC_BIN" alias set h0 http://127.0.0.1:3200 "$MINIO_USER" "$MINIO_PASS" 2> /dev/null; do sleep 1 done bashio::log.info "Ensuring buckets..." "$MC_BIN" mb -p "h0/${S3_BUCKET}" || true bashio::log.info "MinIO buckets ready." } ############################################ # Web (static nginx bundle) ############################################ start_web() { if $DISABLE_WEB_UI; then bashio::log.info "Web UI disabled." return 0 fi ENTE_API_ORIGIN=http://localhost:8080 ENTE_ALBUMS_ORIGIN=http://localhost:3002 export ENTE_API_ORIGIN ENTE_ALBUMS_ORIGIN # Running ente-web-prepare echo "[ente-web-prepare] Substituting origins…" find /www -name '*.js' | xargs sed -i "s#ENTE_API_ORIGIN_PLACEHOLDER#${ENTE_API_ORIGIN}#g" find /www/photos -name '*.js' | xargs sed -i "s#ENTE_ALBUMS_ORIGIN_PLACEHOLDER#${ENTE_ALBUMS_ORIGIN}#g" mkdir -p /run/nginx /var/log/nginx # Set nginx mv /etc/nginx/http.d/web.bak /etc/nginx/http.d/web.conf bashio::log.info "Starting Ente web (nginx, ports 3000‑3004)..." exec nginx -g 'daemon off;' & WEB_PID=$! } ############################################ # Museum (API) ############################################ start_museum_foreground() { if [ ! -f "$CFG" ]; then bashio::log.error "$CFG missing; cannot start museum." return 1 fi if [ ! -x "$MUSEUM_BIN" ] && ! command -v "$MUSEUM_BIN" > /dev/null 2>&1; then bashio::log.error "Museum binary not found; cannot launch Ente API." return 1 fi # Force env overrides (museum merges env > yaml) if $USE_EXTERNAL_DB; then export ENTE_DB_HOST="$DB_HOST_EXT" export ENTE_DB_PORT="$DB_PORT_EXT" else export ENTE_DB_HOST="$DB_HOST_INTERNAL" export ENTE_DB_PORT="$DB_PORT_INTERNAL" fi export ENTE_DB_USER="$DB_USER" export ENTE_DB_PASSWORD="$DB_PASS" export ENTE_DB_NAME="$DB_NAME" export ENTE_DB_SSLMODE=disable bashio::log.info "Starting museum (foreground)..." exec "$MUSEUM_BIN" --config "$CFG" } ############################################ # Main orchestration ############################################ bashio::log.info "=== Ente startup sequence ===" if [ ! -f "$CFG" ]; then create_config else bashio::log.info "Using existing $CFG." fi start_postgres wait_postgres_ready bootstrap_internal_db start_minio wait_minio_ready_and_bucket start_web # Foreground — keeps container alive start_museum_foreground