feat: snare serve — self-hosted callback server#2
Merged
Merged
Conversation
Replaces the Cloudflare Worker backend with a self-hosted Go HTTP server.
## What's included
### internal/serve/ (new package)
- db.go — SQLite (modernc.org/sqlite, pure Go) with schema for
devices, tokens, events tables
- server.go — HTTP server with optional Let's Encrypt TLS via autocert
- handlers.go — All API routes, same contract as the Cloudflare Worker:
GET/POST /c/{token}[/*] canary callback → 1×1 GIF
POST /api/devices create device (server-minted ID)
POST /api/register register token webhook (Bearer auth)
POST /api/revoke remove registration (Bearer auth)
GET /api/events/{token} retrieve events (Bearer auth)
GET /health {"status":"ok"}
Plus dashboard routes:
GET / HTML dashboard (SSR, dark terminal theme)
GET /api/dashboard/alerts recent alerts JSON
GET /api/dashboard/devices registered devices JSON
- webhook.go — Outbound webhook delivery (Discord, Slack, generic JSON)
- dashboard.go — html/template SSR dashboard, auto-refreshes every 10s
- serve_test.go — 13 tests covering canary handler, auth middleware,
device creation, hashing, and DB round-trips
### CLI
- internal/cli/cli.go — added 'snare serve' subcommand with flags:
--port <n> (default 8080)
--db <path> (default ~/.snare/serve/snare.db)
--tls-domain <domain> optional Let's Encrypt
--webhook-url <url> global fallback webhook
### Docker
- Dockerfile — multi-stage build, Alpine runtime, pure Go (CGO_ENABLED=0)
- docker-compose.yml — single-service compose with volume mount and healthcheck
## Privacy guarantee preserved
The /c/{token} handler returns the GIF response before any body is read.
Alert processing runs in a goroutine after the response is written.
Request bodies are never read, stored, or forwarded.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements
snare serve— a self-hosted Go HTTP server that replaces the Cloudflare Worker backend at snare.sh.New package:
internal/serve/db.gomodernc.org/sqlite(pure Go, no CGo). Tables:devices,tokens,events. WAL mode, foreign keys on.server.gogolang.org/x/crypto/acme/autocert.handlers.gowebhook.godashboard.goserve_test.goAPI routes (identical to Worker)
Dashboard routes (new)
CLI
Docker
Compose exposes port 8080, mounts
/datavolume, and ships a healthcheck hitting/health.Privacy guarantee preserved
The canary callback handler writes the GIF response before any goroutine processes the alert. Request bodies are never read, stored, or forwarded — same guarantee as the Worker.
Quality
go build ./...✅go vet ./...✅