class

Beryl::Apply::Netif6

Inherits Beryl::Apply::Primitive < Reference < Object

Primitive netif6 : pose l'IPv6 publique STATIQUE d'un serveur, de façon persistante (sysrc ifconfig_<iface>_ipv6 + ipv6_defaultrouter) ET immédiate — SANS couper l'IPv4. Chez OVH il n'y a ni DHCPv6 ni RA/SLAAC : l'adresse est statique et la passerelle est la link-local fe80::1 (constante, scopée %<iface>).

SÛR pour le SSH v4 : l'adresse est ajoutée en alias et la route par défaut v6 posée à chaud — on ne fait JAMAIS service netif restart (qui couperait l'IPv4 de l'interface publique). Idempotent : skip si l'adresse et la route par défaut sont déjà là ET que rc.conf est à jour.

⚠️ Utiliser une adresse hôte NON nulle (<bloc>::1, pas <bloc>:: qui est l'anycast Subnet-Router → reste en DAD tentative, inutilisable).

- netif6:
    address: 2001:41d0:250:dd00::1
    prefixlen: 64            # optionnel (défaut 64)
    gateway: fe80::1         # optionnel (défaut fe80::1, OVH)
    keep: [2001:db8::5]      # optionnel : autres IPv6 globales à garder

Seules restent sur l'interface l'adresse de la fiche (et keep) : toute AUTRE IPv6 globale est retirée, après la pose de la nouvelle. Une ancienne adresse oubliée servait sinon d'adresse source, non routée (ke, no : ancien bloc resté à côté du bon, rien ne sortait). Les link-local (fe80::) et ::1 ne sont jamais touchées.

Passerelle GLOBALE (anciennes gammes OVH : <bloc /56>ff:ff:ff:ff:ff, hors du /64 du serveur) : elle n'est joignable qu'avec une route hôte « sur le lien » posée AVANT la route par défaut — à chaud (route -6 add -host GW -interface IFACE) et au boot (ipv6_static_routes += beryl_gw, que rc.d/routing applique avant ipv6_defaultrouter). Revenir à fe80::1 retire cette route de rc.conf.

Le routeur interroge alors le serveur (NDP « who has <adresse> ») depuis une adresse HORS du préfixe du serveur ; FreeBSD ignore ces demandes par défaut et le serveur reste injoignable en entrée (il sort, mais personne ne le joint : qwerty, 8 oct. 2026). La primitive active donc net.inet6.icmp6.nd6_onlink_ns_rfc4861=1, à chaud et dans /etc/sysctl.conf. iface: auto # optionnel (défaut : l'interface publique)

Constants

GW_ROUTE = "beryl_gw"

Nom de la route statique rc.conf vers une passerelle globale.

NS_SYSCTL = "net.inet6.icmp6.nd6_onlink_ns_rfc4861"

Réglage noyau : accepter les demandes NDP venues d'un routeur hors préfixe.

Class methods

canonical(address : String) : String

Forme canonique (RFC 5952, compressée) d'une IPv6, %scope gardé : l'API OVH écrit fe80:0000:…:0001, netstat et rc.conf fe80::1. Adresse illisible : rendue telle quelle. Pur, exposé pour test.

Source
gateway_scoped(gateway : String, iface : String) : String

Passerelle scopée : une gw link-local (fe80::…) exige %<iface> pour être routable ; une gw globale reste telle quelle. Pur, exposé pour test.

Source
gw_route_value(gateway : String, iface : String) : String

Valeur ipv6_route_beryl_gw (route hôte sur le lien). Pur, exposé pour test.

Source
rc_value(address : String, prefixlen : String) : String

Valeur ifconfig_<iface>_ipv6 pour rc.conf. Pur, exposé pour test.

Source
stale_globals(current : Array(String), wanted : Array(String)) : Array(String)

IPv6 GLOBALES de l'interface à retirer : ni voulues, ni link-local (fe80::), ni ::1. Formes canoniques comparées. Pur, exposé pour test.

Source

Instance methods

apply(shell : Shell, params : Hash(String, YAML::Any), dry_run : Bool, context : Context) : StepResult

params est le hash brut du step YAML (ex: {"packages" => [...]}), déjà interpolé par l'Executor. context porte les infos dérivées du host (cf. Context).

Source
name

Nom kebab-case utilisé comme clé de step dans les recettes (« pkg-install », « service-enable », …).

Source