Files
summercms/docs/setup/configuration.md
Jakub Zych 0bc390f39f feat(19.3-04): cooler site-cache purge service with site_cache.purge_url and purge_token
- cooler.SiteCachePurger moved from the Journal plugin: loopback-only http,
  32-character token, 2 s detached request, no token in logs or errors
- NewSiteCachePurgerFor names caller keys (for plugin alias keys)
- PurgeSiteCacheAfterCommit through lagoon.AfterCommit, one POST per save
- SiteCacheFromApp for hooks outside serve; Install publishes the purger
  unless a plugin already did, and fails boot on an invalid config
- caching docs section, cooler README, configuration row
2026-10-15 18:21:10 +02:00

78 lines
6.9 KiB
Markdown

---
title: Configuration
description: Configure an application with YAML files, per-environment directories, plugin defaults and SUMMER_ environment variables, and set the keys it needs.
section: setup
order: 30
---
# Configuration
WinterCMS keeps configuration in `config/*.php` files, per-environment directories and `.env`. SummerCMS keeps the same shape with YAML files, merged by [compass](../../modules/compass/README.md) into one tree that you read with dot paths such as `app.name`.
## The config directory
Each YAML file in the application's `config/` directory is a section named after the file, so `config/app.yaml` provides the `app.*` keys and `config/http.yaml` provides `http.*`:
```yaml
# config/app.yaml
name: Acme
url: http://127.0.0.1:8080
timezone: Europe/Warsaw
```
Files for one environment go in `config/env/<environment>/` with the same naming, and override the base files. The environment comes from `SUMMER_ENV` and defaults to `production`, so a development setup sets `SUMMER_ENV=development` and keeps its overrides in `config/env/development/`.
## Plugin defaults
A plugin ships its own defaults embedded in the binary through `pact.HasConfig`. Its `config/config.yaml` becomes `<plugin id>.<key>`, so the `posts_per_page` key of `acme.blog` is read as `acme.blog.posts_per_page`. WinterCMS writes the same key as `acme.blog::posts_per_page`. The application overrides a plugin default like any other key: put `posts_per_page` under `blog:` in `config/acme.yaml`.
## Environment variables
Any key can be overridden with an environment variable. Take the dot path, replace each dot with a double underscore, upper-case it and prefix `SUMMER_`:
| Key | Variable |
|-----|----------|
| `database.dsn` | `SUMMER_DATABASE__DSN` |
| `app.key` | `SUMMER_APP__KEY` |
| `admin.jwt.secret` | `SUMMER_ADMIN__JWT__SECRET` |
A `.env` file next to the `config/` directory supplies `KEY=VALUE` lines for variables that are not already set in the real environment. Keep secrets in the environment or in `.env`, never in committed YAML.
Environment values are strings. Keys that must be numbers, such as `http.body_limits.default_bytes`, belong in a YAML file.
The layers merge in this order, each overriding the ones before it: plugin defaults, `config/*.yaml`, `config/env/<environment>/*.yaml`, `SUMMER_` variables, then runtime overrides that a command saved to `config/env/<environment>/overrides.yaml`.
## Keys an application sets
These are the keys most applications set. Each module's reference page lists all of its keys and their defaults.
| Key | Purpose | Reference |
|-----|---------|-----------|
| `database.dsn` | PostgreSQL connection string. Required by every command that opens the database. | [lagoon](../../modules/lagoon/README.md) |
| `app.key` | Base64 encoding of 32 random bytes, used to encrypt columns. Generate it with `key:generate`. | [lagoon](../../modules/lagoon/README.md) |
| `app.timezone` | Timezone of scheduled commands. Defaults to UTC. | [conga](../../modules/conga/README.md) |
| `app.locale`, `app.fallback_locale` | Default and fallback translation locales. | [phrasebook](../../modules/phrasebook/README.md) |
| `http.body_limits.default_bytes`, `http.body_limits.upload_bytes` | Request body limits. Required by `serve` and `route:list`. | [surf](../../modules/surf/README.md) |
| `http.cors.*`, `http.trusted_proxies` | CORS and the proxies whose forwarded client IP is trusted. | [surf](../../modules/surf/README.md) |
| `http.rate_limit.store` | Where `throttle` counters live: `memory` (per instance, the default) or `redis` (shared by every instance). | [cooler](../../modules/cooler/README.md) |
| `cache.driver`, `cache.prefix`, `cache.memory.max_entries` | The cache driver (`memory`, the default, or `redis`), the key prefix (default from `app.name`) and the memory driver's size bound (default 10000). | [cooler](../../modules/cooler/README.md) |
| `site_cache.purge_url`, `site_cache.purge_token` | The host site's page-cache purge route and its bearer token (at least 32 characters). Set both or neither; http only to a loopback host. Keep the token in `SUMMER_SITE_CACHE__PURGE_TOKEN`. | [cooler](../../modules/cooler/README.md) |
| `redis.url` | Redis URL (`redis://`, `rediss://` or `unix://`), required when a Redis cache or rate-limit store is selected. Keep it in `SUMMER_REDIS__URL` when it carries a password. | [cooler](../../modules/cooler/README.md) |
| `http.access_log` | Logs one record per request with method, matched route pattern, status and duration. Defaults to `false`. | [surf](../../modules/surf/README.md) |
| `storage.uploads.bucket_url` | Uploads bucket, `file://`, `mem://` or `s3://` (the last only in a binary built with the `summercms_s3` tag from `build.tags` in `summer.yaml`; credentials from the AWS environment). Required by `serve`. | [lagoon](../../modules/lagoon/README.md) |
| `storage.uploads.public_url` | Absolute `http` or `https` base of a public bucket or CDN; file and thumbnail URLs become that base plus the partition path. Unset keeps `storage.uploads.public_path_prefix`. Only for a bucket holding public files alone. | [lagoon](../../modules/lagoon/README.md) |
| `storage.uploads.serve` | Mounts `attach.StaticHandlerPublic` under `storage.uploads.public_path_prefix` with `X-Content-Type-Options: nosniff`, a sandboxing CSP and `Content-Disposition: attachment` for anything but a raster image. Defaults to `false`. | [surf](../../modules/surf/README.md) |
| `admin.jwt.secret` | Secret for admin tokens. Required as soon as a plugin registers an admin controller. | [cabana](../../modules/cabana/README.md) |
| `backend.uri` | Path the admin is served under. Defaults to `/backend`. | [cabana](../../modules/cabana/README.md) |
| `mail.driver`, `mail.from`, `mail.smtp.*` | Mail delivery: `memory`, `log` or `smtp`. | [postcard](../../modules/postcard/README.md) |
| `queue.work_in_serve`, `queue.queues.*` | Whether `serve` runs the job worker, and workers per queue. | [conga](../../modules/conga/README.md) |
| `realtime.driver`, `realtime.centrifugo.*` | The realtime driver and its Centrifugo settings. | [lighthouse](../../modules/lighthouse/README.md) |
| `search.driver`, `search.typesense.*` | The search engine and its Typesense settings. | [beachcomber](../../modules/beachcomber/README.md) |
| `push.enabled`, `push.public_key`, `push.private_key` | Web Push with VAPID keys. | [flare](../../modules/flare/README.md) |
> [!NOTE]
> The documentation checks every identifier, link and command name it shows against the code, but not configuration keys. The keys on this page are reviewed by hand; the module reference pages are the authority.
## Reading configuration in a plugin
Plugins read configuration from `backpack.App.Config`, a `compass.Config`. Use `compass.Config.String`, `compass.Config.Int` and `compass.Config.Bool` for single values, which return the zero value for a missing key, `compass.Config.Has` to tell a missing key from a zero value, and `compass.Config.LoadSection` to decode a whole section into a struct.