Aller au contenu principal

CDNSite

Disponible

Fonctionnalité déployée et prise en charge. Les champs et commandes décrits ici sont stables au sein de la version v1alpha1.

apiVersioncdn.stackngo.io/v1alpha1
kindCDNSite
Appliqué parsng apply (manifeste) ou sng cdn create, enable, disable
Commandes liéessng cdn list · upload · clear-cache · delete, sng kind get CDNSite, sng template gen CDNSite

À quoi ça sert​

Un CDNSite publie un site statique sous un nom de votre zone, derrière un cache HTTP. Par défaut, les fichiers sont rangés par la plateforme (stockage default) et vous les envoyez avec sng cdn upload. Un site peut aussi servir un bucket de stockage objet qui vous appartient (spec.s3). Le site peut être mis en maintenance (503) sans perdre son contenu, et un fichier de repli (fallback) sert les routes d'une application monopage.

Exemple minimal​

docs-site.yml
apiVersion: cdn.stackngo.io/v1alpha1
kind: CDNSite
metadata:
name: docs
spec:
domain: docs.acme.dev.stackngo.app
sng apply docs-site.yml
sng cdn upload docs ./dist

Équivalent sans manifeste : sng cdn create docs (qui ajoute fallback: index.html).

Exemple complet commenté​

docs-site.yml
apiVersion: cdn.stackngo.io/v1alpha1
kind: CDNSite
metadata:
name: docs # nom du site : minuscules, chiffres, '-' ; 63 caractères au plus
spec:
domain: v2.docs.acme.dev.stackngo.app # sous <tenant>.dev.stackngo.app, à toute profondeur ; pas de '*'
path: / # préfixe servi (défaut "/")
pathType: Prefix # Prefix (défaut), Exact ou ImplementationSpecific
fallback: index.html # servi pour une route sans extension introuvable ; chemin relatif
maintenanceMode: false # true : 503 sur tout le site, contenu conservé
tlsSecretRef: # facultatif : votre certificat (clés tls.crt et tls.key)
name: docs-tls

Avec votre propre bucket de stockage objet :

assets-site.yml
apiVersion: cdn.stackngo.io/v1alpha1
kind: CDNSite
metadata:
name: assets
spec:
domain: assets.acme.dev.stackngo.app
s3:
bucket: acme-assets # jamais le bucket de la plateforme
endpoint: https://s3.gra.io.cloud.ovh.net # https et public obligatoires ; vide = AWS
region: gra # défaut us-east-1
prefix: site/ # dossier du bucket servi à la racine du site
forcePathStyle: true # URLs path-style (MinIO, certains fournisseurs)
credentialsSecretRef:
name: acme-assets-s3 # Secret de votre tenant, label cdn.stackngo.io/s3-credentials: "true"
accessKeyIDKey: accessKeyId # défaut accessKeyId
secretAccessKeyKey: secretAccessKey # défaut secretAccessKey
# sessionTokenKey: sessionToken # jeton temporaire, facultatif
Secrets référencés

credentialsSecretRef et tlsSecretRef désignent un secret de votre tenant, déclaré par un SSMSecret avec materialize: true : c'est ce qui le rend utilisable par un site statique. Posez ensuite ses clés avec sng secret set --data :

docs-tls.yml
apiVersion: ssm.stackngo.io/v1alpha1
kind: SSMSecret
metadata:
name: docs-tls
spec:
length: 0 # vous posez la valeur vous-même
materialize: true # utilisable par le site statique
sng apply docs-tls.yml
sng secret set docs-tls --data "tls.crt=$(cat fullchain.pem)" --data "tls.key=$(cat privkey.pem)"

Pour credentialsSecretRef, même chose avec les clés accessKeyId et secretAccessKey (ou celles que vous nommez dans accessKeyIDKey / secretAccessKeyKey). Une nouvelle valeur est prise en compte par le site dans les 15 minutes.

Le Secret des clés de votre bucket​

Les clés de credentialsSecretRef ne sont lues que dans un Secret que vous confiez explicitement aux sites statiques. Ce Secret doit :

  • porter le label cdn.stackngo.io/s3-credentials: "true" ;
  • être de type Opaque (le type par défaut d'un Secret générique) ;
  • ne pas être un Secret géré par la plateforme (identifiant de registre, identifiants OIDC d'une application, secret déclaré par un autre manifeste…).

Un Secret qui ne remplit pas ces conditions est refusé sans qu'aucune requête ne parte vers votre bucket : le site reste Pending, avec la condition S3Reachable=False et la raison SecretNotAllowed. Il est réévalué chaque minute : corrigez le Secret, le site passe Ready sans autre action.

Champs​

Règles de validation croisées​

Le schéma ne porte pas de règle croisée ; il refuse un domain vide ou contenant *, un pathType hors liste, un s3 sans bucket ni credentialsSecretRef.name.

L'API refuse en plus, dès sng apply :

  • un domain en majuscules, avec un point final, ou qui n'est pas un nom complet (deux labels au moins) ;
  • un domain sous le domaine de la plateforme mais hors de votre zone (spec.domain "…" : réservé à la plateforme ou à un autre client). Un nom sous votre zone, ou sous un domaine apporté, est accepté : voir Domaine apporté plus bas ;
  • un path qui ne commence pas par / ;
  • un fallback ou un s3.prefix absolu, avec .. ou un caractère hors A-Za-z0-9._~@+=,- ;
  • un s3.bucket mal formé, ou égal au bucket de la plateforme (spec.s3 ne peut pas viser le bucket par défaut : retirer spec.s3) ;
  • un s3.endpoint en http, avec identifiants dans l'URL, interne à la plateforme ou qui résout vers une adresse non publique ;
  • le même nom de site ou le même domaine qu'un autre CDNSite de votre tenant, tous contextes confondus (409) ;
  • metadata.name différent du nom du fichier, un tenant précisé dans le manifeste, un champ inconnu (dont status).

CDNSite​

CDNSite publie un site statique sur votre domaine, servi par le CDN de la plateforme.

ChampDescriptionDéfautValidation
apiVersion stringcdn.stackngo.io/v1alpha1
kind stringCDNSite
metadata ObjectMetaSeul metadata.name est à renseigner (nom de la ressource dans votre tenant).
spec CDNSiteSpec
status CDNSiteStatus

CDNSiteSpec​

CDNSiteSpec décrit le site que vous voulez publier.

ChampDescriptionDéfautValidation
domain stringDomain est le nom d'hôte sous lequel le site est servi (par exemple www.example.com). Le joker (*) est refusé.MinLength: 1
Pattern: ^[^*]+$
Required: {}
path stringPath est le chemin d'URL sous lequel le site est servi (défaut : /)./Optional: {}
pathType stringPathType indique comment le chemin est comparé aux URL demandées : Prefix (le chemin et tout ce qui est en dessous),
Exact (ce chemin seul) ou ImplementationSpecific (règle par défaut de la plateforme).
PrefixEnum: [Prefix Exact ImplementationSpecific]
Optional: {}
maintenanceMode booleanMaintenanceMode : le site répond 503 à toutes les requêtes ; le domaine et le certificat restent en place.falseOptional: {}
fallback stringFallback est le fichier (chemin relatif à la racine du site) servi quand une route d'application
(URL sans extension) ne correspond à aucun fichier. Vide : aucune page de repli.
Exemple : "index.html" ou "public/index.html".
Optional: {}
s3 CDNSiteS3SpecVotre propre stockage objet, d'où le site est servi avec vos clés (credentialsSecretRef obligatoire).
Absent : le site est servi depuis le stockage fourni par la plateforme.
Optional: {}
tlsSecretRef LocalObjectReferenceTLSSecretRef désigne le secret de votre tenant qui contient votre propre certificat TLS (clés tls.crt et tls.key).
Absent : la plateforme obtient et renouvelle un certificat pour le domaine.
Optional: {}

CDNSiteStatus​

CDNSiteStatus est l'état du site constaté par la plateforme, dont l'emplacement effectivement servi.

ChampDescriptionDéfautValidation
observedGeneration integerObservedGeneration est la dernière version du manifeste prise en compte par la plateforme.Optional: {}
phase stringPhase : Pending, Ready, Conflict ou Invalid.Optional: {}
message stringMessage explique la phase (raison d'un Invalid, d'un Conflict…).Optional: {}
storage stringStorage : default (stockage fourni par la plateforme) ou custom (votre stockage, spec.s3).Optional: {}
bucket stringBucket est le bucket d'où le site est servi.Optional: {}
endpoint stringEndpoint est l'URL du stockage objet utilisé (vide : AWS).Optional: {}
region stringRegion est la région du stockage utilisé.Optional: {}
forcePathStyle booleanForcePathStyle indique si l'URL du bucket est construite avec le nom du bucket dans le chemin.Optional: {}
prefix stringPrefix est le dossier servi : choisi par la plateforme en stockage default, spec.s3.prefix en custom.Optional: {}
credentialsSecret stringCredentialsSecret est la référence des clés d'accès utilisées pour lire votre stockage (stockage custom uniquement).Optional: {}
tls CDNSiteTLSStatusTLS décrit le certificat HTTPS du site (mode et validation).Optional: {}
conditions Condition arrayConditions : DomainAllowed (domaine autorisé pour votre tenant), S3Reachable (stockage joignable), Ready (site servi).Optional: {}

CDNSiteS3Spec​

CDNSiteS3Spec décrit votre propre stockage objet (compatible avec l'API AWS), d'où le site est servi.

ChampDescriptionDéfautValidation
bucket stringBucket est le nom de votre bucket.MinLength: 1
Required: {}
endpoint stringEndpoint est l'URL de votre fournisseur de stockage objet (par exemple MinIO). Vide : AWS.Optional: {}
region stringRegion est la région de votre bucket (défaut : us-east-1).us-east-1Optional: {}
prefix stringPrefix est le dossier du bucket qui contient les fichiers du site (facultatif).Optional: {}
forcePathStyle booleanForcePathStyle place le nom du bucket dans le chemin de l'URL plutôt que dans le nom d'hôte (requis par exemple par MinIO).Optional: {}
credentialsSecretRef SecretKeyReferenceCredentialsSecretRef désigne le secret de votre tenant qui contient les clés d'accès au bucket. Ce secret doit porter le label cdn.stackngo.io/s3-credentials: "true" ; un secret géré par la plateforme est refusé.Required: {}

LocalObjectReference​

LocalObjectReference désigne un secret de votre tenant par son nom.

ChampDescriptionDéfautValidation
name stringName est le nom du secret.MinLength: 1

CDNSiteTLSStatus​

CDNSiteTLSStatus décrit le certificat HTTPS du site.

ChampDescriptionDéfautValidation
mode stringMode : None (site servi sans HTTPS), Custom (votre certificat, spec.tlsSecretRef), Wildcard (certificat joker
partagé par tous les sites de la zone) ou Host (certificat propre au domaine du site).
Optional: {}
challenge stringChallenge : validation du certificat obtenu par la plateforme, dns-01 (par DNS) ou http-01 (par HTTP :
le domaine doit déjà répondre depuis la plateforme). Vide pour None et Custom.
Optional: {}

SecretKeyReference​

SecretKeyReference désigne le secret de votre tenant qui contient les clés d'accès à votre stockage objet.

ChampDescriptionDéfautValidation
name stringName est le nom du secret, dans votre tenant.MinLength: 1
Required: {}
accessKeyIDKey stringAccessKeyIDKey est la clé du secret qui contient l'identifiant de la clé d'accès (défaut : accessKeyId).Optional: {}
secretAccessKeyKey stringSecretAccessKeyKey est la clé du secret qui contient la clé d'accès secrète (défaut : secretAccessKey).Optional: {}
sessionTokenKey stringSessionTokenKey est la clé du secret qui contient un jeton de session, si vos clés en exigent un.Optional: {}

Statut et conditions​

PhaseSignification
Readyle site est servi
Pendingstockage injoignable pour l'instant (Secret absent ou refusé, clés manquantes, bucket qui ne répond pas) ; nouvel essai chaque minute
Waitingdomaine apporté dont la zone DNS n'est pas encore vérifiée : le site est déclaré, il n'est servi qu'une fois la zone vérifiée (voir Domaine apporté plus bas)
Invaliddomaine non autorisé, ou stockage refusé ; pas de nouvel essai avant une modification
Conflictun autre site plus ancien, ou une autre ressource, sert déjà ce domaine

Un site qui n'est pas Ready n'est pas exposé : le CDN répond 404. status.message explique la phase ; status.storage, bucket, prefix… décrivent l'emplacement servi, status.tls le certificat (voir Certificat plus bas). sng kind get CDNSite docs affiche ces conditions en commentaires sous le manifeste ; --json donne le status complet.

ConditionTrueFalse (reason)
DomainAllowedAllowedNotAllowed : domaine hors de votre zone et de vos domaines apportés ; WaitingForDNSZone : zone DNS du domaine apporté pas encore vérifiée
S3ReachableReachableInvalid (stockage refusé), Unreachable (stockage injoignable), SecretNotAllowed (Secret des clés refusé)
ReadyReadyInvalid, Pending, Waiting ou Conflict (reprend la phase)
status.messagePhaseAction
domaine "…" non autorisé …Invalidutiliser un nom de votre zone ou d'un domaine apporté par votre tenant
en attente d'une zone DNS vérifiée couvrant "…" (suivi de zone existante en phase … si la zone existe déjà)Waitingrien à lancer : vérifier la zone du domaine, voir Apporter un domaine
domaine déjà utilisé par un autre siteConflictautre nom ; le site d'un autre tenant n'est pas nommé
domaine déjà servi par une autre ressourceConflictautre nom ; la ressource concurrente n'est pas nommée
Secret "…" introuvable …Pendingcréer le Secret référencé
secret TLS "…" introuvable : site servi sans HTTPSReadycréer le secret de tlsSecretRef, ou retirer tlsSecretRef
Secret "…" refusé : label cdn.stackngo.io/s3-credentials="true" absentPending (SecretNotAllowed)ajouter le label au Secret
Secret "…" refusé : type "…" non accepté (Opaque attendu)Pending (SecretNotAllowed)recréer le Secret en type Opaque
Secret "…" refusé : Secret géré par …Pending (SecretNotAllowed)créer un Secret dédié aux clés du bucket
Secret "…" : clés d'accès … manquantesPendingvérifier les clés, ou accessKeyIDKey / secretAccessKeyKey
… injoignable avec ces clés : …Pendingvérifier bucket, région, endpoint, droits des clés
endpoint "…" : https obligatoire (ou adresse non publique, hôte interne interdit)Invalidendpoint public en https
spec.s3 ne peut pas viser le bucket par défaut : retirer spec.s3Invalidretirer spec.s3
stockage par défaut non configuré …Invalidcontacter le support

Ce qui se passe à l'application​

Création. Le site est servi dès qu'il est Ready, en HTTPS sous le domaine demandé. Si deux sites demandent le même domaine, le plus ancien le garde ; un domaine déjà servi par une autre ressource (une App, par exemple) reste à celle-ci si elle est plus ancienne que le site. Avec votre propre bucket, la plateforme teste l'accès avec vos clés avant d'exposer le site ; un changement de vos clés est pris en compte dans les 10 minutes.

Domaine apporté. Un site peut être déclaré sous un domaine apporté avant que sa zone soit prête, et l'ordre des sng apply n'a pas d'importance. Tant que la zone DNS n'est pas vérifiée, le site est en phase Waiting (DomainAllowed=False, raison WaitingForDNSZone) : rien n'est servi, et sng cdn list le montre dans la colonne STATE. Dès que la zone est vérifiée, le site passe Ready et est servi, sans nouvelle commande. Si la zone existe mais n'est pas encore vérifiée, le message le signale avec sa phase.

Certificat. Sans tlsSecretRef, le site reçoit automatiquement un certificat HTTPS valide, en général dans les minutes qui suivent sa création, et il est renouvelé sans intervention. Pour un domaine apporté, tant que sa zone n'est pas déléguée, le certificat est obtenu nom par nom : le domaine doit déjà pointer vers la plateforme (validation HTTP). Après la délégation des serveurs de noms, le certificat joker de la zone prend le relais. Un même certificat joker (*.acme.dev.stackngo.app) couvre tous les sites placés juste sous votre zone (docs.acme.dev.stackngo.app, blog.acme.dev.stackngo.app) : le premier site de la zone l'obtient, les suivants sont en HTTPS dès leur création, et il disparaît avec le dernier. Un nom plus profond (v2.docs.acme.dev.stackngo.app) reçoit son propre certificat. Avec tlsSecretRef, votre certificat est utilisé à la place (s'il manque, le site est servi sans HTTPS et status.message le signale).

status.tls indique le certificat servi :

status.tls.modestatus.tls.challengeCertificat
Wildcarddns-01joker de votre zone, partagé par ses sites, validé par DNS
Hostdns-01propre au domaine du site, validé par DNS
Customle vôtre (tlsSecretRef)
Noneaucun : le site est servi sans HTTPS

sng kind get CDNSite docs --json donne status.tls.

Routes. Chaque dossier sert son index.html, avec ou sans / final : /docs/intro/ et /docs/intro servent docs/intro/index.html (pour /docs/intro, seulement si aucun fichier docs/intro n'existe). Le fallback ne répond qu'ensuite. Un 404 est gardé 30 secondes en cache.

Mise à jour. sng apply, sng cdn enable|disable. La maintenance est effective en 30 secondes environ ; le cache est vidé pendant la transition. Un changement de domain réexpose le site sous le nouveau nom ; en stockage default, le contenu est attaché au domaine : republiez-le (sng cdn upload).

Ce qui se passe quand vous supprimez​

sng cdn delete docs ou sng kind delete CDNSite docs : le site n'est plus servi (404), son contenu en stockage default est supprimé et son cache vidé. Votre propre bucket n'est jamais modifié. Aucun champ deletionPolicy.

Erreurs fréquentes​

SymptômeCauseCorrection
sng apply : spec.domain "…" : réservé à la plateforme ou à un autre clientnom sous le domaine de la plateforme, hors de votre zoneun nom de votre zone ou d'un domaine apporté par votre tenant
Phase Waiting, WaitingForDNSZonezone DNS du domaine apporté pas encore vérifiéeApporter un domaine ; le site se met en service seul
sng cdn upload : le site "assets" sert un bucket injecté : déposez les fichiers dans ce bucket (409)site en spec.s3envoyer les fichiers dans votre bucket, puis sng cdn clear-cache
/blog/ affiche la page d'accueilindex.html n'est servi qu'à la racine ; le fallback répondliens vers /blog/index.html, ou fichier blog.html
Un fichier tout juste publié répond 404404 gardé 30 min en cache, fichier envoyé hors sng cdn uploadsng cdn clear-cache <site>
Phase Pending, Secret "…" introuvableSecret absent du tenantvoir l'avertissement sur les Secrets référencés
Phase Pending, S3Reachable=False, SecretNotAllowedSecret des clés sans le label cdn.stackngo.io/s3-credentials: "true", pas de type Opaque, ou géré par la plateformevoir Le Secret des clés de votre bucket
Phase Conflictdomaine pris par un site plus ancien, ou par une autre ressourceautre nom de site
sng cdn create : un site "docs" existe déjà (gra/staging) (409)nom pris dans un autre contexteautre nom, ou travailler dans ce contexte

Voir aussi​