SIN Community
SIN Community is the developer knowledge hub of the opensecstack ecosystem — a publishing platform for post-mortems, detection recipes, NIS2 guides, and CSAF advisory write-ups. Posts are tagged, full-text searchable via Meilisearch, and optionally anchored into the CITADEL WORM chain for tamper evidence.
The platform is inspired by dev.to. It runs at sin.to and is self-hostable. License: AGPL-3.0-or-later.
Overview
SIN Community is a three-tier application: a Go API backed by PostgreSQL 16 and Meilisearch, and a React + TypeScript + Vite frontend. It supports threaded comments, post reactions, tag-based discovery, push notifications (Web Push via VAPID), TOTP two-factor authentication, and personal API keys.
Authentication is flexible by design. Because SIN Community is a public hub, it keeps its own native account system (email/password with bcrypt and a server-side pepper) alongside sinauth SSO and direct GitHub/Google OAuth. In a fully integrated opensecstack deployment the native path can be disabled entirely, making sinauth the only login — matching the SSO-only posture of the other platforms.
Key features
- Posts, comments, and reactions — Markdown posts with threaded comments (unlimited depth via
parent_idself-reference) and per-kind reactions enforced as unique at the database level. - Tags and spaces — posts are organised by tags; spaces provide a higher-level grouping for topic communities within the hub.
- Full-text search (Meilisearch) — post titles, bodies, tags, and author usernames are indexed in Meilisearch v1.10 for fast, typo-tolerant search.
- Notifications — in-app and Web Push notifications (VAPID) for mentions, replies, and follows.
- TOTP two-factor authentication — time-based OTP for native accounts; sinauth accounts inherit MFA from the identity provider.
- API keys — personal API keys for programmatic access; useful for posting from CI/CD pipelines.
- sinauth SSO — "Continue with SIN" button on the Login and Register pages uses OAuth 2.0 / OIDC (authorization code + PKCE via the server-side flow). A first sinauth login auto-provisions a Community account; an existing account is linked by verified email. sinauth also provides centralised TOTP MFA and social login (Google, GitHub).
- Native accounts + social OAuth — email/password registration with email verification and password reset; direct GitHub and Google OAuth as alternatives. Set
COMMUNITY_NATIVE_AUTH=falseto disable the native path in a sinauth-integrated deployment. - Invite-only mode — set
COMMUNITY_INVITE_ONLY=trueto restrict registration to invited users; optionally combine withCOMMUNITY_ALLOWED_EMAIL_DOMAINSto limit to specific domains. - CITADEL tamper evidence —
community.post.publishedevents are emitted to CITADEL on publish, recording an immutable anchor for each published post. - Four-role RBAC —
viewer,author,moderator,admin.
Architecture
The Go API uses raw SQL via pgx/v5 (no ORM) and serves HTTP on :8090. Session tokens are HMAC-signed JWTs (HS256). The authentication methods that are active at runtime are advertised at GET /api/v1/auth/methods, which the frontend reads to decide which login buttons to render.
Meilisearch is the search backend. Posts are indexed on publish (title, body up to 5 000 characters, tags, author username). The MEILISEARCH_URL and MEILISEARCH_KEY environment variables wire the client; leave MEILISEARCH_URL at the default (http://localhost:7700) for local development.
The CITADEL integration is opt-in: leave COMMUNITY_CITADEL_API_URL empty to disable it entirely. In development, COMMUNITY_CITADEL_DRY_RUN=true (default) logs calls without sending them.
In production the multi-stage Docker image bundles the Go binary and the compiled React SPA into a single container, with nginx serving the frontend and proxying API requests.
Ports & endpoints
| Service | Port | Notes |
|---|---|---|
| Go API | 8090 | COMMUNITY_HTTP_ADDR |
| React frontend (dev) | 5173 | Vite dev server; nginx in production |
| Meilisearch | 7700 | MEILISEARCH_URL |
| PostgreSQL 16 | 5435 | Host-side dev port (COMMUNITY_DB_URL) |
Selected API endpoints (full reference at api/openapi.yaml):
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/auth/methods | Lists active login methods (drives frontend buttons) |
GET | /api/v1/auth/sinauth | Initiates sinauth OAuth flow (server-side) |
POST | /api/v1/auth/register | Native email/password registration |
POST | /api/v1/auth/login | Native email/password login; issues session JWT |
GET POST | /api/v1/posts | List and create posts |
POST | /api/v1/posts/{id}/publish | Publish post; emits CITADEL evidence event |
GET | /api/v1/search | Full-text search via Meilisearch |
GET POST | /api/v1/posts/{id}/comments | Threaded comments |
/api/v1/notifications | GET | In-app notification feed |
Integration
Minimum required environment variables:
COMMUNITY_DB_URL=postgres://community:community@postgres:5432/community COMMUNITY_JWT_SECRET=<32+ random bytes> COMMUNITY_PASSWORD_PEPPER=<32+ random bytes> MEILISEARCH_KEY=<master key> "cm"># sinauth SSO (optional — enable "Continue with SIN" button) SINAUTH_CLIENT_ID=<client id registered in sinauth> SINAUTH_URL=https://auth.sin.to SINAUTH_CALLBACK_URL=https://sin.to/api/v1/auth/sinauth/callback "cm"># CITADEL tamper evidence (optional) COMMUNITY_CITADEL_API_URL=https://citadel.internal COMMUNITY_CITADEL_DRY_RUN=false
To run the full development stack:
git clone https://github.com/opensecstack/opensecstack cd opensecstack/community cp .env.example .env "cm"># edit secrets before proceeding cp web/.env.example web/.env "cm"># set VITE_VAPID_PUBLIC_KEY docker compose -f docker-compose.dev.yml up "cm"># API: http://localhost:8090 "cm"># Frontend: http://localhost:5173 "cm"># Meilisearch: http://localhost:7700 "cm"># Login: admin / admin (change immediately)
SIN Community integrates with one other opensecstack platform by default:
| Platform | Direction | Purpose |
|---|---|---|
| CITADEL | Push on publish | community.post.published events; opt-in via COMMUNITY_CITADEL_API_URL |
| sinauth | OAuth callback | SSO login and account provisioning; opt-in via SINAUTH_CLIENT_ID |
Full documentation
The complete SIN Community documentation — operator guides, content guidelines, badge system, and API reference — is available in the repository:
github.com/opensecstack/opensecstack/tree/main/community/docs