Installation
Brittle runs as a Docker container with Postgres. One command installs both:
curl -fsSL https://brittle.dev/install.sh | shWhen it’s done, open http://localhost:3100 and finish the
setup wizard.
Requirements
Section titled “Requirements”- Docker 24 or newer, with Compose v2.
- A free port. Default is
3100.
Install with Docker Compose
Section titled “Install with Docker Compose”If you’d rather not pipe a script to shell, the manual flow is the
same stack written by hand. Save the file below as
docker-compose.yml in a new directory.
services: postgres: image: postgres:16-alpine environment: POSTGRES_USER: brittle POSTGRES_PASSWORD: brittle POSTGRES_DB: brittle volumes: - postgres-data:/var/lib/postgresql/data healthcheck: test: ['CMD-SHELL', 'pg_isready -U brittle'] interval: 5s retries: 5
init-artifacts: image: alpine:3 volumes: - artifacts:/data command: ['sh', '-c', 'chown -R 1000:1000 /data']
brittle: image: ghcr.io/brittlehq/brittle:latest container_name: brittle depends_on: postgres: condition: service_healthy init-artifacts: condition: service_completed_successfully ports: - '3100:3100' configs: - source: hub-config target: /etc/brittle/hub.config.yaml volumes: - artifacts:/var/lib/brittle/artifacts environment: BRITTLE_CONFIG_PATH: /etc/brittle/hub.config.yaml DATABASE_URL: postgresql://brittle:brittle@postgres:5432/brittle?schema=public JWT_SECRET: ${JWT_SECRET} BRITTLE_AI_SECRET_KEY: ${BRITTLE_AI_SECRET_KEY}
volumes: postgres-data: artifacts:
configs: hub-config: content: | server: host: 0.0.0.0 port: 3100 database: url: $${DATABASE_URL} auth: jwtSecret: $${JWT_SECRET} artifacts: store: local:/var/lib/brittle/artifacts redis: {} session: {} nodes: heartbeat: {} internal: {} tunnel: {} ai: enabled: falseGenerate two secrets and save them next to the Compose file:
cat > .env <<EOFJWT_SECRET=$(openssl rand -hex 32)BRITTLE_AI_SECRET_KEY=$(openssl rand -hex 32)EOFchmod 600 .envThen bring up the stack:
docker compose up -dSetup wizard
Section titled “Setup wizard”The first time you open the dashboard, three short forms appear.
- Account. Email and password. Your admin login.
- Organization. Name and slug. The slug appears in URLs.
- Project. Name and slug.
Mint a token
Section titled “Mint a token”From the dashboard: Manage → Projects → your project → Tokens → New token.
service: long-lived. Use in CI.personal: bound to your user. Use on a laptop.
Copy the token immediately. The plaintext is shown once.
Wire it into your suite at Reporter overview.
Custom port or install directory
Section titled “Custom port or install directory”BRITTLE_PORT=4000 INSTALL_DIR=~/code/brittle \ sh -c "$(curl -fsSL https://brittle.dev/install.sh)"The chosen port is remembered. Re-running the installer reuses it.
Upgrade
Section titled “Upgrade”Re-run the installer. Your data, secrets, and port survive.
curl -fsSL https://brittle.dev/install.sh | shIf you installed with Compose, pull and restart from the install directory:
docker compose pull && docker compose up -dUninstall
Section titled “Uninstall”cd ~/brittle && docker compose down -vdown -v wipes Postgres and artifacts. Delete the install directory
to remove everything else.
Troubleshooting
Section titled “Troubleshooting”Port already in use. Re-run with BRITTLE_PORT=4000, or stop
whatever’s holding the port.
Docker not running. Start Docker Desktop on macOS or Windows,
or sudo systemctl start docker on Linux.
Dashboard never responds. Tail the logs:
cd ~/brittle && docker compose logs -f brittle- Reporter overview: wire results from your test suite into Brittle.
- Self-host overview: what’s in the stack and how the pieces fit.
- Production notes: TLS, a real domain, S3 artifacts, backups.