Files
OpenFrame/.env.docker.example
T
yusufipek 7b60f3bf76 feat(uploads): size one upload against the account's own quota
The per-file ceiling was a flat 5 GiB from the environment, which is both
too small for a paying account with 200 GB of storage and unaware of what
an upload actually costs. The provider derives its own renditions from the
file (1080p, 720p and down) and bills them to the same account, so a file
allowed to fill the quota exactly is over it by the time it finishes
processing.

The ceiling is now 80% of whatever limit the account is held to: 160 GB on
the plan, 2.4 GB on a cardless trial, and it moves on its own when either
number changes. OPENFRAME_MAX_VIDEO_UPLOAD_BYTES keeps working as an
absolute cap for a host that wants one, where the lower of the two applies,
and an instance running without billing has no quota to divide and falls
back to the flat 5 GiB. The refusal now names the ceiling, which the old
one left the client to guess.

Finalize re-checks only the host cap. Re-deriving the account's ceiling
there would delete a finished upload over a plan that lapsed while the
bytes were in flight, and an upload larger than what was declared is
already caught by the declared-size check beside it.
2026-08-20 08:52:26 +03:00

75 lines
2.6 KiB
Bash

# Copy to .env.docker before starting the Docker stack.
# Application URLs
NEXTAUTH_URL="http://localhost:3000"
NEXT_PUBLIC_APP_URL="http://localhost:3000"
AUTH_TRUST_HOST="true"
# Generate a strong random secret before first boot.
NEXTAUTH_SECRET="replace-with-openssl-rand-base64-32"
# Docker Compose defaults
POSTGRES_DB="openframe"
POSTGRES_USER="replace-with-postgres-user"
POSTGRES_PASSWORD="replace-with-strong-postgres-password"
DATABASE_URL="postgresql://replace-with-postgres-user:replace-with-strong-postgres-password@postgres:5432/openframe?schema=public"
NODE_ENV="production"
# Self-host defaults
OPENFRAME_ENABLE_STRIPE="false"
OPENFRAME_ENABLE_BUNNY_UPLOADS="false"
OPENFRAME_ENABLE_S3_VIDEO_UPLOADS="true"
# OPENFRAME_MAX_VIDEO_UPLOAD_BYTES="5368709120"
OPENFRAME_REQUIRE_INVITE_CODE="false"
SELF_HOSTED_AUTO_CREATE_BUCKET="true"
# Project bulk-download manifest limits (GET /api/projects/[projectId]/download).
OPENFRAME_PROJECT_DOWNLOAD_MAX_FILES="250"
# 20 GiB in bytes (20 * 1024 * 1024 * 1024)
OPENFRAME_PROJECT_DOWNLOAD_MAX_BYTES="21474836480"
# Comma-separated hostnames for direct version download URLs (optional).
NEXT_PUBLIC_DIRECT_DOWNLOAD_ALLOWED_HOSTS=""
# Trusted reverse proxy mode — controls which headers getClientIp() trusts for rate limiting.
# Set this only when you have confirmed that your proxy strips/overwrites client-supplied headers.
# cloudflare — trust cf-connecting-ip (Cloudflare edge in front of the origin)
# nginx — trust x-real-ip / last x-forwarded-for (Nginx real_ip_header with set_real_ip_from)
# Leave unset for local dev or when no trusted proxy is in place.
TRUSTED_PROXY_MODE="nginx"
# MinIO-backed S3 storage
MINIO_ROOT_USER="replace-with-minio-root-user"
MINIO_ROOT_PASSWORD="replace-with-strong-minio-password"
R2_ENDPOINT="http://minio:9000"
# Browser-facing MinIO origin for presigned upload URLs (scheme + host, no path).
# Use your public MinIO domain when behind a reverse proxy, e.g. https://minio.example.com
R2_PRESIGN_ENDPOINT="http://localhost:9000"
R2_PUBLIC_BASE_URL="http://localhost:9000/openframe"
R2_ACCESS_KEY_ID="replace-with-minio-root-user"
R2_SECRET_ACCESS_KEY="replace-with-strong-minio-password"
R2_BUCKET_NAME="openframe"
# Optional auth/admin configuration
ADMIN_EMAILS=""
INVITE_CODE=""
# Optional integrations. Leave blank to disable.
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""
GITHUB_CLIENT_ID=""
GITHUB_CLIENT_SECRET=""
SMTP_HOST=""
SMTP_PORT="587"
SMTP_USER=""
SMTP_PASSWORD=""
SMTP_FROM=""
TELEGRAM_BOT_TOKEN=""
STRIPE_SECRET_KEY=""
STRIPE_PRICE_ID=""
STRIPE_WEBHOOK_SECRET=""
BUNNY_STREAM_API_KEY=""
BUNNY_STREAM_LIBRARY_ID=""
BUNNY_API_KEY=""
BUNNY_CDN_URL=""
NEXT_PUBLIC_BUNNY_CDN_URL=""