From Source
Running the Go binaries and the Next.js frontend directly, with infrastructure in Docker — plus the first-run web installer and which database the setup wizard is actually configuring.
For development, or for a deployment that does not want the app in containers. Most people should use Quick Start instead.
Prerequisites
| Requirement | Version |
|---|---|
| Go | 1.25+ |
| Node.js | 20.9+ (images build on 22) with pnpm 10.30.3 via corepack |
| golang-migrate | v4.18.3 — only for the make migrate-* targets; Docker runs migrations for you |
| Docker & Docker Compose | Latest, for the infrastructure services |
| PostgreSQL | 16 (or use Docker) |
| Redis | 7 (or use Docker) |
Infrastructure Only
git clone https://github.com/AmJaradat01/burnerbyte.gitcd burnerbytemake docker-infraThat layers docker-compose.dev.yml over the base file to start Postgres,
Redis and MinIO with their ports published on the host — 5432, 6379, 9000
and 9001, which the base file deliberately does not do. Without the overlay the
binaries running on your machine cannot reach them.
Environment
cp .env.example .envAt minimum set DATABASE_URL, REDIS_URL and JWT_SECRET (32+ characters, or
the API refuses to boot). Every key is in
Configuration.
No configuration file is required — the binaries boot entirely from environment variables and every operational key has a default. If you would rather configure by file:
cp config.example.yaml config.yamlconfig.yaml is gitignored and never baked into an image. BB_CONFIG_PATH
changes where it is read from and written to.
Migrations
make migrate-upThis applies all 50 migrations, producing 36 tables, 74 indexes and 8 triggers. See Database Schema.
Run It
Three processes, in three terminals:
make run-api # :8080make run-smtp # :2525cd web && pnpm install && pnpm dev # :3000The SMTP server is optional for initial setup. Start it when you are ready to receive mail. Then open http://localhost:3000 and continue from Setup Wizard.
First-Run Web Installer
Starting the API with no database configured — DATABASE_URL unset and no
config.yaml — boots a token-gated installer instead of the API. Every other
path answers 503 BurnerByte is not configured yet until it completes.
The startup log prints a one-time URL:
open http://<host>:8080/install?token=<token>The form collects the database URL, Redis URL, JWT secret and (strongly
recommended) an encryption key, verifies the connections, writes config.yaml,
and re-execs into a normal boot. An already-configured instance never exposes
the installer.
Setting DATABASE_URL and REDIS_URL in the environment skips it entirely,
which is what Docker Compose does.
Which Database Am I Configuring?
Database and Redis are the only settings the setup wizard cannot change — its
own state (the owner account, the organization, setup_state, system_configs)
is stored in that database, so the connection has to be resolved before the
API can serve step one. They come from the environment, config.yaml, or the
first-run installer.
So that you can confirm you are configuring the intended instance,
GET /api/v1/setup/status reports the connection targets with credentials
stripped, and the wizard shows them above the admin form:
{ "completed": false, "datastores": { "postgres": "postgres:5432/burnerbyte", "redis": "redis:6379" }}The datastores field is withheld once setup completes.
Development Commands
| Command | What it does |
|---|---|
make test | go test -race ./... — the backend suite, including property tests |
make lint | golangci-lint run ./... |
make web-test | The frontend suite, lint and typecheck in one pass |
make migrate-create | Prompts for a name and scaffolds a sequential up/down pair |
make migrate-test-db | Creates the test database if TEST_DATABASE_URL does not resolve |
make docker-logs | docker compose logs -f across the stack |
Integration tests need a real database; without one they skip, which hides
regressions rather than failing. make migrate-test-db is what CI runs first
for that reason.
Build
make build # bin/api and bin/smtpdcd web && pnpm build # Next.js standalone outputmake docker-up starts the full stack instead, and make docker-down stops
it.