Setup
Try before you install
The live demo runs entirely in your browser with no server — instant load, read-only.
Prerequisites
- Docker Desktop (Mac, Windows, or Linux)
- Git
That's all for the default Docker Compose setup. Local development additionally requires Go 1.23+ and Node.js 20+.
Installation
This single command:
- Pulls the Postgres image and starts it
- Runs all database migrations
- Builds the Go API and React frontend
- Serves everything at http://127.0.0.1:8080
Configuration
The only values needed before first launch are in docker-compose.yml:
| Variable | Default | Description |
|---|---|---|
POSTGRES_PASSWORD |
athlete |
Postgres password — change this before any network exposure |
BASE_URL |
(unset) | Public origin, e.g. https://vault.example.com — required for Strava OAuth on non-localhost |
APP_PORT |
8080 |
Host port the app listens on |
DATA_DIR |
./data |
Host path for Postgres volume and activity blobs |
APP_PUBLIC_MODE |
(unset) | Set to true to allow anyone to view data while restricting writes to authenticated owner only — designed for public demo deployments |
APP_AUTH_RESET |
(unset) | Set to true on a single startup to clear a forgotten password and disable auth — remove immediately after logging back in |
All other settings (Strava credentials, Protomaps API key, HR max, units, password protection) are configured through the Settings page in the UI and stored in the database — no restart required.
Security
By default Athlete Vault is designed for localhost use — no authentication required. If you expose it beyond your own machine, two steps are strongly recommended:
Change the Postgres password
Edit docker-compose.yml before first run and update POSTGRES_PASSWORD (and the matching value in DATABASE_URL) to something strong. The default athlete password is suitable only for localhost.
Enable password protection
- Open Settings → Password protection
- Toggle Enable password protection on
- Enter and confirm a password → Save
Once enabled, every browser session must enter the password before accessing the app. The password is hashed with bcrypt and stored in the database — never in plaintext. Sessions are scoped to the browser tab (cleared on close).
To disable again: open Settings, toggle off, Save — no password prompt to re-disable since you're already authenticated.
Forgotten password? Restart the container with APP_AUTH_RESET=true — this clears the password and disables auth so you can log back in and set a new one. See the Security page for the full steps.
Development mode
For faster iteration, run the API and frontend separately (no Docker for the app itself):
make db-up # start Postgres in Docker
make migrate # apply migrations
make run-dev # start Go API + Vite dev server with hot reload
- Frontend: http://127.0.0.1:5173 (Vite, hot reload)
- API: http://127.0.0.1:8080 (Vite proxies
/apirequests here)
Useful Make targets
| Target | What it does |
|---|---|
make run |
Full stack via Docker Compose |
make run-dev |
Local API + Vite dev server |
make db-up / make db-down |
Start / stop Postgres |
make db-reset |
Wipe and recreate Postgres data |
make migrate |
Apply pending SQL migrations |
make test |
Go tests + frontend production build |
make deploy-frontend |
Rebuild frontend and copy into the running container |
make docs-serve |
Serve this documentation at http://127.0.0.1:8090 |