Files
codevault/README.md
Aleksei Sokol 1ccf40396f Version 0.2.0
Changes:
- forbid to overwrite secrets of other users
- add some logs of success
- add validation on code (length 50)
- use same limiter for POST requests
2026-08-17 18:11:43 +03:00

4.0 KiB

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/401-ing get/post requests
  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 or rate-limited) / '403' (owned by other user).

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, reason is not_found or rate_limited.
  • codevault_set_value_success_total{user} — successful setValue writes, by authenticated login.
  • codevault_set_value_failed_total{reason} — failed writes, reason is bad_request or unauthorized.

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