services: web: image: ${GPT_IMAGE_PANEL_IMAGE:-ghcr.io/z1rconium/gpt-image-linux:v1.5.1} container_name: gpt-image-panel-web ports: - "127.0.0.1:9090:9090" volumes: - ./images:/app/images - ./data:/app/data - ./data/logs:/app/data/logs environment: - DEFAULT_API_URL=${DEFAULT_API_URL:-} - DEFAULT_API_KEY=${DEFAULT_API_KEY:-} - DEFAULT_API_PATH=${DEFAULT_API_PATH:-/v1/images/generations} - DEFAULT_RESPONSES_MODEL=${DEFAULT_RESPONSES_MODEL:-gpt-5.4} - DEFAULT_UPSTREAM_SOCKS5_PROXY=${DEFAULT_UPSTREAM_SOCKS5_PROXY:-} - AIOHTTP_CONNECTION_LIMIT=${AIOHTTP_CONNECTION_LIMIT:-100} - AIOHTTP_CONNECTION_LIMIT_PER_HOST=${AIOHTTP_CONNECTION_LIMIT_PER_HOST:-20} - APP_VERSION=${APP_VERSION:-} - GITHUB_REPO=${GITHUB_REPO:-Z1rconium/gpt-image-linux} - ENABLE_VERSION_CHECK=${ENABLE_VERSION_CHECK:-true} - VERSION_CHECK_TIMEOUT_SECONDS=${VERSION_CHECK_TIMEOUT_SECONDS:-3} - VERSION_CHECK_BRANCH=${VERSION_CHECK_BRANCH:-main} - VERSION_CHECK_CACHE_SECONDS=${VERSION_CHECK_CACHE_SECONDS:-600} - ENABLE_METRICS=${ENABLE_METRICS:-false} - SLOW_GALLERY_QUERY_MS=${SLOW_GALLERY_QUERY_MS:-200} - ENABLE_NGINX_ACCEL_REDIRECT=${ENABLE_NGINX_ACCEL_REDIRECT:-false} - PUBLIC_IMAGE_BASE_URL=${PUBLIC_IMAGE_BASE_URL:-} - PUBLIC_THUMBNAIL_BASE_URL=${PUBLIC_THUMBNAIL_BASE_URL:-} - GRANIAN_WORKERS=${GRANIAN_WORKERS:-1} - GRANIAN_RUNTIME_THREADS=${GRANIAN_RUNTIME_THREADS:-2} - GRANIAN_LOOP=${GRANIAN_LOOP:-uvloop} - GRANIAN_BACKPRESSURE=${GRANIAN_BACKPRESSURE:-100} - GRANIAN_BACKLOG=${GRANIAN_BACKLOG:-2048} - GRANIAN_STATIC_PATH_ROUTE=${GRANIAN_STATIC_PATH_ROUTE:-/_app/immutable} - GRANIAN_STATIC_PATH_MOUNT=${GRANIAN_STATIC_PATH_MOUNT:-/app/frontend/build/_app/immutable} - GRANIAN_STATIC_PATH_EXPIRES=${GRANIAN_STATIC_PATH_EXPIRES:-31536000} - ALLOW_PLAINTEXT_SECRETS=${ALLOW_PLAINTEXT_SECRETS:-false} - PROMPT_OPTIMIZER_ENABLED=${PROMPT_OPTIMIZER_ENABLED:-false} - PROMPT_OPTIMIZER_API_URL=${PROMPT_OPTIMIZER_API_URL:-} - PROMPT_OPTIMIZER_API_KEY=${PROMPT_OPTIMIZER_API_KEY:-} - PROMPT_OPTIMIZER_MODEL=${PROMPT_OPTIMIZER_MODEL:-gpt-4o-mini} - PROMPT_OPTIMIZER_TIMEOUT_SECONDS=${PROMPT_OPTIMIZER_TIMEOUT_SECONDS:-60} - PROMPT_OPTIMIZER_MAX_OUTPUT_CHARS=${PROMPT_OPTIMIZER_MAX_OUTPUT_CHARS:-4000} - PROMPT_OPTIMIZER_MAX_RESPONSE_MB=${PROMPT_OPTIMIZER_MAX_RESPONSE_MB:-8} - PROMPT_OPTIMIZER_HOST_ALLOWLIST=${PROMPT_OPTIMIZER_HOST_ALLOWLIST:-} - AI_ASSISTANT_ENABLED=${AI_ASSISTANT_ENABLED:-true} - AI_ASSISTANT_VISION_MODEL=${AI_ASSISTANT_VISION_MODEL:-gpt-4o-mini} - AI_ASSISTANT_MAX_RESPONSE_MB=${AI_ASSISTANT_MAX_RESPONSE_MB:-8} - AI_ASSISTANT_MAX_CONCURRENCY=${AI_ASSISTANT_MAX_CONCURRENCY:-2} - AI_ASSISTANT_BATCH_MAX_IMAGES=${AI_ASSISTANT_BATCH_MAX_IMAGES:-200} - AI_ASSISTANT_IMAGE_MAX_SIDE=${AI_ASSISTANT_IMAGE_MAX_SIDE:-1024} - AI_ASSISTANT_IMAGE_MAX_BYTES=${AI_ASSISTANT_IMAGE_MAX_BYTES:-1048576} - R2_BACKUP_ENABLED=${R2_BACKUP_ENABLED:-false} - R2_ENDPOINT_URL=${R2_ENDPOINT_URL:-} - R2_ENDPOINT_HOST_ALLOWLIST=${R2_ENDPOINT_HOST_ALLOWLIST:-} - R2_BUCKET_NAME=${R2_BUCKET_NAME:-} - R2_REGION=${R2_REGION:-auto} - R2_KEY_PREFIX=${R2_KEY_PREFIX:-gallery/} - R2_SYNC_INTERVAL_HOURS=${R2_SYNC_INTERVAL_HOURS:-0} - R2_SYNC_CONCURRENCY=${R2_SYNC_CONCURRENCY:-4} - R2_ACCESS_KEY_ID=${R2_ACCESS_KEY_ID:-} - R2_SECRET_ACCESS_KEY=${R2_SECRET_ACCESS_KEY:-} - NODEIMAGE_API_KEY=${NODEIMAGE_API_KEY:-} - ACCESS_KEY=${ACCESS_KEY:-} - ALLOW_UNAUTHENTICATED=${ALLOW_UNAUTHENTICATED:-false} - ACCESS_KEY_COOKIE_NAME=${ACCESS_KEY_COOKIE_NAME:-__Host-gpt_image_access} - ACCESS_COOKIE_SECURE=${ACCESS_COOKIE_SECURE:-true} - ACCESS_MAX_FAILURES=${ACCESS_MAX_FAILURES:-5} - ACCESS_LOCKOUT_SECONDS=${ACCESS_LOCKOUT_SECONDS:-300} - TURNSTILE_ENABLED=${TURNSTILE_ENABLED:-false} - TURNSTILE_SITE_KEY=${TURNSTILE_SITE_KEY:-} - TURNSTILE_SECRET_KEY=${TURNSTILE_SECRET_KEY:-} - IP_ALLOWLIST=${IP_ALLOWLIST:-} - TRUST_PROXY_HEADERS=${TRUST_PROXY_HEADERS:-false} - TRUSTED_PROXY_IPS=${TRUSTED_PROXY_IPS:-} - PUBLIC_ORIGIN=${PUBLIC_ORIGIN:-} - ALLOWED_HOSTS=${ALLOWED_HOSTS:-} - CSRF_ORIGIN_CHECK_ENABLED=${CSRF_ORIGIN_CHECK_ENABLED:-true} - UPSTREAM_HOST_ALLOWLIST=${UPSTREAM_HOST_ALLOWLIST:-} - WEBHOOK_HOST_ALLOWLIST=${WEBHOOK_HOST_ALLOWLIST:-} - WEBHOOK_SIGNING_SECRET=${WEBHOOK_SIGNING_SECRET:-} - WEBHOOK_TIMEOUT_SECONDS=${WEBHOOK_TIMEOUT_SECONDS:-5} - WEBHOOK_MAX_ATTEMPTS=${WEBHOOK_MAX_ATTEMPTS:-3} - MAX_FILE_SIZE_MB=${MAX_FILE_SIZE_MB:-50} - MAX_JSON_BODY_MB=${MAX_JSON_BODY_MB:-1} - MAX_UPSTREAM_JSON_MB=${MAX_UPSTREAM_JSON_MB:-128} - MAX_UPSTREAM_IMAGE_BYTES_PER_TASK_MB=${MAX_UPSTREAM_IMAGE_BYTES_PER_TASK_MB:-50} - UPSTREAM_MEMORY_BUDGET_MB=${UPSTREAM_MEMORY_BUDGET_MB:-256} - MAX_IMAGE_PIXELS=${MAX_IMAGE_PIXELS:-100000000} - IMAGE_CPU_CONCURRENCY=${IMAGE_CPU_CONCURRENCY:-2} - FILE_IO_CONCURRENCY=${FILE_IO_CONCURRENCY:-4} - DB_EXECUTOR_WORKERS=${DB_EXECUTOR_WORKERS:-4} - SQLITE_BUSY_TIMEOUT_MS=${SQLITE_BUSY_TIMEOUT_MS:-250} - SQLITE_BUSY_RETRY_ATTEMPTS=${SQLITE_BUSY_RETRY_ATTEMPTS:-5} - SQLITE_BUSY_RETRY_BASE_MS=${SQLITE_BUSY_RETRY_BASE_MS:-20} - IMAGE_JOB_PROGRESS_PERSIST_INTERVAL_SECONDS=${IMAGE_JOB_PROGRESS_PERSIST_INTERVAL_SECONDS:-1} - RUNTIME_METRICS_REFRESH_SECONDS=${RUNTIME_METRICS_REFRESH_SECONDS:-15} - EVENT_LOOP_LAG_SAMPLE_SECONDS=${EVENT_LOOP_LAG_SAMPLE_SECONDS:-0.5} - IMPORT_ARCHIVE_MAX_MB=${IMPORT_ARCHIVE_MAX_MB:-1000} - IMPORT_MAX_FILES=${IMPORT_MAX_FILES:-500} - IMPORT_MAX_UNCOMPRESSED_MB=${IMPORT_MAX_UNCOMPRESSED_MB:-1024} - IMPORT_MAX_METADATA_BYTES=${IMPORT_MAX_METADATA_BYTES:-2097152} - IMPORT_MAX_ENTRIES=${IMPORT_MAX_ENTRIES:-500} - IMPORT_MAX_OUTPUT_MB=${IMPORT_MAX_OUTPUT_MB:-1024} - IMPORT_MAX_COMPRESSION_RATIO=${IMPORT_MAX_COMPRESSION_RATIO:-20} - MAX_ACTIVE_GENERATE_JOBS=${MAX_ACTIVE_GENERATE_JOBS:-2} - MAX_QUEUED_GENERATE_JOBS=${MAX_QUEUED_GENERATE_JOBS:-20} - IMAGE_JOB_UNIT_LEASE_SECONDS=${IMAGE_JOB_UNIT_LEASE_SECONDS:-120} - IMAGE_JOB_UNIT_POLL_INTERVAL_SECONDS=${IMAGE_JOB_UNIT_POLL_INTERVAL_SECONDS:-0.35} - MAX_PENDING_EDIT_SOURCE_MB=${MAX_PENDING_EDIT_SOURCE_MB:-200} - MAX_SSE_SUBSCRIBERS_GLOBAL=${MAX_SSE_SUBSCRIBERS_GLOBAL:-200} - MAX_SSE_SUBSCRIBERS_PER_IP=${MAX_SSE_SUBSCRIBERS_PER_IP:-10} - SSE_CONNECTION_TTL_SECONDS=${SSE_CONNECTION_TTL_SECONDS:-3600} - IMAGES_DIR=${IMAGES_DIR:-./images} - THUMBNAILS_DIR=${THUMBNAILS_DIR:-./images/thumbs} - THUMBNAIL_MAX_SIDE=${THUMBNAIL_MAX_SIDE:-512} - THUMBNAIL_CPU_CONCURRENCY=${THUMBNAIL_CPU_CONCURRENCY:-1} - DATA_DIR=${DATA_DIR:-./data} - DATABASE_FILE=${DATABASE_FILE:-./data/app.sqlite3} restart: unless-stopped healthcheck: test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:9090/health')"] interval: 30s timeout: 10s retries: 3 start_period: 10s