Gestion programmatique du DNS avec l'API IONOS
Si vous gérez plusieurs domaines et sous-domaines pour un homelab, modifier les enregistrements DNS via une interface web devient vite fastidieux. L’API DNS IONOS (anciennement 1&1) vous permet de gérer tous vos enregistrements par programmation — lister les zones, ajouter des enregistrements A/AAAA/CNAME/MX/TXT, et nettoyer les anciennes entrées.
Cet article couvre les mécanismes de l’API basés sur ma propre configuration homelab, où je gère le DNS pour trois domaines répartis sur une douzaine de sous-domaines.
Identifiants API
Les clés API IONOS se composent de deux parties :
- Un préfixe public (identifiant de type UUID)
- Une clé secrète (longue chaîne aléatoire)
Elles sont générées depuis le portail client IONOS sous Accès API. Stockez-les de manière sécurisée — elles donnent un accès complet à la gestion DNS.
Authentification
L’API utilise l’en-tête d’authentification X-API-Key. La valeur est le préfixe et le secret joints par un point :
PREFIX="your-public-prefix"
SECRET="***"
AUTH="X-API-Key: ${PREFIX}.${SECRET}"
curl -s "https://api.hosting.ionos.com/dns/v1/zones" \
-H "$AUTH" -H "Accept: application/json"
L’authentification HTTP Basic (-u prefix:secret) retourne « Missing or invalid credentials » — l’en-tête X-API-Key est la méthode correcte.
Lister les Zones DNS
curl -s "https://api.hosting.ionos.com/dns/v1/zones" \
-H "$AUTH" | jq
Réponse :
[
{
"name": "tuxvador.fr",
"id": "72f9874f-26e3-11ec-bda4-0a5864441f49",
"type": "NATIVE"
},
...
]
Chaque zone possède un ID unique utilisé pour les opérations ultérieures. Le champ type indique si le DNS est géré par IONOS (NATIVE) ou externe (MASTER/SLAVE).
Lire les Enregistrements d’une Zone
ZONE_ID="72f9874f-..."
curl -s "https://api.hosting.ionos.com/dns/v1/zones/$ZONE_ID" \
-H "$AUTH" | jq '.records[] | {name, type, content, ttl}'
Les enregistrements incluent tous les champs standard : name, rootName, type, content, ttl, disabled, et un id unique pour chaque enregistrement.
Ajouter des Enregistrements via PUT (Remplacement Complet de Zone)
La façon la plus simple d’ajouter des enregistrements est de lire la zone actuelle, modifier la liste des enregistrements, puis renvoyer la zone entière avec PUT :
import urllib.request, json
BASE = f"https://api.hosting.ionos.com/dns/v1/zones/{ZONE_ID}"
HEADERS = {"X-API-Key": f"{PREFIX}.{SECRET}", "Content-Type": "application/json"}
# Lire les enregistrements actuels
req = urllib.request.Request(BASE, headers=HEADERS)
zone = json.loads(urllib.request.urlopen(req).read())
# Ajouter un nouvel enregistrement
zone["records"].append({
"name": "api-test.tuxvador.fr",
"type": "A",
"content": "192.168.1.1",
"ttl": 60
})
# PUT la zone mise à jour
data = json.dumps(zone).encode()
req = urllib.request.Request(BASE, data=data, method="PUT", headers=HEADERS)
resp = urllib.request.urlopen(req)
Important : Le PUT remplace TOUS les enregistrements. Lisez toujours la zone d’abord, modifiez le tableau, puis réécrivez-la. Si vous omettez des enregistrements existants, ils sont supprimés.
Supprimer des Enregistrements Individuels
Pour des suppressions ciblées, utilisez le point de terminaison DELETE pour un enregistrement spécifique :
ZONE_ID = "72f9874f-..."
RECORD_ID = "ad432f9a-b097-..." # issu d'une réponse GET de zone
url = f"https://api.hosting.ionos.com/dns/v1/zones/{ZONE_ID}/records/{RECORD_ID}"
req = urllib.request.Request(url, method="DELETE", headers=HEADERS)
resp = urllib.request.urlopen(req) # HTTP 200 = succès
C’est plus propre que PUT pour supprimer des enregistrements spécifiques sans toucher au reste.
Limitations
La clé API utilisée ici a uniquement les permissions de gestion des zones DNS. La création de nouveaux enregistrements de domaine (achat de nouveaux noms de domaine) retourne UNAUTHORIZED — cela nécessite l’API Domaines ou un jeton élevé.
Opérations disponibles :
- ✅ Lister toutes les zones
- ✅ Lire tous les enregistrements d’une zone
- ✅ Ajouter des enregistrements (via PUT de zone)
- ✅ Supprimer des enregistrements individuels
- ❌ Créer de nouvelles zones DNS
- ❌ Enregistrer de nouveaux domaines
Cas d’Usage : Nettoyer d’Anciens Services
Dans ma configuration, j’avais un service Honcho fonctionnant sur un sous-domaine avec 11 enregistrements DNS (A, AAAA, MX, TXT, CNAME, autodiscover). Après avoir décommissionné le service, j’ai supprimé tous les enregistrements par programmation :
for honcho_id in record_ids:
url = f"https://api.hosting.ionos.com/dns/v1/zones/{Z}/records/{honcho_id}"
urllib.request.Request(url, method="DELETE", headers=HEADERS)
C’est beaucoup plus rapide que de cliquer dans une interface web pour une douzaine d’enregistrements.
Notes de Sécurité
- Les clés API ne peuvent pas être limitées à des domaines spécifiques — elles ont un accès complet à toutes vos zones
- Stockez la clé dans votre environnement (ex.
~/.hermes/.env) plutôt que de l’écrire en dur dans le code - Les identifiants sont réutilisables entre sessions — définissez
IONOS_API_PREFIXetIONOS_API_SECRETdans votre environnement - Les modifications DNS prennent effet immédiatement via le backend de l’API
Script de Flux de Travail Complet
Voici un script complet pour lister tous les enregistrements dans toutes vos zones :
import urllib.request, json
PREFIX = "your-prefix"
SECRET="***"
HEADERS = {"X-API-Key": f"{PREFIX}.{SECRET}"}
# Lister toutes les zones
req = urllib.request.Request(
"https://api.hosting.ionos.com/dns/v1/zones", headers=HEADERS)
zones = json.loads(urllib.request.urlopen(req).read())
for z in zones:
req = urllib.request.Request(
f"https://api.hosting.ionos.com/dns/v1/zones/{z['id']}", headers=HEADERS)
zone_data = json.loads(urllib.request.urlopen(req).read())
print(f"\n## {z['name']}")
for r in zone_data.get("records", []):
if r["type"] not in ("NS", "SOA"):
print(f" {r['name']:40s} {r['type']:6s} {r['content']:40s}")
L’API DNS IONOS est bien adaptée à l’automatisation de homelab — authentification simple, design RESTful et effet immédiat. Combinée avec CI/CD ou une tâche cron, vous pouvez gérer le DNS dynamique, la découverte de services et la documentation d’infrastructure entièrement via du code.