Personal home-server monorepo for learning and personal use. Currently contains 3 services:
| Service | Description |
|---|---|
| bouncer | Authentication service — issues and validates JWTs |
| postiliste | Shopping list app — Go backend + Lit frontend |
| jot | Notes app — Gleam/Wisp backend + Lustre frontend |
flowchart LR
Browser -->|HTTPS| Caddy
Caddy -->|/auth/*| bouncer
Caddy -->|forward_auth\n/auth/validate| bouncer
bouncer -.->|200 / 401| Caddy
Caddy -->|/api/*| backend[postiliste-backend]
Caddy -->|/*| static[static files]
bouncer --- bouncerdb[(bouncer.db)]
backend --- appdb[(shopping.db)]
Caddy's forward_auth directive calls GET /auth/validate before forwarding any /api/* request. Unauthenticated requests are rejected by Caddy — the backend never sees them.
- Go 1.24+
- Bun 1.x
- tmux — terminal multiplexer (development only)
- Overmind — Procfile process manager, uses tmux (development only)
- air — Go hot reload (development only)
- Gleam 1.x — for jot
- watchexec — Gleam hot reload (development only)
- live-server — static file server with live reload (
bun add -g live-server, development only) - direnv — optional, auto-loads per-directory
.envfiles - Caddy 2.x — production only
# Copy and fill in real values
cp config.mk.example config.mk
# Create .env files for each service (see service READMEs for variables)
cp bouncer/.env.example bouncer/.env # edit: set JWT_SECRET
cp postiliste/backend/.env.example postiliste/backend/.env
cp postiliste/frontend/.env.example postiliste/frontend/.env
# Install Go hot-reload tool
go install github.com/air-verse/air@latest
# Install Gleam hot-reload tool (macOS)
brew install watchexec
# Create jot API env file
cp jot/backend/.env.example jot/backend/.env # edit: set JOT_SECRET
# Start all services with hot reload
make devServices listen on:
- Bouncer: http://localhost:8080
- Postiliste backend: http://localhost:8081
- Postiliste frontend: http://localhost:3001
- Huis dashboard: http://localhost:3000
- Jot backend: http://localhost:8082
- Jot frontend: http://localhost:3002
Dev:
make dev Start all services (hot reload + file watch)
make dev/bouncer Start bouncer only
make dev/postiliste-backend Start postiliste backend only
make dev/postiliste-frontend Start postiliste frontend (watch + serve)
make dev/jot-backend Start jot backend (watchexec + gleam run)
make dev/jot-frontend Start jot frontend (watch + serve on :3002)
Build:
make build Build all binaries + frontend bundle
make build/bouncer
make build/postiliste-backend
make build/postiliste-frontend
make build/jot-backend
make build/jot-frontend
First-time deploy:
make deploy/bouncer Cross-compile, upload, install systemd service
make deploy/postiliste Cross-compile, upload, install systemd service + Caddyfile
make deploy/jot Build and deploy jot
Redeploy:
make redeploy Rebuild and restart all services
make redeploy/bouncer
make redeploy/postiliste
make redeploy/jot
User management:
make bouncer/add-user Add a user to bouncer on the server
Copy config.mk.example to config.mk and set your values. config.mk is gitignored.
SERVER = user@your-server-ip
HUIS_DOMAIN = huis.your.domain.tld
PL_DOMAIN = liste.your.domain.tld
JOT_DOMAIN = jot.your.domain.tld
BOUNCER_PORT = 8080 # override to change backend ports
POSTILISTE_PORT = 8081
JOT_PORT = 8082
HUIS_DEV_PORT = 3000 # override to change local dev ports
PL_DEV_PORT = 3001
JOT_DEV_PORT = 3002See each service's README for runtime environment variables.