Updated the documentation for the Website service target to name/reference PostgreSQL instead.

This commit is contained in:
2026-08-05 01:30:32 +02:00
parent 6156cf5b0d
commit f8a263168e
+17 -17
View File
@@ -10,7 +10,7 @@ The service:
- Returns a custom not-found (404) HTML page, localized like the landing page, for any request that matches neither a route nor a static file.
- Compresses responses (gzip/deflate) above a configurable size when the client advertises support.
- Stamps a hardened set of security headers on every response.
- Persists data through [Fluent](https://github.com/hummingbird-project/hummingbird-fluent), against either an ephemeral in-memory SQLite database (the default — no external infrastructure) or a MySQL/MariaDB server, selected by a single configuration key.
- Persists data through [Fluent](https://github.com/hummingbird-project/hummingbird-fluent), against either an ephemeral in-memory SQLite database (the default — no external infrastructure) or a PostgreSQL server, selected by a single configuration key.
## Requirements
- Swift 6.3 toolchain (`swift-tools-version:6.3`).
@@ -55,7 +55,7 @@ the following sources, **highest precedence first**:
5. Built-in defaults
The two files play different roles:
- **`.env`** (git-ignored) holds your deployment values — it is the file the Makefile and Compose read for the `${VAR}` placeholders, and typically selects the MySQL/MariaDB backend.
- **`.env`** (git-ignored) holds your deployment values — it is the file the Makefile and Compose read for the `${VAR}` placeholders, and typically selects the PostgreSQL backend.
- **`.env.local`** (tracked) holds the local development values — the in-memory database and `debug` logging, plus the image/deployment placeholders the Makefile falls back to when no `.env` exists. Because it sits *above* `.env`, a direct launch (`swift run` or a debugger) runs against the local values even when `.env` points at a deployment, the same way `docker-compose.override.yml` overrides the base Compose file. Compose itself never reads it, and the production image does not ship it — only the executable, its resources, and the static files are staged into the final stage.
### Environment variable naming
@@ -92,10 +92,10 @@ A dotted config key maps to an environment variable by upper-casing, splitting c
### Persistence
| Config key | Environment variable | Default | Description |
| --- | --- | --- | --- |
| `database.driver` | `DATABASE_DRIVER` | `inMemory` | Backend: `inMemory` (ephemeral SQLite, no infrastructure) or `mysql` (MySQL/MariaDB). |
| `database.driver` | `DATABASE_DRIVER` | `inMemory` | Backend: `inMemory` (ephemeral SQLite, no infrastructure) or `postgres` (PostgreSQL). |
| `database.migrate` | `DATABASE_MIGRATE` (flag `--database-migrate`) | `false` | When set, run the migrations and exit instead of serving. |
| `database.host` | `DATABASE_HOST` | `localhost` | MySQL/MariaDB host. Ignored for `inMemory`. |
| `database.port` | `DATABASE_PORT` | `3306` | MySQL/MariaDB port. Ignored for `inMemory`. |
| `database.host` | `DATABASE_HOST` | `localhost` | PostgreSQL host. Ignored for `inMemory`. |
| `database.port` | `DATABASE_PORT` | `5432` | PostgreSQL port. Ignored for `inMemory`. |
| `database.name` | `DATABASE_NAME` | `loud` | Database name. Ignored for `inMemory`. |
| `database.username` | `DATABASE_USERNAME` | `loud` | Database username. Ignored for `inMemory`. |
| `database.password` | `DATABASE_PASSWORD` | _(empty)_ | Database password. Provide via the environment/a secret — never commit it. |
@@ -136,7 +136,7 @@ swift run Website # binds to Hummingbird's default 127.0.0.1:8080
swift run Website --http-host 0.0.0.0 --http-port 9000 --log-level debug
```
A direct run picks up the local development overrides from `.env.local` (in-memory database, `debug` logging) over whatever `.env` configures. To run against another backend, override per launch — e.g. `DATABASE_DRIVER=mysql swift run Website` — since process environment variables outrank both files.
A direct run picks up the local development overrides from `.env.local` (in-memory database, `debug` logging) over whatever `.env` configures. To run against another backend, override per launch — e.g. `DATABASE_DRIVER=postgres swift run Website` — since process environment variables outrank both files.
Or via the Makefile / Docker (uses `docker-compose.override.yml`, which builds from source and sets `LOG_LEVEL=debug`):
```sh
@@ -154,8 +154,8 @@ The service persists data through Fluent and selects its backend at runtime with
### In-memory (default)
With no configuration, the service uses an ephemeral in-memory SQLite database. It is created and **migrated on startup** every launch, so `swift run Website` and `docker compose up` work with no external database — ideal for local development and tests.
### MySQL / MariaDB
Set `DATABASE_DRIVER=mysql` and the connection values (`DATABASE_HOST`, `DATABASE_NAME`, `DATABASE_USERNAME`, `DATABASE_PASSWORD`, …). Unlike the in-memory backend, a MySQL/MariaDB database is **not** migrated on boot — a shared database is migrated out of band so multiple instances never race:
### PostgreSQL
Set `DATABASE_DRIVER=postgres` and the connection values (`DATABASE_HOST`, `DATABASE_NAME`, `DATABASE_USERNAME`, `DATABASE_PASSWORD`, …). Unlike the in-memory backend, a PostgreSQL database is **not** migrated on boot — a shared database is migrated out of band so multiple instances never race:
```sh
# Run the registered migrations against the configured database, then exit.
swift run Website --database-migrate
@@ -163,14 +163,14 @@ swift run Website --database-migrate
docker compose -f docker-compose.yml run --rm website --database-migrate
```
A local MariaDB for development lives behind the `database` Compose profile (so a plain `docker compose up` still runs in-memory). Its data directory is bind-mounted to `Tests/DB` (git-ignored), so the database survives `db-unmount` and container restarts:
A local PostgreSQL for development lives behind the `database` Compose profile (so a plain `docker compose up` still runs in-memory). Its data directory is bind-mounted to `Tests/DB` (git-ignored), so the database survives `db-unmount` and container restarts:
```sh
make db-mount # start MariaDB (docker compose --profile database up --wait mariadb)
make db-mount # start PostgreSQL (docker compose --profile database up --wait postgres)
make db-migrate # run migrations against it
make db-shell # open a SQL shell on it
make db-shell # open a SQL shell on it (psql)
make db-unmount # stop and remove the container (data kept in Tests/DB)
make db-reset # stop and remove the container
DATABASE_DRIVER=mysql make site-mount # run the site against MariaDB
DATABASE_DRIVER=postgres make site-mount # run the site against PostgreSQL
```
> **Note:** because the data lives in the bind-mounted `Tests/DB` folder rather than a named volume, `db-reset`'s `--volumes` flag does **not** clear it. To start from an empty database, delete `Tests/DB` by hand.
@@ -187,11 +187,11 @@ make pkg-test
Tests use the [Swift Testing](https://developer.apple.com/documentation/testing/) framework. The `Tests/Website.xctestplan` covers the service's two targets — `WebsiteTests` (the executable/integration tests) and `WebsiteLibraryTests` (the library unit tests) — plus the local packages' suites: `InfrastructureTests`, `PersistenceTests`, `LocalizationTests`, and `UtilityTests`.
The `Persistence` package has its own suite (run it from `Packages/Persistence`). Its tests run against the in-memory backend by default; the MySQL integration test is skipped unless a database is pointed at via `MYSQL_TEST_HOST` (with optional `MYSQL_TEST_PORT`/`NAME`/`USERNAME`/`PASSWORD`), so `swift test` stays runnable with no database:
The `Persistence` package has its own suite (run it from `Packages/Persistence`). Its tests run against the in-memory backend by default; the PostgreSQL integration test is skipped unless a database is pointed at via `POSTGRES_TEST_HOST` (with optional `POSTGRES_TEST_PORT`/`NAME`/`USERNAME`/`PASSWORD`), so `swift test` stays runnable with no database:
```sh
cd ../../Packages/Persistence && swift test # in-memory only
# With the local MariaDB up (make db-mount):
cd ../../Packages/Persistence && MYSQL_TEST_HOST=127.0.0.1 swift test
# With the local PostgreSQL up (make db-mount):
cd ../../Packages/Persistence && POSTGRES_TEST_HOST=127.0.0.1 swift test
```
## Deployment
@@ -262,8 +262,8 @@ The Makefile and Compose files read these from a `.env` file (or the environment
| `LOG_LEVEL` | Runtime log level (default `info`). |
| `HTTP_SERVER_NAME` | Runtime server name (default `LoudWebsite`). |
| `SECURITY_STRICT_TRANSPORT_SECURITY` | HSTS header value (default `max-age=31536000; includeSubDomains`). |
| `DATABASE_DRIVER` | `inMemory` or `mysql`. The production Compose file defaults it to `mysql`; the local override defaults back to the in-memory backend. |
| `DATABASE_HOST`, `DATABASE_PORT`, `DATABASE_NAME`, `DATABASE_USERNAME`, `DATABASE_PASSWORD` | MySQL/MariaDB connection (when `DATABASE_DRIVER=mysql`). Provide the password via a secret. |
| `DATABASE_DRIVER` | `inMemory` or `postgres`. The production Compose file defaults it to `postgres`; the local override defaults back to the in-memory backend. |
| `DATABASE_HOST`, `DATABASE_PORT`, `DATABASE_NAME`, `DATABASE_USERNAME`, `DATABASE_PASSWORD` | PostgreSQL connection (when `DATABASE_DRIVER=postgres`). Provide the password via a secret. |
| `DATABASE_TLS` | TLS posture when connecting: `off`, `prefer`, or `require` (default `prefer` in production — set `require` when the database enforces TLS, so a stripped connection fails instead of silently downgrading to plaintext). |
Run the migrations against the production database once before (or during) rollout: `docker compose -f docker-compose.yml run --rm website --database-migrate`.