- Explicitly stop uwsgi, celery, daphne, and redis-server on SIGTERM;
these are spawned as uwsgi attach-daemons and were not tracked in
pids[], causing exit 137 on docker stop
- Replace fixed sleep 3 with a polling loop (8 s ceiling) that exits as
soon as all processes have stopped
- Use pg_ctl stop -m immediate as the postgres force-stop fallback
instead of SIGKILL to avoid data corruption
- Add _cleanup_done guard to prevent double invocation of cleanup() when
the trap fires and the explicit call at script end both execute
- Register process names at startup in pid_names[] so crash diagnostics
show meaningful names after a process has exited
- Suppress the unexpected-exit diagnostic block on normal docker stop
- Guard all pgrep-based pids+=() against empty values (nginx, vite,
postgres) to prevent empty PID entries corrupting the pids[] array
fix: use psycopg2.sql for safe database drop and create commands
fix: Also check POSTGRES_SSL is true before skipping default POSTGRES_PASSWORD
fix: update usage comment to reflect correct script path
fix: improve cleanup logic to conditionally remove certificate directory
- replaced $_pg_tmp_port with $POSTRGES_PORT in migration logic. Works because "pg_ctl stop -w" is run before entrypoint.sh restarts postgres. Verified that this does not cause a race condition.
- Correcting unquoted environment variables to prevent inappropriate variables from causing execution inconsistencies (still unquoted in comments and prints)
PostgreSQL now runs as the PUID/PGID user ($POSTGRES_USER) instead of the internal postgres system user (UID 102). This fixes container startup failures when PUID/PGID is set, caused by chown permission errors on restricted filesystems (NFS root_squash, CIFS) and UID collisions with the postgres system user.
Changes:
- Run all PostgreSQL operations (initdb, pg_ctl, psql) as $POSTGRES_USER
- Auto-detect PUID/PGID from existing data owner when not explicitly set
- Validate PUID/PGID (reject zero, non-numeric values) before startup
- Migrate existing data ownership with sentinel-based skip optimization
- Use trust auth for local Unix sockets, md5 for network connections
- Add promote_app_role() and ensure_app_database() as idempotent startup guarantees that handle fresh installs, upgrades, and PUID changes
- Preserve postgres role as superuser for rollback compatibility
- Centralize /data/db ownership in 02-postgres.sh (sentinel-aware)
- Add integration test suite (20 scenarios) covering fresh installs, upgrades, restarts, PUID changes, UID collisions, bind mounts, modular mode, PG major upgrades, and end-to-end web UI verification
- Rewrite /etc/profile.d/dispatcharr.sh on every startup instead of only on first run, so container restarts with changed env vars pick up new values
- Quote exported values to prevent breakage from special characters in POSTGRES_PASSWORD or other vars
- Update /etc/environment entries instead of skipping if already present
- Move modular Redis wait from uWSGI exec-pre to entrypoint (exec-pre runs under 'su -' which strips Docker env vars, so DISPATCHARR_ENV and REDIS_HOST were never available)
- Selective flush in modular mode: clears stale app state (stream locks, proxy metadata) while preserving Celery broker/result keys
- AIO mode unchanged: full flushdb via uWSGI exec-pre
- Update unit tests for both flush paths
Replace raw Python AF_INET socket checks with pg_isready (PostgreSQL) and socket.create_connection (Redis) in modular deployment mode
The raw socket check may fail in some Docker environments depending on networking and DNS configurations, causing indefinite hangs. Replaced database check with native pg_isready
and memstore checck with AF_UNSPEC in the case IPv6 is enabled.
Fixes#952
Add support for authentication when connecting to external Redis instances in modular deployment mode. This enables secure Redis deployments using either password-only authentication (Redis <6) or
username + password authentication (Redis 6+ ACL).
Changes:
- Add REDIS_PASSWORD and REDIS_USER environment variables
- Implement URL encoding for special characters in passwords
- Update all Redis connection points to support auth
- Add comprehensive documentation and examples to docker-compose.yml
- Maintains full backward compatibility (empty defaults = no auth)
All authentication mechanisms have been fully tested including pasword-only authentication, Redis 6+ ACL authentication with username + password, volume-mounted configuration files, and special character handling.
Existing deployments are not effected, authentication support is entirely opt-in using docker-compose.
Also, acknowledging the fact that the docker-compose file for modular deployments has been getting out of hand with auth support, the docker-compose.yml file was re-formatted for better visibility in configuration. This seemed like a better way to go than mandating a .env file.
Implements automatic version validation for external databases in modular mode to ensure compatibility.
Changes:
- Added check_external_postgres_version() in 02-postgres.sh
- Integrated version check in entrypoint.sh after database connection
- Enforces minimum PostgreSQL version matching DispatcharrBase
- Allows newer versions with forward compatibility notice
- Rejects older versions with clear upgrade instructions
The version requirement automatically scales when DispatcharrBase is updated, requiring no manual maintenance. Only applies to modular deployments using external databases; AIO deployments are unaffected.
Tested and verified correct behavior with PostgreSQL v17, v18, and v16
Make database ports configurable for users with external PostgreSQL/Redis.
- Add POSTGRES_PORT and REDIS_PORT to docker-compose.yml (web and celery)
- Remove hardcoded CELERY_BROKER_URL (Django builds it from components)
- Add REDIS_PORT export to entrypoint.sh and profile variables
- Add Redis connection check for modular mode (matches PostgreSQL pattern)
Users can now specify custom ports for external databases:
[defaults]
POSTGRES_PORT=5432
REDIS_PORT=6379
Extend ensure_utf8_encoding() to support both internal and external PostgreSQL.
- Modular mode: Uses TCP connection with PGPASSWORD authentication
- AIO mode: Uses Unix socket as postgres user
- Explicitly set database owner during recreation (fixes missing --owner flag)
- Conversion logic (dump/drop/recreate/restore) works for both AIO and modular modes
- Skip internal PostgreSQL setup entirely when DISPATCHARR_ENV=modular
- docker-compose: added service health checks
- dockerfile: added if logic for sed command so missing files do not cause build fail
- entrypoint.celery: change migration detection to not continue until ALL migrations are applied
- entrypoint: trim django key and change external postgres check to python in case postgres binaries are missing
- docker/entrypoint.sh: Conditional PostgreSQL init/startup for modular mode
- docker/entrypoint.celery.sh: New dedicated entrypoint for celery container - prevents race condition in modular deployment
- docker/uwsgi.modular.ini: New uWSGI config without Redis/Celery daemons
- docker/Dockerfile: Add line ending fixes and chmod for entrypoints - adds cross-platform support for image builds
- docker/docker-compose.yml: Configure modular mode with DISPATCHARR_ENV - uses new celery entrypoint and adds depends_on to prevent race condition