Deploy with your own PostgreSQL
Deploy the server image beside your database and reverse proxy. The image contains the application, PostgreSQL adapter and migration tools; you provide storage, TLS and host operations.
Prepare the infrastructure
This guide uses the repository's application-only Compose recipe on a private, same-host Docker network.
Before starting, prepare:
- A dedicated PostgreSQL database, reachable on an existing Docker network. Keep its SQL port private.
- A reviewed ULDA Server image, pinned by immutable digest.
- A reverse proxy or hosting endpoint with trusted HTTPS/WSS and WebSocket forwarding.
- Protected database credentials, backups and monitoring.
Run exactly one application writer per database. Additional server replicas and direct SQL writers are unsupported. The release's integration acceptance uses PostgreSQL 18.6; compatibility with other major versions is not implied.
Use the source revision from the Server Quick Start. Run the following commands from that repository's root.
Set deployment values
Create deploy.env with your actual values. The image digest and infrastructure names below are placeholders:
ULDA_SERVER_IMAGE=uldaio/ulda-server@sha256:REPLACE_WITH_REVIEWED_DIGEST
ULDA_DATABASE_NETWORK=your-existing-database-network
PGHOST=operator-postgres
PGPORT=5432
PGDATABASE=ulda
ULDA_DB_ADMIN_USER=your-database-administrator
ULDA_SECRETS_DIR=/absolute/path/to/protected/secrets
CORS_ORIGINS=https://your-application.example
PGHOST is the database's stable network alias. ULDA_SECRETS_DIR must be an absolute host path. These values configure Compose; database passwords belong in the separate files below.
Prepare the credentials
Place three files in the protected secret directory:
| File | Contents |
|---|---|
postgres_admin_password | The existing database administrator's password. |
postgres_migration_password | A new, independent password for the migration role. |
postgres_runtime_password | A new, independent password for the runtime role. |
Allow the container's Node UID 1000 to read the required files while restricting host access. Keep their contents out of Git, images, logs and command arguments. Changing a file does not rotate an existing database password.
The administrator needs permission to create roles and configure this dedicated database. A managed provider may require DBA-assisted setup.
Initialize a new database
Use this sequence only for a new dedicated database with no existing ULDA roles or tables. Check each command's exit status before continuing:
docker compose --env-file deploy.env -f deploy/compose.external-db.yaml run --rm -e ULDA_DB_SETUP=1 db-setup
docker compose --env-file deploy.env -f deploy/compose.external-db.yaml up -d --no-build
docker compose --env-file deploy.env -f deploy/compose.external-db.yaml ps -a
Setup creates the restricted roles. The migration job must exit 0 before the server starts. The running server receives only its own password file.
For an existing installation, first back up and test restoration, then follow the existing-data adoption procedure, adapted to your database. Do not reinitialize it with the new-database sequence.
Connect through HTTPS
The recipe publishes HTTP on 127.0.0.1:3000. Check /ready locally and wait for HTTP 200 before opening traffic. In PowerShell, use curl.exe:
curl -i http://127.0.0.1:3000/ready
Have your proxy forward the Socket.IO endpoint, including WebSocket upgrades. Keep health probes internal, disable proxy retries of application requests and configure the application's exact browser origins. CORS is not authentication.
Remote SDK clients connect to your HTTPS URL. Do not disable certificate verification. If PostgreSQL moves to another host, configure and verify its transport security separately: this Compose recipe does not enable database TLS.
Operate the deployment
Keep both --env-file deploy.env and -f deploy/compose.external-db.yaml on subsequent lifecycle commands:
docker compose --env-file deploy.env -f deploy/compose.external-db.yaml logs server migrate
docker compose --env-file deploy.env -f deploy/compose.external-db.yaml down
Here, down stops the application services. The database and its volume belong to the operator and are not removed by this recipe.
Continue with configuration and operations before upgrades or capacity changes. The source deployment guide documents the full ownership boundary.