Skip to content

Configuration

Everything is configured in two places, and it is worth knowing which is which:

  • The backend .env — what the system needs in order to start: database, secrets, keys for outside services. You edit it in a text editor and it requires a restart.
  • The panel — what changes day to day: store name, tax details, payment methods, AI provider. Requires no restart at all.

The rule is simple: if it is a secret, it goes in the .env. Everything else goes in the panel. API keys are never stored in the database and never travel to the browser.

The full list of variables, generated from the code, is in reference/environment-variables.md. What follows is what you need to understand in order to decide.


Only one variable is required:

Terminal window
DATABASE_URL=postgres://user:password@localhost:5432/my_store

With nothing else, the system starts and works. Everything else turns things on.

The notification queue, workflows and scheduled tasks live in Postgres and survive a restart just the same. If REDIS_URL is set, the setup wizard shows it as optional; if not, it says nothing. It used to be one more piece to set up and a false warning on the first screen of the wizard.

Terminal window
JWT_SECRET=
COOKIE_SECRET=

With the example values in place, anyone who knows them can sign their own tokens and walk into your panel. Change them before you go live.

Under Docker you can leave them empty: the container generates a set on first run. Set them by hand only if you are going to run several backend replicas — each one would generate its own, and a session would stop being valid the moment a request landed on a different replica.

Terminal window
STORE_CORS=https://mystore.com # the storefront
ADMIN_CORS=https://panel.mystore.com # the panel
AUTH_CORS=https://panel.mystore.com

These are comma-separated lists. If an address is missing, the browser blocks the request and the error does not tell you this is why: it says “CORS”, and you lose half an afternoon looking in the wrong place. When you stand up a new theme on another port, remember to add it to STORE_CORS.


Everything below is optional. Without the variable, the feature simply is not there — it does not fail, it does not warn, it does not get in the way.

Terminal window
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASS=
SMTP_FROM=
CONTACT_TO= # where the contact form lands

Without this there are no order confirmations and no password resets.

Terminal window
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
GOOGLE_API_KEY=
MISTRAL_API_KEY=
OPENROUTER_API_KEY=
VOYAGE_API_KEY= # for meaning-based search only
COHERE_API_KEY=
OLLAMA_URL=http://localhost:11434 # on your own machine, at no cost

Set the key for the provider you want to use, not all of them. The provider itself is chosen afterwards in the panel, under AI.

The key is yours and so is the bill: the system ships with the brakes on (a daily cap and a per-visitor limit), but you are the one paying for the calls. How it works and what it costs: AI.

With no key at all the store works exactly the same — keyword search, product pages, alerts. What needs a key is what writes or reasons.

Terminal window
BTCPAY_URL=
BTCPAY_API_KEY=
BTCPAY_STORE_ID=

Without BTCPAY_URL the payment provider does not even register itself: it does not appear at checkout.

Terminal window
SENDCLOUD_PUBLIC_KEY=
SENDCLOUD_SECRET_KEY=
SENDCLOUD_WEBHOOK_SECRET= # signature on their notifications
SENDCLOUD_FROM_... # origin address, see the .env.example
SENDCLOUD_FALLBACK_EUR=4.95

Without SENDCLOUD_PUBLIC_KEY you are left with the manual provider: flat rates that you configure yourself in the panel.

Terminal window
THEMES_DIR= # where the themes live. Default: themes/
PLUGINS_DIR= # where the plugins live. Default: plugins/
PLUGINS_DISABLED=one,another # turn one off without uninstalling it
LICENSE_PUBLIC_KEY= # verify licences for paid plugins

LICENSE_PUBLIC_KEY is public on purpose: it can only verify signatures, never create them.

Terminal window
STOREFRONT_URL=https://mystore.com
STOREFRONT_RUTA_PRODUCTO=producto # /producto/<handle>

These produce the links the AI and your emails send to customers. If your theme uses a different path — /p/, /item/ — change it here or the links will 404.


The theme does not read the backend .env: it is a different application, very often on a different server. It needs two values of its own:

Terminal window
COMMERCE_URL=https://mystore.com # the store's address
COMMERCE_KEY=pk_... # publishable key for the sales channel

Each stack exposes them its own way: Vite wants VITE_, Next wants NEXT_PUBLIC_ for anything that reaches the browser. Check the theme’s .env.example.

The publishable key decides which products that storefront can see. It is what lets two different stores live on the same backend without their catalogues mixing, so it is worth giving each theme its own.

You create one with npm run preparar on the backend, or from Settings in the panel.


No files, no restart:

Where What
Settings Store name and branding, tax details for invoices, payment methods
AI Provider and model, daily spending cap, what may be written unattended
Themes Which theme is active and its demo content
Extensions Installed plugins and their settings
Users Who gets into the panel

Tax details live in the store, not in the code: changing a tax ID should not require rebuilding anything.