Files
Messenger/README.md
T

129 lines
5.2 KiB
Markdown
Raw Permalink Normal View History

# Messenger
Self-hosted messenger for family and friends. Built from scratch: Go backend,
React PWA frontend, PostgreSQL. Deployed on a home-lab mini PC.
> **Status: v1.0.0** — production-ready. Auth, direct chats and groups,
> real-time delivery, media, reactions, search, Web Push, PWA offline,
> metrics and hardening are all implemented and tested.
## Repository layout
```
server/ Go API
cmd/api/ entrypoint (wiring, migrations, graceful shutdown)
cmd/keygen/ generate VAPID keys for Web Push
cmd/seed/ create demo users and a family group
internal/api/ HTTP handlers: auth, users, contacts, conversations, messages, media, search, push
internal/auth/ argon2id hashing, JWT access tokens, refresh tokens
internal/realtime/ WebSocket hub: events, presence, typing, read receipts
internal/media/ S3-like storage + image thumbnails
internal/store/ PostgreSQL access (pgx), embedded migrations
internal/platform/ config, logging, metrics, rate limiting, version
web/ React + TypeScript + Vite PWA (offline, Web Push)
deploy/ docker-compose (api, postgres, victoriametrics, grafana)
docs/ architecture (mermaid), ADR
.github/ CI workflows
```
## API
All endpoints under `/api/v1`. Auth via httpOnly cookies (`messenger_access`
= JWT 15 min, `messenger_refresh` = opaque token 30 days, rotated on refresh).
| Method | Path | Description |
|--------|------|-------------|
| POST | `/api/v1/auth/register` | Create account (sets cookies) |
| POST | `/api/v1/auth/login` | Sign in (sets cookies) |
| POST | `/api/v1/auth/refresh` | Rotate refresh token |
| POST | `/api/v1/auth/logout` | Revoke session, clear cookies |
| GET | `/api/v1/users/me` | Current user |
| GET | `/api/v1/users?q=` | Search users by username/name |
| GET | `/api/v1/contacts` | Contact list |
| POST | `/api/v1/contacts` | `{user_id}` — add contact |
| DELETE | `/api/v1/contacts/{user_id}` | Remove contact |
| GET | `/api/v1/conversations` | List chats + unread counts |
| POST | `/api/v1/conversations` | `{user_id}` DM or `{type:"group", name, member_ids}` |
| GET | `/api/v1/conversations/{id}/members` | List participants + roles |
| POST | `/api/v1/conversations/{id}/members` | `{user_id}` — add to group |
| DELETE | `/api/v1/conversations/{id}/members/{user_id}` | Remove/leave (owner or self) |
| GET | `/api/v1/conversations/{id}/messages` | History, keyset `?before=` |
| POST | `/api/v1/conversations/{id}/messages` | `{body, temp_id, media_id?}` — send |
| PUT | `/api/v1/conversations/{id}/messages/{msg_id}/reactions` | `{emoji}` — react |
| DELETE | `/api/v1/conversations/{id}/messages/{msg_id}/reactions/{emoji}` | Remove reaction |
| POST | `/api/v1/media` | Upload file (multipart `file`) |
| GET | `/api/v1/media/{id}` | Download file |
| GET | `/api/v1/media/{id}/thumb` | Image thumbnail |
| GET | `/api/v1/search/messages?q=` | Search user's messages |
| POST | `/api/v1/push/subscribe` | Register Web Push subscription |
| DELETE | `/api/v1/push/subscribe` | Unregister Web Push subscription |
| GET | `/ws` | WebSocket (auth via cookie) |
WebSocket event types: `message.created`, `typing`, `presence`, `read`,
`reaction.added/removed`, `member.added/removed`, `conversation.added/removed`.
## Prerequisites
- Go 1.27+, Node.js 22+, PostgreSQL
- Docker + Docker Compose (for deployment)
## Local development
```bash
# create the role once (as postgres superuser)
sudo -u postgres psql -c "CREATE ROLE messenger LOGIN PASSWORD 'messenger';"
sudo -u postgres psql -c "CREATE DATABASE messenger OWNER messenger;"
# backend (migrations run automatically on start)
cd server
go run ./cmd/api # :8080
# frontend (separate terminal)
cd web
npm install
npm run dev # :5173, proxies /api and /ws -> :8080
```
Optional: demo data → `cd server && go run ./cmd/seed`
(users papa/mama/syn/doch, password `password123`, group «Семья»).
## Deployment (Docker Compose)
```bash
cp deploy/.env.example deploy/.env # adjust secrets
cd deploy
docker compose up -d --build
```
Services: `api` (single static binary serving API + frontend), `postgres`,
`victoriametrics` (metrics storage), `grafana` (dashboard «Messenger»
auto-provisioned at http://localhost:3000).
### Metrics
`GET /metrics` exposes Prometheus metrics: HTTP requests by status/path,
request latency, WebSocket connections, Go runtime. Scraped by VictoriaMetrics.
### Web Push (optional)
```bash
cd server && go run ./cmd/keygen # prints the three VAPID variables
```
Put them in `deploy/.env` (`MESSENGER_VAPID_*`) and in `web/.env`
(`VITE_VAPID_PUBLIC_KEY`). Without keys everything works except notifications.
## Architecture & decisions
See `docs/architecture.md` (component and sequence diagrams) and
`docs/adr/` for the rationale behind: monolith, in-memory WS hub, ILIKE
search, S3-like media storage, E2EE roadmap.
## Roadmap
- **Phase 0-3** — skeleton → auth/chats → frontend → groups/reactions/media → search/push/PWA ✅
- **Phase 4** — P2P WebRTC calls via our WebSocket signalling + coturn TURN fallback (planned, major feature)
- **Phase 5** — metrics, docs, hardening ✅
## License
Proprietary for now; open-sourcing at a future major version.