Get Bulwark running in Docker and managing your databases in under 5 minutes.
- Docker 20.10+ with Compose v2
- A browser
git clone https://github.com/bulwark-studio/bulwark.git
cd bulwark
docker compose up -dTwo containers start:
| Container | Image | Port | Purpose |
|---|---|---|---|
bulwark |
Ubuntu 24.04 + Node 22 | 3001 | App server |
bulwark-db |
PostgreSQL 17 Alpine | 5432 (internal) | Bulwark's own database |
Verify:
docker compose ps
curl http://localhost:3001/api/healthOpen http://localhost:3001 in your browser.
| Field | Value |
|---|---|
| Username | admin |
| Password | admin |
Change these immediately in Settings > My Account after login.
Bulwark can manage any PostgreSQL database it can reach over the network. This is the core workflow for using Bulwark as your development dashboard.
If your other apps run in separate Docker Compose stacks, Bulwark needs to join their networks. Add external networks to docker-compose.yml:
services:
bulwark:
networks:
- bulwark-net
- myapp-net # join your app's network
networks:
bulwark-net:
driver: bridge
myapp-net:
external: true # network created by your app's compose stackThen restart:
docker compose up -dTip: Run
docker network lsto see available networks. External networks use the format<directory>_<network-name>(e.g.myapp_default).
- Click DB Projects in the sidebar (under Database)
- Click + Add Project
- Fill in the form:
| Field | Example |
|---|---|
| Project Name | My App |
| PostgreSQL URL | postgresql://user:password@container-name:5432/dbname |
| Description | Optional — shows in the project picker |
| SSL | Check only for cloud-hosted PostgreSQL (Supabase, RDS, etc.) |
- Click Add Project
- Click Test to verify the connection
- Click Use This DB to make it active
The host in the URL is the Docker container name (not localhost), since Bulwark connects from inside the Docker network.
Once you have multiple projects, a project picker appears at the top of every Database view. Click it to switch. All Database views (SQL Editor, Tables, Schema, Migrations, Roles, Backups) use whichever project is active.
A typical development setup with multiple containerized apps:
┌─────────────────────────────────────────────────────┐
│ Bulwark (port 3001) │
│ ├── bulwark-net ──── bulwark-db (Bulwark's own DB) │
│ ├── app-net ──────── app-db (Your app's DB) │
│ └── other-net ────── other-db (Another app's DB) │
└─────────────────────────────────────────────────────┘
Example docker-compose.yml connecting to two external apps:
services:
bulwark:
build: .
container_name: bulwark
ports:
- "3001:3001"
environment:
- MONITOR_PORT=3001
- MONITOR_USER=${MONITOR_USER:?set MONITOR_USER}
- MONITOR_PASS=${MONITOR_PASS:?set MONITOR_PASS}
- DATABASE_URL=postgresql://bulwark:bulwark@postgres:5432/bulwark
- NODE_ENV=production
- DOCKER_HOST=unix:///var/run/docker.sock
depends_on:
postgres:
condition: service_healthy
volumes:
- bulwark-data:/app/data
- /var/run/docker.sock:/var/run/docker.sock
networks:
- bulwark-net
- app-net
- other-net
restart: unless-stopped
postgres:
image: postgres:17-alpine
container_name: bulwark-db
environment:
- POSTGRES_USER=bulwark
- POSTGRES_PASSWORD=bulwark
- POSTGRES_DB=bulwark
volumes:
- pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U bulwark"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
networks:
- bulwark-net
networks:
bulwark-net:
driver: bridge
app-net:
external: true
other-net:
external: true
volumes:
bulwark-data:
pg-data:Then in the GUI, add each database as a DB Project using the container hostname.
Once a project is active, you get a full Supabase-style management suite:
| View | What it does |
|---|---|
| SQL Editor | Write and run SQL with CodeMirror, autocomplete, query history, saved queries. Ask Claude to generate SQL from natural language. |
| Tables | Browse all tables. Click a table to see columns, data (paginated), constraints, foreign keys, and indexes. |
| Schema | View functions, triggers, extensions, and indexes across the database. |
| Migrations | See applied vs pending migrations, run migrations, test in Docker sandbox, diff live schema vs file. |
| Roles | View database roles and permissions. AI security audit scores your role configuration. |
| Backups | Create pg_dump backups, restore from file, AI backup strategy with disaster recovery planning. |
Bulwark can manage Docker containers directly through the dashboard if the Docker socket is mounted (default in the compose file).
The Docker view in the sidebar shows all containers, images, volumes, and networks. You can start, stop, restart, view logs, and inspect any container.
Bulwark uses BYOK (Bring Your Own Key) — your own AI subscriptions, zero cost to Bulwark.
ANTHROPIC_API_KEY=sk-ant-xxx docker compose up -dOr add to a .env file next to docker-compose.yml:
ANTHROPIC_API_KEY=sk-ant-xxx
OPENAI_API_KEY=sk-xxx- Open Terminal in the sidebar
- Run
claude --dangerously-skip-permissions - Follow the authentication flow
Once configured, AI features light up across the platform: SQL generation, security audits, backup strategy analysis, commit messages, daily briefings.
Configure the active provider in Settings > AI Provider.
For teams deploying apps with PostgreSQL, Bulwark provides a migration workflow:
From the SQL Editor, run:
-- View all tables
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public' ORDER BY table_name;
-- View a table's structure
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_name = 'your_table' ORDER BY ordinal_position;Or use pg_dump from the Bulwark terminal:
pg_dump -h container-name -U dbuser -d dbname --schema-only > schema.sqlIf your app uses migration files, navigate to Migrations view:
- Applied migrations are shown with timestamps
- Pending migrations (files on disk not yet applied) are highlighted
- Click Run to apply a pending migration
- Use Test to spin up a temporary PostgreSQL, apply the migration, validate, and destroy — without touching your real database
For clean deployments, create an init.sql that Docker runs on first boot:
your-app/
docker/
postgres/
init.sql # Extensions, schemas, base tables
seed.sql # Default data
docker-compose.yml
services:
db:
image: postgres:17-alpine
volumes:
- ./docker/postgres:/docker-entrypoint-initdb.d
- db-data:/var/lib/postgresql/dataFiles in /docker-entrypoint-initdb.d/ run alphabetically on first volume creation. Name them 01-init.sql, 02-schema.sql, 03-seed.sql to control order.
| Variable | Default | Description |
|---|---|---|
MONITOR_PORT |
3001 |
Server port |
MONITOR_USER |
— | Default admin username (first run) |
MONITOR_PASS |
— | Default admin password (first run) |
DATABASE_URL |
— | Bulwark's own PostgreSQL connection |
VPS_DATABASE_URL |
— | Secondary DB connection (optional) |
ENCRYPTION_KEY |
auto-generated local key | Encrypts stored env vars and can be reused for secret storage |
ANTHROPIC_API_KEY |
— | Claude API key (optional) |
OPENAI_API_KEY |
— | OpenAI API key (optional) |
DOCKER_HOST |
— | Docker socket path |
NODE_ENV |
production |
Node environment |
Container starts but health check fails:
docker compose logs bulwark --tail 30Usually means PostgreSQL isn't ready yet. The depends_on with service_healthy should handle this, but increase start-period in the healthcheck if needed.
Can't connect to external database from DB Projects:
- Verify Bulwark is on the same Docker network:
docker inspect bulwark --format '{{json .NetworkSettings.Networks}}' | jq - Test from inside the container:
docker exec bulwark bash -c "pg_isready -h container-name -U dbuser" - The host must be the container name, not
localhost
Database shows "Not connected" after adding project:
- Click Test on the project card to see the exact error
- Common issues: wrong password, wrong container name, network not connected, SSL required but not checked
Permission denied on Docker socket:
- Set
DOCKER_GIDto match your host's Docker group:stat -c '%g' /var/run/docker.sock - Or run:
DOCKER_GID=$(stat -c '%g' /var/run/docker.sock) docker compose up -d
AI features show "not available":
- Check Settings > AI Provider — make sure a provider is selected
- For Claude CLI: open Terminal and verify
claude --versionworks - For API keys: verify they're set in environment or
.env
# Start
docker compose up -d
# Stop
docker compose down
# Rebuild after code changes
docker compose up -d --build
# View logs
docker compose logs -f bulwark
# Shell into the container
docker exec -it bulwark bash
# Reset everything (destroys data)
docker compose down -v && docker compose up -dBuilt by Bulwark Studio | GitHub | Full Documentation