Nodea — logo

DNS — API v1 i MCP | Dokumentacja Nodea

Moduł DNS udostępnia zarządzanie strefami i rekordami hostowanymi na naszym autorytatywnym klastrze PowerDNS: listowanie stref, podgląd strefy z pełną listą rekordów oraz tworzenie, aktualizację i usuwanie pojedynczych rekordów. Dokument opisuje warstwę REST API v1 (/api/v1/dns) oraz narzędzia MCP z tego modułu.

Uwierzytelnianie i zakresy (scopes)

API v1 uwierzytelnia się tokenem osobistym Passport przez nagłówek Authorization: Bearer <token>. Poziomy dostępu:

  • infra:read — listowanie stref i podgląd strefy z rekordami (index, show).
  • infra:write — tworzenie, aktualizacja i usuwanie rekordów. Rekord to podrzędna konfiguracja strefy, dlatego jego skasowanie NIE wymaga infra:delete (ten poziom rezerwujemy dla niszczenia całych zasobów, np. urządzeń czy serwerów).

Cały moduł jest dodatkowo bramkowany flagą Pennant features:hosting-suite — wyłączenie pakietu hostingowego ukrywa DNS zarówno w web UI, jak i w API/MCP. Limit zapytań: throttle:api-v1 = 240/min na użytkownika tokenu.

Własność i widoczność (ownership)

Model PowerDnsZone nie ma klasy polityki — dostęp na poziomie wiersza jest twardo zawężony do user_id = użytkownik tokenu. Strefa cudza, systemowa (user_id NULL, wspólna infrastruktura) lub nieznana zwraca zawsze 404 — API nigdy nie potwierdza istnienia cudzej strefy (brak enumeracji między najemcami). Parametr {record} korzysta ze scoped route binding względem {zone}, więc rekord należący do innej strefy zwraca 404 jeszcze przed wejściem do kontrolera.

Zapisy odwzorowują web UI: najpierw zapisywany jest lokalny wiersz (baza jest źródłem prawdy), następnie następuje synchroniczny push do PowerDNS. Błędy transportu są przechwytywane i logowane — nieudany push nie kończy żądania błędem, a stan doreconciliuje zadanie cykliczne.

API v1 — endpointy

MetodaŚcieżkaScopeOpis
GET/api/v1/dns/zonesinfra:readLista stref użytkownika, paginowana; z licznikiem rekordów.
GET/api/v1/dns/zones/{zone}infra:readSzczegóły strefy wraz z pełną listą rekordów (sort: type, name).
POST/api/v1/dns/zones/{zone}/recordsinfra:writeUtworzenie rekordu w strefie. Zwraca 201.
PATCH/api/v1/dns/zones/{zone}/records/{record}infra:writeCzęściowa aktualizacja rekordu (tylko przesłane pola). Scoped binding.
DELETE/api/v1/dns/zones/{zone}/records/{record}infra:writeUsunięcie rekordu (scoped binding). Zwraca 204.

GET /dns/zones — parametry zapytania

  • search (string, opcjonalny, max 255) — dopasowanie po nazwie strefy.
  • per_page (int 1–100, domyślnie 20), page (int ≥1).

Odpowiedź: kolekcja DnsZoneResource — pola: id, name, kind, serial (SOA), dnssec (bool), records_count, last_synced_at, created_at, updated_at. W show dochodzi tablica records[] (DnsRecordResource). Konfiguracja wewnętrzna strefy (masters, nsec3param, uchwyt do zdalnego PowerDNS) pozostaje po stronie serwera i nie jest serializowana.

DnsRecordResource — pola rekordu

id, zone_id, name (FQDN), type, content, ttl, priority (nullable), comment (nullable), disabled (bool), created_at, updated_at.

POST/PATCH — parametry ciała rekordu

  • name (string, max 253) — akceptuje @ (apex strefy), gołą etykietę (zostanie dopełniona nazwą strefy) lub pełny FQDN.
  • type (enum) — jeden z: A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, PTR.
  • content (string, max 1000) — adres IP, host docelowy lub wartość tekstowa.
  • ttl (int, 60–604800 s).
  • priority (int, 0–65535, opcjonalny) — dla MX/SRV.
  • comment (string, max 255, opcjonalny).
  • disabled (bool, opcjonalny) — rekord utworzony/oznaczony jako nieserwowany.

POST wymaga kompletu name/type/content/ttl. PATCH jest częściowy — zmienią się wyłącznie przesłane pola (reszta bez zmian), inaczej niż w web UI, gdzie każdorazowo repostowany jest cały rekord.

Kody błędów

  • 401 — brak/niepoprawny token.
  • 403 — brak wymaganego scope.
  • 404 — nieznana, cudza lub systemowa strefa; rekord z innej strefy (scoped binding).
  • 422 — walidacja (niedozwolony typ, TTL poza zakresem, zbyt długa nazwa/treść).

Przykłady — API

Lista stref z wyszukiwaniem

curl -s "https://app.nodea.io/api/v1/dns/zones?search=example&per_page=20" \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Accept: application/json"

Utworzenie rekordu A

curl -s -X POST https://app.nodea.io/api/v1/dns/zones/42/records \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "www",
    "type": "A",
    "content": "203.0.113.10",
    "ttl": 3600
  }'

Rekord MX z priorytetem

curl -s -X POST https://app.nodea.io/api/v1/dns/zones/42/records \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "@",
    "type": "MX",
    "content": "mail.example.com",
    "ttl": 3600,
    "priority": 10
  }'

Częściowa aktualizacja (tylko TTL)

curl -s -X PATCH https://app.nodea.io/api/v1/dns/zones/42/records/1001 \
  -H "Authorization: Bearer $NODEA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "ttl": 300 }'

MCP — narzędzia

Narzędzia MCP dzielą model uwierzytelniania i zakresów z API v1 (Bearer + scope sprawdzany w ensureScope) oraz flagę features:hosting-suite (narzędzie na nieaktywnej fladze znika z tools/list). Strefy i rekordy są adresowane po całkowitych identyfikatorach; brakujący, cudzy i systemowy identyfikator zwracają ten sam błąd (brak enumeracji między najemcami). Odpowiedzi zapisów zawierają flagę syncedfalse oznacza push odroczony do reconcilera, nie błąd.

NarzędzieScopeTrybOpis
dns-zones-listinfra:readread-onlyLista stref; filtr search, page, per_page (max 50). Zwraca id/nazwę/kind/serial/dnssec/licznik/last_synced.
dns-zone-getinfra:readread-onlyStrefa wraz z każdym rekordem (sort type, name). Param: id.
dns-record-createinfra:writezapisDodanie rekordu; zone_id, name, type, content, ttl, opcjonalnie priority/comment/disabled.
dns-record-updateinfra:writeidempotentne (pełny replace)Podmiana rekordu; name/type/content/ttl wymagane za każdym razem (odczytaj wcześniej przez dns-zone-get).
dns-record-deleteinfra:writedestrukcyjneUsunięcie rekordu; wymaga confirm: true. Nazwa przestaje się rozwiązywać natychmiast.

Przykład — MCP (JSON-RPC)

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "dns-record-create",
    "arguments": {
      "zone_id": 42,
      "name": "www",
      "type": "A",
      "content": "203.0.113.10",
      "ttl": 3600
    }
  }
}
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "dns-record-delete",
    "arguments": { "zone_id": 42, "record_id": 1001, "confirm": true }
  }
}