Serve cdn.lux.cloud and cdn.lux.network from the Sites plane

Both names answered 404 at every path: the declaration that served them
(k8s/lux-k8s/cdn/cdn.yaml) addressed an in-cluster S3 bucket on DOKS, and that
account is suspended. DNS and the tunnel already deliver both to the ingress --
each returns the ingress's own "404 page not found" -- so what was missing was a
route, not a path to the cluster.

deploy/lux-cdn/lux-cdn.yaml is that route, on the same pattern as every other
static host here: one staticFiles middleware over s3://hanzo-sites/lux/lux-cdn,
one rule matching both names, and no Deployment, because a static host is not a
pod. luxfi/cdn publishes the prefix from its own lane.

NO spaMode, and that is the one place this differs from the sites beside it.
The exchange's rule is that a mark which exists nowhere is reported missing and
never drawn, and that only holds if the host says so: in SPA mode an unknown
path answers 200 with index.html, so a caller asking for a PNG receives an HTML
document, caches it, and reports nothing.

The prefix is lux/lux-cdn rather than lux/cdn because `cdn` is on cloud's
reserved-label list beside api, admin and gateway -- no site may be published at
cdn.<apex> and shadow real infrastructure -- so that slug cannot be created and
the prefix cannot be published to.

assets.lux.network keeps its own declaration in that directory until it moves.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-09-08 10:34:47 -07:00
co-authored by Hanzo Dev
parent 30c1374991
commit 1de35d7464
3 changed files with 57 additions and 94 deletions
+54
View File
@@ -0,0 +1,54 @@
# cdn.lux.cloud is files: one Middleware that serves them, one route that names it,
# and the endpoint-less Service the route schema requires. No image, so the
# chart renders no Deployment -- a static host is not a pod.
#
# Host law: lux.network is for decentralized network surfaces; centralized
# storage lives on lux.cloud. cdn.lux.network is the older name, kept serving
# because shipped clients -- the wallets, Safe's chain list, the ad server's
# VAST -- fetch it from users' machines and cannot be repointed by editing a
# repo. New references use cdn.lux.cloud. Both names, one rule, one prefix:
# there is no second copy of the files to fall behind.
#
# The prefix is lux/lux-cdn and not lux/cdn: `cdn` is on cloud's reserved-label
# list (apps/sites/reserved.go), alongside api, admin, gateway and the brand
# terms, so that nobody can publish a site at cdn.<apex> and shadow real
# infrastructure. A slug that cannot be created is a prefix that cannot be
# published to.
#
# This replaces k8s/lux-k8s/cdn/cdn.yaml, which served the same two hosts from
# an in-cluster S3 bucket through an addPrefix middleware on DOKS. The bytes now
# come from the Sites plane, published by luxfi/cdn's own lane, which is the one
# way every other static host here already reaches the edge.
#
# NO spaMode. The exchange's rule is that a mark which exists nowhere is
# reported missing, never drawn, and that only holds if the host says so: in SPA
# mode every unknown path answers 200 with index.html, so a caller asking for a
# PNG gets an HTML document, caches it, and reports nothing. Off, a missing mark
# is a 404.
cd:
automated: true
ports:
- name: http
containerPort: 80
middlewares:
- name: cdn
spec:
staticFiles:
root: s3://hanzo-sites/lux/lux-cdn
indexFiles:
- index.html
routes:
- name: cdn
spec:
entryPoints:
- websecure
routes:
- match: Host(`cdn.lux.cloud`) || Host(`cdn.lux.network`)
kind: Rule
priority: 100
middlewares:
- name: cdn
services:
- name: lux-cdn
port: 80
tls: {}
-93
View File
@@ -1,93 +0,0 @@
# cdn.lux.cloud — public asset delivery for Lux.
#
# Host law: lux.network is for decentralized network surfaces; centralized
# storage lives on lux.cloud. cdn.lux.network is the legacy alias, kept
# serving because shipped clients (xwallet, dwallet, Safe chains.json, adx
# VAST) fetch it from users' machines and cannot be repointed by editing
# a repo. New references use cdn.lux.cloud.
#
# cdn.lux.cloud is delivery only — public read, no listing, no auth.
# s3.lux.cloud is the authenticated S3 API and stays 403 to anonymous.
# Keeping the two apart is what stops "serve the assets" from meaning
# "open the API".
#
# Serving model: objects live in the in-cluster S3 bucket `lux-cdn`; the
# ingress adds the bucket prefix. Anonymous callers get Read and only
# Read — the `anonymous` identity in lux-system/seaweedfs-s3-identity
# carries `Read:lux-cdn` with no `List:` grant, so ListObjects returns
# AccessDenied while GetObject serves. Read and List are separate,
# exact-matched actions in hanzoai/s3; granting one never implies the
# other.
#
# Refresh = publish objects through the filer inside the cluster, so no
# bucket credential ever leaves it.
---
apiVersion: hanzo.ai/v1alpha1
kind: Middleware
metadata:
name: lux-cdn-bucket-prefix
namespace: hanzo
spec:
addPrefix:
prefix: /lux-cdn
---
apiVersion: v1
kind: Service
metadata:
name: lux-cdn
namespace: hanzo
labels:
app: lux-cdn
app.kubernetes.io/managed-by: lux-universe
app.kubernetes.io/part-of: lux-cdn
spec:
type: ExternalName
externalName: s3.lux-system.svc.cluster.local
ports:
- { name: http, port: 9000 }
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: lux-cdn
namespace: hanzo
labels:
app.kubernetes.io/managed-by: lux-universe
app.kubernetes.io/part-of: lux-cdn
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
ingress.kubernetes.io/router.entrypoints: web,websecure
ingress.kubernetes.io/router.tls: "true"
ingress.kubernetes.io/router.middlewares: hanzo-lux-cdn-bucket-prefix@kubernetescrd
spec:
ingressClassName: ingress
tls:
- hosts:
- cdn.lux.cloud
secretName: lux-cdn-cloud-tls
- hosts:
- cdn.lux.network
secretName: lux-cdn-tls
rules:
# canonical
- host: cdn.lux.cloud
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: lux-cdn
port:
number: 9000
# legacy alias — shipped clients still dial this; do not remove
- host: cdn.lux.network
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: lux-cdn
port:
number: 9000
+3 -1
View File
@@ -3,6 +3,8 @@ kind: Kustomization
namespace: hanzo
# cdn.yaml is gone: cdn.lux.cloud / cdn.lux.network are served from the Sites
# plane now, declared at deploy/lux-cdn/lux-cdn.yaml. assets.lux.network still
# reads the in-cluster bucket and keeps its declaration until it moves too.
resources:
- assets.yaml
- cdn.yaml