#!/bin/bash set -euo pipefail # InvenTree runtime setup for Cloudron: # 1. map the Cloudron postgresql + redis addons onto INVENTREE_* env # and pin the data dir into localstorage (/app/data) # 2. wait for both addons # 3. drive `invoke update` (migrations + static collection) before # serving; the image ENTRYPOINT is bypassed so we control ordering # 4. background the RQ worker (gated on the web port = migrations # done), then exec gunicorn on :8000 # # Authentication: OIDC via the Cloudron platform provider, mapped into # INVENTREE_SOCIAL_PROVIDERS (django-allauth openid_connect). The first # admin is seeded via INVENTREE_ADMIN_* with a generated password, # persisted at /app/data/.admin_password (see README). DATA_DIR="/app/data" ADMIN_PASS_FILE="${DATA_DIR}/.admin_password" mkdir -p "${DATA_DIR}" # --- 1. Cloudron -> INVENTREE_* environment --------------------------------------- export INVENTREE_DATA_DIR="${DATA_DIR}" export INVENTREE_CONFIG_FILE="${DATA_DIR}/config.yaml" export INVENTREE_DB_ENGINE=postgresql export INVENTREE_DB_HOST="${CLOUDRON_POSTGRESQL_HOST:-127.0.0.1}" export INVENTREE_DB_PORT="${CLOUDRON_POSTGRESQL_PORT:-5432}" export INVENTREE_DB_NAME="${CLOUDRON_POSTGRESQL_DATABASE:-inventree}" export INVENTREE_DB_USER="${CLOUDRON_POSTGRESQL_USERNAME:-inventree}" export INVENTREE_DB_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD:-}" export INVENTREE_CACHE_ENABLED=true export INVENTREE_CACHE_HOST="${CLOUDRON_REDIS_HOST:-127.0.0.1}" export INVENTREE_CACHE_PORT="${CLOUDRON_REDIS_PORT:-6379}" export INVENTREE_CACHE_PASSWORD="${CLOUDRON_REDIS_PASSWORD:-}" export INVENTREE_CACHE_DB=1 export INVENTREE_SITE_URL="${CLOUDRON_APP_ORIGIN:-http://localhost}" export INVENTREE_SECRET_KEY="$(cat "${DATA_DIR}/.secret_key" 2>/dev/null || true)" if [[ -z "${INVENTREE_SECRET_KEY}" ]]; then ( umask 077; head -c 48 /dev/urandom | od -An -tx1 | tr -d ' \n' > "${DATA_DIR}/.secret_key" ) export INVENTREE_SECRET_KEY="$(cat "${DATA_DIR}/.secret_key")" echo "Generated new InvenTree secret key" fi # first admin: generated password, stored under /app/data if [[ ! -s "${ADMIN_PASS_FILE}" ]]; then ( umask 077; head -c 12 /dev/urandom | od -An -tx1 | tr -d ' \n' > "${ADMIN_PASS_FILE}" ) echo "Generated admin password (stored at ${ADMIN_PASS_FILE} - see README)" fi export INVENTREE_ADMIN_USER="${INVENTREE_ADMIN_USER:-admin}" export INVENTREE_ADMIN_PASSWORD="${INVENTREE_ADMIN_PASSWORD:-$(cat "${ADMIN_PASS_FILE}")}" export INVENTREE_ADMIN_EMAIL="${INVENTREE_ADMIN_EMAIL:-admin@${CLOUDRON_APP_DOMAIN:-localhost}}" # platform OIDC -> django-allauth openid_connect (server_url drives # .well-known discovery; PKCE on) if [[ -n "${CLOUDRON_OIDC_CLIENT_ID:-}" ]]; then export INVENTREE_SOCIAL_PROVIDERS="$(jq -nc \ --arg cid "${CLOUDRON_OIDC_CLIENT_ID}" \ --arg csec "${CLOUDRON_OIDC_CLIENT_SECRET:-}" \ --arg issuer "${CLOUDRON_OIDC_ISSUER:-}" \ '{openid_connect: {OAUTH_PKCE_ENABLED: true, APPS: [{provider_id: "cloudron", name: "Cloudron SSO", server_url: $issuer, client_id: $cid, secret: $csec}]}}')" fi # --- 2. wait for the addons --------------------------------------------------------- wait_tcp() { local host="$1" port="$2" name="$3" echo "Waiting for ${name} at ${host}:${port} ..." until (exec 3<>"/dev/tcp/${host}/${port}") 2>/dev/null; do echo "${name} is unavailable - sleeping" sleep 2 done echo "${name} is up" } wait_tcp "${INVENTREE_DB_HOST}" "${INVENTREE_DB_PORT}" "PostgreSQL" wait_tcp "${INVENTREE_CACHE_HOST}" "${INVENTREE_CACHE_PORT}" "Redis" # --- 3. schema + static + plugin setup ---------------------------------------------- # image layout: INVENTREE_HOME=/home/inventree (tasks.py + gunicorn.conf.py # + init.sh live here), INVENTREE_BACKEND_DIR=/home/inventree/src/backend cd "${INVENTREE_HOME:-/home/inventree}" echo "Running invoke update (migrations + static files) ..." invoke update # --- 4. worker + web server ---------------------------------------------------------- ( until (exec 3<>/dev/tcp/127.0.0.1/8000) 2>/dev/null; do sleep 2; done echo "web port is up - starting InvenTree worker" exec invoke worker ) & echo "Starting InvenTree web server on :8000 ..." exec gunicorn -c ./gunicorn.conf.py InvenTree.wsgi -b 0.0.0.0:8000 \ --chdir "${INVENTREE_BACKEND_DIR:-/home/inventree/src/backend}/InvenTree"