External Database Setup
If you are using your own PostgreSQL instance (e.g., AWS RDS, Azure Database, CloudNativePG, or a local installation) instead of the provided Docker Compose setup, follow these steps to ensure the database is correctly configured.
!WARNINGCommunity Supported Only External and managed database configurations are not officially tested or supported by the core application maintainers. Use this guide at your own risk.
1. Database and Users
The application uses two database roles:
- SPARKY_FITNESS_DB_USER: Used for migrations and schema management.
- SPARKY_FITNESS_APP_DB_USER: Used by the application components with restricted permissions.
!IMPORTANT The application automatically creates the App User (
SPARKY_FITNESS_APP_DB_USER) and grants it all necessary permissions on first startup. The DB User (SPARKY_FITNESS_DB_USER) must haveCREATEROLEto do this.
Option A — Standard Setup (SparkyFitness creates the SPARKY_FITNESS_APP_DB_USER User automatically)
Run the following as a database superuser:
-- 1. Create the Database
CREATE DATABASE sparkyfitness_db;
-- 2. Create the DB Owner user (referenced in .env as SPARKY_FITNESS_DB_USER)
CREATE USER sparky_admin WITH PASSWORD 'your_secure_password';
-- 3. Grant database ownership so sparky_admin can create schemas and tables
ALTER DATABASE sparkyfitness_db OWNER TO sparky_admin;
-- 4. Grant Role Creation privilege
-- Required so the app can automatically create SPARKY_FITNESS_APP_DB_USER
-- on first startup (see utils/dbMigrations.ts)
ALTER USER sparky_admin CREATEROLE;
-- 5. PostgreSQL 15+ only: the default public schema permissions changed in PG 15.
-- Explicitly grant create rights to the owner:
GRANT ALL ON SCHEMA public TO sparky_admin;
Option B — Reduced Privilege Setup (you create the SPARKY_FITNESS_APP_DB_USER User manually)
If your environment does not allow CREATEROLE (e.g., strict managed databases), you can pre-create the App User yourself. The application checks whether the role already exists before attempting to create it — if it finds it, CREATE ROLE is skipped entirely and CREATEROLE is not required.
-- 1. Create the Database
CREATE DATABASE sparkyfitness_db;
-- 2. Create the DB Owner user (referenced in .env as SPARKY_FITNESS_DB_USER)
CREATE USER sparky_admin WITH PASSWORD 'your_secure_password';
-- 3. Grant database ownership
ALTER DATABASE sparkyfitness_db OWNER TO sparky_admin;
-- 4. PostgreSQL 15+ only
GRANT ALL ON SCHEMA public TO sparky_admin;
-- 5. Pre-create the App User (referenced in .env as SPARKY_FITNESS_APP_DB_USER)
-- The app detects this role already exists and skips CREATE ROLE,
-- so sparky_admin does NOT need CREATEROLE.
CREATE USER sparky_app WITH PASSWORD 'another_secure_password';
Set both users in your .env:
SPARKY_FITNESS_DB_USER=sparky_admin
SPARKY_FITNESS_DB_PASSWORD=your_secure_password
SPARKY_FITNESS_APP_DB_USER=sparky_app
SPARKY_FITNESS_APP_DB_PASSWORD=another_secure_password
!NOTE With Option B,
sparky_adminstill needs database ownership to run migrations (create tables, schemas, functions, indexes). The only privilege that is no longer required isCREATEROLE.
2. PostgreSQL Extensions
!NOTENo extensions required. As of v0.17.0 release, SparkyFitness no longer depends on
uuid-ossp,pgcrypto, orpg_stat_statements.
- UUID generation uses the built-in
gen_random_uuid()(PostgreSQL 13+), which requires no extension.- Encryption is handled entirely in application code (AES-256-GCM via Node.js
crypto), not via database functions.If you are upgrading an existing installation that has these extensions installed, the
20260618000000_remove_superuser_extensions.sqlmigration will attempt to remove them automatically. Non-superuser environments will skip theDROP EXTENSIONstep gracefully — the extensions are unused and harmless if left in place.
3. Row Level Security (RLS)
The sparky_admin user must be the owner of the tables to enable and manage RLS policies. Setting ALTER DATABASE ... OWNER TO sparky_admin ensures that any tables created during migrations are automatically owned by sparky_admin.
4. Environment Configuration
In your .env file, ensure you point to your external database:
SPARKY_FITNESS_DB_HOST=your-db-host
SPARKY_FITNESS_DB_NAME=sparkyfitness_db
SPARKY_FITNESS_DB_USER=sparky_admin
SPARKY_FITNESS_DB_PASSWORD=your_secure_password
SPARKY_FITNESS_DB_PORT=5432
# App user — created automatically (Option A) or pre-created by you (Option B)
SPARKY_FITNESS_APP_DB_USER=sparky_app
SPARKY_FITNESS_APP_DB_PASSWORD=another_secure_password
!IMPORTANT
SPARKY_FITNESS_APP_DB_USERandSPARKY_FITNESS_APP_DB_PASSWORDare always required in the.envfile — the app uses them for the live query connection pool regardless of which setup option you chose.
- Option A: the app creates this role automatically using these values.
- Option B: the role already exists; the password in
.envmust match the one set when you created it manually.
5. Security Hardening (applies only to Option A)
The CREATEROLE privilege is only required during the initial installation or when a future update needs to create a new specialized database role.
Revoking CREATEROLE
Once the application has successfully started for the first time and you see the log Successfully created role, you can revoke this privilege:
ALTER USER sparky_admin NOCREATEROLE;
!CAUTIONPotential Issues with NOCREATEROLE If you revoke this privilege, future application updates that require creating new database roles will fail. If you encounter a "Permission Denied" error during a future upgrade, temporarily re-grant
CREATEROLEor manually create the required role as a superuser, then revoke it again.
