CodeVault
A small HTTP service that stores string values under access codes: write a
value with setValue under a code, later retrieve it with getValue using
that code. Basic Auth protects writes; reads are open but rate-limited by
failed-lookup count per client IP to slow down code guessing.
Features
POST /api/v1/setValue— store a value under a code (Basic Auth required).POST /api/v1/getValue— retrieve a value by code (public, rate-limited).- Interactive API docs at
/api(Swagger UI, embedded assets — no CDN). - Prometheus metrics for HTTP requests and business events (successful/failed gets and sets).
- OpenTelemetry logging, with optional OTLP export.
- SQLite storage (pure Go driver, no CGO).
- Configurable trusted proxies so client IPs are resolved correctly behind a reverse proxy (e.g. nginx).
Running
Locally
go build
./codevault config-example ./config.yaml # write a starter config
./codevault add-user --db-path ./codevault.db --login admin # prompts for a password
./codevault run --config ./config.yaml
Or via the Makefile: make build, make config-example, make add-user,
make run.
Docker
cp docker-compose.yaml.example docker-compose.yaml
go run . config-example ./config.yaml # or hand-write one, see Configuration below
docker compose up -d --build
docker compose exec codevault ./codevault add-user --db-path /app/data/codevault.db --login admin
The compose file mounts config.yaml read-only and keeps the SQLite database
in a named volume (codevault-data). Edit server.trusted_proxies in your
config.yaml to match the proxy/network actually in front of the container
(gin needs IPs/CIDRs, not hostnames).
Configuration
config-example writes a documented starting point. Key sections:
environment: development # development | production
server:
address: :8080
trusted_proxies: # IPs/CIDRs allowed to set X-Forwarded-For / X-Real-IP
- 172.16.0.0/12 # empty/omitted = trust nothing, use the raw remote address
database:
path: ./codevault.db
rate_limit:
max_failures: 10 # failed getValue lookups per IP before 404-ing everything
window: 1m0s # sliding window for max_failures
observability:
logging:
stderr: INFO # DEBUG|INFO|WARNING|ERROR|PANIC|FATAL, empty disables
files:
INFO: ./info.log # per-level log files, optional
exporter: # optional OTLP log export
level: INFO
endpoint: http://127.0.0.1:4317/v1/logs
transport: grpc # grpc | http
metrics:
host: 127.0.0.1
port: 9092 # Prometheus /metrics endpoint
API
Full OpenAPI spec: internal/api/openapi.yaml.
When the server is running, browse it interactively at /api, or fetch the
raw spec from /api/openapi.json.
POST /api/v1/getValue{"code": "..."}→200 {"value": "..."}/404(not found or rate-limited) /400(bad body).POST /api/v1/setValue{"code": "...", "value": "..."}(Basic Auth) →204/400(bad body) /401(bad credentials).
Metrics
Exposed on http://<metrics.host>:<metrics.port>/metrics:
http_requests_total,http_request_duration_seconds— generic per-route HTTP metrics.codevault_get_value_success_total{code}— successful getValue lookups, by code.codevault_get_value_failed_total{reason}— failed lookups,reasonisnot_foundorrate_limited.codevault_set_value_success_total{user}— successful setValue writes, by authenticated login.codevault_set_value_failed_total{reason}— failed writes,reasonisbad_requestorunauthorized.
Development
make build # go build
make lint # golangci-lint
make generate # regenerate internal/api from openapi.yaml (oapi-codegen)
make test # go test ./...
make docker-build