Airbrew is a single-tenant personal-cloud workspace shipped as one Go binary. It bundles an OAuth 2.1 / OpenID Connect provider with productivity surfaces (mail, drive, contacts, chat, AI agents, automation workflows). The binary embeds its React SPA, so deployment is one file + one SQLite database.
| Module | State |
|---|---|
| Auth | Users/sessions/password, case-insensitive email, session revoke on password change |
| OAuth/OIDC | Schema ready, endpoints not yet built |
| Inbound/outbound drivers, mailbox storage, threading, outbox auto-retry, IMAP/POP3 poll | |
| Drive | Files, folders, zip download, shares (password/expiry/limit), trash, quota |
| Contacts | Address book, groups, vCard import/export, avatars |
| Chat | Direct/group rooms, real-time SSE, edit/delete, replay-on-reconnect |
| AI | Provider abstraction, streaming chat, tool-calling agents |
| Workflow | Graph engine (trigger/logic/action), webhook/schedule/manual, run history, SPA editor |
| Passwords | Zero-knowledge vault, delta sync, attachments |
See docs/auth.md for the milestone roadmap.
Requirements:
- Go 1.22+ (built with Go 1.26)
- Node.js 20+ (only for SPA development)
# Build SPA and Go binary
make build
# Run
AIRBREW_HTTP_ADDR=:5050 AIRBREW_SESSION_SECRET=$(openssl rand -hex 32) ./bin/airbrew
# Health check
curl localhost:5050/healthz # -> {"ok":true}
# Register + login + me
curl -X POST localhost:5050/api/auth/register \
-H 'content-type: application/json' \
-d '{"email":"alice@example.com","password":"hunter2hunter2"}'# Run API and Vite dev servers
make dev
# SPA at http://localhost:5051make dev:api rebuilds and restarts the Go API when backend files change.
make dev:web runs Vite HMR. Use either command to run one side separately.
To build only the SPA into web/dist/ so make build:api serves it from the binary:
make install:web
make build:webAll knobs are environment variables prefixed with AIRBREW_:
| Variable | Default (dev) | Notes |
|---|---|---|
AIRBREW_HTTP_ADDR |
:5050 |
Listen address |
AIRBREW_DATABASE_PATH |
./airbrew.db |
SQLite file path |
AIRBREW_PUBLIC_URL |
http://localhost:5050 |
Issuer / SPA base URL |
AIRBREW_SESSION_SECRET |
dev default (32+ bytes required) | HMAC secret for session cookies |
AIRBREW_SESSION_MAX_AGE |
336h (14 days) |
Session lifetime |
AIRBREW_LOG_LEVEL |
info |
slog level |
AIRBREW_BOOTSTRAP_ADMIN_EMAIL |
admin@airbrew.local |
First-run admin email |
AIRBREW_BOOTSTRAP_ADMIN_PASSWORD |
random generated password | Optional fixed first-run admin password |
On startup, if no admin user exists, Airbrew creates one and prints the credentials to stdout. A generated password is shown only once.
cmd/airbrew/ Single entry point
internal/
config/ Env-based configuration
db/ SQLite open + embedded SQL migrations
id/ nanoid-style ID generator
httpserver/ Server bootstrap + middleware (requestid, recover, access log)
auth/ Auth module (OAuth/OIDC provider)
user/ User domain, repository, service
password/ argon2id hashing
session/ Browser session lifecycle
oauth/ Reserved for OAuth/OIDC endpoints
handler/ JSON HTTP handlers
mail/ Mail module (mailboxes, inbound/outbound drivers)
letter/ shared MIME helpers (Address, Outgoing, BuildRFC822, Parse)
inbox/ Mailbox + Message domain, repository, service
provider/ admin-selectable driver registry (mail_providers)
inbound/ receive drivers: cloudflare/ses (webhook) + imap/pop3 (poll)
outbound/ send drivers: sendgrid/mailgun/ncloud/ses/cloudflare/smtp
handler/ JSON HTTP handlers
drive/ Stub
contacts/ Stub
chat/ Stub
ai/ Stub
workflow/ Stub
server/ Root mux wiring all modules
web/ Vite + React SPA (embedded via go:embed)
docs/ Architecture and feature design docs
- Single binary: everything ships in one executable.
- CGO-free:
modernc.org/sqlite(pure Go) so cross-compilation just works. - Standard library first:
net/http(Go 1.22+ pattern routing),log/slog,crypto/rand,database/sql. Only essential external deps:argon2. - Application-generated IDs: 21-char nanoid-style for all primary keys.
- Single-tenant: no
workspace_idcolumns; one SQLite file per deployment.
Proprietary.