- Go 96.1%
- HTML 3.9%
| cmd/posta-server | ||
| internal | ||
| .gitignore | ||
| .golangci.yml | ||
| Basefile | ||
| CLIENT_API.md | ||
| go.mod | ||
| go.sum | ||
| llms.txt | ||
| README.md | ||
posta-server
The posta inbox daemon plus the authenticated client API for native apps.
posta-server runs the wire-protocol receiver from
SPEC.md and serves a REST + SSE client API at
/api/v1/* documented in CLIENT_API.md.
It is the deployment unit: the binary that runs in the arne-posta /
marcus-posta containers, replacing posta serve. The wire protocol stays
unchanged; existing peers don't notice the swap.
Build
go build ./cmd/posta-server
Static, cgo-free build for the Alpine deployment:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -trimpath -ldflags="-s -w -X main.version=$(git describe --always --dirty)" \
-o posta-server ./cmd/posta-server
Run
posta-server serve \
--url https://arne.posta.no \
--listen 0.0.0.0:80 \
--keys /etc/posta/keys.json \
--db /var/lib/posta/inbox.db \
--acl open \
--name Arne
Flags can also live in config.toml (default
$XDG_CONFIG_HOME/posta-server/config.toml) or POSTA_SERVER_* env vars.
Layering order: flag > env > config > default.
Token management
Clients (iOS, the new TUI) authenticate with bearer tokens. Tokens are minted on the host:
posta-server token create --name "Arne's iPhone" # prints mst_… once
posta-server token list # active + revoked
posta-server token revoke "Arne's iPhone" # affected devices stop authenticating
Tokens never leave the host as plaintext after the create call — only the SHA-256 hash is persisted. Lost tokens are not recoverable; revoke and re-pair.
Storage layout
Single SQLite database at --db. posta-server applies migrations on startup
and keeps the schema as a strict superset of posta's own daemon schema, so an
existing inbox.db (with messages, contacts, FTS5) is adopted in place. New
tables: identity, auth_tokens, devices, schema_version.
The legacy posta TUI reading the same DB continues to work; the new TUI and
iOS apps go through /api/v1/*.
Architecture overview
┌────────────────── caddy (TLS) ──────────────────┐
│ │
wire │ /api/v1/* (Bearer) │
peer ────┼──> posta-server ┌─ inbox handler ── DB │
│ ┌──────────┐ HTTP ├─ outbox loop ──> DB │
iOS / TUI ───┼──> │ router │ ───────┤ │
│ └──────────┘ ├─ api handlers ── DB │
│ └─ SSE hub ── ring buf │
└─────────────────────────────────────────────────┘
Wire receiver and client API share the same SQLite store. The SSE hub
publishes events from the inbox handler, the outbox loop, and the API
handlers themselves (e.g. PATCH /identity triggers identity-changed).
Layout
cmd/posta-server/ cobra CLI (serve, token, version)
internal/api/ REST + SSE handlers for /api/v1/*
internal/auth/ bearer middleware, token mint/hash
internal/config/ TOML / env / flag layering
internal/inbox/ wire-protocol receiver
internal/keys/ read-only loader for keys.json
internal/outbox/ send loop with retry/backoff
internal/sse/ in-memory pub/sub + ring buffer
internal/store/ SQLite schema, migrations, queries
Status
v0.1.0 — first release. APNs is deferred (no /api/v1/devices, no push from
the daemon). Foreground iOS via SSE; backgrounded apps see new messages on
relaunch.