docs: expand reference pages and fix children shortcode rendering
Enable Goldmark block-level attributes so the relearn `children` shortcode applies its CSS classes instead of printing them literally in the table-of-contents pages. Also expand the deploy, plugins, records, and email reference docs and add the checks pages.
This commit is contained in:
parent
f50dcc8ba9
commit
6b6a8c847f
13 changed files with 1457 additions and 501 deletions
12
config.yml
12
config.yml
|
|
@ -62,5 +62,17 @@ params:
|
|||
- identifier: relearn-dark
|
||||
|
||||
|
||||
# The relearn theme attaches CSS classes to generated blocks (e.g. the
|
||||
# `children` shortcode appends `{class="children ..."}` after its list).
|
||||
# Goldmark only interprets that as block attributes when block parsing is
|
||||
# enabled; otherwise it is rendered as literal text.
|
||||
markup:
|
||||
goldmark:
|
||||
parser:
|
||||
attribute:
|
||||
block: true
|
||||
renderer:
|
||||
unsafe: true
|
||||
|
||||
outputs:
|
||||
home: [ "HTML", "RSS", "PRINT"]
|
||||
|
|
|
|||
|
|
@ -7,69 +7,335 @@ weight: 15
|
|||
happyDomain is sponsored by Docker.
|
||||
You'll find the official container image on [the Docker Hub](https://hub.docker.com/r/happydomain/happydomain/).
|
||||
|
||||
This image will run happyDomain as a single process, with a LevelDB database (similarly to sqlite, LevelDB is stored on disk, no need to configure anything).
|
||||
The image runs happyDomain as a single process with a LevelDB database stored on disk — no extra database to configure.
|
||||
|
||||
|
||||
## Supported tags and architectures
|
||||
|
||||
All tags are build for `amd64`, `arm64` and `arm/v7` and are based on alpine.
|
||||
All tags are built for `amd64`, `arm64` and `arm/v7` and are based on Alpine.
|
||||
|
||||
Currently, available tags are:
|
||||
Currently available tags:
|
||||
|
||||
- `latest`: this is a the most up to date version, corresponding to the master branch.
|
||||
- `latest`: the most up-to-date version, corresponding to the master branch.
|
||||
|
||||
## Using this image
|
||||
|
||||
### For testing purpose
|
||||
## Quick start (single container)
|
||||
|
||||
You can test happyDomain or use it for your own usage, with the option `HAPPYDOMAIN_NO_AUTH=1`: this will automatically creates a default account, and disable all features related to the user management (signup, login, ...).
|
||||
For a quick test or personal use, pass `HAPPYDOMAIN_NO_AUTH=1` to skip account management:
|
||||
|
||||
```
|
||||
docker run -e HAPPYDOMAIN_NO_AUTH=1 -p 8081:8081 happydomain/happydomain
|
||||
```
|
||||
|
||||
Data are stored in `/data` directory. If you want to keep your settings from one run to another, you'll need to attach this directory to a Docker managed volume or to a directory on your host:
|
||||
Data are stored inside the container. To keep them across restarts, attach a volume:
|
||||
|
||||
```
|
||||
docker volume create happydomain_data
|
||||
docker run -e HAPPYDOMAIN_NO_AUTH=1 -v happydomain_data:/data -p 8081:8081 happydomain/happydomain
|
||||
```
|
||||
|
||||
### In production
|
||||
|
||||
happyDomain needs to send e-mail, in order to verify addresses and doing password recovery, so you need basically to configure a SMTP relay.
|
||||
Use the options `HAPPYDOMAIN_MAIL_SMTP_HOST`, `HAPPYDOMAIN_MAIL_SMTP_PORT` (default 25), `HAPPYDOMAIN_MAIL_SMTP_USERNAME` and `HAPPYDOMAIN_MAIL_SMTP_PASSWORD` for this purpose:
|
||||
For a production single-container setup that sends e-mail:
|
||||
|
||||
```
|
||||
docker run -e HAPPYDOMAIN_MAIL_SMTP_HOST=smtp.yourcompany.com -e HAPPYDOMAIN_MAIL_SMTP_USERNAME=happydomain -e HAPPYDOMAIN_MAIL_SMTP_PASSWORD=secret -v /var/lib/happydomain:/data -p 8081:8081 happydomain/happydomain
|
||||
```
|
||||
|
||||
If you prefer using a configuration file, you can place it either in `/data/happydomain.conf` to use the volume, or bind your file to `/etc/happydomain.conf`:
|
||||
|
||||
```
|
||||
docker run -v happydomain.conf:/etc/happydomain.conf -p 8081:8081 happydomain/happydomain
|
||||
```
|
||||
|
||||
#### Extend the base image
|
||||
|
||||
By default, happyDomain uses `sendmail`, if you prefer, you can create you own image with the package `ssmtp`:
|
||||
|
||||
```
|
||||
FROM happydomain/happydomain
|
||||
RUN apk --no-cache add ssmtp
|
||||
COPY my_ssmtp.conf /etc/ssmtp/ssmtp.conf
|
||||
docker run \
|
||||
-e HAPPYDOMAIN_MAIL_SMTP_HOST=smtp.yourcompany.com \
|
||||
-e HAPPYDOMAIN_MAIL_SMTP_USERNAME=happydomain \
|
||||
-e HAPPYDOMAIN_MAIL_SMTP_PASSWORD=secret \
|
||||
-v /var/lib/happydomain:/data \
|
||||
-p 8081:8081 \
|
||||
happydomain/happydomain
|
||||
```
|
||||
|
||||
|
||||
## Admin Interface
|
||||
## Full deployment with all checkers
|
||||
|
||||
happyDomain exposes some administration command through a unix socket. The docker container contains a script to access this admin part: `hadmin`.
|
||||
happyDomain ships every checker built-in, but several of them rely on
|
||||
external tools (DNSViz, Zonemaster, Matrix federation tester) that are
|
||||
packaged in their own container images. Running these as separate services
|
||||
gives you the full checker experience and better isolation.
|
||||
|
||||
You can use it this way:
|
||||
The recommended approach is `docker compose`. Save the following file as
|
||||
`docker-compose.yml` and run `docker compose up -d`.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
happydomain:
|
||||
image: happydomain/happydomain
|
||||
ports:
|
||||
- "8080:8081"
|
||||
environment:
|
||||
# Uncomment for single-user / testing
|
||||
# HAPPYDOMAIN_NO_AUTH: "1"
|
||||
|
||||
# Mail configuration (required for multi-user production use)
|
||||
# HAPPYDOMAIN_MAIL_SMTP_HOST: "mailer"
|
||||
|
||||
# ── DNS / DNSSEC ─────────────────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_DNSVIZ_ENDPOINT: "http://checker-dnsviz:8080"
|
||||
HAPPYDOMAIN_CHECKER_DNSSEC_ENDPOINT: "http://checker-dnssec:8080"
|
||||
HAPPYDOMAIN_CHECKER_ZONEMASTER_ENDPOINT: "http://checker-zonemaster:8080"
|
||||
HAPPYDOMAIN_CHECKER_ZONEMASTER_ZONEMASTERAPIURL: "http://zonemaster:5000"
|
||||
HAPPYDOMAIN_CHECKER_DELEGATION_ENDPOINT: "http://checker-delegation:8080"
|
||||
HAPPYDOMAIN_CHECKER_AUTHORITATIVE_CONSISTENCY_ENDPOINT: "http://checker-authoritative-consistency:8080"
|
||||
HAPPYDOMAIN_CHECKER_ALIAS_ENDPOINT: "http://checker-alias:8080"
|
||||
HAPPYDOMAIN_CHECKER_LEGACY_RECORDS_ENDPOINT: "http://checker-legacy-records:8080"
|
||||
HAPPYDOMAIN_CHECKER_NS_RESTRICTIONS_ENDPOINT: "http://checker-ns-restrictions:8080"
|
||||
HAPPYDOMAIN_CHECKER_RESOLVER_PROPAGATION_ENDPOINT: "http://checker-resolver-propagation:8080"
|
||||
HAPPYDOMAIN_CHECKER_REVERSE_ZONE_ENDPOINT: "http://checker-reverse-zone:8080"
|
||||
HAPPYDOMAIN_CHECKER_PTR_ENDPOINT: "http://checker-ptr:8080"
|
||||
HAPPYDOMAIN_CHECKER_DANGLING_ENDPOINT: "http://checker-dangling:8080"
|
||||
|
||||
# ── Security / Certificates ───────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_TLS_ENDPOINT: "http://checker-tls:8080"
|
||||
HAPPYDOMAIN_CHECKER_DANE_ENDPOINT: "http://checker-dane:8080"
|
||||
HAPPYDOMAIN_CHECKER_CAA_ENDPOINT: "http://checker-caa:8080"
|
||||
HAPPYDOMAIN_CHECKER_BLACKLIST_ENDPOINT: "http://checker-blacklist:8080"
|
||||
|
||||
# ── E-mail ────────────────────────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_SMTP_ENDPOINT: "http://checker-smtp:8080"
|
||||
HAPPYDOMAIN_CHECKER_EMAIL_AUTOCONFIG_ENDPOINT: "http://checker-email-autoconfig:8080"
|
||||
HAPPYDOMAIN_CHECKER_OPENPGPKEY_SMIMEA_ENDPOINT: "http://checker-email-keys:8080"
|
||||
|
||||
# ── Web & Protocols ───────────────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_HTTP_ENDPOINT: "http://checker-http:8080"
|
||||
HAPPYDOMAIN_CHECKER_SSH_ENDPOINT: "http://checker-ssh:8080"
|
||||
HAPPYDOMAIN_CHECKER_PING_ENDPOINT: "http://checker-ping:8080"
|
||||
HAPPYDOMAIN_CHECKER_SRV_ENDPOINT: "http://checker-srv:8080"
|
||||
|
||||
# ── Collaboration / Messaging ─────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_MATRIXIM_ENDPOINT: "http://checker-matrix:8080"
|
||||
HAPPYDOMAIN_CHECKER_MATRIXIM_FEDERATIONTESTERSERVER: "http://matrixfederationtester:8080/api/report?server_name=%s"
|
||||
HAPPYDOMAIN_CHECKER_XMPP_ENDPOINT: "http://checker-xmpp:8080"
|
||||
HAPPYDOMAIN_CHECKER_SIP_ENDPOINT: "http://checker-sip:8080"
|
||||
|
||||
# ── Directory & Auth ──────────────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_LDAP_ENDPOINT: "http://checker-ldap:8080"
|
||||
HAPPYDOMAIN_CHECKER_KERBEROS_ENDPOINT: "http://checker-kerberos:8080"
|
||||
HAPPYDOMAIN_CHECKER_STUNTURN_ENDPOINT: "http://checker-stun-turn:8080"
|
||||
|
||||
# ── CalDAV / CardDAV ──────────────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_CALDAV_ENDPOINT: "http://checker-caldav:8080"
|
||||
HAPPYDOMAIN_CHECKER_CARDDAV_ENDPOINT: "http://checker-carddav:8080"
|
||||
|
||||
# ── Optional: happyDeliver integration ────────────────────────────────
|
||||
# HAPPYDOMAIN_CHECKER_HAPPYDELIVER_ENDPOINT: "http://checker-happydeliver:8080"
|
||||
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- storage:/var/lib/happydomain:rw
|
||||
|
||||
# ── DNS / DNSSEC checkers ──────────────────────────────────────────────────
|
||||
|
||||
checker-dnsviz:
|
||||
image: happydomain/checker-dnsviz
|
||||
restart: unless-stopped
|
||||
|
||||
checker-dnssec:
|
||||
image: happydomain/checker-dnssec
|
||||
restart: unless-stopped
|
||||
|
||||
checker-zonemaster:
|
||||
image: happydomain/checker-zonemaster
|
||||
restart: unless-stopped
|
||||
|
||||
zonemaster:
|
||||
image: zonemaster/backend
|
||||
command: full
|
||||
restart: unless-stopped
|
||||
|
||||
checker-delegation:
|
||||
image: happydomain/checker-delegation
|
||||
restart: unless-stopped
|
||||
|
||||
checker-authoritative-consistency:
|
||||
image: happydomain/checker-authoritative-consistency
|
||||
restart: unless-stopped
|
||||
|
||||
checker-alias:
|
||||
image: happydomain/checker-alias
|
||||
restart: unless-stopped
|
||||
|
||||
checker-legacy-records:
|
||||
image: happydomain/checker-legacy-records
|
||||
restart: unless-stopped
|
||||
|
||||
checker-ns-restrictions:
|
||||
image: happydomain/checker-ns-restrictions
|
||||
restart: unless-stopped
|
||||
|
||||
checker-resolver-propagation:
|
||||
image: happydomain/checker-resolver-propagation
|
||||
restart: unless-stopped
|
||||
|
||||
checker-reverse-zone:
|
||||
image: happydomain/checker-reverse-zone
|
||||
restart: unless-stopped
|
||||
|
||||
checker-ptr:
|
||||
image: happydomain/checker-ptr
|
||||
restart: unless-stopped
|
||||
|
||||
checker-dangling:
|
||||
image: happydomain/checker-dangling
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Security / Certificate checkers ───────────────────────────────────────
|
||||
|
||||
checker-tls:
|
||||
image: happydomain/checker-tls
|
||||
restart: unless-stopped
|
||||
|
||||
checker-dane:
|
||||
image: happydomain/checker-dane
|
||||
restart: unless-stopped
|
||||
|
||||
checker-caa:
|
||||
image: happydomain/checker-caa
|
||||
restart: unless-stopped
|
||||
|
||||
checker-blacklist:
|
||||
image: happydomain/checker-blacklist
|
||||
restart: unless-stopped
|
||||
|
||||
# ── E-mail checkers ────────────────────────────────────────────────────────
|
||||
|
||||
checker-smtp:
|
||||
image: happydomain/checker-smtp
|
||||
restart: unless-stopped
|
||||
|
||||
checker-email-autoconfig:
|
||||
image: happydomain/checker-email-autoconfig
|
||||
restart: unless-stopped
|
||||
|
||||
checker-email-keys:
|
||||
image: happydomain/checker-email-keys
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Web & Protocol checkers ────────────────────────────────────────────────
|
||||
|
||||
checker-http:
|
||||
image: happydomain/checker-http
|
||||
restart: unless-stopped
|
||||
|
||||
checker-ssh:
|
||||
image: happydomain/checker-ssh
|
||||
restart: unless-stopped
|
||||
|
||||
checker-ping:
|
||||
image: happydomain/checker-ping
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
- NET_RAW # required for ICMP ping
|
||||
|
||||
checker-srv:
|
||||
image: happydomain/checker-srv
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Collaboration / Messaging checkers ─────────────────────────────────────
|
||||
|
||||
checker-matrix:
|
||||
image: happydomain/checker-matrix
|
||||
restart: unless-stopped
|
||||
|
||||
matrixfederationtester:
|
||||
image: matrixdotorg/federation-tester-backend
|
||||
environment:
|
||||
BIND_ADDRESS: "0.0.0.0:8080"
|
||||
restart: unless-stopped
|
||||
|
||||
checker-xmpp:
|
||||
image: happydomain/checker-xmpp
|
||||
restart: unless-stopped
|
||||
|
||||
checker-sip:
|
||||
image: happydomain/checker-sip
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Directory & Auth checkers ──────────────────────────────────────────────
|
||||
|
||||
checker-ldap:
|
||||
image: happydomain/checker-ldap
|
||||
restart: unless-stopped
|
||||
|
||||
checker-kerberos:
|
||||
image: happydomain/checker-kerberos
|
||||
restart: unless-stopped
|
||||
|
||||
checker-stun-turn:
|
||||
image: happydomain/checker-stun-turn
|
||||
restart: unless-stopped
|
||||
|
||||
# ── CalDAV / CardDAV checkers ──────────────────────────────────────────────
|
||||
|
||||
checker-caldav:
|
||||
image: happydomain/checker-caldav
|
||||
restart: unless-stopped
|
||||
|
||||
checker-carddav:
|
||||
image: happydomain/checker-carddav
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
storage:
|
||||
```
|
||||
|
||||
### How it works
|
||||
|
||||
Each checker runs as a standalone HTTP service. happyDomain delegates check
|
||||
requests to the matching container via the `HAPPYDOMAIN_CHECKER_<ID>_ENDPOINT`
|
||||
environment variable. When an endpoint is not set, the corresponding checker
|
||||
runs locally inside the happyDomain process instead.
|
||||
|
||||
Two checkers rely on additional third-party backends:
|
||||
|
||||
- **Zonemaster** (`checker-zonemaster`) queries the `zonemaster/backend`
|
||||
service. The `HAPPYDOMAIN_CHECKER_ZONEMASTER_ZONEMASTERAPIURL` variable tells
|
||||
the checker where that backend listens.
|
||||
- **Matrix federation tester** (`checker-matrix`) queries the
|
||||
`matrixdotorg/federation-tester-backend` service. The
|
||||
`HAPPYDOMAIN_CHECKER_MATRIXIM_FEDERATIONTESTERSERVER` variable points to its
|
||||
report endpoint.
|
||||
|
||||
### Optional: happyDeliver
|
||||
|
||||
If you run a [happyDeliver](https://happydeliver.io) instance for mail-flow
|
||||
monitoring, uncomment the `HAPPYDOMAIN_CHECKER_HAPPYDELIVER_ENDPOINT` line and
|
||||
add the corresponding service:
|
||||
|
||||
```yaml
|
||||
checker-happydeliver:
|
||||
image: happydomain/checker-happydeliver
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
### Optional: blacklist API keys
|
||||
|
||||
The `checker-blacklist` service works without API keys (it uses DNS-based
|
||||
blocklists by default), but you can enable additional sources — Google Safe
|
||||
Browsing, VirusTotal, abuse.ch URLhaus — by configuring the matching admin
|
||||
options from the happyDomain administration interface once the stack is running.
|
||||
|
||||
|
||||
## Admin interface
|
||||
|
||||
happyDomain exposes administration commands through a Unix socket. The
|
||||
container includes the `hadmin` wrapper:
|
||||
|
||||
```
|
||||
docker exec my_container hadmin /api/users
|
||||
docker exec my_container hadmin /api/users/0123456789/send_validation_email -X POST
|
||||
```
|
||||
|
||||
This is in fact a wrapper above `curl`, but you have to start by the URL, and place options after it.
|
||||
`hadmin` is a thin wrapper around `curl` — start with the URL path, then add
|
||||
any `curl` options after it.
|
||||
|
||||
|
||||
## Using a configuration file
|
||||
|
||||
Instead of environment variables, you can place a configuration file either in
|
||||
`/data/happydomain.conf` (inside the data volume) or bind-mount it to
|
||||
`/etc/happydomain.conf`:
|
||||
|
||||
```
|
||||
docker run -v happydomain.conf:/etc/happydomain.conf -p 8081:8081 happydomain/happydomain
|
||||
```
|
||||
|
|
|
|||
|
|
@ -4,78 +4,340 @@ title: Avec Docker
|
|||
weight: 15
|
||||
---
|
||||
|
||||
happyDomain est sponsorisé Docker.
|
||||
happyDomain est sponsorisé par Docker.
|
||||
Vous trouverez notre image officielle sur [le Docker Hub](https://hub.docker.com/r/happydomain/happydomain/).
|
||||
|
||||
Cette image exécutera happyDomain en tant que processus unique, avec une base de données LevelDB (similaire à sqlite, LevelDB est une base de données stockée sur le disque, il n'est pas nécessaire de configurer quoi que ce soit d'autre).
|
||||
L'image exécute happyDomain en tant que processus unique avec une base de données LevelDB stockée sur le disque — aucune base de données supplémentaire à configurer.
|
||||
|
||||
|
||||
## Versions, étiquettes and architectures supportés
|
||||
## Versions, étiquettes et architectures supportées
|
||||
|
||||
Toutes les étiquettes (*tags*) sont construites pour les architectures de processeur les plus courantes (`amd64`, `arm64` et `arm/v7`).
|
||||
Nous ne construisons des images uniquement basées sur la distribution Alpine Linux, ce qui assure des images de taille minimale.
|
||||
Toutes les étiquettes (*tags*) sont construites pour `amd64`, `arm64` et `arm/v7` et sont basées sur Alpine.
|
||||
|
||||
Actuellement, les étiquettes disponibles sont :
|
||||
Les étiquettes actuellement disponibles :
|
||||
|
||||
- `latest`: il s'agit de la version la plus récente, correspondant à la branche `master` de notre dépôt de sources.
|
||||
- `latest` : la version la plus récente, correspondant à la branche `master` de notre dépôt.
|
||||
|
||||
|
||||
## Utilisation de l'image
|
||||
## Démarrage rapide (conteneur unique)
|
||||
|
||||
### À des fins de test
|
||||
|
||||
Vous pouvez tester happyDomain ou l'utiliser pour votre usage personnel, avec l'option `HAPPYDOMAIN_NO_AUTH=1` : cela créera automatiquement un compte par défaut, et désactivera toutes les fonctionnalités liées à la gestion des utilisateurs (inscription, connexion, ...).
|
||||
Pour un test rapide ou un usage personnel, utilisez `HAPPYDOMAIN_NO_AUTH=1` pour désactiver la gestion des comptes :
|
||||
|
||||
```
|
||||
docker run -e HAPPYDOMAIN_NO_AUTH=1 -p 8081:8081 happydomain/happydomain
|
||||
```
|
||||
|
||||
Les données sont stockées dans le répertoire `/data`.
|
||||
Si vous souhaitez conserver vos paramètres d'une exécution à l'autre, vous devrez attacher ce répertoire à un volume géré par Docker ou à un répertoire sur votre hôte :
|
||||
Les données sont stockées à l'intérieur du conteneur. Pour les conserver entre les redémarrages, attachez un volume :
|
||||
|
||||
```
|
||||
docker volume create happydomain_data
|
||||
docker run -e HAPPYDOMAIN_NO_AUTH=1 -v happydomain_data:/data -p 8081:8081 happydomain/happydomain
|
||||
```
|
||||
|
||||
|
||||
### En production
|
||||
|
||||
happyDomain a besoin d'envoyer du courrier électronique, afin de vérifier les adresses et d'effectuer la récupération des mots de passe, vous devez donc configurer un relais SMTP.
|
||||
Utilisez les options `HAPPYDOMAIN_MAIL_SMTP_HOST`, `HAPPYDOMAIN_MAIL_SMTP_PORT` (par défaut 25), `HAPPYDOMAIN_MAIL_SMTP_USERNAME` et `HAPPYDOMAIN_MAIL_SMTP_PASSWORD` à cette fin :
|
||||
Pour une instance de production avec envoi d'e-mails :
|
||||
|
||||
```
|
||||
docker run -e HAPPYDOMAIN_MAIL_SMTP_HOST=smtp.yourcompany.com -e HAPPYDOMAIN_MAIL_SMTP_USERNAME=happydomain -e HAPPYDOMAIN_MAIL_SMTP_PASSWORD=secret -v /var/lib/happydomain:/data -p 8081:8081 happydomain/happydomain
|
||||
```
|
||||
|
||||
Si vous préférez utiliser un fichier de configuration, vous pouvez le placer soit dans `/data/happydomain.conf` pour utiliser le volume, soit lier votre fichier à `/etc/happydomain.conf` :
|
||||
|
||||
```
|
||||
docker run -v happydomain.conf:/etc/happydomain.conf -p 8081:8081 happydomain/happydomain
|
||||
docker run \
|
||||
-e HAPPYDOMAIN_MAIL_SMTP_HOST=smtp.votreentreprise.com \
|
||||
-e HAPPYDOMAIN_MAIL_SMTP_USERNAME=happydomain \
|
||||
-e HAPPYDOMAIN_MAIL_SMTP_PASSWORD=secret \
|
||||
-v /var/lib/happydomain:/data \
|
||||
-p 8081:8081 \
|
||||
happydomain/happydomain
|
||||
```
|
||||
|
||||
|
||||
#### Étendre l'image de base
|
||||
## Déploiement complet avec tous les vérificateurs
|
||||
|
||||
Par défaut, happyDomain utilise `sendmail`, si vous préférez, vous pouvez créer votre propre image avec le paquet `ssmtp` :
|
||||
happyDomain intègre tous les vérificateurs (*checkers*) en natif, mais certains
|
||||
d'entre eux s'appuient sur des outils externes (DNSViz, Zonemaster, Matrix
|
||||
federation tester) distribués dans leurs propres images Docker. Les faire
|
||||
tourner comme des services séparés vous donne l'expérience complète des
|
||||
vérificateurs et une meilleure isolation.
|
||||
|
||||
L'approche recommandée est `docker compose`. Enregistrez le fichier suivant
|
||||
sous le nom `docker-compose.yml` et lancez `docker compose up -d`.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
happydomain:
|
||||
image: happydomain/happydomain
|
||||
ports:
|
||||
- "8080:8081"
|
||||
environment:
|
||||
# Décommentez pour un usage mono-utilisateur / test
|
||||
# HAPPYDOMAIN_NO_AUTH: "1"
|
||||
|
||||
# Configuration mail (obligatoire en production multi-utilisateurs)
|
||||
# HAPPYDOMAIN_MAIL_SMTP_HOST: "mailer"
|
||||
|
||||
# ── DNS / DNSSEC ─────────────────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_DNSVIZ_ENDPOINT: "http://checker-dnsviz:8080"
|
||||
HAPPYDOMAIN_CHECKER_DNSSEC_ENDPOINT: "http://checker-dnssec:8080"
|
||||
HAPPYDOMAIN_CHECKER_ZONEMASTER_ENDPOINT: "http://checker-zonemaster:8080"
|
||||
HAPPYDOMAIN_CHECKER_ZONEMASTER_ZONEMASTERAPIURL: "http://zonemaster:5000"
|
||||
HAPPYDOMAIN_CHECKER_DELEGATION_ENDPOINT: "http://checker-delegation:8080"
|
||||
HAPPYDOMAIN_CHECKER_AUTHORITATIVE_CONSISTENCY_ENDPOINT: "http://checker-authoritative-consistency:8080"
|
||||
HAPPYDOMAIN_CHECKER_ALIAS_ENDPOINT: "http://checker-alias:8080"
|
||||
HAPPYDOMAIN_CHECKER_LEGACY_RECORDS_ENDPOINT: "http://checker-legacy-records:8080"
|
||||
HAPPYDOMAIN_CHECKER_NS_RESTRICTIONS_ENDPOINT: "http://checker-ns-restrictions:8080"
|
||||
HAPPYDOMAIN_CHECKER_RESOLVER_PROPAGATION_ENDPOINT: "http://checker-resolver-propagation:8080"
|
||||
HAPPYDOMAIN_CHECKER_REVERSE_ZONE_ENDPOINT: "http://checker-reverse-zone:8080"
|
||||
HAPPYDOMAIN_CHECKER_PTR_ENDPOINT: "http://checker-ptr:8080"
|
||||
HAPPYDOMAIN_CHECKER_DANGLING_ENDPOINT: "http://checker-dangling:8080"
|
||||
|
||||
# ── Sécurité / Certificats ────────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_TLS_ENDPOINT: "http://checker-tls:8080"
|
||||
HAPPYDOMAIN_CHECKER_DANE_ENDPOINT: "http://checker-dane:8080"
|
||||
HAPPYDOMAIN_CHECKER_CAA_ENDPOINT: "http://checker-caa:8080"
|
||||
HAPPYDOMAIN_CHECKER_BLACKLIST_ENDPOINT: "http://checker-blacklist:8080"
|
||||
|
||||
# ── E-mail ────────────────────────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_SMTP_ENDPOINT: "http://checker-smtp:8080"
|
||||
HAPPYDOMAIN_CHECKER_EMAIL_AUTOCONFIG_ENDPOINT: "http://checker-email-autoconfig:8080"
|
||||
HAPPYDOMAIN_CHECKER_OPENPGPKEY_SMIMEA_ENDPOINT: "http://checker-email-keys:8080"
|
||||
|
||||
# ── Web & Protocoles ──────────────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_HTTP_ENDPOINT: "http://checker-http:8080"
|
||||
HAPPYDOMAIN_CHECKER_SSH_ENDPOINT: "http://checker-ssh:8080"
|
||||
HAPPYDOMAIN_CHECKER_PING_ENDPOINT: "http://checker-ping:8080"
|
||||
HAPPYDOMAIN_CHECKER_SRV_ENDPOINT: "http://checker-srv:8080"
|
||||
|
||||
# ── Collaboration / Messagerie ────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_MATRIXIM_ENDPOINT: "http://checker-matrix:8080"
|
||||
HAPPYDOMAIN_CHECKER_MATRIXIM_FEDERATIONTESTERSERVER: "http://matrixfederationtester:8080/api/report?server_name=%s"
|
||||
HAPPYDOMAIN_CHECKER_XMPP_ENDPOINT: "http://checker-xmpp:8080"
|
||||
HAPPYDOMAIN_CHECKER_SIP_ENDPOINT: "http://checker-sip:8080"
|
||||
|
||||
# ── Annuaire & Authentification ───────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_LDAP_ENDPOINT: "http://checker-ldap:8080"
|
||||
HAPPYDOMAIN_CHECKER_KERBEROS_ENDPOINT: "http://checker-kerberos:8080"
|
||||
HAPPYDOMAIN_CHECKER_STUNTURN_ENDPOINT: "http://checker-stun-turn:8080"
|
||||
|
||||
# ── CalDAV / CardDAV ──────────────────────────────────────────────────
|
||||
HAPPYDOMAIN_CHECKER_CALDAV_ENDPOINT: "http://checker-caldav:8080"
|
||||
HAPPYDOMAIN_CHECKER_CARDDAV_ENDPOINT: "http://checker-carddav:8080"
|
||||
|
||||
# ── Optionnel : intégration happyDeliver ──────────────────────────────
|
||||
# HAPPYDOMAIN_CHECKER_HAPPYDELIVER_ENDPOINT: "http://checker-happydeliver:8080"
|
||||
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- storage:/var/lib/happydomain:rw
|
||||
|
||||
# ── Vérificateurs DNS / DNSSEC ─────────────────────────────────────────────
|
||||
|
||||
checker-dnsviz:
|
||||
image: happydomain/checker-dnsviz
|
||||
restart: unless-stopped
|
||||
|
||||
checker-dnssec:
|
||||
image: happydomain/checker-dnssec
|
||||
restart: unless-stopped
|
||||
|
||||
checker-zonemaster:
|
||||
image: happydomain/checker-zonemaster
|
||||
restart: unless-stopped
|
||||
|
||||
zonemaster:
|
||||
image: zonemaster/backend
|
||||
command: full
|
||||
restart: unless-stopped
|
||||
|
||||
checker-delegation:
|
||||
image: happydomain/checker-delegation
|
||||
restart: unless-stopped
|
||||
|
||||
checker-authoritative-consistency:
|
||||
image: happydomain/checker-authoritative-consistency
|
||||
restart: unless-stopped
|
||||
|
||||
checker-alias:
|
||||
image: happydomain/checker-alias
|
||||
restart: unless-stopped
|
||||
|
||||
checker-legacy-records:
|
||||
image: happydomain/checker-legacy-records
|
||||
restart: unless-stopped
|
||||
|
||||
checker-ns-restrictions:
|
||||
image: happydomain/checker-ns-restrictions
|
||||
restart: unless-stopped
|
||||
|
||||
checker-resolver-propagation:
|
||||
image: happydomain/checker-resolver-propagation
|
||||
restart: unless-stopped
|
||||
|
||||
checker-reverse-zone:
|
||||
image: happydomain/checker-reverse-zone
|
||||
restart: unless-stopped
|
||||
|
||||
checker-ptr:
|
||||
image: happydomain/checker-ptr
|
||||
restart: unless-stopped
|
||||
|
||||
checker-dangling:
|
||||
image: happydomain/checker-dangling
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Vérificateurs Sécurité / Certificats ───────────────────────────────────
|
||||
|
||||
checker-tls:
|
||||
image: happydomain/checker-tls
|
||||
restart: unless-stopped
|
||||
|
||||
checker-dane:
|
||||
image: happydomain/checker-dane
|
||||
restart: unless-stopped
|
||||
|
||||
checker-caa:
|
||||
image: happydomain/checker-caa
|
||||
restart: unless-stopped
|
||||
|
||||
checker-blacklist:
|
||||
image: happydomain/checker-blacklist
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Vérificateurs e-mail ────────────────────────────────────────────────────
|
||||
|
||||
checker-smtp:
|
||||
image: happydomain/checker-smtp
|
||||
restart: unless-stopped
|
||||
|
||||
checker-email-autoconfig:
|
||||
image: happydomain/checker-email-autoconfig
|
||||
restart: unless-stopped
|
||||
|
||||
checker-email-keys:
|
||||
image: happydomain/checker-email-keys
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Vérificateurs Web & Protocoles ─────────────────────────────────────────
|
||||
|
||||
checker-http:
|
||||
image: happydomain/checker-http
|
||||
restart: unless-stopped
|
||||
|
||||
checker-ssh:
|
||||
image: happydomain/checker-ssh
|
||||
restart: unless-stopped
|
||||
|
||||
checker-ping:
|
||||
image: happydomain/checker-ping
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
- NET_RAW # requis pour l'ICMP
|
||||
|
||||
checker-srv:
|
||||
image: happydomain/checker-srv
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Vérificateurs Collaboration / Messagerie ────────────────────────────────
|
||||
|
||||
checker-matrix:
|
||||
image: happydomain/checker-matrix
|
||||
restart: unless-stopped
|
||||
|
||||
matrixfederationtester:
|
||||
image: matrixdotorg/federation-tester-backend
|
||||
environment:
|
||||
BIND_ADDRESS: "0.0.0.0:8080"
|
||||
restart: unless-stopped
|
||||
|
||||
checker-xmpp:
|
||||
image: happydomain/checker-xmpp
|
||||
restart: unless-stopped
|
||||
|
||||
checker-sip:
|
||||
image: happydomain/checker-sip
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Vérificateurs Annuaire & Authentification ───────────────────────────────
|
||||
|
||||
checker-ldap:
|
||||
image: happydomain/checker-ldap
|
||||
restart: unless-stopped
|
||||
|
||||
checker-kerberos:
|
||||
image: happydomain/checker-kerberos
|
||||
restart: unless-stopped
|
||||
|
||||
checker-stun-turn:
|
||||
image: happydomain/checker-stun-turn
|
||||
restart: unless-stopped
|
||||
|
||||
# ── Vérificateurs CalDAV / CardDAV ─────────────────────────────────────────
|
||||
|
||||
checker-caldav:
|
||||
image: happydomain/checker-caldav
|
||||
restart: unless-stopped
|
||||
|
||||
checker-carddav:
|
||||
image: happydomain/checker-carddav
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
storage:
|
||||
```
|
||||
FROM happydomain/happydomain
|
||||
RUN apk --no-cache add ssmtp
|
||||
COPY my_ssmtp.conf /etc/ssmtp/ssmtp.conf
|
||||
|
||||
### Comment ça fonctionne
|
||||
|
||||
Chaque vérificateur tourne comme un service HTTP autonome. happyDomain lui délègue
|
||||
les demandes de vérification via la variable d'environnement
|
||||
`HAPPYDOMAIN_CHECKER_<ID>_ENDPOINT`. Si aucun point d'accès n'est configuré, le
|
||||
vérificateur correspondant s'exécute localement dans le processus happyDomain.
|
||||
|
||||
Deux vérificateurs s'appuient sur des services tiers supplémentaires :
|
||||
|
||||
- **Zonemaster** (`checker-zonemaster`) interroge le service `zonemaster/backend`.
|
||||
La variable `HAPPYDOMAIN_CHECKER_ZONEMASTER_ZONEMASTERAPIURL` indique au
|
||||
vérificateur l'adresse de ce service.
|
||||
- **Matrix federation tester** (`checker-matrix`) interroge le service
|
||||
`matrixdotorg/federation-tester-backend`. La variable
|
||||
`HAPPYDOMAIN_CHECKER_MATRIXIM_FEDERATIONTESTERSERVER` pointe vers son point
|
||||
d'accès de rapport.
|
||||
|
||||
### Optionnel : happyDeliver
|
||||
|
||||
Si vous exploitez une instance [happyDeliver](https://happydeliver.io) pour
|
||||
surveiller les flux e-mail, décommentez la ligne
|
||||
`HAPPYDOMAIN_CHECKER_HAPPYDELIVER_ENDPOINT` et ajoutez le service correspondant :
|
||||
|
||||
```yaml
|
||||
checker-happydeliver:
|
||||
image: happydomain/checker-happydeliver
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
### Optionnel : clés API pour checker-blacklist
|
||||
|
||||
Le service `checker-blacklist` fonctionne sans clé API (il utilise des listes
|
||||
de blocage DNS par défaut), mais vous pouvez activer des sources supplémentaires
|
||||
— Google Safe Browsing, VirusTotal, abuse.ch URLhaus — en configurant les
|
||||
options d'administration correspondantes depuis l'interface d'administration de
|
||||
happyDomain une fois la pile démarrée.
|
||||
|
||||
|
||||
## Interface d'administration
|
||||
|
||||
happyDomain expose certaines commandes d'administration à travers un socket unix.
|
||||
Le conteneur docker contient un script pour accéder à cette partie d'administration : `hadmin`.
|
||||
|
||||
Vous pouvez l'utiliser de cette manière :
|
||||
happyDomain expose des commandes d'administration à travers un socket Unix.
|
||||
Le conteneur inclut l'utilitaire `hadmin` :
|
||||
|
||||
```
|
||||
docker exec my_container hadmin /api/users
|
||||
docker exec my_container hadmin /api/users/0123456789/send_validation_email -X POST
|
||||
```
|
||||
|
||||
Il s'agit en fait d'une surcouche au-dessus de `curl`, mais vous devez commencer par l'URL, et placer les options après.
|
||||
`hadmin` est une surcouche légère autour de `curl` — commencez par le chemin
|
||||
d'URL, puis ajoutez les options `curl` après.
|
||||
|
||||
|
||||
## Utilisation d'un fichier de configuration
|
||||
|
||||
Plutôt que des variables d'environnement, vous pouvez placer un fichier de
|
||||
configuration dans `/data/happydomain.conf` (dans le volume de données) ou le
|
||||
monter directement sur `/etc/happydomain.conf` :
|
||||
|
||||
```
|
||||
docker run -v happydomain.conf:/etc/happydomain.conf -p 8081:8081 happydomain/happydomain
|
||||
```
|
||||
|
|
|
|||
174
content/pages/checks.en.md
Normal file
174
content/pages/checks.en.md
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
---
|
||||
date: 2026-04-05T12:00:00+02:00
|
||||
title: Monitoring & Checks
|
||||
author: nemunaire
|
||||
weight: 35
|
||||
description: "Set up automated health checks to monitor your domains and services"
|
||||
---
|
||||
|
||||
happyDomain includes a built-in monitoring system that lets you run automated health checks on your domains and services. Checkers periodically collect data (such as ping response times, domain expiry dates, or DNS audit results), evaluate it against thresholds you define, and report a clear status: OK, Warning, Critical, or Error.
|
||||
|
||||
## Browsing available checkers
|
||||
|
||||
You can see all available checkers by navigating to the **Checkers** page from the main menu.
|
||||
|
||||
<!-- TODO: screenshot of the checkers list page -->
|
||||
|
||||
Each checker is labelled with the scope it applies to:
|
||||
|
||||
- **Domain-level**: checks that concern the domain itself, independent of DNS records (e.g. domain expiry via WHOIS).
|
||||
- **Zone-level**: checks that need the full zone content (e.g. DNSSEC validation).
|
||||
- **Service-level**: checks that target a specific service on a subdomain (e.g. ping, HTTP check).
|
||||
|
||||
Use the search bar to filter checkers by name. Click on a checker to see its description and configuration options.
|
||||
|
||||
|
||||
## Configuring a checker for your domain
|
||||
|
||||
To set up a checker on one of your domains:
|
||||
|
||||
1. Go to your domain's page and open the **Checks** tab.
|
||||
2. You will see a table of checkers available for this domain. Click **Configure** next to the checker you want to set up.
|
||||
|
||||
<!-- TODO: screenshot of the domain checks list -->
|
||||
|
||||
On the configuration page, you will find several sections:
|
||||
|
||||
### Checker options
|
||||
|
||||
Options are grouped by category:
|
||||
|
||||
- **Admin Options** -- system-wide settings controlled by the administrator (read-only for regular users).
|
||||
- **Configuration** -- user-level preferences such as warning and critical thresholds. These are the main settings you will adjust.
|
||||
- **Domain-specific Settings** -- values automatically filled in based on the domain being checked (e.g. the domain name itself).
|
||||
- **Checker Parameters** -- additional runtime parameters.
|
||||
|
||||
Fill in or adjust the options to match your needs, then click **Save**.
|
||||
|
||||
<!-- TODO: screenshot of the checker configuration page with options -->
|
||||
|
||||
### Rules
|
||||
|
||||
Each checker comes with one or more **rules** that evaluate different aspects of the collected data. For example, a ping checker might have separate rules for latency and packet loss.
|
||||
|
||||
You can enable or disable individual rules using the toggle switches. Each rule may also have its own specific options that you can configure.
|
||||
|
||||
<!-- TODO: screenshot of the rules section with toggles -->
|
||||
|
||||
|
||||
## Scheduling automatic checks
|
||||
|
||||
Once a checker is configured, you can schedule it to run automatically at a regular interval.
|
||||
|
||||
In the **Schedule** section of the checker configuration page:
|
||||
|
||||
1. Toggle **Run automatically** to enable scheduling.
|
||||
2. Set the **Check interval** (in hours) -- this determines how often the check runs.
|
||||
3. The **Next scheduled run** time is displayed so you know when the next execution will happen.
|
||||
4. Click **Save** to apply the schedule.
|
||||
|
||||
<!-- TODO: screenshot of the schedule card -->
|
||||
|
||||
{{% notice style="info" title="Interval limits" icon="clock" %}}
|
||||
Each checker defines minimum and maximum intervals to prevent overloading external services. The interface will respect these bounds when you configure the schedule.
|
||||
{{% /notice %}}
|
||||
|
||||
When scheduling is disabled, the checker can still be run manually at any time.
|
||||
|
||||
|
||||
## Running a check manually
|
||||
|
||||
You can trigger a check at any time without waiting for the schedule:
|
||||
|
||||
1. Navigate to the checker's **Executions** page (from the domain checks list, click **View Results**).
|
||||
2. Click **Run Check Now**.
|
||||
3. A dialog opens where you can:
|
||||
- Select which rules to run for this execution.
|
||||
- Override options temporarily (these overrides are not saved).
|
||||
4. Click **Run Check** to start the execution.
|
||||
|
||||
<!-- TODO: screenshot of the Run Check modal -->
|
||||
|
||||
A confirmation message will appear with the execution ID. The result will show up in the executions list once the check completes.
|
||||
|
||||
|
||||
## Viewing check results
|
||||
|
||||
All past executions are listed on the checker's **Executions** page, accessible from your domain's Checks tab by clicking **View Results**.
|
||||
|
||||
<!-- TODO: screenshot of the executions list -->
|
||||
|
||||
The executions table shows:
|
||||
|
||||
| Column | Description |
|
||||
|--------|-------------|
|
||||
| **Executed at** | When the check ran |
|
||||
| **Status** | The result: OK, Warning, Critical, Error, or Unknown |
|
||||
| **Message** | A summary of the findings |
|
||||
| **Duration** | How long the check took to complete |
|
||||
| **Type** | Whether it was a scheduled or manual run |
|
||||
|
||||
Click **View** on any execution to see its detailed results.
|
||||
|
||||
|
||||
## Understanding execution details
|
||||
|
||||
The execution detail page presents the results in the most appropriate format depending on what the checker provides.
|
||||
|
||||
### Metrics
|
||||
|
||||
When a checker produces metrics (e.g. response time, packet loss percentage), the detail page shows:
|
||||
|
||||
- A **line chart** plotting the metric values over time across recent executions.
|
||||
- A **data table** listing each metric with its name, value, and unit.
|
||||
|
||||
<!-- TODO: screenshot of the metrics chart and table -->
|
||||
|
||||
### HTML reports
|
||||
|
||||
Some checkers generate rich HTML reports (e.g. detailed DNS audit results). These are rendered directly in the page.
|
||||
|
||||
### Raw data
|
||||
|
||||
You can always switch to the **Raw JSON** view to inspect the full observation data collected during the execution. Use the view toggle at the top of the report section to switch between Metrics, HTML Report, and Raw JSON.
|
||||
|
||||
### Rule evaluations
|
||||
|
||||
Each rule that ran during the execution reports its own status and message. You can see the per-rule breakdown to understand which specific aspect triggered a warning or critical status.
|
||||
|
||||
<!-- TODO: screenshot of rule evaluation results -->
|
||||
|
||||
|
||||
## Service-level checks
|
||||
|
||||
Checkers that apply at the service level are configured from the service's own page rather than the domain-level Checks tab.
|
||||
|
||||
1. Navigate to your domain, then to the specific subdomain and service.
|
||||
2. Open the **Checks** tab for that service.
|
||||
3. The workflow is the same as for domain-level checkers: configure options, set up scheduling, run checks, and view results.
|
||||
|
||||
Service-level checkers automatically receive information about the service they are attached to (such as IP addresses from a Server service), so they require less manual configuration.
|
||||
|
||||
|
||||
## Managing check results
|
||||
|
||||
From the executions list, you can:
|
||||
|
||||
- **Delete a single result** by clicking the delete action on a specific execution.
|
||||
- **Delete all results** for a checker using the bulk delete option (a confirmation dialog will appear).
|
||||
|
||||
This can be useful to clean up old data or reset after configuration changes.
|
||||
|
||||
|
||||
## Status reference
|
||||
|
||||
Checkers report one of the following statuses, in order of severity:
|
||||
|
||||
| Status | Meaning |
|
||||
|--------|---------|
|
||||
| **OK** | Everything is within acceptable parameters |
|
||||
| **Info** | Informational finding, no action needed |
|
||||
| **Warning** | A threshold is approaching; attention recommended |
|
||||
| **Critical** | A threshold has been exceeded; action required |
|
||||
| **Error** | The check itself failed (collection error, bad configuration) |
|
||||
| **Unknown** | The check could not determine a result |
|
||||
174
content/pages/checks.fr.md
Normal file
174
content/pages/checks.fr.md
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
---
|
||||
date: 2026-04-05T12:00:00+02:00
|
||||
title: Surveillance & Vérifications
|
||||
author: nemunaire
|
||||
weight: 35
|
||||
description: "Mettez en place des vérifications automatiques pour surveiller vos domaines et vos services"
|
||||
---
|
||||
|
||||
happyDomain intègre un système de surveillance qui permet de lancer des vérifications automatiques sur vos domaines et vos services. Les vérificateurs collectent périodiquement des données (temps de réponse au ping, date d'expiration d'un domaine ou résultats d'audit DNS, par exemple), les évaluent au regard des seuils que vous définissez et rapportent un statut clair : OK, Avertissement, Critique ou Erreur.
|
||||
|
||||
## Parcourir les vérificateurs disponibles
|
||||
|
||||
Vous pouvez consulter l'ensemble des vérificateurs disponibles depuis la page **Vérifications**, accessible par le menu principal.
|
||||
|
||||
<!-- TODO: screenshot of the checkers list page -->
|
||||
|
||||
Chaque vérificateur indique la portée à laquelle il s'applique :
|
||||
|
||||
- **Niveau domaine** : vérifications qui concernent le domaine lui-même, indépendamment des enregistrements DNS (par exemple l'expiration du domaine via WHOIS).
|
||||
- **Niveau zone** : vérifications qui nécessitent le contenu complet de la zone (par exemple la validation DNSSEC).
|
||||
- **Niveau service** : vérifications qui ciblent un service précis sur un sous-domaine (par exemple un ping ou une vérification HTTP).
|
||||
|
||||
Utilisez la barre de recherche pour filtrer les vérificateurs par nom. Cliquez sur un vérificateur pour afficher sa description et ses options de configuration.
|
||||
|
||||
|
||||
## Configurer un vérificateur pour votre domaine
|
||||
|
||||
Pour mettre en place un vérificateur sur l'un de vos domaines :
|
||||
|
||||
1. Rendez-vous sur la page de votre domaine et ouvrez l'onglet **Vérifications**.
|
||||
2. Un tableau présente les vérificateurs disponibles pour ce domaine. Cliquez sur **Configurer** en regard du vérificateur souhaité.
|
||||
|
||||
<!-- TODO: screenshot of the domain checks list -->
|
||||
|
||||
La page de configuration regroupe plusieurs sections :
|
||||
|
||||
### Options du vérificateur
|
||||
|
||||
Les options sont réparties par catégorie :
|
||||
|
||||
- **Options d'administration** : paramètres globaux contrôlés par l'administrateur (en lecture seule pour les utilisateurs ordinaires).
|
||||
- **Configuration** : préférences au niveau de l'utilisateur, comme les seuils d'avertissement et critique. Ce sont les principaux réglages que vous ajusterez.
|
||||
- **Paramètres propres au domaine** : valeurs renseignées automatiquement à partir du domaine vérifié (par exemple le nom de domaine lui-même).
|
||||
- **Paramètres du vérificateur** : paramètres d'exécution supplémentaires.
|
||||
|
||||
Renseignez ou ajustez les options selon vos besoins, puis cliquez sur **Enregistrer**.
|
||||
|
||||
<!-- TODO: screenshot of the checker configuration page with options -->
|
||||
|
||||
### Règles
|
||||
|
||||
Chaque vérificateur s'accompagne d'une ou plusieurs **règles** qui évaluent différents aspects des données collectées. Un vérificateur de ping peut par exemple comporter des règles distinctes pour la latence et la perte de paquets.
|
||||
|
||||
Vous pouvez activer ou désactiver chaque règle à l'aide des interrupteurs. Chaque règle peut également disposer de ses propres options à configurer.
|
||||
|
||||
<!-- TODO: screenshot of the rules section with toggles -->
|
||||
|
||||
|
||||
## Planifier des vérifications automatiques
|
||||
|
||||
Une fois un vérificateur configuré, vous pouvez planifier son exécution automatique à intervalle régulier.
|
||||
|
||||
Dans la section **Planification** de la page de configuration du vérificateur :
|
||||
|
||||
1. Activez **Exécuter automatiquement** pour mettre en place la planification.
|
||||
2. Définissez l'**intervalle de vérification** (en heures) : il détermine la fréquence d'exécution.
|
||||
3. L'heure de la **prochaine exécution planifiée** est affichée afin que vous sachiez quand aura lieu la prochaine vérification.
|
||||
4. Cliquez sur **Enregistrer** pour appliquer la planification.
|
||||
|
||||
<!-- TODO: screenshot of the schedule card -->
|
||||
|
||||
{{% notice style="info" title="Limites d'intervalle" icon="clock" %}}
|
||||
Chaque vérificateur définit un intervalle minimal et maximal afin d'éviter de surcharger les services externes. L'interface respecte ces bornes lorsque vous configurez la planification.
|
||||
{{% /notice %}}
|
||||
|
||||
Lorsque la planification est désactivée, le vérificateur peut tout de même être lancé manuellement à tout moment.
|
||||
|
||||
|
||||
## Lancer une vérification manuellement
|
||||
|
||||
Vous pouvez déclencher une vérification à tout moment, sans attendre la planification :
|
||||
|
||||
1. Rendez-vous sur la page **Exécutions** du vérificateur (depuis la liste des vérifications du domaine, cliquez sur **Voir les résultats**).
|
||||
2. Cliquez sur **Lancer la vérification**.
|
||||
3. Une fenêtre s'ouvre, dans laquelle vous pouvez :
|
||||
- Sélectionner les règles à exécuter pour cette exécution.
|
||||
- Remplacer temporairement certaines options (ces remplacements ne sont pas enregistrés).
|
||||
4. Cliquez sur **Lancer la vérification** pour démarrer l'exécution.
|
||||
|
||||
<!-- TODO: screenshot of the Run Check modal -->
|
||||
|
||||
Un message de confirmation apparaît avec l'identifiant de l'exécution. Le résultat s'affiche dans la liste des exécutions une fois la vérification terminée.
|
||||
|
||||
|
||||
## Consulter les résultats des vérifications
|
||||
|
||||
Toutes les exécutions passées sont répertoriées sur la page **Exécutions** du vérificateur, accessible depuis l'onglet Vérifications de votre domaine en cliquant sur **Voir les résultats**.
|
||||
|
||||
<!-- TODO: screenshot of the executions list -->
|
||||
|
||||
Le tableau des exécutions présente :
|
||||
|
||||
| Colonne | Description |
|
||||
|--------|-------------|
|
||||
| **Exécutée le** | Date à laquelle la vérification a été lancée |
|
||||
| **Statut** | Le résultat : OK, Avertissement, Critique, Erreur ou Inconnu |
|
||||
| **Message** | Un résumé des constats |
|
||||
| **Durée** | Le temps qu'a pris la vérification |
|
||||
| **Type** | S'il s'agit d'une exécution planifiée ou manuelle |
|
||||
|
||||
Cliquez sur **Voir** sur une exécution pour en afficher les résultats détaillés.
|
||||
|
||||
|
||||
## Comprendre le détail d'une exécution
|
||||
|
||||
La page de détail d'une exécution présente les résultats sous la forme la plus adaptée à ce que fournit le vérificateur.
|
||||
|
||||
### Métriques
|
||||
|
||||
Lorsqu'un vérificateur produit des métriques (temps de réponse, pourcentage de perte de paquets, etc.), la page de détail affiche :
|
||||
|
||||
- Un **graphique en courbes** qui trace l'évolution des valeurs de la métrique au fil des exécutions récentes.
|
||||
- Un **tableau de données** qui répertorie chaque métrique avec son nom, sa valeur et son unité.
|
||||
|
||||
<!-- TODO: screenshot of the metrics chart and table -->
|
||||
|
||||
### Rapports HTML
|
||||
|
||||
Certains vérificateurs génèrent des rapports HTML détaillés (par exemple les résultats d'un audit DNS). Ces rapports sont affichés directement dans la page.
|
||||
|
||||
### Données brutes
|
||||
|
||||
Vous pouvez à tout moment basculer vers la vue **JSON brut** pour examiner l'ensemble des données d'observation collectées durant l'exécution. Utilisez le sélecteur de vue en haut de la section du rapport pour passer de Métriques à Rapport HTML et JSON brut.
|
||||
|
||||
### Évaluation des règles
|
||||
|
||||
Chaque règle exécutée durant l'exécution rapporte son propre statut et son propre message. Le détail règle par règle permet de comprendre quel aspect précis a déclenché un statut d'avertissement ou critique.
|
||||
|
||||
<!-- TODO: screenshot of rule evaluation results -->
|
||||
|
||||
|
||||
## Vérifications au niveau service
|
||||
|
||||
Les vérificateurs qui s'appliquent au niveau service se configurent depuis la page du service concerné, et non depuis l'onglet Vérifications du domaine.
|
||||
|
||||
1. Rendez-vous sur votre domaine, puis sur le sous-domaine et le service concernés.
|
||||
2. Ouvrez l'onglet **Vérifications** de ce service.
|
||||
3. Le déroulement est identique à celui des vérificateurs de niveau domaine : configurer les options, mettre en place la planification, lancer des vérifications et consulter les résultats.
|
||||
|
||||
Les vérificateurs de niveau service reçoivent automatiquement les informations relatives au service auquel ils sont rattachés (comme les adresses IP d'un service Serveur), ce qui réduit la configuration manuelle.
|
||||
|
||||
|
||||
## Gérer les résultats des vérifications
|
||||
|
||||
Depuis la liste des exécutions, vous pouvez :
|
||||
|
||||
- **Supprimer un résultat** en cliquant sur l'action de suppression d'une exécution précise.
|
||||
- **Supprimer tous les résultats** d'un vérificateur grâce à l'option de suppression groupée (une fenêtre de confirmation apparaît).
|
||||
|
||||
Cela peut être utile pour faire le ménage dans les anciennes données ou repartir de zéro après des changements de configuration.
|
||||
|
||||
|
||||
## Référence des statuts
|
||||
|
||||
Les vérificateurs rapportent l'un des statuts suivants, par ordre de gravité :
|
||||
|
||||
| Statut | Signification |
|
||||
|--------|---------|
|
||||
| **OK** | Tout se situe dans les paramètres acceptables |
|
||||
| **Information** | Constat informatif, aucune action nécessaire |
|
||||
| **Avertissement** | Un seuil est sur le point d'être atteint ; une attention est recommandée |
|
||||
| **Critique** | Un seuil a été dépassé ; une action est requise |
|
||||
| **Erreur** | La vérification elle-même a échoué (erreur de collecte, mauvaise configuration) |
|
||||
| **Inconnu** | La vérification n'a pas pu déterminer de résultat |
|
||||
|
|
@ -1,311 +1,235 @@
|
|||
---
|
||||
title: "Writing a happyDomain Plugin"
|
||||
description: "Technical guide for developing test plugins for happyDomain"
|
||||
title: "Writing a happyDomain Checker Plugin"
|
||||
description: "Technical guide for developing checker plugins for happyDomain"
|
||||
---
|
||||
|
||||
happyDomain supports external **test plugins** — shared libraries (`.so` files) that add domain or service health checks to a running instance. Plugins are loaded at startup without recompiling the server; the operator simply drops a `.so` file into a configured directory.
|
||||
happyDomain can be extended with external **checker plugins** — shared libraries (`.so` files) that add automated diagnostics on zones, domains, services or users. A checker plugin is loaded into the running happyDomain process at startup; the operator simply drops a `.so` file into a configured directory, no recompilation of the server required.
|
||||
|
||||
## How it works
|
||||
|
||||
A plugin receives a set of options assembled from several configuration scopes, runs a check (HTTP call, DNS query, …), and returns a result with a status level and an optional detailed report. Results are stored and displayed in the happyDomain UI alongside the domain or service they concern.
|
||||
|
||||
When happyDomain starts it scans every directory listed in the `plugins-directories` configuration option. For each file it finds, it:
|
||||
|
||||
1. Opens the shared library.
|
||||
2. Looks up the exported symbol `NewTestPlugin`.
|
||||
3. Calls `NewTestPlugin()` to obtain a plugin value.
|
||||
4. Registers the plugin under each name returned by `PluginEnvName()`.
|
||||
|
||||
If the file is not a valid Go plugin, if `NewTestPlugin` is missing, or if it returns an error, a warning is logged and the file is skipped. The server always starts regardless of individual plugin load failures.
|
||||
|
||||
---
|
||||
|
||||
## The `TestPlugin` interface
|
||||
|
||||
Every plugin must implement four methods:
|
||||
|
||||
```go
|
||||
type TestPlugin interface {
|
||||
PluginEnvName() []string
|
||||
Version() PluginVersionInfo
|
||||
AvailableOptions() PluginOptionsDocumentation
|
||||
RunTest(PluginOptions, map[string]string) (*PluginResult, error)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Project structure
|
||||
|
||||
A plugin is a standalone Go module compiled with `-buildmode=plugin`. It must be in `package main` and export exactly one symbol:
|
||||
|
||||
```go
|
||||
func NewTestPlugin() (happydns.TestPlugin, error)
|
||||
```
|
||||
|
||||
Recommended layout:
|
||||
|
||||
```
|
||||
myplugin/
|
||||
├── go.mod
|
||||
├── Makefile
|
||||
└── plugin.go # (or split across multiple .go files)
|
||||
```
|
||||
|
||||
### go.mod
|
||||
|
||||
```
|
||||
module git.happydns.org/happyDomain/plugins/myplugin
|
||||
|
||||
go 1.25
|
||||
|
||||
require git.happydns.org/happyDomain v0.0.0
|
||||
replace git.happydns.org/happyDomain => ../../
|
||||
```
|
||||
|
||||
The `replace` directive points to your local happyDomain checkout, ensuring the plugin is compiled against the exact same types as the server.
|
||||
A checker has two halves: it **collects** raw data about a target (an observation), then **evaluates** that data against a set of rules to produce a status. Results are stored and displayed in the happyDomain UI alongside the domain or service they concern.
|
||||
|
||||
{{< notice style="warning" >}}
|
||||
A Go plugin and the host process share the same runtime. They **must** be compiled with the same Go toolchain version and the same versions of every shared dependency. Any mismatch produces a hard error at load time.
|
||||
A `.so` plugin is loaded into the happyDomain process and runs with the same privileges as the server. Treat the plugin directory as a trusted location: happyDomain refuses to load plugins from a directory it cannot trust (see [Security and deployment](#security-and-deployment)).
|
||||
{{< /notice >}}
|
||||
|
||||
---
|
||||
|
||||
## Entry point
|
||||
## What a checker plugin must export
|
||||
|
||||
Plugins are built against the **`checker-sdk-go`** module, published separately from the happyDomain core. Throughout this page, `checker` refers to the package `git.happydns.org/checker-sdk-go/checker`.
|
||||
|
||||
happyDomain's loader looks for a single exported symbol named `NewCheckerPlugin` with this exact signature:
|
||||
|
||||
```go
|
||||
func NewCheckerPlugin() (*checker.CheckerDefinition, checker.ObservationProvider, error)
|
||||
```
|
||||
|
||||
The two return values describe the two halves of a checker:
|
||||
|
||||
- **`*CheckerDefinition`** describes the checker: its identifier, name, version, the observation keys it relies on, the options it accepts, its rules, an optional aggregator, a scheduling interval, and whether it exposes HTML reports or metrics. See the [field table](#checkerdefinition-fields) below.
|
||||
- **`ObservationProvider`** is the data-collection half. It exposes a `Key()` (the observation key the rules look up) and a `Collect(ctx, opts)` method that returns the raw observation payload. happyDomain serialises that result to JSON and caches it per observation context.
|
||||
- Return a non-nil `error` if the plugin cannot initialise (a missing environment variable, a broken cgo dependency, …). The host logs the error and skips the file rather than aborting startup.
|
||||
|
||||
A single `.so` may export several plugin kinds. The loader runs every known plugin loader against every file, then skips any symbol it does not recognise, so one binary can ship more than one plugin.
|
||||
|
||||
---
|
||||
|
||||
## Minimal example
|
||||
|
||||
This is the smallest plugin that loads. It collects a fixed observation and declares no rules. Adapt it from [`checker-dummy`](https://git.happydns.org/checker-dummy), the reference implementation.
|
||||
|
||||
```go
|
||||
// Command plugin is the happyDomain plugin entrypoint for the dummy checker.
|
||||
//
|
||||
// Build with:
|
||||
// go build -buildmode=plugin -o checker-dummy.so ./plugin
|
||||
package main
|
||||
|
||||
import "git.happydns.org/happyDomain/model"
|
||||
import (
|
||||
"context"
|
||||
|
||||
func NewTestPlugin() (happydns.TestPlugin, error) {
|
||||
return &MyPlugin{}, nil
|
||||
"git.happydns.org/checker-sdk-go/checker"
|
||||
)
|
||||
|
||||
type dummyProvider struct{}
|
||||
|
||||
func (dummyProvider) Key() checker.ObservationKey { return "dummy.observation" }
|
||||
|
||||
func (dummyProvider) Collect(ctx context.Context, opts checker.CheckerOptions) (any, error) {
|
||||
return map[string]string{"hello": "world"}, nil
|
||||
}
|
||||
|
||||
// NewCheckerPlugin is the symbol resolved by happyDomain at startup.
|
||||
func NewCheckerPlugin() (*checker.CheckerDefinition, checker.ObservationProvider, error) {
|
||||
def := &checker.CheckerDefinition{
|
||||
ID: "com.example.dummy",
|
||||
Name: "Dummy checker",
|
||||
Version: "0.1.0",
|
||||
ObservationKeys: []checker.ObservationKey{"dummy.observation"},
|
||||
// Add Rules / Aggregator / Options here in a real plugin.
|
||||
}
|
||||
return def, dummyProvider{}, nil
|
||||
}
|
||||
```
|
||||
|
||||
The constructor is a good place to perform one-time initialisation (open config files, create an HTTP client, …). Return an error if the plugin cannot function.
|
||||
{{< notice style="warning" >}}
|
||||
A Go plugin and the host process share the same runtime. They **must** be compiled with the same Go toolchain version and the same versions of every shared dependency. Any mismatch produces a hard error at load time. See [Build constraints](#build-constraints).
|
||||
{{< /notice >}}
|
||||
|
||||
---
|
||||
|
||||
## Naming — `PluginEnvName()`
|
||||
## `CheckerDefinition` fields
|
||||
|
||||
Returns one or more short, lowercase identifiers. These names are used to look up the plugin via the API and to key its stored configuration.
|
||||
|
||||
```go
|
||||
func (p *MyPlugin) PluginEnvName() []string {
|
||||
return []string{"myplugin"}
|
||||
}
|
||||
```
|
||||
|
||||
Choose names that are unlikely to collide (e.g. `"zonemaster"`, `"matrixim"`) and keep them **stable across versions** because they are persisted alongside user configuration. If two loaded plugins claim the same name, the second one is skipped and a conflict is logged.
|
||||
|
||||
---
|
||||
|
||||
## Version and availability — `Version()`
|
||||
|
||||
Describes the plugin and controls where it appears in the UI:
|
||||
|
||||
```go
|
||||
func (p *MyPlugin) Version() happydns.PluginVersionInfo {
|
||||
return happydns.PluginVersionInfo{
|
||||
Name: "My Plugin",
|
||||
Version: "1.0",
|
||||
AvailableOn: happydns.PluginAvailability{
|
||||
ApplyToDomain: true,
|
||||
ApplyToService: false,
|
||||
LimitToProviders: nil, // nil or empty = all providers
|
||||
LimitToServices: []string{"abstract.MatrixIM"},
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
The `*CheckerDefinition` returned by `NewCheckerPlugin` is the description of your checker:
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `ApplyToDomain` | `bool` | Plugin can be run against a whole domain |
|
||||
| `ApplyToService` | `bool` | Plugin can be run against a specific DNS service |
|
||||
| `LimitToProviders` | `[]string` | Restrict to certain DNS provider identifiers (empty = no restriction) |
|
||||
| `LimitToServices` | `[]string` | Restrict to certain service type identifiers, e.g. `"abstract.MatrixIM"` (empty = no restriction) |
|
||||
| `ID` | `string` | **Required.** Stable, persistent identifier. Pick a namespaced value (`com.example.dnssec-freshness`, not `dnssec`) and never change it: it keys stored results and user configuration. |
|
||||
| `Name` | `string` | Human-readable name shown in the UI. |
|
||||
| `Version` | `string` | Plugin version (e.g. `"1.0.0"`). |
|
||||
| `Availability` | `CheckerAvailability` | Declares which scopes the checker applies to and any provider/service restrictions (see below). |
|
||||
| `Options` | `CheckerOptionsDocumentation` | Documents the options the checker accepts, grouped by scope (see below). |
|
||||
| `Rules` | `[]CheckRule` | The rules evaluated against the collected observation. |
|
||||
| `Aggregator` | `CheckAggregator` | Optional. Combines the per-rule `CheckState`s into a single summary state. |
|
||||
| `Interval` | `*CheckIntervalSpec` | Optional scheduling bounds (`Min`, `Max`, `Default` durations). |
|
||||
| `HasHTMLReport` | `bool` | Set when the provider implements `CheckerHTMLReporter`. |
|
||||
| `HasMetrics` | `bool` | Set when the provider implements `CheckerMetricsReporter`. |
|
||||
| `ObservationKeys` | `[]ObservationKey` | The observation keys this checker reads. |
|
||||
|
||||
Both `ApplyToDomain` and `ApplyToService` may be `true` simultaneously.
|
||||
### Availability
|
||||
|
||||
---
|
||||
|
||||
## Options — `AvailableOptions()`
|
||||
|
||||
Options are key/value pairs (`map[string]any`) that configure each test run. They are declared grouped by **scope**, i.e. who sets them and how long they persist:
|
||||
|
||||
```go
|
||||
func (p *MyPlugin) AvailableOptions() happydns.PluginOptionsDocumentation {
|
||||
return happydns.PluginOptionsDocumentation{
|
||||
RunOpts: []happydns.PluginOptionDocumentation{ /* … */ },
|
||||
ServiceOpts: []happydns.PluginOptionDocumentation{ /* … */ },
|
||||
DomainOpts: []happydns.PluginOptionDocumentation{ /* … */ },
|
||||
UserOpts: []happydns.PluginOptionDocumentation{ /* … */ },
|
||||
AdminOpts: []happydns.PluginOptionDocumentation{ /* … */ },
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Option scopes
|
||||
|
||||
| Scope | Who sets it | Storage key | Typical use |
|
||||
|---|---|---|---|
|
||||
| `RunOpts` | User, at test time | _(transient)_ | Per-invocation parameters |
|
||||
| `ServiceOpts` | User | plugin + user + domain + service | Service-level configuration |
|
||||
| `DomainOpts` | User | plugin + user + domain | Domain-level configuration |
|
||||
| `UserOpts` | User | plugin + user | Personal preferences (e.g. language) |
|
||||
| `AdminOpts` | Administrator | plugin | Instance-wide settings, shared credentials |
|
||||
|
||||
Before `RunTest` is called, happyDomain merges all scoped values from least specific (admin) to most specific (run-time). More-specific values silently override less-specific ones. `RunTest` always receives a single flat map and does not need to know which scope each value came from.
|
||||
|
||||
### Option fields
|
||||
|
||||
Each option is a `PluginOptionDocumentation` (an alias for `Field`):
|
||||
`CheckerAvailability` controls where the checker is offered in the UI:
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `Id` | `string` | **Required.** Key used in the `PluginOptions` map inside `RunTest` |
|
||||
| `Type` | `string` | Input type: `"string"`, `"select"` |
|
||||
| `Label` | `string` | Human-readable label shown in the UI |
|
||||
| `Placeholder` | `string` | Placeholder text for the input field |
|
||||
| `Default` | `any` | Default value pre-filled in the form |
|
||||
| `Choices` | `[]string` | Options for `"select"` inputs |
|
||||
| `Required` | `bool` | Whether the field must be filled before running |
|
||||
| `Secret` | `bool` | Marks the field as sensitive (e.g. an API key) |
|
||||
| `Hide` | `bool` | Hides the field from the user entirely |
|
||||
| `Textarea` | `bool` | Renders a multiline text area |
|
||||
| `Description` | `string` | Help text displayed below the field |
|
||||
| `AutoFill` | `string` | Populate the field automatically from context (see below) |
|
||||
| `ApplyToDomain` | `bool` | Checker can run against a whole domain. |
|
||||
| `ApplyToZone` | `bool` | Checker can run against a zone. |
|
||||
| `ApplyToService` | `bool` | Checker can run against a specific service. |
|
||||
| `LimitToProviders` | `[]string` | Restrict to certain DNS provider identifiers (empty = no restriction). |
|
||||
| `LimitToServices` | `[]string` | Restrict to certain service type identifiers, e.g. `"abstract.MatrixIM"` (empty = no restriction). |
|
||||
|
||||
### Auto-fill
|
||||
### Options
|
||||
|
||||
When `AutoFill` is set, happyDomain populates the field from the test context; the user is not prompted:
|
||||
Options are declared grouped by **scope**, i.e. who sets them and how long they persist. Each scope is a slice of `CheckerOptionDocumentation`:
|
||||
|
||||
| Constant | String value | Populated with |
|
||||
| Scope | Who sets it | Typical use |
|
||||
|---|---|---|
|
||||
| `happydns.AutoFillDomainName` | `"domain_name"` | FQDN of the domain under test, e.g. `"example.com."` |
|
||||
| `happydns.AutoFillSubdomain` | `"subdomain"` | Subdomain relative to the zone, e.g. `"www"` — service-scoped tests only |
|
||||
| `happydns.AutoFillServiceType` | `"service_type"` | Service type identifier, e.g. `"abstract.MatrixIM"` — service-scoped tests only |
|
||||
| `AdminOpts` | Administrator | Instance-wide settings, shared credentials. |
|
||||
| `UserOpts` | User | Personal preferences (e.g. language). |
|
||||
| `DomainOpts` | User | Domain-level configuration. |
|
||||
| `ServiceOpts` | User | Service-level configuration. |
|
||||
| `RunOpts` | User, at run time | Per-invocation parameters. |
|
||||
|
||||
```go
|
||||
{
|
||||
Id: "domainName",
|
||||
Type: "string",
|
||||
Label: "Domain name",
|
||||
AutoFill: happydns.AutoFillDomainName,
|
||||
Required: true,
|
||||
}
|
||||
```
|
||||
happyDomain merges the scoped values from least specific (admin) to most specific (run-time) before calling `Collect`, so the provider receives a single flat `CheckerOptions` map. Each option is a `CheckerOptionField` with fields such as `Id`, `Type`, `Label`, `Default`, `Choices`, `Required`, `Secret`, `Description` and `AutoFill`. Read typed values out of the map with the SDK helpers `checker.GetOption`, `checker.GetIntOption`, `checker.GetBoolOption`, …
|
||||
|
||||
{{< notice style="info" >}}
|
||||
When happyDomain registers an externalisable checker, it automatically appends an `endpoint` admin option, so the administrator can delegate collection to a remote HTTP endpoint instead of running the checker in-process. Leave it empty to run locally.
|
||||
{{< /notice >}}
|
||||
|
||||
---
|
||||
|
||||
## Running the check — `RunTest()`
|
||||
## The `ObservationProvider`
|
||||
|
||||
`RunTest` receives the merged option map and a metadata map (reserved for future use), performs the check, and returns a `PluginResult`.
|
||||
|
||||
Always assert option values to a concrete type before use — the map holds `any`:
|
||||
The provider is the data-collection half of the checker:
|
||||
|
||||
```go
|
||||
func (p *MyPlugin) RunTest(opts happydns.PluginOptions, _ map[string]string) (*happydns.PluginResult, error) {
|
||||
domain, ok := opts["domainName"].(string)
|
||||
if !ok || domain == "" {
|
||||
return nil, fmt.Errorf("domainName option is required")
|
||||
}
|
||||
|
||||
// … perform the check …
|
||||
|
||||
return &happydns.PluginResult{
|
||||
Status: happydns.PluginResultStatusOK,
|
||||
StatusLine: "All good",
|
||||
Report: myStructuredReport,
|
||||
}, nil
|
||||
type ObservationProvider interface {
|
||||
Key() ObservationKey
|
||||
Collect(ctx context.Context, opts CheckerOptions) (any, error)
|
||||
}
|
||||
```
|
||||
|
||||
Return a **non-nil error** only for unexpected failures (network errors, invalid configuration). For expected check failures — the monitored service is down, DNS records are wrong — return a `PluginResult` with an appropriate status and a human-readable `StatusLine`.
|
||||
- `Key()` returns the observation key this provider fills. It must match one of the `ObservationKeys` declared in the definition.
|
||||
- `Collect` performs the actual work (a DNS query, an HTTP call, …) and returns any JSON-serialisable value. happyDomain marshals it to JSON and caches it; the rules then read it back.
|
||||
|
||||
### Result fields
|
||||
A provider can optionally implement additional SDK interfaces to extend its behaviour:
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `Status` | `PluginResultStatus` | Overall result level (see below) |
|
||||
| `StatusLine` | `string` | Short summary displayed in the UI |
|
||||
| `Report` | `any` | Any JSON-serialisable value stored as structured diagnostic data |
|
||||
|
||||
### Status levels (worst → best)
|
||||
|
||||
| Constant | Meaning |
|
||||
| Interface | Purpose |
|
||||
|---|---|
|
||||
| `PluginResultStatusKO` | Check failed |
|
||||
| `PluginResultStatusWarn` | Check passed with warnings |
|
||||
| `PluginResultStatusInfo` | Informational, no action required |
|
||||
| `PluginResultStatusOK` | Check fully passed |
|
||||
| `CheckerHTMLReporter` | `GetHTMLReport(ctx ReportContext)` renders the stored observation as an HTML document. |
|
||||
| `CheckerMetricsReporter` | `ExtractMetrics(ctx ReportContext, collectedAt)` produces time-series metrics. |
|
||||
| `CheckEnabler` | `IsEligible(ctx, opts)` decides, from the target's actual data, whether running the checker is meaningful at all. |
|
||||
| `DiscoveryPublisher` | `DiscoverEntries(data)` publishes `DiscoveryEntry` records other checkers can consume. |
|
||||
|
||||
Rules return `CheckState` values whose `Status` is one of `StatusOK`, `StatusInfo`, `StatusWarn`, `StatusCrit`, `StatusError` or `StatusUnknown`.
|
||||
|
||||
### Optional: standalone server
|
||||
|
||||
The SDK also provides `checker.Server`, HTTP scaffolding for running a checker as a remote endpoint instead of (or alongside) an in-process plugin. It exposes the routes `/health` and `/collect`, plus `/definition`, `/evaluate` and `/report` when the provider implements the matching optional interfaces. A provider that implements `CheckerInteractive` (`RenderForm` / `ParseForm`) additionally gets a human-facing form on `/check`, usable outside of happyDomain. See the [SDK README](https://git.happydns.org/checker-sdk-go) for details; the in-process plugin path described above does not require any of this.
|
||||
|
||||
---
|
||||
|
||||
## Building
|
||||
## Build constraints
|
||||
|
||||
```bash
|
||||
go build -buildmode=plugin -o happydomain-plugin-test-myplugin.so \
|
||||
git.happydns.org/happyDomain/plugins/myplugin
|
||||
```
|
||||
Go's `plugin` package is unforgiving. To load successfully, your plugin must be built with:
|
||||
|
||||
Minimal `Makefile`:
|
||||
- the **same Go toolchain version** as happyDomain itself, including the same patch level;
|
||||
- the **same versions of every shared dependency** (pin them in your `go.mod`, vendoring the exact versions happyDomain ships);
|
||||
- `CGO_ENABLED=1`;
|
||||
- the same `GOOS`/`GOARCH` as the host binary.
|
||||
|
||||
```makefile
|
||||
PLUGIN_NAME=myplugin
|
||||
TARGET=../happydomain-plugin-test-$(PLUGIN_NAME).so
|
||||
If any of these do not match, `plugin.Open` fails with a (sometimes cryptic) error like *"plugin was built with a different version of package …"*. The host logs it and skips the file.
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): *.go
|
||||
go build -buildmode=plugin -o $@ git.happydns.org/happyDomain/plugins/$(PLUGIN_NAME)
|
||||
```
|
||||
|
||||
The prefix `happydomain-plugin-test-` is a convention; happyDomain loads every file in the plugin directories regardless of its name.
|
||||
Go's `plugin` package only works on **linux**, **darwin** and **freebsd**. On other platforms happyDomain is built without plugin support and the configured plugin directories are ignored, with a warning logged at startup.
|
||||
|
||||
---
|
||||
|
||||
## Deployment
|
||||
## Security and deployment
|
||||
|
||||
### 1. Copy the `.so` file
|
||||
### Directory and file permissions
|
||||
|
||||
Loading a `.so` file is arbitrary code execution as the happyDomain process, so the loader enforces strict ownership before it touches any file:
|
||||
|
||||
- The plugin directory **must not be a symbolic link** — happyDomain refuses to follow one, to prevent it being redirected to an attacker-controlled path.
|
||||
- The plugin directory **must not be group- or world-writable**. A directory writable by anyone but the owner is treated as a fatal misconfiguration and aborts loading.
|
||||
- Any individual `.so` file that is **group- or world-writable is skipped** (logged and ignored), even inside a properly locked-down directory.
|
||||
|
||||
In practice: keep the directory owned by the happyDomain user, mode `0755`, and the plugin files mode `0644`.
|
||||
|
||||
```bash
|
||||
cp happydomain-plugin-test-myplugin.so /usr/lib/happydomain/plugins/
|
||||
sudo install -d -m 0755 -o happydomain /var/lib/happydomain/plugins
|
||||
sudo install -m 0644 -o happydomain checker-dummy.so /var/lib/happydomain/plugins/
|
||||
```
|
||||
|
||||
### 2. Point happyDomain at the directory
|
||||
|
||||
`happydomain.conf`:
|
||||
|
||||
```
|
||||
plugins-directories=/usr/lib/happydomain/plugins
|
||||
```
|
||||
|
||||
Environment variable:
|
||||
### Building the plugin
|
||||
|
||||
```bash
|
||||
HAPPYDOMAIN_PLUGINS_DIRECTORIES=/usr/lib/happydomain/plugins
|
||||
CGO_ENABLED=1 go build -buildmode=plugin -o checker-dummy.so ./plugin
|
||||
```
|
||||
|
||||
Multiple directories may be listed as a comma-separated value.
|
||||
### Pointing happyDomain at the directory
|
||||
|
||||
### 3. Check the logs
|
||||
The directory is configured with the **`--plugins-directory`** flag, which **may be repeated** to scan several directories:
|
||||
|
||||
On a successful load:
|
||||
|
||||
```
|
||||
Plugin My Plugin loaded (version 1.0)
|
||||
```bash
|
||||
happydomain --plugins-directory /var/lib/happydomain/plugins
|
||||
```
|
||||
|
||||
On a name conflict or load error a warning is logged with the filename and reason.
|
||||
The equivalent environment variable is `HAPPYDOMAIN_PLUGINS_DIRECTORY`.
|
||||
|
||||
The loader scans each configured directory and attempts to load every `.so` file it finds. An individual plugin that fails to load — wrong build, missing symbols, a panic in its factory — is logged and skipped without aborting startup; one bad `.so` never prevents the others from loading.
|
||||
|
||||
### Restart and check the logs
|
||||
|
||||
```bash
|
||||
sudo systemctl restart happydomain
|
||||
```
|
||||
|
||||
On a successful load, happyDomain logs:
|
||||
|
||||
```
|
||||
Plugin com.example.dummy (/var/lib/happydomain/plugins/checker-dummy.so) loaded
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Reference implementations
|
||||
## Licensing
|
||||
|
||||
Two plugins are bundled in this directory:
|
||||
Checker plugins import only `git.happydns.org/checker-sdk-go/checker`, which is licensed under **Apache-2.0**. The SDK is deliberately split out of the AGPL-3.0 happyDomain core as a small, stable public API for third-party checkers.
|
||||
|
||||
- **`matrix/`** — queries the Matrix federation tester API. Demonstrates `ApplyToService` with `LimitToServices` and `AdminOpts` for the backend URL.
|
||||
- **`zonemaster/`** — drives the Zonemaster JSON-RPC API, polls for completion, and maps results to severity levels. Demonstrates `AutoFillDomainName`, `UserOpts` for language selection, and multi-level status mapping.
|
||||
A plugin built against this SDK is therefore **not** a derivative work of happyDomain, and you may distribute your checker `.so` under any license you choose (MIT, Apache, proprietary, AGPL — whatever fits your needs).
|
||||
|
||||
---
|
||||
|
||||
## Reference implementation
|
||||
|
||||
[`checker-dummy`](https://git.happydns.org/checker-dummy) is the fully working, documented template that this page mirrors. Start from it when writing your own checker.
|
||||
|
|
|
|||
|
|
@ -1,311 +1,235 @@
|
|||
---
|
||||
title: "Écrire un plugin happyDomain"
|
||||
description: "Guide technique pour développer des plugins de test pour happyDomain"
|
||||
title: "Écrire un plugin de vérification happyDomain"
|
||||
description: "Guide technique pour développer des plugins checker pour happyDomain"
|
||||
---
|
||||
|
||||
happyDomain prend en charge des **plugins de test** externes — des bibliothèques partagées (fichiers `.so`) qui ajoutent des vérifications de santé sur les domaines ou les services d'une instance en cours d'exécution. Les plugins sont chargés au démarrage sans recompiler le serveur ; l'opérateur dépose simplement un fichier `.so` dans un répertoire configuré.
|
||||
happyDomain peut être étendu par des **plugins de vérification** (*checkers*) externes : des bibliothèques partagées (fichiers `.so`) qui ajoutent des diagnostics automatisés sur les zones, les domaines, les services ou les utilisateurs. Un plugin checker est chargé dans le processus happyDomain au démarrage. L'opérateur dépose simplement un fichier `.so` dans un répertoire configuré, sans recompiler le serveur.
|
||||
|
||||
## Fonctionnement
|
||||
|
||||
Un plugin reçoit un ensemble d'options assemblées depuis plusieurs portées de configuration, exécute une vérification (appel HTTP, requête DNS, …) et renvoie un résultat avec un niveau de statut et un rapport détaillé optionnel. Les résultats sont stockés et affichés dans l'interface happyDomain aux côtés du domaine ou du service concerné.
|
||||
|
||||
Au démarrage, happyDomain parcourt chaque répertoire listé dans l'option de configuration `plugins-directories`. Pour chaque fichier trouvé, il :
|
||||
|
||||
1. Ouvre la bibliothèque partagée.
|
||||
2. Recherche le symbole exporté `NewTestPlugin`.
|
||||
3. Appelle `NewTestPlugin()` pour obtenir une valeur de plugin.
|
||||
4. Enregistre le plugin sous chaque nom renvoyé par `PluginEnvName()`.
|
||||
|
||||
Si le fichier n'est pas un plugin Go valide, si `NewTestPlugin` est absent ou s'il retourne une erreur, un avertissement est journalisé et le fichier est ignoré. Le serveur démarre toujours, quels que soient les échecs de chargement individuels.
|
||||
|
||||
---
|
||||
|
||||
## L'interface `TestPlugin`
|
||||
|
||||
Tout plugin doit implémenter quatre méthodes :
|
||||
|
||||
```go
|
||||
type TestPlugin interface {
|
||||
PluginEnvName() []string
|
||||
Version() PluginVersionInfo
|
||||
AvailableOptions() PluginOptionsDocumentation
|
||||
RunTest(PluginOptions, map[string]string) (*PluginResult, error)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Structure du projet
|
||||
|
||||
Un plugin est un module Go autonome compilé avec `-buildmode=plugin`. Il doit être dans `package main` et exporter exactement un symbole :
|
||||
|
||||
```go
|
||||
func NewTestPlugin() (happydns.TestPlugin, error)
|
||||
```
|
||||
|
||||
Organisation recommandée :
|
||||
|
||||
```
|
||||
myplugin/
|
||||
├── go.mod
|
||||
├── Makefile
|
||||
└── plugin.go # (ou réparti sur plusieurs fichiers .go)
|
||||
```
|
||||
|
||||
### go.mod
|
||||
|
||||
```
|
||||
module git.happydns.org/happyDomain/plugins/myplugin
|
||||
|
||||
go 1.25
|
||||
|
||||
require git.happydns.org/happyDomain v0.0.0
|
||||
replace git.happydns.org/happyDomain => ../../
|
||||
```
|
||||
|
||||
La directive `replace` pointe vers votre dépôt local happyDomain, garantissant que le plugin est compilé avec exactement les mêmes types que le serveur.
|
||||
Un checker comporte deux moitiés. Il **collecte** d'abord des données brutes sur une cible (une observation). Il **évalue** ensuite ces données au regard d'un ensemble de règles afin de produire un statut. Les résultats sont stockés puis affichés dans l'interface de happyDomain, à côté du domaine ou du service concerné.
|
||||
|
||||
{{< notice style="warning" >}}
|
||||
Un plugin Go et le processus hôte partagent le même environnement d'exécution. Ils **doivent** être compilés avec la même version de la chaîne d'outils Go et les mêmes versions de toutes les dépendances partagées. Tout écart provoque une erreur fatale au chargement.
|
||||
Un plugin `.so` est chargé dans le processus happyDomain et s'exécute avec les mêmes privilèges que le serveur. Le répertoire des plugins doit être considéré comme un emplacement de confiance : happyDomain refuse de charger des plugins depuis un répertoire qui ne l'est pas (voir [Sécurité et déploiement](#sécurité-et-déploiement)).
|
||||
{{< /notice >}}
|
||||
|
||||
---
|
||||
|
||||
## Point d'entrée
|
||||
## Ce qu'un plugin checker doit exporter
|
||||
|
||||
Les plugins sont construits avec le module **`checker-sdk-go`**, publié séparément du cœur de happyDomain. Dans cette page, `checker` désigne le paquet `git.happydns.org/checker-sdk-go/checker`.
|
||||
|
||||
Le chargeur de happyDomain recherche un unique symbole exporté nommé `NewCheckerPlugin`, avec cette signature exacte :
|
||||
|
||||
```go
|
||||
func NewCheckerPlugin() (*checker.CheckerDefinition, checker.ObservationProvider, error)
|
||||
```
|
||||
|
||||
Les deux valeurs de retour décrivent les deux moitiés d'un checker :
|
||||
|
||||
- **`*CheckerDefinition`** décrit le checker : son identifiant, son nom, sa version, les clés d'observation dont il dépend, les options qu'il accepte, ses règles, un agrégateur optionnel, un intervalle de planification, et s'il expose des rapports HTML ou des métriques. Voir le [tableau des champs](#champs-de-checkerdefinition) ci-dessous.
|
||||
- **`ObservationProvider`** est la moitié chargée de la collecte. Elle expose une méthode `Key()` (la clé d'observation que les règles consultent) et une méthode `Collect(ctx, opts)` qui renvoie la charge utile brute de l'observation. happyDomain sérialise ce résultat en JSON et le met en cache pour chaque contexte d'observation.
|
||||
- Renvoyez une `error` non nulle si le plugin ne peut pas s'initialiser (variable d'environnement manquante, dépendance cgo cassée, …). L'hôte journalise l'erreur et ignore le fichier, sans interrompre le démarrage.
|
||||
|
||||
Un même fichier `.so` peut exporter plusieurs types de plugins. Le chargeur applique chaque chargeur connu à chaque fichier, puis ignore tout symbole qu'il ne reconnaît pas. Un binaire peut donc fournir plusieurs plugins.
|
||||
|
||||
---
|
||||
|
||||
## Exemple minimal
|
||||
|
||||
Voici le plus petit plugin qui se charge. Il collecte une observation fixe et ne déclare aucune règle. On peut l'adapter à partir de [`checker-dummy`](https://git.happydns.org/checker-dummy), l'implémentation de référence.
|
||||
|
||||
```go
|
||||
// Command plugin is the happyDomain plugin entrypoint for the dummy checker.
|
||||
//
|
||||
// Build with:
|
||||
// go build -buildmode=plugin -o checker-dummy.so ./plugin
|
||||
package main
|
||||
|
||||
import "git.happydns.org/happyDomain/model"
|
||||
import (
|
||||
"context"
|
||||
|
||||
func NewTestPlugin() (happydns.TestPlugin, error) {
|
||||
return &MyPlugin{}, nil
|
||||
"git.happydns.org/checker-sdk-go/checker"
|
||||
)
|
||||
|
||||
type dummyProvider struct{}
|
||||
|
||||
func (dummyProvider) Key() checker.ObservationKey { return "dummy.observation" }
|
||||
|
||||
func (dummyProvider) Collect(ctx context.Context, opts checker.CheckerOptions) (any, error) {
|
||||
return map[string]string{"hello": "world"}, nil
|
||||
}
|
||||
|
||||
// NewCheckerPlugin is the symbol resolved by happyDomain at startup.
|
||||
func NewCheckerPlugin() (*checker.CheckerDefinition, checker.ObservationProvider, error) {
|
||||
def := &checker.CheckerDefinition{
|
||||
ID: "com.example.dummy",
|
||||
Name: "Dummy checker",
|
||||
Version: "0.1.0",
|
||||
ObservationKeys: []checker.ObservationKey{"dummy.observation"},
|
||||
// Add Rules / Aggregator / Options here in a real plugin.
|
||||
}
|
||||
return def, dummyProvider{}, nil
|
||||
}
|
||||
```
|
||||
|
||||
Le constructeur est l'endroit idéal pour effectuer une initialisation unique (ouvrir des fichiers de configuration, créer un client HTTP, …). Retournez une erreur si le plugin ne peut pas fonctionner.
|
||||
{{< notice style="warning" >}}
|
||||
Un plugin Go et le processus hôte partagent le même *runtime*. Ils **doivent** être compilés avec la même version de la chaîne d'outils Go et les mêmes versions de chaque dépendance partagée. Toute divergence produit une erreur bloquante au chargement. Voir [Contraintes de build](#contraintes-de-build).
|
||||
{{< /notice >}}
|
||||
|
||||
---
|
||||
|
||||
## Nommage — `PluginEnvName()`
|
||||
## Champs de `CheckerDefinition`
|
||||
|
||||
Renvoie un ou plusieurs identifiants courts en minuscules. Ces noms sont utilisés pour retrouver le plugin via l'API et pour indexer sa configuration stockée.
|
||||
|
||||
```go
|
||||
func (p *MyPlugin) PluginEnvName() []string {
|
||||
return []string{"myplugin"}
|
||||
}
|
||||
```
|
||||
|
||||
Choisissez des noms peu susceptibles d'entrer en conflit (ex. `"zonemaster"`, `"matrixim"`) et gardez-les **stables entre les versions**, car ils sont persistés avec la configuration utilisateur. Si deux plugins chargés revendiquent le même nom, le second est ignoré et un conflit est journalisé.
|
||||
|
||||
---
|
||||
|
||||
## Version et disponibilité — `Version()`
|
||||
|
||||
Décrit le plugin et contrôle l'endroit où il apparaît dans l'interface :
|
||||
|
||||
```go
|
||||
func (p *MyPlugin) Version() happydns.PluginVersionInfo {
|
||||
return happydns.PluginVersionInfo{
|
||||
Name: "My Plugin",
|
||||
Version: "1.0",
|
||||
AvailableOn: happydns.PluginAvailability{
|
||||
ApplyToDomain: true,
|
||||
ApplyToService: false,
|
||||
LimitToProviders: nil, // nil ou vide = tous les fournisseurs
|
||||
LimitToServices: []string{"abstract.MatrixIM"},
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
Le `*CheckerDefinition` renvoyé par `NewCheckerPlugin` est la description de votre checker :
|
||||
|
||||
| Champ | Type | Description |
|
||||
|---|---|---|
|
||||
| `ApplyToDomain` | `bool` | Le plugin peut être exécuté sur un domaine entier |
|
||||
| `ApplyToService` | `bool` | Le plugin peut être exécuté sur un service DNS spécifique |
|
||||
| `LimitToProviders` | `[]string` | Restreint à certains identifiants de fournisseurs DNS (vide = aucune restriction) |
|
||||
| `LimitToServices` | `[]string` | Restreint à certains types de services, ex. `"abstract.MatrixIM"` (vide = aucune restriction) |
|
||||
| `ID` | `string` | **Requis.** Identifiant stable et persistant. Choisissez une valeur préfixée par un espace de noms (`com.example.dnssec-freshness`, et non `dnssec`) et ne la changez jamais : elle indexe les résultats stockés et la configuration utilisateur. |
|
||||
| `Name` | `string` | Nom lisible affiché dans l'interface. |
|
||||
| `Version` | `string` | Version du plugin (par exemple `"1.0.0"`). |
|
||||
| `Availability` | `CheckerAvailability` | Déclare les portées auxquelles le checker s'applique et d'éventuelles restrictions de fournisseur ou de service (voir ci-dessous). |
|
||||
| `Options` | `CheckerOptionsDocumentation` | Documente les options acceptées par le checker, regroupées par portée (voir ci-dessous). |
|
||||
| `Rules` | `[]CheckRule` | Les règles évaluées sur l'observation collectée. |
|
||||
| `Aggregator` | `CheckAggregator` | Optionnel. Combine les `CheckState` produits par chaque règle en un état de synthèse unique. |
|
||||
| `Interval` | `*CheckIntervalSpec` | Bornes de planification optionnelles (durées `Min`, `Max`, `Default`). |
|
||||
| `HasHTMLReport` | `bool` | À activer lorsque le provider implémente `CheckerHTMLReporter`. |
|
||||
| `HasMetrics` | `bool` | À activer lorsque le provider implémente `CheckerMetricsReporter`. |
|
||||
| `ObservationKeys` | `[]ObservationKey` | Les clés d'observation que ce checker lit. |
|
||||
|
||||
`ApplyToDomain` et `ApplyToService` peuvent être tous les deux `true` simultanément.
|
||||
### Disponibilité
|
||||
|
||||
---
|
||||
|
||||
## Options — `AvailableOptions()`
|
||||
|
||||
Les options sont des paires clé/valeur (`map[string]any`) qui configurent chaque exécution de test. Elles sont déclarées regroupées par **portée**, c'est-à-dire qui les définit et combien de temps elles persistent :
|
||||
|
||||
```go
|
||||
func (p *MyPlugin) AvailableOptions() happydns.PluginOptionsDocumentation {
|
||||
return happydns.PluginOptionsDocumentation{
|
||||
RunOpts: []happydns.PluginOptionDocumentation{ /* … */ },
|
||||
ServiceOpts: []happydns.PluginOptionDocumentation{ /* … */ },
|
||||
DomainOpts: []happydns.PluginOptionDocumentation{ /* … */ },
|
||||
UserOpts: []happydns.PluginOptionDocumentation{ /* … */ },
|
||||
AdminOpts: []happydns.PluginOptionDocumentation{ /* … */ },
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Portées des options
|
||||
|
||||
| Portée | Qui la définit | Clé de stockage | Usage typique |
|
||||
|---|---|---|---|
|
||||
| `RunOpts` | L'utilisateur, au moment du test | _(transitoire)_ | Paramètres propres à l'exécution |
|
||||
| `ServiceOpts` | L'utilisateur | plugin + utilisateur + domaine + service | Configuration au niveau du service |
|
||||
| `DomainOpts` | L'utilisateur | plugin + utilisateur + domaine | Configuration au niveau du domaine |
|
||||
| `UserOpts` | L'utilisateur | plugin + utilisateur | Préférences personnelles (ex. langue) |
|
||||
| `AdminOpts` | L'administrateur | plugin | Paramètres d'instance, identifiants partagés |
|
||||
|
||||
Avant l'appel à `RunTest`, happyDomain fusionne toutes les valeurs par portée, de la moins spécifique (admin) à la plus spécifique (exécution). Les valeurs plus spécifiques écrasent silencieusement les moins spécifiques. `RunTest` reçoit toujours une map plate unique et n'a pas besoin de savoir de quelle portée provient chaque valeur.
|
||||
|
||||
### Champs d'une option
|
||||
|
||||
Chaque option est un `PluginOptionDocumentation` (un alias pour `Field`) :
|
||||
`CheckerAvailability` contrôle l'endroit où le checker est proposé dans l'interface :
|
||||
|
||||
| Champ | Type | Description |
|
||||
|---|---|---|
|
||||
| `Id` | `string` | **Obligatoire.** Clé utilisée dans la map `PluginOptions` dans `RunTest` |
|
||||
| `Type` | `string` | Type de saisie : `"string"`, `"select"` |
|
||||
| `Label` | `string` | Libellé lisible affiché dans l'interface |
|
||||
| `Placeholder` | `string` | Texte indicatif du champ de saisie |
|
||||
| `Default` | `any` | Valeur par défaut pré-remplie dans le formulaire |
|
||||
| `Choices` | `[]string` | Options pour les saisies de type `"select"` |
|
||||
| `Required` | `bool` | Indique si le champ doit être rempli avant l'exécution |
|
||||
| `Secret` | `bool` | Marque le champ comme sensible (ex. une clé API) |
|
||||
| `Hide` | `bool` | Masque entièrement le champ à l'utilisateur |
|
||||
| `Textarea` | `bool` | Affiche une zone de texte multiligne |
|
||||
| `Description` | `string` | Texte d'aide affiché sous le champ |
|
||||
| `AutoFill` | `string` | Remplit le champ automatiquement depuis le contexte (voir ci-dessous) |
|
||||
| `ApplyToDomain` | `bool` | Le checker peut s'exécuter sur un domaine entier. |
|
||||
| `ApplyToZone` | `bool` | Le checker peut s'exécuter sur une zone. |
|
||||
| `ApplyToService` | `bool` | Le checker peut s'exécuter sur un service précis. |
|
||||
| `LimitToProviders` | `[]string` | Restreint à certains identifiants de fournisseurs DNS (vide = aucune restriction). |
|
||||
| `LimitToServices` | `[]string` | Restreint à certains identifiants de types de services, par exemple `"abstract.MatrixIM"` (vide = aucune restriction). |
|
||||
|
||||
### Remplissage automatique
|
||||
### Options
|
||||
|
||||
Lorsque `AutoFill` est défini, happyDomain remplit le champ à partir du contexte du test ; l'utilisateur n'est pas sollicité :
|
||||
Les options sont déclarées par **portée**, c'est-à-dire selon qui les définit et combien de temps elles persistent. Chaque portée est une tranche de `CheckerOptionDocumentation` :
|
||||
|
||||
| Constante | Valeur chaîne | Rempli avec |
|
||||
| Portée | Qui la définit | Usage habituel |
|
||||
|---|---|---|
|
||||
| `happydns.AutoFillDomainName` | `"domain_name"` | FQDN du domaine testé, ex. `"example.com."` |
|
||||
| `happydns.AutoFillSubdomain` | `"subdomain"` | Sous-domaine relatif à la zone, ex. `"www"` — tests à portée service uniquement |
|
||||
| `happydns.AutoFillServiceType` | `"service_type"` | Identifiant du type de service, ex. `"abstract.MatrixIM"` — tests à portée service uniquement |
|
||||
| `AdminOpts` | Administrateur | Réglages valables pour toute l'instance, identifiants partagés. |
|
||||
| `UserOpts` | Utilisateur | Préférences personnelles (par exemple la langue). |
|
||||
| `DomainOpts` | Utilisateur | Configuration au niveau du domaine. |
|
||||
| `ServiceOpts` | Utilisateur | Configuration au niveau du service. |
|
||||
| `RunOpts` | Utilisateur, au moment de l'exécution | Paramètres propres à une invocation. |
|
||||
|
||||
```go
|
||||
{
|
||||
Id: "domainName",
|
||||
Type: "string",
|
||||
Label: "Nom de domaine",
|
||||
AutoFill: happydns.AutoFillDomainName,
|
||||
Required: true,
|
||||
}
|
||||
```
|
||||
happyDomain fusionne les valeurs des différentes portées, de la moins spécifique (administrateur) à la plus spécifique (exécution), avant d'appeler `Collect`. Le provider reçoit donc une unique table `CheckerOptions` à plat. Chaque option est un `CheckerOptionField` avec des champs comme `Id`, `Type`, `Label`, `Default`, `Choices`, `Required`, `Secret`, `Description` et `AutoFill`. On lit les valeurs typées de la table à l'aide des fonctions du SDK `checker.GetOption`, `checker.GetIntOption`, `checker.GetBoolOption`, …
|
||||
|
||||
{{< notice style="info" >}}
|
||||
Lorsque happyDomain enregistre un checker externalisable, il ajoute automatiquement une option d'administration `endpoint`. L'administrateur peut ainsi déléguer la collecte à un point d'accès HTTP distant plutôt que de l'exécuter dans le processus. Laissée vide, elle fait fonctionner le checker localement.
|
||||
{{< /notice >}}
|
||||
|
||||
---
|
||||
|
||||
## Exécuter la vérification — `RunTest()`
|
||||
## L'`ObservationProvider`
|
||||
|
||||
`RunTest` reçoit la map d'options fusionnée et une map de métadonnées (réservée à un usage futur), effectue la vérification et renvoie un `PluginResult`.
|
||||
|
||||
Convertissez toujours les valeurs d'options vers un type concret avant de les utiliser — la map contient des valeurs de type `any` :
|
||||
Le provider est la moitié du checker chargée de la collecte :
|
||||
|
||||
```go
|
||||
func (p *MyPlugin) RunTest(opts happydns.PluginOptions, _ map[string]string) (*happydns.PluginResult, error) {
|
||||
domain, ok := opts["domainName"].(string)
|
||||
if !ok || domain == "" {
|
||||
return nil, fmt.Errorf("l'option domainName est obligatoire")
|
||||
}
|
||||
|
||||
// … effectuer la vérification …
|
||||
|
||||
return &happydns.PluginResult{
|
||||
Status: happydns.PluginResultStatusOK,
|
||||
StatusLine: "Tout est bon",
|
||||
Report: myStructuredReport,
|
||||
}, nil
|
||||
type ObservationProvider interface {
|
||||
Key() ObservationKey
|
||||
Collect(ctx context.Context, opts CheckerOptions) (any, error)
|
||||
}
|
||||
```
|
||||
|
||||
Retournez une **erreur non nulle** uniquement pour les échecs inattendus (erreurs réseau, configuration invalide). Pour les échecs de vérification attendus — le service surveillé est indisponible, les enregistrements DNS sont incorrects — retournez un `PluginResult` avec un statut approprié et un `StatusLine` lisible par un humain.
|
||||
- `Key()` renvoie la clé d'observation que ce provider remplit. Elle doit correspondre à l'une des `ObservationKeys` déclarées dans la définition.
|
||||
- `Collect` effectue le travail réel (une requête DNS, un appel HTTP, …) et renvoie n'importe quelle valeur sérialisable en JSON. happyDomain la convertit en JSON et la met en cache ; les règles la relisent ensuite.
|
||||
|
||||
### Champs du résultat
|
||||
Un provider peut implémenter des interfaces supplémentaires du SDK pour étendre son comportement :
|
||||
|
||||
| Champ | Type | Description |
|
||||
|---|---|---|
|
||||
| `Status` | `PluginResultStatus` | Niveau de résultat global (voir ci-dessous) |
|
||||
| `StatusLine` | `string` | Résumé court affiché dans l'interface |
|
||||
| `Report` | `any` | Toute valeur sérialisable en JSON, stockée comme données de diagnostic structurées |
|
||||
|
||||
### Niveaux de statut (du pire au meilleur)
|
||||
|
||||
| Constante | Signification |
|
||||
| Interface | Rôle |
|
||||
|---|---|
|
||||
| `PluginResultStatusKO` | La vérification a échoué |
|
||||
| `PluginResultStatusWarn` | La vérification a réussi avec des avertissements |
|
||||
| `PluginResultStatusInfo` | Informatif, aucune action requise |
|
||||
| `PluginResultStatusOK` | La vérification a entièrement réussi |
|
||||
| `CheckerHTMLReporter` | `GetHTMLReport(ctx ReportContext)` rend l'observation stockée sous forme de document HTML. |
|
||||
| `CheckerMetricsReporter` | `ExtractMetrics(ctx ReportContext, collectedAt)` produit des métriques temporelles. |
|
||||
| `CheckEnabler` | `IsEligible(ctx, opts)` décide, à partir des données réelles de la cible, s'il est pertinent d'exécuter le checker. |
|
||||
| `DiscoveryPublisher` | `DiscoverEntries(data)` publie des enregistrements `DiscoveryEntry` que d'autres checkers peuvent consommer. |
|
||||
|
||||
Les règles renvoient des valeurs `CheckState` dont le `Status` vaut `StatusOK`, `StatusInfo`, `StatusWarn`, `StatusCrit`, `StatusError` ou `StatusUnknown`.
|
||||
|
||||
### Optionnel : serveur autonome
|
||||
|
||||
Le SDK fournit aussi `checker.Server`, une ossature HTTP pour exécuter un checker comme un point d'accès distant plutôt que (ou en plus) d'un plugin chargé dans le processus. Elle expose les routes `/health` et `/collect`, ainsi que `/definition`, `/evaluate` et `/report` lorsque le provider implémente les interfaces optionnelles correspondantes. Un provider qui implémente `CheckerInteractive` (`RenderForm` / `ParseForm`) dispose en outre d'un formulaire `/check` destiné aux humains, utilisable en dehors de happyDomain. Voir le [README du SDK](https://git.happydns.org/checker-sdk-go) pour les détails ; le mode plugin décrit plus haut n'en a pas besoin.
|
||||
|
||||
---
|
||||
|
||||
## Compilation
|
||||
## Contraintes de build
|
||||
|
||||
```bash
|
||||
go build -buildmode=plugin -o happydomain-plugin-test-myplugin.so \
|
||||
git.happydns.org/happyDomain/plugins/myplugin
|
||||
```
|
||||
Le paquet `plugin` de Go est intransigeant. Pour se charger correctement, votre plugin doit être compilé avec :
|
||||
|
||||
`Makefile` minimal :
|
||||
- la **même version de la chaîne d'outils Go** que happyDomain, jusqu'au même niveau de correctif ;
|
||||
- les **mêmes versions de chaque dépendance partagée** (à figer dans votre `go.mod`, en vendorisant les versions exactes que happyDomain embarque) ;
|
||||
- `CGO_ENABLED=1` ;
|
||||
- les mêmes `GOOS` et `GOARCH` que le binaire hôte.
|
||||
|
||||
```makefile
|
||||
PLUGIN_NAME=myplugin
|
||||
TARGET=../happydomain-plugin-test-$(PLUGIN_NAME).so
|
||||
Si l'un de ces points ne correspond pas, `plugin.Open` échoue avec une erreur parfois obscure, du type *« plugin was built with a different version of package … »*. L'hôte la journalise et ignore le fichier.
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): *.go
|
||||
go build -buildmode=plugin -o $@ git.happydns.org/happyDomain/plugins/$(PLUGIN_NAME)
|
||||
```
|
||||
|
||||
Le préfixe `happydomain-plugin-test-` est une convention ; happyDomain charge tous les fichiers présents dans les répertoires de plugins, quel que soit leur nom.
|
||||
Le paquet `plugin` de Go ne fonctionne que sur **linux**, **darwin** et **freebsd**. Sur les autres plateformes, happyDomain est construit sans prise en charge des plugins et les répertoires configurés sont ignorés, avec un avertissement journalisé au démarrage.
|
||||
|
||||
---
|
||||
|
||||
## Déploiement
|
||||
## Sécurité et déploiement
|
||||
|
||||
### 1. Copier le fichier `.so`
|
||||
### Permissions du répertoire et des fichiers
|
||||
|
||||
Charger un fichier `.so` revient à exécuter du code arbitraire avec les droits du processus happyDomain. Le chargeur impose donc des règles strictes de propriété avant de toucher au moindre fichier :
|
||||
|
||||
- Le répertoire des plugins **ne doit pas être un lien symbolique** : happyDomain refuse de le suivre, pour éviter qu'il soit redirigé vers un chemin contrôlé par un attaquant.
|
||||
- Le répertoire des plugins **ne doit pas être accessible en écriture au groupe ni à tous**. Un répertoire modifiable par quelqu'un d'autre que son propriétaire est traité comme une erreur de configuration bloquante et interrompt le chargement.
|
||||
- Tout fichier `.so` **accessible en écriture au groupe ou à tous est ignoré** (journalisé puis écarté), même dans un répertoire par ailleurs verrouillé.
|
||||
|
||||
En pratique : conservez le répertoire détenu par l'utilisateur happydomain, en mode `0755`, et les fichiers de plugins en mode `0644`.
|
||||
|
||||
```bash
|
||||
cp happydomain-plugin-test-myplugin.so /usr/lib/happydomain/plugins/
|
||||
sudo install -d -m 0755 -o happydomain /var/lib/happydomain/plugins
|
||||
sudo install -m 0644 -o happydomain checker-dummy.so /var/lib/happydomain/plugins/
|
||||
```
|
||||
|
||||
### 2. Indiquer le répertoire à happyDomain
|
||||
|
||||
`happydomain.conf` :
|
||||
|
||||
```
|
||||
plugins-directories=/usr/lib/happydomain/plugins
|
||||
```
|
||||
|
||||
Variable d'environnement :
|
||||
### Construire le plugin
|
||||
|
||||
```bash
|
||||
HAPPYDOMAIN_PLUGINS_DIRECTORIES=/usr/lib/happydomain/plugins
|
||||
CGO_ENABLED=1 go build -buildmode=plugin -o checker-dummy.so ./plugin
|
||||
```
|
||||
|
||||
Plusieurs répertoires peuvent être listés en les séparant par des virgules.
|
||||
### Indiquer le répertoire à happyDomain
|
||||
|
||||
### 3. Vérifier les journaux
|
||||
Le répertoire se configure avec l'option **`--plugins-directory`**, qui **peut être répétée** pour analyser plusieurs répertoires :
|
||||
|
||||
En cas de chargement réussi :
|
||||
|
||||
```
|
||||
Plugin My Plugin loaded (version 1.0)
|
||||
```bash
|
||||
happydomain --plugins-directory /var/lib/happydomain/plugins
|
||||
```
|
||||
|
||||
En cas de conflit de nom ou d'erreur de chargement, un avertissement est journalisé avec le nom du fichier et la raison.
|
||||
La variable d'environnement équivalente est `HAPPYDOMAIN_PLUGINS_DIRECTORY`.
|
||||
|
||||
Le chargeur analyse chaque répertoire configuré et tente de charger tous les fichiers `.so` qu'il y trouve. Un plugin qui échoue au chargement (mauvaise compilation, symboles absents, panique dans sa fabrique) est journalisé puis ignoré, sans interrompre le démarrage : un seul `.so` défectueux n'empêche jamais le chargement des autres.
|
||||
|
||||
### Redémarrer et vérifier les journaux
|
||||
|
||||
```bash
|
||||
sudo systemctl restart happydomain
|
||||
```
|
||||
|
||||
En cas de chargement réussi, happyDomain journalise :
|
||||
|
||||
```
|
||||
Plugin com.example.dummy (/var/lib/happydomain/plugins/checker-dummy.so) loaded
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implémentations de référence
|
||||
## Licence
|
||||
|
||||
Deux plugins sont fournis dans ce répertoire :
|
||||
Les plugins checker n'importent que `git.happydns.org/checker-sdk-go/checker`, sous licence **Apache-2.0**. Le SDK a été délibérément détaché du cœur de happyDomain (sous AGPL-3.0) pour offrir une API publique réduite et stable aux checkers tiers.
|
||||
|
||||
- **`matrix/`** — interroge l'API de test de fédération Matrix. Illustre `ApplyToService` avec `LimitToServices` et `AdminOpts` pour l'URL du serveur tiers.
|
||||
- **`zonemaster/`** — pilote l'API JSON-RPC de Zonemaster, attend la fin du test et agrège les résultats par niveau de sévérité. Illustre `AutoFillDomainName`, `UserOpts` pour la sélection de la langue et la gestion de statuts multi-niveaux.
|
||||
Un plugin construit avec ce SDK n'est donc **pas** une œuvre dérivée de happyDomain. Vous pouvez distribuer votre `.so` sous la licence de votre choix (MIT, Apache, propriétaire ou AGPL, selon vos besoins).
|
||||
|
||||
---
|
||||
|
||||
## Implémentation de référence
|
||||
|
||||
[`checker-dummy`](https://git.happydns.org/checker-dummy) est le modèle complet et documenté dont s'inspire cette page. Partez-en pour écrire votre propre checker.
|
||||
|
|
|
|||
|
|
@ -2,9 +2,36 @@
|
|||
date: 2021-01-12T21:38:49+02:00
|
||||
author: Frederic
|
||||
title: SOA (Start Of Authority)
|
||||
description: "Understand the Start Of Authority record, the mandatory record at the apex of every DNS zone, and how happyDomain manages it for you."
|
||||
weight: 10
|
||||
aliases:
|
||||
records/SOA
|
||||
---
|
||||
|
||||
The Start of Authority-SOA is the first record of a zone.
|
||||
The **Start Of Authority** (SOA) record is defined by [RFC 1035](https://www.rfc-editor.org/rfc/rfc1035). It is mandatory and unique: exactly one SOA must sit at the apex (the root) of every DNS zone. Its presence declares that the name server is authoritative for the zone and carries the parameters that govern how the zone is replicated between servers and cached by resolvers.
|
||||
|
||||
## Fields of the SOA record
|
||||
|
||||
The SOA record gathers seven values:
|
||||
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| **MNAME** (primary name server) | The hostname of the primary (master) name server for the zone. |
|
||||
| **RNAME** (responsible party) | The email address of the person responsible for the zone, encoded in DNS form: the `@` is replaced by a dot (for example `hostmaster.example.com.` means `hostmaster@example.com`). |
|
||||
| **Serial** | A version number for the zone. It must increase every time the zone changes, so that secondary servers know they need to transfer the new content. |
|
||||
| **Refresh** | How often (in seconds) a secondary server checks the primary for an updated serial. |
|
||||
| **Retry** | How long (in seconds) a secondary waits before retrying a failed refresh. |
|
||||
| **Expire** | How long (in seconds) a secondary keeps serving the zone when it cannot reach the primary, before considering the data stale. |
|
||||
| **Minimum** (negative-cache TTL) | The duration for which resolvers cache negative answers (NXDOMAIN), per [RFC 2308](https://www.rfc-editor.org/rfc/rfc2308). |
|
||||
|
||||
## The SOA in happyDomain
|
||||
|
||||
happyDomain does not present the SOA as a standalone record to edit field by field. Instead, the apex of your zone is modelled as an **Origin** service, which groups the SOA together with the zone's name servers (NS records). You will therefore find the SOA at the root of your domain, alongside the list of authoritative name servers, rather than in a separate form.
|
||||
|
||||
The **serial** is, in most cases, handled automatically. When you publish your changes, many DNS providers manage the serial themselves: happyDomain detects this capability and re-reads the zone after publication to reflect the serial the provider actually assigned. You normally do not need (nor are you expected) to set it by hand.
|
||||
|
||||
{{% notice style="info" title="What you can and cannot change" %}}
|
||||
The exact behaviour depends on your DNS provider. Some providers expose the full SOA and let happyDomain submit its values; others manage the SOA serial — and sometimes the other timers — on their side. When the provider takes care of the serial, any value happyDomain shows for it simply reflects the published state and is refreshed automatically.
|
||||
{{% /notice %}}
|
||||
|
||||
For more on how the apex and other groupings are represented, see the {{< relref "../services" >}} chapter.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,36 @@
|
|||
---
|
||||
date: 2020-12-15T01:01:08+01:00
|
||||
title: SOA (Start Of Authority)
|
||||
description: "Comprendre l'enregistrement Start Of Authority, présent obligatoirement à la racine de chaque zone DNS, et la façon dont happyDomain le gère pour vous."
|
||||
weight: 10
|
||||
aliases:
|
||||
records/SOA
|
||||
---
|
||||
|
||||
Le SOA est le premier enregistrement d'une zone.
|
||||
L'enregistrement **Start Of Authority** (SOA) est défini par la [RFC 1035](https://www.rfc-editor.org/rfc/rfc1035). Il est obligatoire et unique : un seul SOA figure à l'apex (la racine) de chaque zone DNS. Sa présence indique que le serveur de noms fait autorité sur la zone. Il porte également les paramètres qui régissent la réplication de la zone entre serveurs et sa mise en cache par les résolveurs.
|
||||
|
||||
## Les champs de l'enregistrement SOA
|
||||
|
||||
Le SOA réunit sept valeurs :
|
||||
|
||||
| Champ | Description |
|
||||
|---|---|
|
||||
| **MNAME** (serveur primaire) | Le nom du serveur de noms primaire (maître) de la zone. |
|
||||
| **RNAME** (responsable) | L'adresse de courriel du responsable de la zone, encodée à la manière du DNS : le `@` est remplacé par un point. Ainsi, `hostmaster.example.com.` désigne `hostmaster@example.com`. |
|
||||
| **Serial** | Un numéro de version de la zone. Il augmente à chaque modification, afin que les serveurs secondaires sachent qu'ils doivent transférer le nouveau contenu. |
|
||||
| **Refresh** | L'intervalle (en secondes) au bout duquel un serveur secondaire vérifie le numéro de série auprès du primaire. |
|
||||
| **Retry** | Le délai (en secondes) que respecte un secondaire avant de retenter une vérification ayant échoué. |
|
||||
| **Expire** | La durée (en secondes) pendant laquelle un secondaire continue de servir la zone lorsqu'il ne parvient pas à joindre le primaire, avant de considérer les données comme périmées. |
|
||||
| **Minimum** (cache négatif) | La durée pendant laquelle les résolveurs conservent en cache les réponses négatives (NXDOMAIN), selon la [RFC 2308](https://www.rfc-editor.org/rfc/rfc2308). |
|
||||
|
||||
## Le SOA dans happyDomain
|
||||
|
||||
happyDomain ne présente pas le SOA comme un enregistrement à éditer champ par champ. La racine de votre zone est plutôt modélisée par un service **Origin**, qui regroupe le SOA et les serveurs de noms de la zone (les enregistrements NS). On retrouve donc le SOA à la racine du domaine, aux côtés de la liste des serveurs faisant autorité, et non dans un formulaire distinct.
|
||||
|
||||
Le **numéro de série** est, dans la plupart des cas, géré automatiquement. Lors de la publication de vos modifications, de nombreux hébergeurs DNS gèrent eux-mêmes ce numéro. happyDomain détecte cette capacité, puis relit la zone après publication afin de refléter le numéro de série réellement attribué par l'hébergeur. Vous n'avez normalement pas à le renseigner à la main.
|
||||
|
||||
{{% notice style="info" title="Ce que l'on peut modifier, et ce que l'on ne peut pas" %}}
|
||||
Le comportement exact dépend de votre hébergeur DNS. Certains exposent l'ensemble du SOA et laissent happyDomain en transmettre les valeurs ; d'autres gèrent eux-mêmes le numéro de série (et parfois les autres minuteries). Lorsque l'hébergeur prend en charge le numéro de série, la valeur affichée par happyDomain reflète simplement l'état publié et se met à jour automatiquement.
|
||||
{{% /notice %}}
|
||||
|
||||
Pour en savoir plus sur la représentation de l'apex et des autres regroupements, consultez le chapitre {{< relref "../services" >}}.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,40 @@ title: TXT
|
|||
weight: 20
|
||||
aliases:
|
||||
records/TXT
|
||||
description: "The TXT record attaches free-form text to a DNS name. Learn what it is used for and how happyDomain edits it through the Text Record service."
|
||||
---
|
||||
|
||||
Please, help us to write this Documentation screen
|
||||
A **TXT record** (defined in [RFC 1035](https://www.rfc-editor.org/rfc/rfc1035)) attaches one or more free-form text strings to a name in your zone. It carries no predefined meaning of its own, which makes it one of the most versatile record types: any application is free to define its own convention for the text it stores there.
|
||||
|
||||
## Common uses
|
||||
|
||||
Because a TXT record can hold arbitrary text, it has become the carrier for many widespread conventions:
|
||||
|
||||
- **Domain ownership and site verification** — a provider asks you to publish a token so it can confirm you control the domain.
|
||||
- **SPF** — declares which servers are allowed to send e-mail for your domain.
|
||||
- **DKIM** — publishes the public key used to sign your outgoing e-mail.
|
||||
- **DMARC** — sets the policy applied when SPF or DKIM checks fail.
|
||||
- Various other key or policy publications defined by different tools.
|
||||
|
||||
For most of these purposes, happyDomain offers dedicated, higher-level **services** (SPF, DKIM, DMARC, site verification, and more) that are easier and safer to use than a raw TXT record: they guide you with the right fields and validate the syntax for you. Browse them in the {{< relref "/reference/services" >}} chapter, in particular the e-mail-related services. Prefer those services whenever one matches your need.
|
||||
|
||||
{{% notice style="info" title="When a TXT record becomes a service" %}}
|
||||
When happyDomain reads your zone, it recognises TXT records that follow a known convention (SPF, DKIM, DMARC, …) and presents them as their dedicated service rather than as a plain Text Record. Only TXT records without a recognised prefix or syntax are shown as a raw **Text Record**.
|
||||
{{% /notice %}}
|
||||
|
||||
## Editing a TXT record in happyDomain
|
||||
|
||||
In the zone editor, a plain TXT record appears as a **Text Record** service. It is intentionally minimal: a single field holds the text content of the record.
|
||||
|
||||
To work with one:
|
||||
|
||||
1. Open the subdomain where the record should live (the apex of the zone, or any subdomain such as `www`).
|
||||
2. Add or open the **Text Record** service.
|
||||
3. Type the full text string in its only field.
|
||||
4. Adjust the **TTL** if needed, then publish your changes to apply them.
|
||||
|
||||
The value you enter is stored verbatim. Editing it and publishing updates the corresponding TXT record on that subdomain.
|
||||
|
||||
{{% notice style="note" title="Long strings" %}}
|
||||
A single text string inside a TXT record cannot exceed 255 bytes at the DNS protocol level. Longer values are automatically split into 255-byte chunks for you. You simply enter the complete string in happyDomain — no manual splitting is required.
|
||||
{{% /notice %}}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,40 @@ title: TXT
|
|||
weight: 20
|
||||
aliases:
|
||||
records/TXT
|
||||
description: "L'enregistrement TXT associe du texte libre à un nom DNS. Découvrez à quoi il sert et comment happyDomain l'édite grâce au service Enregistrement texte."
|
||||
---
|
||||
|
||||
Documentation à faire
|
||||
Un **enregistrement TXT** (défini par la [RFC 1035](https://www.rfc-editor.org/rfc/rfc1035)) associe une ou plusieurs chaînes de texte libre à un nom de votre zone. Il ne porte aucune signification propre. C'est ce qui en fait l'un des types d'enregistrement les plus polyvalents : chaque application est libre de définir sa propre convention pour le texte qu'elle y dépose.
|
||||
|
||||
## Usages courants
|
||||
|
||||
Comme un enregistrement TXT peut contenir n'importe quel texte, il est devenu le support de nombreuses conventions répandues :
|
||||
|
||||
- **Vérification de propriété ou de site** : un fournisseur demande de publier un jeton afin de confirmer que l'on contrôle bien le domaine.
|
||||
- **SPF** : déclare quels serveurs sont autorisés à envoyer du courrier pour le domaine.
|
||||
- **DKIM** : publie la clé publique servant à signer le courrier sortant.
|
||||
- **DMARC** : définit la politique à appliquer lorsqu'une vérification SPF ou DKIM échoue.
|
||||
- Diverses autres publications de clés ou de politiques propres à différents outils.
|
||||
|
||||
Pour la plupart de ces usages, happyDomain propose des **services** dédiés, de plus haut niveau (SPF, DKIM, DMARC, vérification de site, etc.). Ils sont plus simples et plus sûrs à utiliser qu'un enregistrement TXT brut : ils guident la saisie avec les bons champs et en valident la syntaxe. On les retrouve dans le chapitre {{< relref "/reference/services" >}}, notamment parmi les services liés au courrier électronique. Mieux vaut recourir à ces services dès que l'un d'eux correspond au besoin.
|
||||
|
||||
{{% notice style="info" title="Quand un enregistrement TXT devient un service" %}}
|
||||
Lorsque happyDomain lit votre zone, il reconnaît les enregistrements TXT qui suivent une convention connue (SPF, DKIM, DMARC, etc.) et les présente sous leur service dédié plutôt que comme un simple enregistrement texte. Seuls les enregistrements TXT sans préfixe ni syntaxe reconnus apparaissent comme un **Enregistrement texte** brut.
|
||||
{{% /notice %}}
|
||||
|
||||
## Éditer un enregistrement TXT dans happyDomain
|
||||
|
||||
Dans l'éditeur de zone, un enregistrement TXT ordinaire apparaît sous la forme d'un service **Enregistrement texte**. Il est volontairement minimal : un unique champ contient le contenu textuel de l'enregistrement.
|
||||
|
||||
Pour le manipuler :
|
||||
|
||||
1. Ouvrez le sous-domaine où l'enregistrement doit se trouver (la racine de la zone, ou un sous-domaine comme `www`).
|
||||
2. Ajoutez ou ouvrez le service **Enregistrement texte**.
|
||||
3. Saisissez la chaîne de texte complète dans son unique champ.
|
||||
4. Ajustez la **durée de vie** (TTL) si besoin, puis publiez vos modifications pour les appliquer.
|
||||
|
||||
La valeur saisie est conservée telle quelle. La modifier puis publier met à jour l'enregistrement TXT correspondant sur ce sous-domaine.
|
||||
|
||||
{{% notice style="note" title="Chaînes longues" %}}
|
||||
Au niveau du protocole DNS, une chaîne de texte ne peut excéder 255 octets dans un enregistrement TXT. Les valeurs plus longues sont automatiquement découpées en fragments de 255 octets. Il suffit de saisir la chaîne complète dans happyDomain : aucun découpage manuel n'est nécessaire.
|
||||
{{% /notice %}}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,57 @@
|
|||
date: 2021-01-12T21:38:49+02:00
|
||||
author: Frederic
|
||||
title: E-Mail
|
||||
description: "Declare the mail servers of a zone (MX records) and the related anti-spoofing services (SPF, DKIM, DMARC) that govern how mail is sent and received."
|
||||
aliases:
|
||||
services/email
|
||||
---
|
||||
|
||||
The E-Mail service allows you to define an e-mail server on the zone, as well as the zone settings for sending/receiving e-mails.
|
||||
The **E-Mail** service lets you declare the mail servers responsible for a zone, and points you to the companion services that control how mail is sent and authenticated for that domain.
|
||||
|
||||
In happyDomain, this service is named **E-Mail servers**: its single job is to publish the `MX` records that tell the rest of the Internet *where* to deliver mail addressed to your domain. Everything that protects *outgoing* mail (proving that a message really comes from you) is handled by separate, dedicated services described further down.
|
||||
|
||||
## Receiving mail: MX records
|
||||
|
||||
An `MX` (Mail eXchanger) record names a host that accepts mail for the domain. A zone usually publishes several of them so that delivery keeps working if one server is unavailable.
|
||||
|
||||
Each entry has two parts:
|
||||
|
||||
- **Priority** — a number that orders the servers. Sending servers try the **lowest** number first; higher numbers are used only as fallbacks. Two records sharing the same priority are treated as equivalent and load-balanced.
|
||||
- **Mail server** — the hostname of the machine that receives the mail (for example `mx1.example.com.`). This host must itself resolve to an address; it should not be a bare IP.
|
||||
|
||||
A common setup looks like this:
|
||||
|
||||
| Priority | Mail server |
|
||||
|---|---|
|
||||
| 10 | `mx1.example.com.` |
|
||||
| 20 | `mx2.example.com.` |
|
||||
|
||||
Here `mx1` is tried first, and `mx2` is the backup.
|
||||
|
||||
{{% notice style="info" title="One E-Mail service per subdomain" %}}
|
||||
The E-Mail servers service is *single*: a given subdomain can hold only one such service, which gathers all of its `MX` records together. To declare mail servers for both the apex (`example.com`) and a subdomain (`mail.example.com`), add the service to each of them separately.
|
||||
{{% /notice %}}
|
||||
|
||||
## Sending mail: authentication and anti-spoofing
|
||||
|
||||
Publishing `MX` records is enough to *receive* mail, but it says nothing about which servers are allowed to *send* mail on your behalf. Without that, anyone can forge messages using your domain. happyDomain offers several dedicated services, each managing its own DNS records, to establish that posture:
|
||||
|
||||
- **SPF** (*Sender Policy Framework*) — a `TXT` record, usually at the zone apex, that lists the servers authorized to send mail for the domain. Receivers compare the sending server against this list.
|
||||
- **DKIM** (*DomainKeys Identified Mail*) — publishes the public half of a signing key as a `TXT` record under a `._domainkey` selector. Your mail servers sign outgoing messages, and receivers verify the signature against this published key.
|
||||
- **DMARC** (*Domain-based Message Authentication, Reporting and Conformance*) — a `TXT` record at `_dmarc` that tells receivers what to do with messages failing SPF or DKIM checks (let them through, quarantine, or reject), and where to send aggregate reports.
|
||||
|
||||
Two further services cover transport security and reporting:
|
||||
|
||||
- **MTA-STS** — declares that mail to your domain must be delivered over a secured (TLS) connection.
|
||||
- **TLS-RPT** — collects reports about TLS delivery problems encountered by sending servers.
|
||||
|
||||
These services are independent of the E-Mail servers service. You can add only the ones you need, but a complete and well-protected mail configuration typically combines `MX`, SPF, DKIM and DMARC.
|
||||
|
||||
## In the zone editor
|
||||
|
||||
To configure mail for a subdomain in the happyDomain zone editor:
|
||||
|
||||
1. Add the **E-Mail servers** service to the subdomain and fill in one line per mail server, with its priority and hostname.
|
||||
2. Add **SPF**, **DKIM** and **DMARC** as their own services on the relevant subdomain (SPF and DMARC usually at the apex). Each one presents a dedicated form rather than raw record text.
|
||||
|
||||
Because each of these is a distinct abstract service, you manage them separately even though they all work together to make mail for your domain both deliverable and trustworthy. See the {{< relref "/reference/services" >}} chapter for the full list of available services.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,57 @@
|
|||
---
|
||||
date: 2020-12-15T01:01:08+01:00
|
||||
title: E-Mail
|
||||
description: "Déclarez les serveurs de courrier d'une zone (enregistrements MX) ainsi que les services complémentaires (SPF, DKIM, DMARC) qui encadrent l'envoi et la réception des courriels."
|
||||
aliases:
|
||||
services/email
|
||||
---
|
||||
|
||||
Le service E-Mail permet de définir un serveur de courrier électronique sur la zone, ainsi que le paramétrage de la zone en vue d'envoyer/recevoir des courriels.
|
||||
Le service **E-Mail** permet de déclarer les serveurs de courrier responsables d'une zone. Il oriente également vers les services associés, qui régissent la manière dont le courrier est envoyé et authentifié pour le domaine.
|
||||
|
||||
Dans happyDomain, ce service porte le nom de **E-Mail servers**. Son unique rôle consiste à publier les enregistrements `MX`, ceux qui indiquent au reste d'Internet *où* livrer les courriels adressés à votre domaine. Tout ce qui protège le courrier *sortant*, c'est-à-dire prouver qu'un message provient réellement de vous, relève de services dédiés et distincts, décrits plus bas.
|
||||
|
||||
## Recevoir du courrier : les enregistrements MX
|
||||
|
||||
Un enregistrement `MX` (*Mail eXchanger*) désigne une machine qui accepte le courrier du domaine. Une zone en publie généralement plusieurs, afin que la livraison continue de fonctionner si l'un des serveurs devient indisponible.
|
||||
|
||||
Chaque entrée comporte deux parties :
|
||||
|
||||
- **La priorité** : un nombre qui ordonne les serveurs. Les serveurs émetteurs essaient d'abord le nombre le **plus bas** ; les valeurs plus élevées ne servent que de secours. Deux enregistrements partageant la même priorité sont considérés comme équivalents et se répartissent la charge.
|
||||
- **Le serveur de courrier** : le nom d'hôte de la machine qui reçoit le courrier (par exemple `mx1.example.com.`). Cet hôte doit lui-même se résoudre vers une adresse ; il ne s'agit pas d'indiquer directement une adresse IP.
|
||||
|
||||
Une configuration courante ressemble à ceci :
|
||||
|
||||
| Priorité | Serveur de courrier |
|
||||
|---|---|
|
||||
| 10 | `mx1.example.com.` |
|
||||
| 20 | `mx2.example.com.` |
|
||||
|
||||
Ici, `mx1` est contacté en premier et `mx2` sert de secours.
|
||||
|
||||
{{% notice style="info" title="Un seul service E-Mail par sous-domaine" %}}
|
||||
Le service E-Mail servers est *unique* : un sous-domaine donné ne peut héberger qu'un seul service de ce type, qui rassemble l'ensemble de ses enregistrements `MX`. Pour déclarer des serveurs de courrier à la fois sur l'apex (`example.com`) et sur un sous-domaine (`mail.example.com`), on ajoute le service à chacun d'eux séparément.
|
||||
{{% /notice %}}
|
||||
|
||||
## Envoyer du courrier : authentification et lutte contre l'usurpation
|
||||
|
||||
Publier des enregistrements `MX` suffit pour *recevoir* du courrier, mais ne dit rien sur les serveurs autorisés à en *envoyer* en votre nom. Sans cette indication, n'importe qui peut forger des messages au nom de votre domaine. happyDomain propose plusieurs services dédiés, chacun gérant ses propres enregistrements DNS, pour établir cette protection :
|
||||
|
||||
- **SPF** (*Sender Policy Framework*) : un enregistrement `TXT`, placé en général à l'apex de la zone, qui énumère les serveurs autorisés à envoyer du courrier pour le domaine. Les destinataires comparent le serveur émetteur à cette liste.
|
||||
- **DKIM** (*DomainKeys Identified Mail*) : publie la partie publique d'une clé de signature dans un enregistrement `TXT`, sous un sélecteur `._domainkey`. Vos serveurs signent les messages sortants, et les destinataires vérifient la signature à l'aide de cette clé publiée.
|
||||
- **DMARC** (*Domain-based Message Authentication, Reporting and Conformance*) : un enregistrement `TXT` placé sur `_dmarc`, qui indique aux destinataires comment traiter les messages échouant aux contrôles SPF ou DKIM (les laisser passer, les mettre en quarantaine ou les rejeter), et où envoyer les rapports agrégés.
|
||||
|
||||
Deux autres services couvrent la sécurité du transport et la remontée d'informations :
|
||||
|
||||
- **MTA-STS** : déclare que le courrier destiné à votre domaine doit être livré au travers d'une connexion sécurisée (TLS).
|
||||
- **TLS-RPT** : recueille les rapports relatifs aux problèmes de livraison TLS rencontrés par les serveurs émetteurs.
|
||||
|
||||
Ces services sont indépendants du service E-Mail servers. On peut n'ajouter que ceux dont on a besoin, mais une configuration de courrier complète et bien protégée associe le plus souvent `MX`, SPF, DKIM et DMARC.
|
||||
|
||||
## Dans l'éditeur de zone
|
||||
|
||||
Pour configurer le courrier d'un sous-domaine dans l'éditeur de zone de happyDomain :
|
||||
|
||||
1. On ajoute le service **E-Mail servers** au sous-domaine, puis on renseigne une ligne par serveur de courrier, avec sa priorité et son nom d'hôte.
|
||||
2. On ajoute **SPF**, **DKIM** et **DMARC** en tant que services à part entière sur le sous-domaine concerné (SPF et DMARC se placent généralement à l'apex). Chacun présente un formulaire dédié plutôt que le contenu brut de l'enregistrement.
|
||||
|
||||
Comme chacune de ces abstractions constitue un service distinct, on les gère séparément, même si elles concourent toutes à rendre le courrier de votre domaine à la fois livrable et digne de confiance. Le chapitre {{< relref "/reference/services" >}} présente la liste complète des services disponibles.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue