Skip to main content

Dedicated database install (bring your own PostgreSQL)

This install runs only the Tagaris app container and points it at a PostgreSQL server you already run. Use it when you have a database server you would rather keep everything on, or a managed PostgreSQL service, and do not want another database to support or manage.

Tagaris installs three ways, and this is the dedicated-database one. The alternatives are the standard install, which brings its own PostgreSQL container, and a self-contained install, which puts the database inside the app container.

Requirements

  • Docker and the Docker Compose plugin.
  • A PostgreSQL server, version 16 recommended, reachable from the app container.
  • A database and a role for Tagaris on that server. The role must own the database (or be able to create tables), so migrations can build the schema on first start.

Create them on your server, for example:

CREATE ROLE tagaris WITH LOGIN PASSWORD 'letters_and_digits_only';
CREATE DATABASE tagaris OWNER tagaris;

Use letters and digits only in the password: it is spliced into the connection URL, so characters like : @ / break it.

Install with Docker Compose

1. Create a directory

mkdir -p /opt/tagaris && cd /opt/tagaris

2. Create docker-compose.yml

Save the following as docker-compose.yml. One service and two volumes for uploaded files; its settings come from the .env file next to it. There is no database service, because DATABASE_URL points at your server.

services:
app:
image: goodhallsolutions/tagaris:latest
restart: unless-stopped
environment:
DATABASE_URL: ${DATABASE_URL}
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
BETTER_AUTH_URL: ${BETTER_AUTH_URL}
BETTER_AUTH_TRUSTED_ORIGINS: ${BETTER_AUTH_TRUSTED_ORIGINS:-}
API_ENABLED: ${API_ENABLED:-true}
SSO_ISSUER: ${SSO_ISSUER:-}
SSO_CLIENT_ID: ${SSO_CLIENT_ID:-}
SSO_CLIENT_SECRET: ${SSO_CLIENT_SECRET:-}
SSO_PROVIDER_NAME: ${SSO_PROVIDER_NAME:-}
NODE_ENV: production
UPLOADS_DIR: /app/uploads
PHOTOS_DIR: /app/data/photos
ports:
- "3000:3000"
volumes:
- uploads:/app/uploads
- photos:/app/data/photos
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:3000/api/health || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 40s

volumes:
uploads:
photos:

This uses the official goodhallsolutions/tagaris image, the same as the standard install. Only the database differs: there is no PostgreSQL container here.

The examples use the latest tag for simplicity. For anything beyond a trial, pin to a major version such as goodhallsolutions/tagaris:2 so upgrades stay within version 2. See Upgrading for tags, update steps and database upgrades.

3. Create .env

Save this as .env in the same directory, then set the connection string, the secret and the URL.

# Point this at your PostgreSQL server, database and role.
# Letters and digits only in the password (it is spliced into the URL).
DATABASE_URL=postgresql://tagaris:letters_and_digits_only@db.example.internal:5432/tagaris?schema=public

# BETTER_AUTH_URL is the public address people reach the app on, not localhost.
# Generate the secret with: openssl rand -base64 32
BETTER_AUTH_SECRET=change_me_generate_with_openssl_rand_base64_32
BETTER_AUTH_URL=https://assets.example.com
BETTER_AUTH_TRUSTED_ORIGINS=

# Single sign-on is normally configured in the app; leave these blank.
SSO_ISSUER=
SSO_CLIENT_ID=
SSO_CLIENT_SECRET=
SSO_PROVIDER_NAME=

4. Start it

docker compose up -d

The app connects to your database, applies any pending migrations, then listens on port 3000.

5. Sign in

Open http://your-host:3000. The first visit opens the setup wizard, which creates your organisation and the first administrator account. Give it a strong password and store it safely: it is the install owner and the break-glass login.

6. Put it behind HTTPS

Serve Tagaris through a reverse proxy that terminates TLS (Cloudflare, nginx or Caddy), and set BETTER_AUTH_URL to the https:// address. Session cookies and sign-in depend on it.

Install without Compose (plain docker run)

docker volume create tagaris_photos tagaris_uploads

docker run -d --name tagaris -p 3000:3000 \
-e DATABASE_URL="postgresql://tagaris:change_me@db.example.internal:5432/tagaris?schema=public" \
-e BETTER_AUTH_SECRET="a_long_random_secret" \
-e BETTER_AUTH_URL="http://your-host:3000" \
-v tagaris_photos:/app/data/photos -v tagaris_uploads:/app/uploads \
goodhallsolutions/tagaris:latest

Migrations run automatically at start, and the first visit opens the setup wizard.

Configuration

The variables match the standard install, with one difference: DATABASE_URL points at your own server rather than a postgres container, and there are no POSTGRES_USER, POSTGRES_PASSWORD or POSTGRES_DB values (those only configure the database container the other installs run). See the standard install's configuration table for the full reference.

Persistent storage

The database lives on your server and is yours to back up. The app container keeps uploaded files in two volumes:

  • photos (mounted at /app/data/photos): asset photos, thumbnails and attachments.
  • uploads (mounted at /app/uploads): other uploaded files, including the backups folder.

Back these up alongside your database. Rebuilding or updating the image never touches the volumes.

The in-app scheduled backups (Application settings) still work here: they run pg_dump against DATABASE_URL, so they capture your external database too. See Backups and restore.

Troubleshooting

  • Database connection error at start (Prisma error P1013): the password contains characters that break the connection URL, such as : @ /. Use letters and digits only.
  • Cannot reach the database: check the app container can route to the server's host and port, and that the server accepts connections from the container's address.
  • Migrations fail on first start with a permissions error: the role in DATABASE_URL needs rights to create tables. Make it the database owner.