diff --git a/docs/api-reference.md b/docs/api-reference.md new file mode 100644 index 0000000..6b96ef4 --- /dev/null +++ b/docs/api-reference.md @@ -0,0 +1,155 @@ +# API Reference + +Complete reference for the VectorDNS Go server REST API. + +## Base URL & Authentication + +**Base URL:** `https:///api/v1` + +All requests (except `/health`) require an API key header: + +``` +X-API-Key: +``` + +Set `API_KEY` in your server environment to enable authentication. If left empty, auth is disabled (not recommended for production). + +--- + +## Endpoints + +### `POST /dns/lookup` + +Resolve DNS records for a domain. Query one or more record types in a single request. + +**Request:** + +```json +{ + "domain": "example.com", + "types": ["A", "AAAA", "MX", "TXT", "NS", "CNAME", "SOA", "CAA", "SRV"], + "nameserver": "8.8.8.8" +} +``` + +| Field | Required | Description | +|---|---|---| +| `domain` | Yes | The domain to query. | +| `types` | No | Record types to query. Defaults to all 9 supported types if omitted. | +| `nameserver` | No | Specific nameserver to query. Defaults to system resolver. | + +**Response (200):** + +```json +{ + "domain": "example.com", + "nameserver": "8.8.8.8", + "records": { + "A": [{ "value": "93.184.216.34", "ttl": 300 }], + "MX": [{ "value": "mail.example.com", "priority": 10, "ttl": 3600 }] + }, + "query_time_ms": 12 +} +``` + +--- + +### `POST /dns/propagation` + +Check DNS propagation across multiple public resolvers. Queries resolvers in parallel and compares results. + +**Request:** + +```json +{ + "domain": "example.com", + "type": "A", + "resolvers": ["8.8.8.8", "1.1.1.1", "9.9.9.9"] +} +``` + +| Field | Required | Description | +|---|---|---| +| `domain` | Yes | The domain to check. | +| `type` | Yes | The record type to check (e.g. `A`, `MX`). | +| `resolvers` | No | List of resolver IPs. Defaults to a built-in list of public resolvers. | + +**Response (200):** + +```json +{ + "domain": "example.com", + "type": "A", + "results": [ + { "resolver": "8.8.8.8", "values": ["93.184.216.34"], "ttl": 300 }, + { "resolver": "1.1.1.1", "values": ["93.184.216.34"], "ttl": 280 }, + { "resolver": "9.9.9.9", "values": ["93.184.216.34"], "ttl": 295 } + ], + "consistent": true +} +``` + +--- + +### `POST /dns/validate` + +DNSSEC validation for a domain. Checks the AD flag and verifies the signature chain. + +**Request:** + +```json +{ + "domain": "example.com" +} +``` + +| Field | Required | Description | +|---|---|---| +| `domain` | Yes | The domain to validate. | + +**Response (200):** + +```json +{ + "domain": "example.com", + "dnssec": true, + "chain_valid": true, + "details": "RRSIG verified for A record" +} +``` + +--- + +### `GET /health` + +Health check. No authentication required. Use this for uptime monitoring. + +**Response (200):** + +```json +{ + "status": "ok", + "version": "0.1.0" +} +``` + +--- + +## Error Responses + +All errors return a consistent JSON body: + +```json +{ + "error": "invalid domain", + "code": "INVALID_DOMAIN" +} +``` + +| HTTP Status | Code | Description | +|---|---|---| +| 400 | `INVALID_DOMAIN` | Malformed or missing domain | +| 400 | `INVALID_TYPE` | Unsupported record type | +| 401 | `UNAUTHORIZED` | Missing or invalid API key | +| 500 | `DNS_ERROR` | Upstream DNS query failed | +| 500 | `INTERNAL` | Unexpected server error | diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..3bacbc6 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,119 @@ +# Configuration + +All server configuration is done via environment variables or a `.env` file in the project root. + +## Example .env + +```env +PORT=8080 +API_KEY=your-secret-api-key +CORS_ORIGINS=https://yourdomain.com,https://app.yourdomain.com +LOG_FORMAT=json +``` + +Copy `.env.example` to get started: + +```bash +cp .env.example .env +``` + +--- + +## Environment Variables + +| Variable | Default | Required | Description | +|---|---|---|---| +| `PORT` | `8080` | No | Port the HTTP server listens on. | +| `API_KEY` | — | No* | Shared secret for API key auth. Auth is disabled when empty — do not leave empty in production. | +| `CORS_ORIGINS` | `http://localhost:3000` | No | Comma-separated list of allowed CORS origins. | +| `LOG_FORMAT` | `text` | No | `text` for human-readable, `json` for structured logging (recommended for production). | + +--- + +## API Key Authentication + +The Go server uses a shared API key. This is intentional: the server is an internal service called only by the Next.js backend, not directly by end users. + +When `API_KEY` is set, every request (except `GET /health`) must include: + +``` +X-API-Key: your-secret-api-key +``` + +Requests with a missing or incorrect key get `401 UNAUTHORIZED`: + +```json +{ + "error": "missing or invalid API key", + "code": "UNAUTHORIZED" +} +``` + +### Calling from Next.js + +```typescript +const res = await fetch(`${process.env.DNS_SERVER_URL}/api/v1/dns/lookup`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-API-Key": process.env.DNS_API_KEY!, + }, + body: JSON.stringify({ domain, types }), +}); +``` + +Store `DNS_API_KEY` as a secret environment variable in your Next.js deployment. Never expose it client-side. + +--- + +## CORS + +CORS is handled by [go-chi/cors](https://github.com/go-chi/cors). Configure allowed origins via `CORS_ORIGINS`. + +```env +# Development +CORS_ORIGINS=http://localhost:3000 + +# Production (single domain) +CORS_ORIGINS=https://app.yourdomain.com + +# Production (multiple domains) +CORS_ORIGINS=https://app.yourdomain.com,https://yourdomain.com +``` + +Since the Go server is an internal API called server-side by Next.js, CORS is mostly relevant for development. In production, only your Next.js server IP/domain needs access. + +--- + +## Rate Limiting + +Rate limiting is provided by [go-chi/httprate](https://github.com/go-chi/httprate) and is enabled by default. + +- Rate limiting is applied per IP address. +- Limits are enforced at the router middleware level. +- Requests exceeding the limit receive `429 Too Many Requests`. + +### Per-API-key rate limiting (planned) + +When billing tiers are added, rate limits will be enforced per API key: + +| Tier | Limit | +|---|---| +| Free | Limited requests per day, daily checks | +| Pro | Higher limits, hourly checks | +| Team | Highest limits, shared across org | + +--- + +## Redis Caching (planned) + +DNS result caching via Redis is on the roadmap. When available, the server will check Redis before querying upstream DNS, storing results with TTL-based expiry. + +Planned configuration: + +```env +REDIS_URL=redis://localhost:6379 +REDIS_TTL=300 # seconds +``` + +The cache layer will use [go-redis](https://github.com/redis/go-redis) as middleware before DNS resolution. A `docker-compose.yml` bundling the Go server with Redis will be provided for self-hosting. See [self-hosting.md](./self-hosting.md) for the planned compose configuration. diff --git a/docs/self-hosting.md b/docs/self-hosting.md new file mode 100644 index 0000000..ecbb858 --- /dev/null +++ b/docs/self-hosting.md @@ -0,0 +1,146 @@ +# Self-Hosting + +Run the VectorDNS Go server on your own VPS or infrastructure. The DNS API is a single stateless binary — no database required. + +## Prerequisites + +- **Docker** — Recommended. No Go toolchain needed on the host. +- **Go 1.22+** — Required only if building from source. +- **Port 8080** — Default port (configurable via `PORT` env var). + +--- + +## Docker (Recommended) + +### 1. Clone the repository + +```bash +git clone https://github.com/yourusername/vectordns-server.git +cd vectordns-server +``` + +### 2. Create your .env file + +```bash +cp .env.example .env +nano .env +``` + +At minimum, set `API_KEY` and `CORS_ORIGINS`. See [configuration.md](./configuration.md) for all options. + +### 3. Build the Docker image + +```bash +docker build -t vectordns-server . +``` + +### 4. Run the container + +```bash +docker run -d -p 8080:8080 --env-file .env --name vectordns-server vectordns-server +``` + +### 5. Verify it's running + +```bash +curl http://localhost:8080/api/v1/health +# {"status":"ok","version":"0.1.0"} +``` + +--- + +## From Source + +Requires Go 1.22+. + +```bash +# Install dependencies +go mod tidy + +# Configure environment +cp .env.example .env && nano .env + +# Run +go run ./cmd/server + +# Or build a binary +go build -o vectordns-server ./cmd/server +./vectordns-server +``` + +--- + +## VPS Deployment + +### Reverse proxy with nginx + +Serve the Go server behind nginx to add TLS and a clean domain path. + +```nginx +# /etc/nginx/sites-available/vectordns +server { + listen 443 ssl; + server_name api.yourdomain.com; + + location /api/ { + proxy_pass http://localhost:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } +} +``` + +### systemd service (non-Docker) + +Keep the server running across reboots without Docker. + +```ini +# /etc/systemd/system/vectordns-server.service +[Unit] +Description=VectorDNS Go Server +After=network.target + +[Service] +ExecStart=/opt/vectordns/vectordns-server +EnvironmentFile=/opt/vectordns/.env +Restart=on-failure +User=www-data + +[Install] +WantedBy=multi-user.target +``` + +```bash +sudo systemctl enable vectordns-server +sudo systemctl start vectordns-server +``` + +### docker-compose with Redis (planned) + +Once Redis caching ships, a docker-compose setup will be provided: + +```yaml +# docker-compose.yml (planned) +services: + server: + build: . + ports: + - "8080:8080" + env_file: .env + depends_on: + - redis + + redis: + image: redis:7-alpine + ports: + - "6379:6379" +``` + +--- + +## Security Checklist + +- Set a strong `API_KEY` — do not leave auth disabled in production. +- Set `CORS_ORIGINS` to your exact frontend domain, not `*`. +- Always run behind TLS (use Let's Encrypt via Certbot with nginx). +- Rate limiting is enabled by default — keep it on.