mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 09:36:08 +00:00
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
142 lines
6.6 KiB
Bash
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_..."
|