This guide explains how to set up PostgreSQL as the database backend for CIRIS Agent.
- PostgreSQL installed and running
- sudo access to your system
sudo ./tools/database/setup_postgres_sudo.sh ciris_test_db ciris_test ciris_test_passwordArguments:
ciris_test_db- Main database nameciris_test- PostgreSQL usernameciris_test_password- Password for the user
For production, use different credentials:
sudo ./tools/database/setup_postgres_sudo.sh ciris_db ciris_user your_secure_passwordexport CIRIS_DB_URL='postgresql://ciris_test:ciris_test_password@localhost:5432/ciris_test_db'python main.py --adapter cli --mock-llmThat's it! CIRIS will now use PostgreSQL for all data storage.
The script automatically:
- ✅ Checks if PostgreSQL is running (starts it if needed)
- ✅ Creates the database user with appropriate permissions
- ✅ Creates three databases:
- Main database (
ciris_test_db) - Core CIRIS data - Secrets database (
ciris_test_db_secrets) - Encrypted secrets storage - Auth database (
ciris_test_db_auth) - Authentication data
- Main database (
- ✅ Runs any pending migrations
- ✅ Tests all database connections
- ✅ Displays the connection string for CIRIS
If you prefer to set up manually or need more control:
sudo -u postgres psqlCREATE USER ciris_test WITH PASSWORD 'ciris_test_password';
ALTER USER ciris_test CREATEDB;
\qsudo -u postgres psql <<EOF
CREATE DATABASE ciris_test_db OWNER ciris_test;
CREATE DATABASE ciris_test_db_secrets OWNER ciris_test;
CREATE DATABASE ciris_test_db_auth OWNER ciris_test;
GRANT ALL PRIVILEGES ON DATABASE ciris_test_db TO ciris_test;
GRANT ALL PRIVILEGES ON DATABASE ciris_test_db_secrets TO ciris_test;
GRANT ALL PRIVILEGES ON DATABASE ciris_test_db_auth TO ciris_test;
EOFPGPASSWORD=ciris_test_password psql -h localhost -U ciris_test -d ciris_test_db -c "SELECT 1"CIRIS uses three separate PostgreSQL databases:
postgresql://user:pass@host:port/ciris_db ← Main database (set via CIRIS_DB_URL)
├── _secrets ← Automatically derived
└── _auth ← Automatically derived
Why three databases?
- Security isolation: Secrets are stored in a separate database
- Auth separation: Authentication data is isolated from application data
- Easier backups: You can backup each database independently
You only need to specify the main database in CIRIS_DB_URL. CIRIS automatically:
- Connects to
{main_db}_secretsfor secrets storage - Connects to
{main_db}_authfor authentication
# Required - tells CIRIS to use PostgreSQL
export CIRIS_DB_URL='postgresql://username:password@host:port/database_name'
# Optional - override default host/port
export CIRIS_DB_URL='postgresql://ciris_test:ciris_test_password@192.168.1.100:5433/ciris_test_db'
# Passwords with special characters (@, {, }, [, ], etc.) are supported
# Both formats work (URL-encoded or non-encoded):
export CIRIS_DB_URL='postgresql://user:p@ss{w}rd[123]@localhost:5432/db' # Non-encoded
export CIRIS_DB_URL='postgresql://user:p%40ss%7Bw%7Drd%5B123%5D@localhost:5432/db' # URL-encodedAlternatively, add to config/essential.yaml:
database:
database_url: "postgresql://ciris_test:ciris_test_password@localhost:5432/ciris_test_db"Note: Environment variable takes precedence over config file.
CIRIS automatically detects the database type from the connection string:
unset CIRIS_DB_URL # Uses data/ciris.db
python main.py --adapter cliexport CIRIS_DB_URL='postgresql://ciris_test:ciris_test_password@localhost:5432/ciris_test_db'
python main.py --adapter cliNo code changes needed - CIRIS handles the dialect translation automatically!
The user needs CREATEDB privilege:
sudo -u postgres psql -c "ALTER USER ciris_test CREATEDB;"Run the setup script or manually create the databases as shown above.
Check your connection string:
- Username is correct
- Password is correct (check for special characters that need URL encoding)
- PostgreSQL is configured to accept password authentication
Edit /etc/postgresql/*/main/pg_hba.conf:
# Add this line for local connections:
host all all 127.0.0.1/32 md5
Then restart PostgreSQL:
sudo systemctl restart postgresqlPostgreSQL might not be running:
sudo systemctl status postgresql
sudo systemctl start postgresqlTo migrate existing SQLite data to PostgreSQL:
-
Backup your SQLite database:
cp data/ciris.db data/ciris.db.backup
-
Set up PostgreSQL (follow steps above)
-
Note: There is currently no automatic migration tool. You'll start fresh with PostgreSQL.
-
Use strong passwords:
# Generate a strong password openssl rand -base64 32 -
Restrict database access:
-- Connect only from localhost REVOKE ALL ON DATABASE ciris_db FROM PUBLIC; GRANT CONNECT ON DATABASE ciris_db TO ciris_user;
-
Enable SSL connections:
export CIRIS_DB_URL='postgresql://user:pass@host:5432/db?sslmode=require'
-
Adjust PostgreSQL settings in
/etc/postgresql/*/main/postgresql.conf:shared_buffers = 256MB effective_cache_size = 1GB maintenance_work_mem = 64MB -
Enable connection pooling (future feature)
# Backup all three databases
pg_dump -h localhost -U ciris_test ciris_test_db > backup_main.sql
pg_dump -h localhost -U ciris_test ciris_test_db_secrets > backup_secrets.sql
pg_dump -h localhost -U ciris_test ciris_test_db_auth > backup_auth.sql
# Restore
psql -h localhost -U ciris_test ciris_test_db < backup_main.sql
psql -h localhost -U ciris_test ciris_test_db_secrets < backup_secrets.sql
psql -h localhost -U ciris_test ciris_test_db_auth < backup_auth.sqlVerify your setup:
# 1. Set environment
export CIRIS_DB_URL='postgresql://ciris_test:ciris_test_password@localhost:5432/ciris_test_db'
# 2. Run CIRIS with timeout
python main.py --adapter cli --mock-llm --timeout 10
# 3. Check logs
tail -f logs/latest.logExpected output:
✓ Database initialized at postgresql://ciris_test:...
✓ Database integrity verified
✓ Phase database completed successfully
If you encounter issues:
- Check the logs:
logs/incidents_latest.log - Verify PostgreSQL is running:
sudo systemctl status postgresql - Test connection manually:
psql -h localhost -U ciris_test -d ciris_test_db - Review this guide for troubleshooting steps
Quick commands for testing:
# Setup (one time)
sudo ./tools/database/setup_postgres_sudo.sh ciris_test_db ciris_test ciris_test_password
# Run CIRIS with PostgreSQL
export CIRIS_DB_URL='postgresql://ciris_test:ciris_test_password@localhost:5432/ciris_test_db'
python main.py --adapter cli --mock-llm
# Switch back to SQLite
unset CIRIS_DB_URL
python main.py --adapter cliThat's it! You now have CIRIS running on PostgreSQL. 🎉