# ============================================================================= # InsForge Environment Configuration # ============================================================================= # Copy this file to .env and fill in your values: # cp .env.example .env # # Security Notes: # - Never commit .env to version control # - Use strong, unique secrets in production # - Rotate secrets regularly # ============================================================================= # Compose project name — prefixes every container, volume and network, so keep # it stable across upgrades. A second instance on the same host needs its own # value here, or `docker compose up` will adopt this one's containers. COMPOSE_PROJECT_NAME=insforge # Which compose file `docker compose` runs. Below is the development stack; it # has to stay equal to what Compose would discover on its own in this directory. A self-hosted install points it at the image-only compose # file instead — deploy/setup.sh writes that for you: # COMPOSE_FILE=deploy/docker-compose/docker-compose.yml # Add a storage overlay by appending it with a colon: # COMPOSE_FILE=deploy/docker-compose/docker-compose.yml:docker-compose.minio.yml COMPOSE_FILE=docker-compose.yml # ----------------------------------------------------------------------------- # Server Configuration # ----------------------------------------------------------------------------- PORT=7130 # Max body size for JSON payloads (default: 100mb) # High default ensures "out-of-the-box" reliability for large metadata/storage requests. # Users can decrease this for hardened security on low-resource environments. MAX_JSON_BODY_SIZE=100mb # Max body size for URL-encoded payloads (default: 10mb) MAX_URLENCODED_BODY_SIZE=10mb # Keep-alive timeout for idle HTTP connections in milliseconds (default: 65000) # Must exceed the idle timeout of any load balancer or proxy in front of the # backend so clients never reuse a connection the server has already closed. KEEP_ALIVE_TIMEOUT_MS=65000 # Max concurrent connections from the backend to PostgREST (default: 50) # Tune per instance size, and keep it aligned with PostgREST's database pool # (PGRST_DB_POOL): raising it beyond the pool only moves queuing into PostgREST. POSTGREST_MAX_SOCKETS=50 # Idle keep-alive connections retained toward PostgREST (default: 10) POSTGREST_MAX_FREE_SOCKETS=10 # How long an idle keep-alive connection toward PostgREST is kept before the # backend closes it (default: 4000). Must stay below PostgREST's server-side # idle timeout so the backend always closes idle sockets first — reusing a # socket the server already closed causes ECONNRESET ("socket hang up"). POSTGREST_FREE_SOCKET_TIMEOUT_MS=4000 # PostgREST's own database connection pool. Keep aligned with POSTGREST_MAX_SOCKETS. # PGRST_DB_POOL=50 # Public URL PostgREST advertises in its OpenAPI output. # POSTGREST_OPENAPI_SERVER_PROXY_URI= # ----------------------------------------------------------------------------- # PostgreSQL Configuration # ----------------------------------------------------------------------------- # These are optional - defaults are shown below # In production, use strong passwords and consider external database services POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres POSTGRES_DB=insforge # ----------------------------------------------------------------------------- # Ports (Configurable) # ----------------------------------------------------------------------------- # PostgreSQL POSTGRES_PORT=5432 # PostgREST API POSTGREST_PORT=5430 # Main application ports APP_PORT=7130 AUTH_PORT=7131 UI_PORT=7132 # Deno serverless runtime DENO_PORT=7133 # API Base URLs - Update if running on different host/port API_BASE_URL=http://localhost:7130 VITE_API_BASE_URL=http://localhost:7130 # ----------------------------------------------------------------------------- # Authentication & Security # ----------------------------------------------------------------------------- # JWT_SECRET: Must be at least 32 characters. Use a secure random generator! # Example: openssl rand -base64 32 JWT_SECRET=your-secret-key-here-must-be-32-char-or-above # Root admin credentials - CHANGE THESE IN PRODUCTION! ROOT_ADMIN_USERNAME=admin ROOT_ADMIN_PASSWORD=change-this-password # Encryption key for secrets and database encryption # IMPORTANT: Set this to a separate 32+ character secret from JWT_SECRET. # If not set, JWT_SECRET is used as fallback — but rotating JWT_SECRET will # permanently corrupt all stored secrets (API keys, OAuth tokens, etc.). # Generate with: openssl rand -base64 32 ENCRYPTION_KEY= # API key for authenticated requests ('ik_' prefix), and anon key for public # clients ('anon_'). Leave empty and the backend generates them on first boot; # deploy/setup.sh generates them for you. Whatever is here is used as-is, so do # not leave a placeholder — it becomes this instance's real key. ACCESS_API_KEY= ACCESS_ANON_KEY= # Cloud API Host (Optional) # Only needed if using cloud features CLOUD_API_HOST=https://api.insforge.dev # ----------------------------------------------------------------------------- # Deployment Configuration (Optional) # ----------------------------------------------------------------------------- # Required for self-hosted site deployments and custom domains. # Legacy deployments also require AWS_S3_BUCKET to be configured. VERCEL_TOKEN= VERCEL_TEAM_ID= VERCEL_PROJECT_ID= # ----------------------------------------------------------------------------- # AWS Config Bucket Configuration (Optional) # ----------------------------------------------------------------------------- # Used for loading remote configuration files from S3 # If not provided, defaults will be used AWS_CONFIG_BUCKET=insforge-config AWS_CONFIG_REGION=us-east-2 # ----------------------------------------------------------------------------- # Storage Configuration # ----------------------------------------------------------------------------- # Storage options: # - Local filesystem: leave S3_BUCKET empty (default) # - Any S3-compatible store (AWS S3, MinIO, RustFS, Wasabi, R2, Tencent COS, # Aliyun OSS ...): set the S3_* variables. For AWS S3, leave S3_ENDPOINT_URL # empty (SDK default endpoints; credentials may also come from an IAM role). # # Local storage directory (default: ./insforge-storage relative to cwd) # In Docker this is set to /insforge-storage automatically via the Dockerfile. # PaaS deployments (Zeabur, Render, etc.) should set this to match the # persistent volume mount path. # STORAGE_DIR=./insforge-storage # # Bucket name — setting this selects the S3 storage provider S3_BUCKET= # SigV4 signing region (default us-east-2; any value works for MinIO/RustFS — # gateway clients must sign with the same region) S3_REGION= # Store credentials S3_ACCESS_KEY_ID= S3_SECRET_ACCESS_KEY= # Custom endpoint for non-AWS stores (leave empty for AWS S3) S3_ENDPOINT_URL= # Max upload file size in bytes (default: 52428800 = 50MB) # Examples: 10485760 = 10MB, 104857600 = 100MB MAX_FILE_SIZE= # Path-style addressing (default true, required by MinIO). Set to false for # providers that require virtual-hosted-style (Tencent COS, Aliyun OSS). S3_FORCE_PATH_STYLE=true # Presigned URLs (default true): clients upload/download directly against the # S3 endpoint. Set to false for PROXY MODE: all object bytes stream through # the backend instead. Required when the endpoint is not reachable by # browsers (bundled MinIO/RustFS on the Docker network) or lacks POST-policy # support (Cloudflare R2). In proxy mode uploads are capped by the storage # max-file-size setting; larger objects go through the S3 gateway. S3_USE_PRESIGNED_URLS=true # Max single S3-gateway upload in bytes (default 5368709120 = 5GB) S3_MAX_OBJECT_SIZE_BYTES= # ⚠️ AWS_* variables are for InsForge Cloud projects only — cloud provisioning # sets them on managed instances. For self-hosting, use the S3_* variables # above and leave these untouched. (AWS_S3_BUCKET / AWS_REGION are the legacy # names and still work as fallbacks for S3_BUCKET / S3_REGION; # AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY are AWS-account credentials used # by CloudWatch logging and CloudFront.) AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_REGION= AWS_S3_BUCKET= # Bundled object store (optional): run MinIO or RustFS next to InsForge by # appending its overlay to COMPOSE_FILE above. Proxy mode is preconfigured, so # no S3_* settings below are needed: # COMPOSE_FILE=deploy/docker-compose/docker-compose.yml:docker-compose.minio.yml # Override the default store credentials (DO change these in production): # MINIO_ROOT_USER=insforge # MINIO_ROOT_PASSWORD=insforge-minio-secret # RUSTFS_ACCESS_KEY=insforge # RUSTFS_SECRET_KEY=insforge-rustfs-secret # Publish the MinIO admin console on the host (off by default): # MINIO_CONSOLE_PORT=9001 # CloudFront signed URLs (InsForge Cloud projects only — self-hosting should # leave these untouched) # When AWS_CLOUDFRONT_URL is set, storage downloads are served through # CloudFront with signed URLs instead of S3 presigned URLs. Ignored when # S3_ENDPOINT_URL is set (CloudFront does not front S3-compatible providers). # Setup: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html # # AWS_CLOUDFRONT_URL: CloudFront distribution domain (e.g. https://d1234abcd.cloudfront.net) # AWS_CLOUDFRONT_KEY_PAIR_ID: Trusted key group key-pair ID (e.g. K2JCJMDEHXQW5F) # AWS_CLOUDFRONT_PRIVATE_KEY: PEM private key. Use \n for newlines when kept on one line. # If URL is set but key pair or private key is missing, downloads fall back to S3 presigned URLs. AWS_CLOUDFRONT_URL= AWS_CLOUDFRONT_KEY_PAIR_ID= AWS_CLOUDFRONT_PRIVATE_KEY= # ----------------------------------------------------------------------------- # Logging Configuration # ----------------------------------------------------------------------------- # CloudWatch Logging: Set AWS_REGION + AWS credentials above # File-based Logging: Configure LOGS_DIR below (used when AWS credentials not provided) # Directory where log files will be stored (defaults to ./logs) LOGS_DIR= # ----------------------------------------------------------------------------- # Anonymous Telemetry # ----------------------------------------------------------------------------- # InsForge sends anonymous self-host usage events so maintainers can understand # active deployments, version adoption, and deployment success. It never sends # secrets, environment variables, logs, domains, file paths, project names, or # database contents. # # Disable all telemetry: # INSFORGE_TELEMETRY_DISABLED=1 # ----------------------------------------------------------------------------- # AI/LLM Configuration # ----------------------------------------------------------------------------- # OpenRouter compatibility credential. On first startup, the value is copied into # InsForge's encrypted secret store and remains a fallback when no stored key exists. # Model Gateway Settings can replace it; stored values always take precedence. # Get an API key from https://openrouter.ai/keys OPENROUTER_API_KEY= # Maximum output tokens per chat completion request (default: 16384). # Increase this for models with larger output windows (e.g. 32768 for 32K-output models). # Must be a positive integer. Invalid values are silently ignored and the default is used. MAX_COMPLETION_TOKENS=16384 # ----------------------------------------------------------------------------- # Stripe Payments Configuration (Optional) # ----------------------------------------------------------------------------- # Developer-owned Stripe secret keys. Test key is used for implementation and # validation. Live key is used only for explicit go-live flows. STRIPE_LIVE_SECRET_KEY= STRIPE_TEST_SECRET_KEY= # ----------------------------------------------------------------------------- # Razorpay Payments Configuration (Optional) # ----------------------------------------------------------------------------- # Developer-owned Razorpay keys. Test keys are used for implementation and # validation. Live keys are used only for explicit go-live flows. RAZORPAY_LIVE_KEY_ID= RAZORPAY_LIVE_KEY_SECRET= RAZORPAY_TEST_KEY_ID= RAZORPAY_TEST_KEY_SECRET= # ----------------------------------------------------------------------------- # Analytics Configuration # ----------------------------------------------------------------------------- # PostHog - Only needed for local development # Get your key from https://posthog.com/settings/project VITE_PUBLIC_POSTHOG_KEY= # ----------------------------------------------------------------------------- # OAuth Configuration (Optional) # ----------------------------------------------------------------------------- # Enable social login by configuring one or more providers below. # Each provider requires registering an application in their developer console. # # Google OAuth # Console: https://console.cloud.google.com/ # Redirect URI: http://localhost:7130/auth/google/callback GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= # GitHub OAuth # Console: https://github.com/settings/developers # Redirect URI: http://localhost:7130/auth/github/callback GITHUB_CLIENT_ID= GITHUB_CLIENT_SECRET= # Microsoft OAuth (Azure AD) # Console: https://portal.azure.com/ # Redirect URI: http://localhost:7130/auth/microsoft/callback MICROSOFT_CLIENT_ID= MICROSOFT_CLIENT_SECRET= # Discord OAuth # Console: https://discord.com/developers/applications # Redirect URI: http://localhost:7130/auth/discord/callback DISCORD_CLIENT_ID= DISCORD_CLIENT_SECRET= # LinkedIn OAuth # Console: https://www.linkedin.com/developers/apps # Redirect URI: http://localhost:7130/auth/linkedin/callback LINKEDIN_CLIENT_ID= LINKEDIN_CLIENT_SECRET= # X (Twitter) OAuth # Console: https://developer.twitter.com/en/portal/dashboard # Redirect URI: http://localhost:7130/auth/x/callback X_CLIENT_ID= X_CLIENT_SECRET= # Apple OAuth (Sign in with Apple) # Console: https://developer.apple.com/account/resources/identifiers/list # APPLE_CLIENT_ID: Your Services ID (e.g., com.yourapp.service) # APPLE_CLIENT_SECRET: JSON string with teamId, keyId, and privateKey # Format: {"teamId":"XXX","keyId":"YYY","privateKey":"-----BEGIN PRIVATE KEY-----\n..."} # Redirect URI: http://localhost:7130/auth/apple/callback APPLE_CLIENT_ID= APPLE_CLIENT_SECRET= # ----------------------------------------------------------------------------- # Multi-tenant Cloud Configuration # ----------------------------------------------------------------------------- # These are only used for the cloud-hosted solution # Leave empty for self-hosted deployments. # # PROJECT_ID is safe to set when self-hosting: it scopes compute services and edge # function deployments, and is not taken as a signal that this is a cloud-managed # project. What marks a deployment as cloud-managed is AWS_INSTANCE_PROFILE_NAME, which # only our provisioning sets. DEPLOYMENT_ID= PROJECT_ID= APP_KEY= # ----------------------------------------------------------------------------- # Serverless Functions Configuration # ----------------------------------------------------------------------------- # Deno Deploy - For hosting serverless edge functions # Get your token from: https://dash.deno.com/account#access-tokens # Get your org ID from: https://dash.deno.com/ DENO_DEPLOY_TOKEN= DENO_DEPLOY_ORG_ID= # Edge-function execution timeout in milliseconds. # WORKER_TIMEOUT_MS=60000 # Edge-function host mode: development or production. # DENO_ENV=production # ─── Compute Services (Fly.io) ────────────────────────────────────────────── # Deploy Docker containers with persistent URLs. # Full setup + architecture: https://docs.insforge.dev/core-concepts/compute/architecture # # Setup — both FLY_API_TOKEN and FLY_ORG are required. FLY_ORG must be YOUR # Fly org slug; leaving it blank or as "insforge" will fail with an opaque # Fly auth error because that's our internal org. Compute auto-enables when # both are set. # 1. Create a Fly.io account: https://fly.io # 2. Find your org slug: fly orgs list # 3. Create an API token scoped to that org: fly tokens create org -o # 4. Set FLY_API_TOKEN= and FLY_ORG= # # Optional: Set COMPUTE_DOMAIN only if you own a wildcard domain pointed at # Fly (e.g. *.compute.yourdomain.com CNAME'd to fly.dev). Leave unset to use # Fly's own .fly.dev hostname, which works out of the box. FLY_API_TOKEN= FLY_ORG= COMPUTE_DOMAIN= # ─── Custom Compute: Docker provider (self-host, opt-in) ─────────────────────── # Runs your containers on THIS host instead of Fly.io. Enabled by mounting the # Docker socket into the InsForge container — see the commented lines in # docker-compose.prod.yml. The driver registers itself when the socket is # reachable, so nothing runs containers on your host unless you grant that. # # Security: the provider builds every container spec itself and never forwards # caller-supplied options, so a leaked InsForge API key cannot ask for a # privileged container or a host bind mount. The socket itself is still # root-equivalent on the host, so treat mounting it as the decision it is. # # Known limitation: there are no persistent volumes yet (the Fly path has none # either). Container state survives restarts and host reboots, but changing the # image, env vars, or port recreates the container and discards anything written # inside it. Use the project's Postgres or Storage for data you need to keep. # Which provider new services go to: fly | cloud | docker | off. Leave empty to # auto-detect. Not a restriction — providers coexist, and each service is managed # by the one that created it. COMPUTE_PROVIDER= # Ingress for services that do not choose their own: # none (default) — internal network only; no host port, no URL # port — published on a host port # host — reachable at a hostname via your own gateway COMPUTE_DEFAULT_INGRESS=none # Host address used to build URLs for `port` ingress. Left empty, no URL is # advertised — better than handing out one that does not resolve. COMPUTE_PUBLIC_HOST= # Bind address for published ports. Loopback by default: Docker's own default # publishes on 0.0.0.0 AND [::], i.e. the whole internet on a reachable host. COMPUTE_BIND_ADDRESS=127.0.0.1 # Path to the Docker socket, if it is not in the usual place — rootless Docker # ($XDG_RUNTIME_DIR/docker.sock) or Podman (/run/podman/podman.sock). The compose # files mount it at this same path inside the container, so one value covers both # sides. Only read when the socket mount is uncommented. DOCKER_SOCKET_PATH=/var/run/docker.sock # Ceiling on an uploaded source-build context (default 64mb). The whole tarball is # buffered in memory before the build starts, and only one upload is accepted at a # time, so this is the memory the build path can cost — lower it on a small host. COMPUTE_BUILD_MAX_CONTEXT= # Seconds a build upload may send nothing before it is treated as stalled and cut # loose (default 30). Builds run one at a time, so a connection that stops making # progress would otherwise block every other deploy. The timer resets on each chunk, # so this bounds silence, not total upload time — a slow but active link is fine. COMPUTE_BUILD_UPLOAD_IDLE_TIMEOUT= # Set true to keep compute containers off this project's network. Off by default: # sitting next to the database and storage is the point, and `postgres:5432` # resolves from inside a compute container exactly as it does for edge functions. COMPUTE_ISOLATE_NETWORK= # Cloud-mode compute (provisioned automatically when PROJECT_ID + CLOUD_API_HOST # are set by insforge-cloud). Self-host users with FLY_API_TOKEN always take # priority and do not need to set PROJECT_ID. # ============================================================================= # End of Configuration # ============================================================================= # After configuring this file: # 1. Run: docker compose up -d # 2. Check logs: docker compose logs -f # 3. Access the dashboard at: http://localhost:7131 # # For more information, visit: https://insforge.dev/docs # =============================================================================