From eae7b4ed7af5d9a7c23943b80884683feeaf109a Mon Sep 17 00:00:00 2001 From: Andrew Stoltz <1578013+astoltz@users.noreply.github.com> Date: Sun, 21 Jun 2026 11:53:26 -0500 Subject: [PATCH] infra(cx2-5): DNS auth/NetPol substrate, air-gap landing, arm64 ARC runner + tenant landing manifests - fc-dns: add OnePasswordItem CRD for DNS API keys + NetworkPolicy for Phase 0 auth hardening; bump dns-web image tag - fc-landing: rewrite landing HTML to remove CDN dependencies (air-gap safe); add preview.html standalone preview - github-runner: add TOOLCACHE_ARCH to install-ruby-toolcache.sh for arm64 support; add Dockerfile.arm64 for arm64 ARC runner image - docs/gx10-tenant-landing: per-user Deployment+IngressRoute manifests (andrew/dustin/erik/fit/matt) + CUTOVER-RUNBOOK.md Co-Authored-By: Claude Opus 4.8 --- apps/fc-dns/fc-dns.yaml | 86 +++- apps/fc-landing/fc-landing.yaml | 485 +++++++++++++----- apps/fc-landing/preview.html | 356 +++++++++++++ apps/github-runner/Dockerfile.arm64 | 63 +++ apps/github-runner/install-ruby-toolcache.sh | 8 +- docs/gx10-tenant-landing/CUTOVER-RUNBOOK.md | 83 +++ docs/gx10-tenant-landing/andrew-deploy.yaml | 225 ++++++++ .../andrew-ingressroute.yaml | 18 + docs/gx10-tenant-landing/dustin-deploy.yaml | 208 ++++++++ .../dustin-ingressroute.yaml | 18 + docs/gx10-tenant-landing/erik-deploy.yaml | 225 ++++++++ .../erik-ingressroute.yaml | 18 + docs/gx10-tenant-landing/fit-deploy.yaml | 225 ++++++++ .../gx10-tenant-landing/fit-ingressroute.yaml | 18 + docs/gx10-tenant-landing/matt-deploy.yaml | 208 ++++++++ .../matt-ingressroute.yaml | 18 + 16 files changed, 2122 insertions(+), 140 deletions(-) create mode 100644 apps/fc-landing/preview.html create mode 100644 apps/github-runner/Dockerfile.arm64 create mode 100644 docs/gx10-tenant-landing/CUTOVER-RUNBOOK.md create mode 100644 docs/gx10-tenant-landing/andrew-deploy.yaml create mode 100644 docs/gx10-tenant-landing/andrew-ingressroute.yaml create mode 100644 docs/gx10-tenant-landing/dustin-deploy.yaml create mode 100644 docs/gx10-tenant-landing/dustin-ingressroute.yaml create mode 100644 docs/gx10-tenant-landing/erik-deploy.yaml create mode 100644 docs/gx10-tenant-landing/erik-ingressroute.yaml create mode 100644 docs/gx10-tenant-landing/fit-deploy.yaml create mode 100644 docs/gx10-tenant-landing/fit-ingressroute.yaml create mode 100644 docs/gx10-tenant-landing/matt-deploy.yaml create mode 100644 docs/gx10-tenant-landing/matt-ingressroute.yaml diff --git a/apps/fc-dns/fc-dns.yaml b/apps/fc-dns/fc-dns.yaml index c57c0d5..52f5c28 100644 --- a/apps/fc-dns/fc-dns.yaml +++ b/apps/fc-dns/fc-dns.yaml @@ -26,6 +26,20 @@ metadata: spec: itemPath: "vaults/IAmWorkin/items/dns-oidc-client" --- +# Service X-Api-Key for the cert-manager ACME webhook -> dns-web call path +# (Phase 0 auth-flip). The 1Password operator resolves this item into a K8s +# Secret of the same name; the `api_key` field becomes Secret key `api_key`. +# dns-web reads it as FlowerCore__Auth__ApiKey (FcApiKey scheme, Operator +# principal); dns-acme-webhook sends it as the X-Api-Key header. Dormant while +# FlowerCore__Auth__Enabled=false (all policies allow-all). +apiVersion: onepassword.com/v1 +kind: OnePasswordItem +metadata: + name: dns-api-keys + namespace: fc-dns +spec: + itemPath: "vaults/IAmWorkin/items/FlowerCore DNS API Keys" +--- apiVersion: v1 kind: PersistentVolumeClaim metadata: @@ -111,7 +125,7 @@ spec: fsGroup: 1654 containers: - name: dns-web - image: localhost/fc-dns-web:v20260614-wave5-isolation-6124856 + image: localhost/fc-dns-web:v20260615-phase0-hybrid-f77fb94 imagePullPolicy: Never securityContext: readOnlyRootFilesystem: true @@ -148,6 +162,16 @@ spec: name: dns-oidc-client key: client_secret optional: true + # Service X-Api-Key accepted by the FcApiKey scheme. The standard + # key maps to an Operator principal (satisfies OperatorPolicy on the + # ACME present/cleanup endpoints). optional:true keeps the pod + # starting if the 1P operator has not yet produced the secret. + - name: FlowerCore__Auth__ApiKey + valueFrom: + secretKeyRef: + name: dns-api-keys + key: api_key + optional: true - name: FlowerCore__Auth__Enabled value: "false" - name: FlowerCore__Auth__Oidc__Enabled @@ -209,6 +233,54 @@ spec: targetPort: 5320 type: ClusterIP --- +# Defense-in-depth ingress isolation for dns-web (Phase 0). NetworkPolicy is +# L3/L4 and cannot path-scope, so it CANNOT restrict only present/cleanup — the +# real control on those endpoints is the X-Api-Key + OperatorPolicy. This policy +# simply confines who may reach dns-web:5320 to known network zones without +# breaking any live path: +# * Traefik pods -> UI/API on dns.iamworkin.lan +# * same fc-dns namespace -> dns-acme-webhook -> present/cleanup +# * cluster pod CIDR (10.42/16) -> in-cluster Prometheus scrape, etc. +# * node + LAN CIDRs -> kubelet probes, noc1 host-net Prometheus +# Egress is intentionally left unrestricted: dns-web must reach pfSense +# (diag_command.php / HTTPS), the K8s API, Authentik OIDC discovery, step-ca, +# and DNS — over-tight egress would break the provider + auth paths. +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: dns-web-ingress-isolation + namespace: fc-dns +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: dns-web + policyTypes: + - Ingress + ingress: + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: traefik-system + podSelector: + matchLabels: + app.kubernetes.io/name: traefik + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: fc-dns + - ipBlock: + cidr: 10.42.0.0/16 + - ipBlock: + cidr: 10.0.56.0/24 + - ipBlock: + cidr: 10.0.57.0/24 + - ipBlock: + cidr: 10.0.58.0/24 + - ipBlock: + cidr: 10.0.68.0/27 + ports: + - port: 5320 + protocol: TCP +--- apiVersion: v1 kind: ServiceAccount metadata: @@ -303,7 +375,7 @@ spec: fsGroup: 1654 containers: - name: dns-acme-webhook - image: localhost/fc-dns-acme-webhook:v20260614-wave5-isolation-6124856 + image: localhost/fc-dns-acme-webhook:v20260615-phase0-hybrid-f77fb94 imagePullPolicy: Never securityContext: readOnlyRootFilesystem: true @@ -322,6 +394,16 @@ spec: value: /tls/tls.key - name: FlowerCore__Dns__AcmeWebhook__ServiceBaseUrl value: http://dns-web:5320 + # X-Api-Key sent to dns-web on present/cleanup so the webhook + # authenticates as an Operator once dns-web auth is enabled. + # optional:true keeps the webhook starting before the 1P secret + # exists; the header is simply omitted when the value is empty. + - name: FlowerCore__Dns__AcmeWebhook__ApiKey + valueFrom: + secretKeyRef: + name: dns-api-keys + key: api_key + optional: true - name: FlowerCore__Dns__AcmeWebhook__GroupName value: acme.flowercore.io - name: FlowerCore__Dns__AcmeWebhook__SolverName diff --git a/apps/fc-landing/fc-landing.yaml b/apps/fc-landing/fc-landing.yaml index f6d2c34..f8eb785 100644 --- a/apps/fc-landing/fc-landing.yaml +++ b/apps/fc-landing/fc-landing.yaml @@ -9,7 +9,7 @@ metadata: labels: app.kubernetes.io/part-of: bluejay-infra --- -# Landing page HTML (public-safe - no internal LAN references) +# Landing page HTML (public-safe - no internal LAN references, no CDN) apiVersion: v1 kind: ConfigMap metadata: @@ -20,144 +20,357 @@ data: - - - FlowerCore - + + + FlowerCore + + -
- -

FlowerCore

-

Blue Jay Lab

-

- Multi-tenant service management platform built on .NET 10, - Kubernetes, and GitOps. Digital signage, telephony IVR, - MySQL/PHP hosting, and infrastructure automation. -

+ + + + + +
+ + - -
-
-
17
-
Services
-
-
-
13
-
VLANs
-
-
-
12k+
-
Tests
-
-
- + + +

FlowerCore

+

More to come.

+ + + + + + Update Center + + +

Software updates & releases

+
+ +
+ © FlowerCore +
--- diff --git a/apps/fc-landing/preview.html b/apps/fc-landing/preview.html new file mode 100644 index 0000000..e1dea4d --- /dev/null +++ b/apps/fc-landing/preview.html @@ -0,0 +1,356 @@ + + + + + + FlowerCore + + + + + + + + + +
+ + + + +

FlowerCore

+

More to come.

+ + + + + + Update Center + + +

Software updates & releases

+
+ +
+ © FlowerCore +
+ + \ No newline at end of file diff --git a/apps/github-runner/Dockerfile.arm64 b/apps/github-runner/Dockerfile.arm64 new file mode 100644 index 0000000..5fb0ab3 --- /dev/null +++ b/apps/github-runner/Dockerfile.arm64 @@ -0,0 +1,63 @@ +FROM myoung34/github-runner:latest + +# arm64 variant of the FlowerCore self-hosted runner image. +# Built/maintained alongside the amd64 Dockerfile. The ONLY substantive +# difference from the amd64 image is that the Actions/Ruby tool-cache arch +# label is "arm64" instead of the amd64 "x64". Ruby itself is still compiled +# from source via ruby-build, so it is naturally arm64 on an aarch64 host. + +ARG RUBY_VERSION=3.3.11 +ARG RUBY_MINOR=3.3 +ARG RUBY_BUILD_VERSION=v20260326 +ARG RUNNER_UID=1001 +ARG RUNNER_GID=1001 +# arm64 tool-cache arch label (was x64 on amd64). ruby/setup-ruby@v1 on a +# self-hosted aarch64 Linux runner discovers Ruby under _tool/Ruby//arm64. +ARG TOOLCACHE_ARCH=arm64 + +ENV RUNNER_TOOL_CACHE=/home/runner/_tool +ENV RUNNER_RUBY_TOOLCACHE=/opt/runner-toolcache +ENV PATH="/home/runner/_tool/Ruby/${RUBY_MINOR}/${TOOLCACHE_ARCH}/bin:/opt/runner-toolcache/Ruby/${RUBY_MINOR}/${TOOLCACHE_ARCH}/bin:${PATH}" + +USER root + +# Bake the IAmWorkin step-ca root CA into the system trust store. Without +# this, .NET HttpClient calls from CI tests against *.iamworkin.lan +# (e.g. https://selenium.iamworkin.lan/session) fail with `PartialChain` +# because the runner image's default Ubuntu trust bundle doesn't include +# our internal Root CA. update-ca-certificates regenerates +# /etc/ssl/certs/ca-certificates.crt, which OpenSSL + .NET on Linux read +# automatically — no SSL_CERT_FILE env var needed. +COPY step-ca-root.crt /usr/local/share/ca-certificates/iamworkin-step-ca-root.crt + +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + autoconf \ + bison \ + build-essential \ + ca-certificates \ + curl \ + libdb-dev \ + libffi-dev \ + libgdbm-dev \ + libgmp-dev \ + libncurses-dev \ + libreadline-dev \ + libssl-dev \ + libyaml-dev \ + patch \ + pkg-config \ + uuid-dev \ + zlib1g-dev \ + && update-ca-certificates \ + && curl -fsSL "https://github.com/rbenv/ruby-build/archive/refs/tags/${RUBY_BUILD_VERSION}.tar.gz" -o /tmp/ruby-build.tar.gz \ + && mkdir -p /tmp/ruby-build \ + && tar -xzf /tmp/ruby-build.tar.gz --strip-components=1 -C /tmp/ruby-build \ + && /tmp/ruby-build/install.sh \ + && rm -rf /tmp/ruby-build /tmp/ruby-build.tar.gz /var/lib/apt/lists/* + +COPY install-ruby-toolcache.sh /usr/local/bin/install-ruby-toolcache.sh + +RUN chmod +x /usr/local/bin/install-ruby-toolcache.sh \ + && RUBY_VERSION="${RUBY_VERSION}" RUBY_MINOR="${RUBY_MINOR}" TOOLCACHE_ARCH="${TOOLCACHE_ARCH}" TOOLCACHE_ROOT="${RUNNER_RUBY_TOOLCACHE}" RUNNER_UID="${RUNNER_UID}" RUNNER_GID="${RUNNER_GID}" /usr/local/bin/install-ruby-toolcache.sh \ + && ruby -v diff --git a/apps/github-runner/install-ruby-toolcache.sh b/apps/github-runner/install-ruby-toolcache.sh index 544b25a..d753d54 100644 --- a/apps/github-runner/install-ruby-toolcache.sh +++ b/apps/github-runner/install-ruby-toolcache.sh @@ -6,12 +6,16 @@ RUBY_MINOR="${RUBY_MINOR:-3.3}" TOOLCACHE_ROOT="${TOOLCACHE_ROOT:-/opt/runner-toolcache}" RUNNER_UID="${RUNNER_UID:-1001}" RUNNER_GID="${RUNNER_GID:-1001}" -RUBY_PREFIX="${TOOLCACHE_ROOT}/Ruby/${RUBY_VERSION}/x64" +# Tool-cache arch label. Defaults to x64 (amd64 image, unchanged). The arm64 +# Dockerfile passes TOOLCACHE_ARCH=arm64 so ruby/setup-ruby@v1 finds Ruby on +# aarch64 self-hosted runners. +TOOLCACHE_ARCH="${TOOLCACHE_ARCH:-x64}" +RUBY_PREFIX="${TOOLCACHE_ROOT}/Ruby/${RUBY_VERSION}/${TOOLCACHE_ARCH}" mkdir -p "${TOOLCACHE_ROOT}/Ruby" RUBY_CONFIGURE_OPTS="${RUBY_CONFIGURE_OPTS:---disable-install-doc --disable-yjit}" ruby-build "${RUBY_VERSION}" "${RUBY_PREFIX}" -touch "${TOOLCACHE_ROOT}/Ruby/${RUBY_VERSION}/x64.complete" +touch "${TOOLCACHE_ROOT}/Ruby/${RUBY_VERSION}/${TOOLCACHE_ARCH}.complete" ln -sfn "${RUBY_VERSION}" "${TOOLCACHE_ROOT}/Ruby/${RUBY_MINOR}" "${RUBY_PREFIX}/bin/ruby" -v diff --git a/docs/gx10-tenant-landing/CUTOVER-RUNBOOK.md b/docs/gx10-tenant-landing/CUTOVER-RUNBOOK.md new file mode 100644 index 0000000..5c82b16 --- /dev/null +++ b/docs/gx10-tenant-landing/CUTOVER-RUNBOOK.md @@ -0,0 +1,83 @@ +# GX10 Tenant Landing-Site Migration — Cutover Runbook + +Date: 2026-06-16. Migrates the 5 per-tenant public landing sites from the OLD RKE2 +cluster (`10.0.56.200` Traefik) to the GX10 ARM64 cluster (`10.0.57.202` VIP / +NodePort `10.0.56.14:32491`). + +## Deployed on GX10 (DONE — staged-verified, NOT yet receiving public traffic) + +| Domain(s) | GX10 ns | Workload | TLS secret (in ns + traefik-system) | Live content replicated | +|-----------------------------------|--------------------|---------------|-------------------------------------|-------------------------| +| bluejay.dev, www.bluejay.dev | `fc-tenant-andrew` | nginx:alpine | `cf-origin-bluejay-dev` | "Blue Jay" (custom) | +| timeforta.co, www.timeforta.co | `fc-tenant-dustin` | nginx:alpine | `cf-origin-timeforta-co` | "Coming Soon" (generic) | +| erckak.dev, www.erckak.dev | `fc-tenant-erik` | nginx:alpine | `cf-origin-erckak-dev` | "Erckak" (custom) | +| flowerinsider.xyz, www.* | `fc-tenant-fit` | nginx:alpine | `cf-origin-flowerinsider-xyz` | "Flower Insider" (custom)| +| matt.flowercore.io | `fc-tenant-matt` | nginx:alpine | `cf-origin-flowercore-io` | "Coming Soon" (generic) | + +All nginx pods 1/1 Running, IngressRoutes priority 100 (override the GX10 +`public-catchall`). Each site replicates EXACTLY what was live on OLD at migration +time, so cutover is content-invisible. + +Staged verification (all HTTP 200, correct content, SNI-correct cert): +``` +curl -sk --resolve :32491:10.0.56.14 https://:32491/ +``` + +## Public routing reality (why NO automatic cutover happened) + +Every tenant domain enters the network through Cloudflare (proxied) → a dedicated +pfSense WAN IP in 74.40.140.16/28 → pfSense port-forward. ALL FIVE currently forward +to OLD Traefik `10.0.56.200:443`: + +| Domain | CF origin WAN IP | pfSense rdr today | +|-------------------|------------------|--------------------| +| bluejay.dev | 74.40.140.17 | → 10.0.56.200:443 | +| matt.flowercore.io| 74.40.140.19 | → 10.0.56.200:443 | +| timeforta.co | 74.40.140.21 | → 10.0.56.200:443 | +| erckak.dev | 74.40.140.23 | → 10.0.56.200:443 | +| flowerinsider.xyz | 74.40.140.25 | → 10.0.56.200:443 | + +(Contrast: main flowercore.io = WAN `.24` → already GX10 `10.0.56.14:32491`.) +NOTE: matt.flowercore.io is bound to WAN `.19` (the MATT VPN IP), NOT `.24`, so the +"*.flowercore.io already NATs to GX10" assumption does NOT cover matt. + +Because none of these NAT to GX10 yet, no cutover was performed (live sites untouched). + +## OPERATOR ACTION — cutover = repoint the pfSense port-forward target + +For each domain, change the HTTPS (and HTTP) port-forward TARGET from +`10.0.56.200` to `10.0.56.14:32491` (HTTPS) / `10.0.56.14:30776` (HTTP). pfSense +port-forwards (Firewall → NAT → Port Forward), edit these rule descriptions: + +- `ANDREW: HTTPS to Traefik` 74.40.140.17:443 → change target `10.0.56.200:443` to `10.0.56.14:32491` +- `MATT: HTTPS to Traefik` 74.40.140.19:443 → change target `10.0.56.200:443` to `10.0.56.14:32491` +- `DUSTIN: HTTPS to Traefik` 74.40.140.21:443 → change target `10.0.56.200:443` to `10.0.56.14:32491` +- `ERIK: HTTPS to Traefik` 74.40.140.23:443 → change target `10.0.56.200:443` to `10.0.56.14:32491` +- `FIT: HTTPS to Traefik` 74.40.140.25:443 → change target `10.0.56.200:443` to `10.0.56.14:32491` +- (corresponding `:80 → 10.0.56.14:30776` HTTP rules likewise, optional — sites are HTTPS-only) + +No Cloudflare DNS change is required: the WAN IPs stay the same, only the internal +NAT target moves. Each can be flipped independently (per-tenant blast radius). + +Post-flip verify (external): +``` +curl -sI https:/// # expect HTTP 200, Server: cloudflare, unchanged content +``` + +## Rollback + +OLD cluster left fully intact (ArgoCD apps infra-andrew/dustin/erik/fit Synced+Healthy, +pods Running). To roll back any domain: revert that pfSense port-forward target to +`10.0.56.200`. + +## Notes +- The OLD cluster has DUPLICATE namespaces per tenant (`tenant-X` custom page + + `fc-tenant-X` generic landing), both with IngressRoutes claiming the same host. + Traefik non-deterministically picked a winner; live content was: andrew/erik/fit = + custom (`tenant-X`), dustin/matt = generic (`fc-tenant-X`). GX10 consolidates to ONE + namespace per tenant (`fc-tenant-X`) serving the content that was actually live. +- `infra-worldbuilder` (worldbuilder.iamworkin.lan, internal .NET app) was ALREADY + migrated to GX10 (`fc-worldbuilder`, 1/1 Running) — no action. +- `infra-flowercore` (tenant-flowercore/flowercore-web demo) has NO public route and is + superseded by the production `fc-system/fc-landing-public` (flowercore.io root) already + live on GX10 — intentionally NOT migrated. diff --git a/docs/gx10-tenant-landing/andrew-deploy.yaml b/docs/gx10-tenant-landing/andrew-deploy.yaml new file mode 100644 index 0000000..1380abd --- /dev/null +++ b/docs/gx10-tenant-landing/andrew-deploy.yaml @@ -0,0 +1,225 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: fc-tenant-andrew + labels: + app.kubernetes.io/part-of: bluejay-infra + flowercore.io/tenant: andrew +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: andrew-web-html + namespace: fc-tenant-andrew +data: + index.html: | + + + + + + Blue Jay — bluejay.dev + + + +
+
+
Andrew's Space
+
🐦
+

Blue Jay

+

bluejay.dev

+
+ +

Coming Soon

+
+
+ +
+ + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: andrew-web-nginx-conf + namespace: fc-tenant-andrew +data: + default.conf: | + server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + location / { try_files $uri $uri/ =404; } + location /healthz { access_log off; return 200 "ok"; add_header Content-Type text/plain; } + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: andrew-web + namespace: fc-tenant-andrew + labels: + app: andrew-web +spec: + replicas: 1 + selector: + matchLabels: + app: andrew-web + template: + metadata: + labels: + app: andrew-web + spec: + containers: + - name: nginx + image: nginx:alpine + ports: + - containerPort: 80 + name: http + volumeMounts: + - name: nginx-conf + mountPath: /etc/nginx/conf.d/default.conf + subPath: default.conf + - name: html + mountPath: /usr/share/nginx/html + resources: + requests: { memory: 32Mi, cpu: 10m } + limits: { memory: 64Mi, cpu: 50m } + livenessProbe: + httpGet: { path: /healthz, port: 80 } + initialDelaySeconds: 5 + periodSeconds: 10 + readinessProbe: + httpGet: { path: /healthz, port: 80 } + initialDelaySeconds: 3 + periodSeconds: 5 + volumes: + - name: nginx-conf + configMap: { name: andrew-web-nginx-conf } + - name: html + configMap: { name: andrew-web-html } +--- +apiVersion: v1 +kind: Service +metadata: + name: andrew-web + namespace: fc-tenant-andrew +spec: + selector: + app: andrew-web + ports: + - port: 80 + targetPort: 80 + name: http diff --git a/docs/gx10-tenant-landing/andrew-ingressroute.yaml b/docs/gx10-tenant-landing/andrew-ingressroute.yaml new file mode 100644 index 0000000..1c24197 --- /dev/null +++ b/docs/gx10-tenant-landing/andrew-ingressroute.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: andrew-web + namespace: fc-tenant-andrew +spec: + entryPoints: + - websecure + routes: + - match: Host(`bluejay.dev`) || Host(`www.bluejay.dev`) + kind: Rule + priority: 100 + services: + - name: andrew-web + port: 80 + tls: + secretName: cf-origin-bluejay-dev diff --git a/docs/gx10-tenant-landing/dustin-deploy.yaml b/docs/gx10-tenant-landing/dustin-deploy.yaml new file mode 100644 index 0000000..39c1dc4 --- /dev/null +++ b/docs/gx10-tenant-landing/dustin-deploy.yaml @@ -0,0 +1,208 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: fc-tenant-dustin + labels: + app.kubernetes.io/part-of: bluejay-infra + flowercore.io/tenant: dustin +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: dustin-web-html + namespace: fc-tenant-dustin +data: + index.html: | + + + + + + timeforta.co — Coming Soon + + + +
+
🌮
+

timeforta.co

+
Dustin
+
+

It's always time for tacos.

+
+ + Under Construction +
+
+
+ Powered by FlowerCore • Hosted on Blue Jay Infrastructure +
+ + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: dustin-web-nginx-conf + namespace: fc-tenant-dustin +data: + default.conf: | + server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + location / { try_files $uri $uri/ =404; } + location /healthz { access_log off; return 200 "ok"; add_header Content-Type text/plain; } + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dustin-web + namespace: fc-tenant-dustin + labels: + app: dustin-web +spec: + replicas: 1 + selector: + matchLabels: + app: dustin-web + template: + metadata: + labels: + app: dustin-web + spec: + containers: + - name: nginx + image: nginx:alpine + ports: + - containerPort: 80 + name: http + volumeMounts: + - name: nginx-conf + mountPath: /etc/nginx/conf.d/default.conf + subPath: default.conf + - name: html + mountPath: /usr/share/nginx/html + resources: + requests: { memory: 32Mi, cpu: 10m } + limits: { memory: 64Mi, cpu: 50m } + livenessProbe: + httpGet: { path: /healthz, port: 80 } + initialDelaySeconds: 5 + periodSeconds: 10 + readinessProbe: + httpGet: { path: /healthz, port: 80 } + initialDelaySeconds: 3 + periodSeconds: 5 + volumes: + - name: nginx-conf + configMap: { name: dustin-web-nginx-conf } + - name: html + configMap: { name: dustin-web-html } +--- +apiVersion: v1 +kind: Service +metadata: + name: dustin-web + namespace: fc-tenant-dustin +spec: + selector: + app: dustin-web + ports: + - port: 80 + targetPort: 80 + name: http diff --git a/docs/gx10-tenant-landing/dustin-ingressroute.yaml b/docs/gx10-tenant-landing/dustin-ingressroute.yaml new file mode 100644 index 0000000..03a18f4 --- /dev/null +++ b/docs/gx10-tenant-landing/dustin-ingressroute.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: dustin-web + namespace: fc-tenant-dustin +spec: + entryPoints: + - websecure + routes: + - match: Host(`timeforta.co`) || Host(`www.timeforta.co`) + kind: Rule + priority: 100 + services: + - name: dustin-web + port: 80 + tls: + secretName: cf-origin-timeforta-co diff --git a/docs/gx10-tenant-landing/erik-deploy.yaml b/docs/gx10-tenant-landing/erik-deploy.yaml new file mode 100644 index 0000000..fcf3164 --- /dev/null +++ b/docs/gx10-tenant-landing/erik-deploy.yaml @@ -0,0 +1,225 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: fc-tenant-erik + labels: + app.kubernetes.io/part-of: bluejay-infra + flowercore.io/tenant: erik +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: erik-web-html + namespace: fc-tenant-erik +data: + index.html: | + + + + + + Erckak — erckak.dev + + + +
+
+
Erik's Space
+
🚀
+

Erckak

+

erckak.dev

+
+ +

Coming Soon

+
+
+ +
+ + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: erik-web-nginx-conf + namespace: fc-tenant-erik +data: + default.conf: | + server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + location / { try_files $uri $uri/ =404; } + location /healthz { access_log off; return 200 "ok"; add_header Content-Type text/plain; } + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: erik-web + namespace: fc-tenant-erik + labels: + app: erik-web +spec: + replicas: 1 + selector: + matchLabels: + app: erik-web + template: + metadata: + labels: + app: erik-web + spec: + containers: + - name: nginx + image: nginx:alpine + ports: + - containerPort: 80 + name: http + volumeMounts: + - name: nginx-conf + mountPath: /etc/nginx/conf.d/default.conf + subPath: default.conf + - name: html + mountPath: /usr/share/nginx/html + resources: + requests: { memory: 32Mi, cpu: 10m } + limits: { memory: 64Mi, cpu: 50m } + livenessProbe: + httpGet: { path: /healthz, port: 80 } + initialDelaySeconds: 5 + periodSeconds: 10 + readinessProbe: + httpGet: { path: /healthz, port: 80 } + initialDelaySeconds: 3 + periodSeconds: 5 + volumes: + - name: nginx-conf + configMap: { name: erik-web-nginx-conf } + - name: html + configMap: { name: erik-web-html } +--- +apiVersion: v1 +kind: Service +metadata: + name: erik-web + namespace: fc-tenant-erik +spec: + selector: + app: erik-web + ports: + - port: 80 + targetPort: 80 + name: http diff --git a/docs/gx10-tenant-landing/erik-ingressroute.yaml b/docs/gx10-tenant-landing/erik-ingressroute.yaml new file mode 100644 index 0000000..397465f --- /dev/null +++ b/docs/gx10-tenant-landing/erik-ingressroute.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: erik-web + namespace: fc-tenant-erik +spec: + entryPoints: + - websecure + routes: + - match: Host(`erckak.dev`) || Host(`www.erckak.dev`) + kind: Rule + priority: 100 + services: + - name: erik-web + port: 80 + tls: + secretName: cf-origin-erckak-dev diff --git a/docs/gx10-tenant-landing/fit-deploy.yaml b/docs/gx10-tenant-landing/fit-deploy.yaml new file mode 100644 index 0000000..1fabaac --- /dev/null +++ b/docs/gx10-tenant-landing/fit-deploy.yaml @@ -0,0 +1,225 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: fc-tenant-fit + labels: + app.kubernetes.io/part-of: bluejay-infra + flowercore.io/tenant: fit +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: fit-web-html + namespace: fc-tenant-fit +data: + index.html: | + + + + + + Flower Insider — flowerinsider.xyz + + + +
+
+
Flower Insider Team
+
🌸
+

Flower Insider

+

flowerinsider.xyz

+
+ +

Coming Soon

+
+
+ +
+ + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: fit-web-nginx-conf + namespace: fc-tenant-fit +data: + default.conf: | + server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + location / { try_files $uri $uri/ =404; } + location /healthz { access_log off; return 200 "ok"; add_header Content-Type text/plain; } + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: fit-web + namespace: fc-tenant-fit + labels: + app: fit-web +spec: + replicas: 1 + selector: + matchLabels: + app: fit-web + template: + metadata: + labels: + app: fit-web + spec: + containers: + - name: nginx + image: nginx:alpine + ports: + - containerPort: 80 + name: http + volumeMounts: + - name: nginx-conf + mountPath: /etc/nginx/conf.d/default.conf + subPath: default.conf + - name: html + mountPath: /usr/share/nginx/html + resources: + requests: { memory: 32Mi, cpu: 10m } + limits: { memory: 64Mi, cpu: 50m } + livenessProbe: + httpGet: { path: /healthz, port: 80 } + initialDelaySeconds: 5 + periodSeconds: 10 + readinessProbe: + httpGet: { path: /healthz, port: 80 } + initialDelaySeconds: 3 + periodSeconds: 5 + volumes: + - name: nginx-conf + configMap: { name: fit-web-nginx-conf } + - name: html + configMap: { name: fit-web-html } +--- +apiVersion: v1 +kind: Service +metadata: + name: fit-web + namespace: fc-tenant-fit +spec: + selector: + app: fit-web + ports: + - port: 80 + targetPort: 80 + name: http diff --git a/docs/gx10-tenant-landing/fit-ingressroute.yaml b/docs/gx10-tenant-landing/fit-ingressroute.yaml new file mode 100644 index 0000000..4b9007c --- /dev/null +++ b/docs/gx10-tenant-landing/fit-ingressroute.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: fit-web + namespace: fc-tenant-fit +spec: + entryPoints: + - websecure + routes: + - match: Host(`flowerinsider.xyz`) || Host(`www.flowerinsider.xyz`) + kind: Rule + priority: 100 + services: + - name: fit-web + port: 80 + tls: + secretName: cf-origin-flowerinsider-xyz diff --git a/docs/gx10-tenant-landing/matt-deploy.yaml b/docs/gx10-tenant-landing/matt-deploy.yaml new file mode 100644 index 0000000..b5dfd58 --- /dev/null +++ b/docs/gx10-tenant-landing/matt-deploy.yaml @@ -0,0 +1,208 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: fc-tenant-matt + labels: + app.kubernetes.io/part-of: bluejay-infra + flowercore.io/tenant: matt +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: matt-web-html + namespace: fc-tenant-matt +data: + index.html: | + + + + + + matt.flowercore.io — Coming Soon + + + +
+
🔥
+

matt.flowercore.io

+
Matt
+
+

Building something extraordinary.

+
+ + Under Construction +
+
+ + + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: matt-web-nginx-conf + namespace: fc-tenant-matt +data: + default.conf: | + server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + location / { try_files $uri $uri/ =404; } + location /healthz { access_log off; return 200 "ok"; add_header Content-Type text/plain; } + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: matt-web + namespace: fc-tenant-matt + labels: + app: matt-web +spec: + replicas: 1 + selector: + matchLabels: + app: matt-web + template: + metadata: + labels: + app: matt-web + spec: + containers: + - name: nginx + image: nginx:alpine + ports: + - containerPort: 80 + name: http + volumeMounts: + - name: nginx-conf + mountPath: /etc/nginx/conf.d/default.conf + subPath: default.conf + - name: html + mountPath: /usr/share/nginx/html + resources: + requests: { memory: 32Mi, cpu: 10m } + limits: { memory: 64Mi, cpu: 50m } + livenessProbe: + httpGet: { path: /healthz, port: 80 } + initialDelaySeconds: 5 + periodSeconds: 10 + readinessProbe: + httpGet: { path: /healthz, port: 80 } + initialDelaySeconds: 3 + periodSeconds: 5 + volumes: + - name: nginx-conf + configMap: { name: matt-web-nginx-conf } + - name: html + configMap: { name: matt-web-html } +--- +apiVersion: v1 +kind: Service +metadata: + name: matt-web + namespace: fc-tenant-matt +spec: + selector: + app: matt-web + ports: + - port: 80 + targetPort: 80 + name: http diff --git a/docs/gx10-tenant-landing/matt-ingressroute.yaml b/docs/gx10-tenant-landing/matt-ingressroute.yaml new file mode 100644 index 0000000..ee70091 --- /dev/null +++ b/docs/gx10-tenant-landing/matt-ingressroute.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: matt-web + namespace: fc-tenant-matt +spec: + entryPoints: + - websecure + routes: + - match: Host(`matt.flowercore.io`) + kind: Rule + priority: 100 + services: + - name: matt-web + port: 80 + tls: + secretName: cf-origin-flowercore-io