Files
OpenFrame/.env.example
T
yusufipk 52e4169db2 feat: add project bulk download and bulk video delete
Add a "Download project" / "Download selected" flow that builds a
server-side manifest of downloadable media, plus a selection mode with
bulk delete for project videos.

Gate viewer downloads behind a new project allowDownloads setting
(default off, opt-in). Admins can always download; enabling on a public
project allows anonymous visitors to download. Enforce the setting on
every download surface (manifest, version, asset, watch, video routes)
via canDownloadProjectMedia.

Add rate limits for the manifest endpoint, host allowlisting for direct
download URLs, and configurable file/byte caps.

Closes #16
Closes #19
2026-06-27 13:24:05 +02:00

142 lines
6.6 KiB
Bash

# Copy this file to .env and fill in your values
# ============================================================================
# DATABASE
# ============================================================================
# PostgreSQL connection string
DATABASE_URL="postgresql://user:password@localhost:5432/openframe?schema=public"
# Enable PostgreSQL pool connect/acquire debug logs (set to "true" only when debugging)
DB_POOL_DEBUG="false"
# ============================================================================
# AUTHENTICATION - NextAuth.js
# ============================================================================
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="your-secret-key-here-generate-with-openssl-rand-base64-32"
# ============================================================================
# OPTIONAL SELF-HOSTING FEATURE FLAGS
# ============================================================================
OPENFRAME_ENABLE_STRIPE="true"
OPENFRAME_ENABLE_BUNNY_UPLOADS="true"
# Self-hosted direct video uploads to your S3-compatible storage (R2_* vars below).
# Mutually exclusive with Bunny: set OPENFRAME_ENABLE_BUNNY_UPLOADS=false when enabling this.
OPENFRAME_ENABLE_S3_VIDEO_UPLOADS="false"
# Max size per uploaded video file in bytes (default 5GB if unset)
OPENFRAME_MAX_VIDEO_UPLOAD_BYTES="5368709120"
# Direct browser uploads require bucket CORS allowing PUT from your app origin(s).
# Run once after creating the bucket: bun run r2:configure-cors
# Or set CORS manually in Cloudflare R2 -> bucket -> Settings -> CORS policy.
OPENFRAME_REQUIRE_INVITE_CODE="true"
SELF_HOSTED_AUTO_CREATE_BUCKET="false"
# ============================================================================
# OAUTH PROVIDERS
# ============================================================================
# Google OAuth
# Create credentials at: https://console.cloud.google.com/apis/credentials
GOOGLE_CLIENT_ID="your-google-client-id.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
# GitHub OAuth
# Create credentials at: https://github.com/settings/developers
GITHUB_CLIENT_ID="your-github-client-id"
GITHUB_CLIENT_SECRET="your-github-client-secret"
# ============================================================================
# FILE STORAGE
# ============================================================================
# Cloudflare R2 (S3-compatible)
# For self-hosted S3-compatible storage such as MinIO, set:
# - R2_ENDPOINT (server/container endpoint)
# - R2_PRESIGN_ENDPOINT (browser-reachable endpoint for presigned upload URLs)
# - R2_PUBLIC_BASE_URL (public base URL for served files)
R2_ACCOUNT_ID="your-account-id"
R2_ENDPOINT=""
R2_PRESIGN_ENDPOINT=""
R2_PUBLIC_BASE_URL=""
R2_ACCESS_KEY_ID="your-access-key"
R2_SECRET_ACCESS_KEY="your-secret-key"
R2_BUCKET_NAME="openframe"
# R2 orphan cleanup configuration (script + external cron; app runtime does not schedule this)
# R2_ORPHAN_CLEANUP_CRON="*/15 * * * *"
# Scheduled delete mode:
# */15 * * * * cd /home/yusuf/Programming/OpenFrame && bun run r2:cleanup-orphans
# ============================================================================
# EMAIL & NOTIFICATIONS
# ============================================================================
# Telegram bot token from @BotFather — shared across all users
# Users only need to provide their own Chat ID in Settings
TELEGRAM_BOT_TOKEN="your-telegram-bot-token"
SMTP_HOST="smtp.gmail.com"
SMTP_PORT="587"
SMTP_USER="[email protected]"
SMTP_PASSWORD="your-app-specific-password"
SMTP_FROM="[email protected]"
# ============================================================================
# APPLICATION
# ============================================================================
NEXT_PUBLIC_APP_URL="http://localhost:3000"
# development | production | test
NODE_ENV="development"
# Disable all app-level rate limiting for local testing. Leave unset to keep rate limiting enabled.
# Accepted truthy values: "true", "1", "yes", "on"
# DISABLE_RATE_LIMIT="true"
# 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="cloudflare"
# Admin emails for accessing the /admin panel (comma separated list)
# e.g., "[email protected],[email protected]"
ADMIN_EMAILS=""
# Invite code for internal registration (required to sign up)
# Generate a secure code for your team
INVITE_CODE="your-secret-invite-code"
# Enable debug logging
# DEBUG="openframe:*"
# ============================================================================
# DOWNLOADS
# ============================================================================
# Project bulk-download manifest limits (GET /api/projects/[projectId]/download).
# Caps how many files and total known bytes a single manifest may enumerate.
OPENFRAME_PROJECT_DOWNLOAD_MAX_FILES="250"
# 20 GiB in bytes (20 * 1024 * 1024 * 1024)
OPENFRAME_PROJECT_DOWNLOAD_MAX_BYTES="21474836480"
# Comma-separated hostnames allowed for direct (non-proxied) version download URLs
# in manifests and the video page. Bunny CDN host is always allowed when configured.
# Example: "cdn.example.com,files.example.com"
NEXT_PUBLIC_DIRECT_DOWNLOAD_ALLOWED_HOSTS=""
# ============================================================================
# VIDEO PROCESSING
# ============================================================================
# Bunny Stream for direct video uploads
BUNNY_STREAM_API_KEY="your-stream-library-api-key"
BUNNY_STREAM_LIBRARY_ID="your-library-id"
# Bunny Core API key (account-level) used to enforce KeepOriginalFiles/ExposeOriginals on the library
BUNNY_API_KEY="your-account-api-key"
# Bunny Stream CDN base URL (for HLS streaming)
BUNNY_CDN_URL="your-url-to-bunny-cdn"
NEXT_PUBLIC_BUNNY_CDN_URL="your-url-to-bunny-cdn"
# Bunny orphan cleanup configuration (script + external cron; app runtime does not schedule this)
# Grace period is fixed at 24 hours in the script.
# */15 * * * * cd /home/yusuf/Programming/OpenFrame && bun run bunny:cleanup-orphans
# ============================================================================
# BILLING
# ============================================================================
# Stripe recurring price used for paid accounts
STRIPE_SECRET_KEY="sk_test_..."
STRIPE_PRICE_ID="prod_UBWFFKZC3d80z4"
STRIPE_WEBHOOK_SECRET="whsec_..."