CDNSite
Fonctionnalité déployée et prise en charge. Les champs et commandes décrits ici sont stables au sein de la version v1alpha1.
apiVersion | cdn.stackngo.io/v1alpha1 |
kind | CDNSite |
| Appliqué par | sng apply (manifeste) ou sng cdn create, enable, disable |
| Commandes liées | sng 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
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é
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 :
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
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 :
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
domainen majuscules, avec un point final, ou qui n'est pas un nom complet (deux labels au moins) ; - un
domainsous 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
pathqui ne commence pas par/; - un
fallbackou uns3.prefixabsolu, avec..ou un caractère horsA-Za-z0-9._~@+=,-; - un
s3.bucketmal formé, ou égal au bucket de la plateforme (spec.s3 ne peut pas viser le bucket par défaut : retirer spec.s3) ; - un
s3.endpointenhttp, 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
CDNSitede votre tenant, tous contextes confondus (409) ; metadata.namedifférent du nom du fichier, un tenant précisé dans le manifeste, un champ inconnu (dontstatus).
CDNSite
CDNSite publie un site statique sur votre domaine, servi par le CDN de la plateforme.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
apiVersion string | cdn.stackngo.io/v1alpha1 | ||
kind string | CDNSite | ||
metadata ObjectMeta | Seul 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.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
domain string | Domain 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 string | Path est le chemin d'URL sous lequel le site est servi (défaut : /). | / | Optional: {} |
pathType string | PathType 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). | Prefix | Enum: [Prefix Exact ImplementationSpecific] Optional: {} |
maintenanceMode boolean | MaintenanceMode : le site répond 503 à toutes les requêtes ; le domaine et le certificat restent en place. | false | Optional: {} |
fallback string | Fallback 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 CDNSiteS3Spec | Votre 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 LocalObjectReference | TLSSecretRef 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.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
observedGeneration integer | ObservedGeneration est la dernière version du manifeste prise en compte par la plateforme. | Optional: {} | |
phase string | Phase : Pending, Ready, Conflict ou Invalid. | Optional: {} | |
message string | Message explique la phase (raison d'un Invalid, d'un Conflict…). | Optional: {} | |
storage string | Storage : default (stockage fourni par la plateforme) ou custom (votre stockage, spec.s3). | Optional: {} | |
bucket string | Bucket est le bucket d'où le site est servi. | Optional: {} | |
endpoint string | Endpoint est l'URL du stockage objet utilisé (vide : AWS). | Optional: {} | |
region string | Region est la région du stockage utilisé. | Optional: {} | |
forcePathStyle boolean | ForcePathStyle indique si l'URL du bucket est construite avec le nom du bucket dans le chemin. | Optional: {} | |
prefix string | Prefix est le dossier servi : choisi par la plateforme en stockage default, spec.s3.prefix en custom. | Optional: {} | |
credentialsSecret string | CredentialsSecret est la référence des clés d'accès utilisées pour lire votre stockage (stockage custom uniquement). | Optional: {} | |
tls CDNSiteTLSStatus | TLS décrit le certificat HTTPS du site (mode et validation). | Optional: {} | |
conditions Condition array | Conditions : 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.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
bucket string | Bucket est le nom de votre bucket. | MinLength: 1 Required: {} | |
endpoint string | Endpoint est l'URL de votre fournisseur de stockage objet (par exemple MinIO). Vide : AWS. | Optional: {} | |
region string | Region est la région de votre bucket (défaut : us-east-1). | us-east-1 | Optional: {} |
prefix string | Prefix est le dossier du bucket qui contient les fichiers du site (facultatif). | Optional: {} | |
forcePathStyle boolean | ForcePathStyle 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 SecretKeyReference | CredentialsSecretRef 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.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
name string | Name est le nom du secret. | MinLength: 1 |
CDNSiteTLSStatus
CDNSiteTLSStatus décrit le certificat HTTPS du site.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
mode string | Mode : 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 string | Challenge : 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.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
name string | Name est le nom du secret, dans votre tenant. | MinLength: 1 Required: {} | |
accessKeyIDKey string | AccessKeyIDKey est la clé du secret qui contient l'identifiant de la clé d'accès (défaut : accessKeyId). | Optional: {} | |
secretAccessKeyKey string | SecretAccessKeyKey est la clé du secret qui contient la clé d'accès secrète (défaut : secretAccessKey). | Optional: {} | |
sessionTokenKey string | SessionTokenKey est la clé du secret qui contient un jeton de session, si vos clés en exigent un. | Optional: {} |
Statut et conditions
| Phase | Signification |
|---|---|
Ready | le site est servi |
Pending | stockage injoignable pour l'instant (Secret absent ou refusé, clés manquantes, bucket qui ne répond pas) ; nouvel essai chaque minute |
Waiting | domaine 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) |
Invalid | domaine non autorisé, ou stockage refusé ; pas de nouvel essai avant une modification |
Conflict | un 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.
| Condition | True | False (reason) |
|---|---|---|
DomainAllowed | Allowed | NotAllowed : domaine hors de votre zone et de vos domaines apportés ; WaitingForDNSZone : zone DNS du domaine apporté pas encore vérifiée |
S3Reachable | Reachable | Invalid (stockage refusé), Unreachable (stockage injoignable), SecretNotAllowed (Secret des clés refusé) |
Ready | Ready | Invalid, Pending, Waiting ou Conflict (reprend la phase) |
status.message | Phase | Action |
|---|---|---|
domaine "…" non autorisé … | Invalid | utiliser 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à) | Waiting | rien à lancer : vérifier la zone du domaine, voir Apporter un domaine |
domaine déjà utilisé par un autre site | Conflict | autre nom ; le site d'un autre tenant n'est pas nommé |
domaine déjà servi par une autre ressource | Conflict | autre nom ; la ressource concurrente n'est pas nommée |
Secret "…" introuvable … | Pending | créer le Secret référencé |
secret TLS "…" introuvable : site servi sans HTTPS | Ready | créer le secret de tlsSecretRef, ou retirer tlsSecretRef |
Secret "…" refusé : label cdn.stackngo.io/s3-credentials="true" absent | Pending (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 … manquantes | Pending | vérifier les clés, ou accessKeyIDKey / secretAccessKeyKey |
… injoignable avec ces clés : … | Pending | vérifier bucket, région, endpoint, droits des clés |
endpoint "…" : https obligatoire (ou adresse non publique, hôte interne interdit) | Invalid | endpoint public en https |
spec.s3 ne peut pas viser le bucket par défaut : retirer spec.s3 | Invalid | retirer spec.s3 |
stockage par défaut non configuré … | Invalid | contacter 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.mode | status.tls.challenge | Certificat |
|---|---|---|
Wildcard | dns-01 | joker de votre zone, partagé par ses sites, validé par DNS |
Host | dns-01 | propre au domaine du site, validé par DNS |
Custom | le vôtre (tlsSecretRef) | |
None | aucun : 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ôme | Cause | Correction |
|---|---|---|
sng apply : spec.domain "…" : réservé à la plateforme ou à un autre client | nom sous le domaine de la plateforme, hors de votre zone | un nom de votre zone ou d'un domaine apporté par votre tenant |
Phase Waiting, WaitingForDNSZone | zone DNS du domaine apporté pas encore vérifiée | Apporter 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.s3 | envoyer les fichiers dans votre bucket, puis sng cdn clear-cache |
/blog/ affiche la page d'accueil | index.html n'est servi qu'à la racine ; le fallback répond | liens vers /blog/index.html, ou fichier blog.html |
Un fichier tout juste publié répond 404 | 404 gardé 30 min en cache, fichier envoyé hors sng cdn upload | sng cdn clear-cache <site> |
Phase Pending, Secret "…" introuvable | Secret absent du tenant | voir l'avertissement sur les Secrets référencés |
Phase Pending, S3Reachable=False, SecretNotAllowed | Secret des clés sans le label cdn.stackngo.io/s3-credentials: "true", pas de type Opaque, ou géré par la plateforme | voir Le Secret des clés de votre bucket |
Phase Conflict | domaine pris par un site plus ancien, ou par une autre ressource | autre nom de site |
sng cdn create : un site "docs" existe déjà (gra/staging) (409) | nom pris dans un autre contexte | autre nom, ou travailler dans ce contexte |
Voir aussi
- Guides : Publier un site statique, Maintenance et cache.
- CLI :
sng cdn,sng kind. - Autres kinds :
App(sites dynamiques),DNSRecord.