Add a database
Add a managed PostgreSQL to the landscape and wire its secrets into env vars.
This guide adds a PostgreSQL database to a landscape and hands its address to your app. Harthelm creates the database at the Sync, keeps its password in the workspace's vault and dumps it every night.
Add the managed service
Add a managed service next to your app, and give the app the database's
address:
schema: harthelm/v1
services:
db:
type: managed
provider: postgres
config:
postgresVersion: "18"
database: app
user: app
secrets:
password: ${{ secrets.DB_PASSWORD }}
web:
type: steps
steps: [{run: npm start}]
needs: [db]
env:
DATABASE_URL: ${{ services.db.dsn }}
ports:
- port: 3000
routes: [{path: /}]provider: postgresis the built-in PostgreSQL. The console's Managed services → Catalog shows what else your installation offers: MariaDB, Valkey, RabbitMQ and S3 object storage are built in (Managed services).configsets the version ("18"or"17"; it cannot change later), the database and the user.secrets.passwordnames a vault key. The password itself never goes into the file.${{ services.db.dsn }}becomespostgresql://app:<password>@<host>:5432/appwhenwebstarts.
Sync and give it a password
Click Sync in the Run panel. The review lists db under "To add" and says that DB_PASSWORD has no value yet.
Click Enter secrets, then Generate for a random 32-character password, or type one with 12 to
128 characters. Then click Sync.
The database is ready in about a minute; its row in the Run panel shows "Managed service: Synchronized". Run or
restart web so it picks up DATABASE_URL.
Other ways to connect
| Template | Value |
|---|---|
${{ services.db.host }} | the host |
${{ services.db.port }} | the port, 5432 |
${{ services.db.dsn }} | the full URL with user, password and database |
${{ services.db.secret }} | the password alone Since 1.3.0 |
${{ services.db.details.<field> }} | another field the provider reports |
For libraries that read the PG* variables:
env:
PGHOST: ${{ services.db.host }}
PGPORT: ${{ services.db.port }}
PGDATABASE: app
PGUSER: app
PGPASSWORD: ${{ services.db.secret }}${{ services.db.secret }} follows a password rotation by itself; ${{ secrets.DB_PASSWORD }} keeps the value of
your last Sync until you sync again.
Size and storage
db:
type: managed
provider: postgres
plan: small
resources:
storage: 2Giplan is tiny (the default: 0.25 vCPU, 256 MiB, 1 GiB) or small (0.5 vCPU, 512 MiB, 5 GiB). resources changes
what the plan lets you change. Sizes are MiB as a number, or 2048Mi, 2Gi, 1.5Gi; decimal units like 2GB are
refused. Storage can only grow, and only where your installation's storage class can grow volumes: otherwise the Sync
refuses a plan that needs more storage with update-constraint.
Rotate the password
Open the database in Managed services and click Rotate under Secrets. Harthelm generates a new value, stores it in the vault, and the services that read the connection restart with it.
Pause, resume and delete
- Teardown pauses the database; the data stays. The next Sync resumes it.
- Removing or renaming the service in
harthelm.ymldeletes the database and its data at the next Sync; the review warns first.
Backups
The database is dumped every night (backups: true is the default). The details drawer in Managed services
shows the last dump and has Dump now.
MariaDB instead
A MariaDB works the same way, with provider: mariadb Since 1.3.0:
db:
type: managed
provider: mariadb
config:
mariadbVersion: "11.8"
database: shop
user: shop
secrets:
password: ${{ secrets.DB_PASSWORD }}${{ services.db.dsn }} is then mysql://shop:<password>@<host>:3306/shop, and ${{ services.db.details.jdbcUrl }}
the JDBC URL without credentials. mariadbVersion is "12.3", "11.8" (the default) or "11.4". You can move to a
newer series later by changing it; the server is upgraded in place and cannot go back, so click Dump now
first.