# Copy to .env next to compose.yaml and keep the file private. # Leave the eight secrets below commented out to generate them on first start, # or set your own. A replace-with-* example value is refused and nothing is created. # Generated values are recorded in ./data/secrets.env. Back that file up with the # database. Secrets must remain unchanged across restarts, redeploys, and restores. # Release and public endpoint COMPOSE_PROJECT_NAME=synaplan-production # The release to install. Only an immutable SemVer version is accepted; `latest` # and any mutable tag are rejected before a container starts, so a redeploy can # never pull a different version behind your back. Newer releases are listed at # https://github.com/metadist/synaplan/releases — see docs/UPDATE_SELFHOST.md. SYNAPLAN_VERSION=5.6.4 SYNAPLAN_PULL_POLICY=always SYNAPLAN_HTTP_BIND=127.0.0.1 # After `docker compose up -d`, open http://127.0.0.1:8000. # Change the bind or this port and open that address instead. SYNAPLAN_HTTP_PORT=8000 # Local network is opt-in and off until you run deploy/scripts/local-tls.sh # with the address people open (10.x, 172.16–31.x, 192.168.x, 100.64.x, # 169.254.x, or any other block this site does not announce). That adds the # local-tls profile and sets the three URLs below to https://
. # Leave SYNAPLAN_HTTP_BIND at 127.0.0.1. See README.md, "Local network". # Open http://127.0.0.1:8000 after the first start. If you change the bind, # the port, or the public address, set APP_URL, FRONTEND_URL and # REALTIME_ALLOWED_ORIGINS to that same address. Live chat stays disconnected # when these three do not match the address in the browser. APP_URL=http://127.0.0.1:8000 FRONTEND_URL=http://127.0.0.1:8000 # Stable secrets. On the first start, a value you set here is adopted unchanged # and recorded in ./data/secrets.env. After that file exists, editing these # lines does nothing. Add the value to that file instead. # You can also delete these eight lines. Left unset, the first start generates an # independent value for each of them and records the whole set in # ./data/secrets.env, which is then the backup copy and is never rewritten — so a # value once in use stays in use. That file is secret material: include it in every # backup (a database restored without it can no longer be opened), keep it private, # and never commit it. # If you do set values here, generate each one separately with # "openssl rand -hex 32". Docker Compose reads this file with its own rules and # would change a value that contains "$", surrounding quotes, " #", or # leading/trailing spaces; the deployment refuses such a value instead of storing a # mangled credential. Generated hex values avoid that; if you type a value # yourself, use only letters, digits, "-" and "_". # APP_SECRET= # TOKEN_SECRET= # MARIADB_PASSWORD= # MARIADB_ROOT_PASSWORD= # REALTIME_API_KEY= # REALTIME_TOKEN_SECRET= # REALTIME_ADMIN_PASSWORD= # REALTIME_ADMIN_SECRET= # Optional first administrator. Deliberately empty: an unedited copy of this file # must never create a working administrator whose password is published in this # repository. Leaving both values empty is a valid choice — the bootstrap is # skipped and you promote an administrator yourself later. # To create one on the first start, set both variables; a stack that receives # only one of the two refuses to start. The bootstrap only acts while no # administrator exists; later restarts never reset an existing administrator. # Password: 8-64 characters; below 16 characters it also needs an uppercase # letter, a lowercase letter, and a number. Full rules: docs/INSTALLATION.md. # Here the character rule above matters most: if this file changes the password, # the value you noted down will not log you in. Generate it: openssl rand -hex 32. BOOTSTRAP_ADMIN_EMAIL= BOOTSTRAP_ADMIN_PASSWORD= # Auth-surface switches. Left EMPTY they are managed inside the app: the # first-run setup wizard asks for both on its last step, and an administrator can # change them later under Admin > Configuration. Both default to enabled. # # Filling one in here PINS it: the value wins over anything stored in the app and # the matching toggle is shown as locked. Do that when the decision belongs to # the deployment rather than to an administrator — e.g. REGISTRATION_ENABLED=false # on an install reachable from the internet with nobody watching sign-ups, or # both false for an SSO-/OIDC-only deployment (issues #462 and #1517). REGISTRATION_ENABLED= GUEST_CHAT_ENABLED= # Feature-flag pins. Every wave feature (people & sharing, AI assistants, tools # and approvals, saved-task steps, watched pages, desktop client, linked # platforms, office document tools) is ON by default and switchable under # Operate > System configuration > Features. Leave these empty to manage them in # the app; set one to false to pin it off for this deployment (the toggle then # shows as locked). The name is the BCONFIG key with a FEATURE_ prefix: # IAM.SHARING_ENABLED -> FEATURE_IAM_SHARING_ENABLED. Full list: docs/FEATURE_FLAGS.md FEATURE_DESKTOP_AGENT_ENABLED= FEATURE_PLATFORM_LINKS_ENABLED= FEATURE_IAM_GROUP_POLICIES_ENABLED= # Share-picker user search (IAM.USER_SEARCH_ENABLED) is OFF unless enabled: # when on, anyone can find user accounts by name or email when sharing. A # company deployment that wants account search sets this to true. # FEATURE_IAM_USER_SEARCH_ENABLED=true # Synaplan Demo (14-day shared evaluation key via web.synaplan.com; off by default in deploy/): # FEATURE_FREEAPI_ENABLED=true # Browser Web Speech API for chat speech-to-text streams audio to the browser # vendor's cloud. Air-gapped deployments set false: the input then records for # server-side transcription (local Whisper or an API model) or hides the mic. WEB_SPEECH_ENABLED= # The first-run setup wizard. With BOOTSTRAP_ADMIN_* empty above, opening the app # leads to /setup, which creates the first administrator, stores an AI provider # key and sets the two switches above. Until that is done the API answers # 503 SETUP_REQUIRED, so nobody can register or use the guest chat before you. # Set to false to switch the wizard off; you then need BOOTSTRAP_ADMIN_*, an OIDC # provider that grants admin through role claims, or # `docker compose exec backend php bin/console app:admin:reset-password` to get in. SETUP_WIZARD_ENABLED= # Cloud AI is the default. Provider keys can instead be configured after login in # Admin > AI Providers, where they are encrypted in MariaDB. AI_DEFAULT_PROVIDER=groq GROQ_API_KEY= OPENAI_API_KEY= ANTHROPIC_API_KEY= GOOGLE_GEMINI_API_KEY= MISTRAL_API_KEY= XAI_API_KEY= # Meta Model API (Muse Spark, Muse Wonder, Muse Image, Muse Voice Transcribe). Create a key at https://dev.meta.ai/ → API keys. META_API_KEY= # Leave empty for the Cloud-AI stack. Set exactly "local-ai" and redeploy to add # Ollama and Whisper. Local chat remains separately opt-in because it is large. # File work: add compute (COMPOSE_PROFILES=compute or compute,office). # prepare.sh then writes data/compute.token. It does not fill COMPUTE_TOKEN # here. Spoken answers start with the stack. COMPOSE_PROFILES= ENABLE_LOCAL_GPT_OSS=false WHISPER_DEFAULT_MODEL=tiny COMPUTE_URL= COMPUTE_TOKEN= # Operator billing, off by default. While STRIPE_SECRET_KEY is empty, the install # runs in open-source mode: no plans, no quotas, no upgrade prompts, and every # feature gate open. Fill these in to sell subscriptions to YOUR users through # YOUR Stripe account — see docs/BILLING_SELFHOST.md for the full setup. STRIPE_SECRET_KEY= STRIPE_WEBHOOK_SECRET= STRIPE_PRICE_PRO= STRIPE_PRICE_TEAM= STRIPE_PRICE_BUSINESS= COST_BUDGET_GATE_ENABLED=false # Optional production integrations # MAILER_DSN is a URL: percent-encode special characters in the SMTP password # ("$" as "%24", "@" as "%40", ":" as "%3A"). Details: docs/EMAIL.md MAILER_DSN=null://null APP_SENDER_EMAIL= APP_SENDER_NAME=Synaplan # Same address as APP_URL. Change all three together when the bind, the port, # or the public address changes. REALTIME_ALLOWED_ORIGINS=http://127.0.0.1:8000 PHP_MAX_FILE_UPLOADS=100 LOG_FORMAT=json # Authentication cookies are marked "Secure" when APP_URL uses https, which is # the case for every deployment following this file. Override only when the # detection cannot work: "true" when TLS terminates in a proxy APP_URL does not # reveal, "false" for a deployment deliberately served over plain HTTP (a # browser silently drops Secure cookies there, ending every session at the next # request). Empty means "derive it" — see docs/CONFIGURATION.md. AUTH_COOKIE_SECURE=