No description
  • Blade 58.9%
  • PHP 37.7%
  • Dockerfile 1.6%
  • Nix 0.7%
  • Shell 0.5%
  • Other 0.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-19 23:43:09 -04:00
.claude/skills/laravel-best-practices feat: Initial version 2026-07-19 23:16:41 -04:00
app feat: Initial version 2026-07-19 23:16:41 -04:00
bootstrap feat: Initial version 2026-07-19 23:16:41 -04:00
config feat: Initial version 2026-07-19 23:16:41 -04:00
database feat: Initial version 2026-07-19 23:16:41 -04:00
docker feat: Initial version 2026-07-19 23:16:41 -04:00
public feat: Initial version 2026-07-19 23:16:41 -04:00
resources chore: Don't delete the file 2026-07-19 23:43:09 -04:00
routes feat: Initial version 2026-07-19 23:16:41 -04:00
storage feat: Initial version 2026-07-19 23:16:41 -04:00
tests chore: Don't delete the file 2026-07-19 23:43:09 -04:00
.dockerignore feat: Initial version 2026-07-19 23:16:41 -04:00
.editorconfig feat: Initial version 2026-07-19 23:16:41 -04:00
.env.example feat: Initial version 2026-07-19 23:16:41 -04:00
.envrc feat: Initial version 2026-07-19 23:16:41 -04:00
.gitattributes feat: Initial version 2026-07-19 23:16:41 -04:00
.gitignore feat: Initial version 2026-07-19 23:16:41 -04:00
.mcp.json feat: Initial version 2026-07-19 23:16:41 -04:00
.npmrc feat: Initial version 2026-07-19 23:16:41 -04:00
artisan feat: Initial version 2026-07-19 23:16:41 -04:00
boost.json feat: Initial version 2026-07-19 23:16:41 -04:00
bun.lock feat: Initial version 2026-07-19 23:16:41 -04:00
CLAUDE.md feat: Initial version 2026-07-19 23:16:41 -04:00
composer.json feat: Initial version 2026-07-19 23:16:41 -04:00
composer.lock feat: Initial version 2026-07-19 23:16:41 -04:00
devenv.lock feat: Initial version 2026-07-19 23:16:41 -04:00
devenv.nix chore: Don't delete the file 2026-07-19 23:43:09 -04:00
devenv.yaml feat: Initial version 2026-07-19 23:16:41 -04:00
Dockerfile feat: Initial version 2026-07-19 23:16:41 -04:00
package.json feat: Initial version 2026-07-19 23:16:41 -04:00
phpunit.xml feat: Initial version 2026-07-19 23:16:41 -04:00
README.md feat: Initial version 2026-07-19 23:16:41 -04:00
vite.config.js feat: Initial version 2026-07-19 23:16:41 -04:00

Cluster Tester

A single-page, no-auth Laravel utility for smoke-testing a Kubernetes cluster from inside a running container. It checks that a mounted storage volume, the database, the cache/Redis backend, and injected environment variables are all wired up as expected.

⚠️ There is no authentication and the environment viewer shows secrets unmasked. Keep this service internal to the cluster — do not expose it publicly.

The tools

Everything lives on /, one card per check:

Tool What it does
💾 Storage Upload a file → writes it to the local disk, reads it back, deletes it. Reports path, size, disk root.
🗄️ Database Shows live connection info (driver / host / database / server version / reachable). Button to run migrations; once migrated, a form to create records and a list of them.
Cache / Redis Writes a key to the active cache store and reads it back.
🔧 Environment & Config Dumps $_ENV and resolved config (DB host/port, disk, cache/queue/session drivers, app url/env).

The page loads even when the database or cache is down — each tool reports its own failure inline, so you can always tell which backend is broken.

Run in Kubernetes

Build and push the image:

docker build -t <your-registry>/cluster-tester:latest .
docker push <your-registry>/cluster-tester:latest

The container serves plain HTTP on :8080 (point a Service at it; use GET / for liveness/ readiness probes). Configure everything through environment variables — inject the ones matching the backend you want to test:

Environment variables

Variable Purpose
APP_KEY Recommended via a Secret (base64:…, e.g. php artisan key:generate --show). If unset, each pod generates an ephemeral key, which breaks shared sessions across replicas.
DB_CONNECTION mysql, pgsql, mariadb, or sqlite (drivers bundled in the image).
DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD Point the database tool at a cluster DB. Use the DB Service DNS name for DB_HOST (e.g. postgres.default.svc.cluster.local).
CACHE_STORE Set to redis to make the cache tool exercise Redis.
REDIS_HOST, REDIS_PORT, REDIS_PASSWORD Redis Service address (e.g. redis.default.svc.cluster.local, 6379).
APP_ENV, APP_DEBUG Default production / false. Set APP_DEBUG=true to see full stack traces.

Image defaults keep page rendering independent of the database: SESSION_DRIVER=file, CACHE_STORE=file, QUEUE_CONNECTION=sync, LOG_CHANNEL=stderr. Override any of them via env.

Volume mounts

To exercise the storage tool against a real volume, mount your PVC at the local disk root:

Mount path What it is
/app/storage/app/private Root of the local filesystem disk — the storage tool writes/reads here. Mount your PVC here to test a real PersistentVolume.

The container runs as www-data (uid 33) — make the volume writable by it, e.g. set fsGroup: 33 on the pod's securityContext.

Example Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cluster-tester
spec:
  replicas: 1
  selector:
    matchLabels: { app: cluster-tester }
  template:
    metadata:
      labels: { app: cluster-tester }
    spec:
      securityContext:
        fsGroup: 33                       # www-data — lets the pod write the mounted PVC
      containers:
        - name: cluster-tester
          image: <your-registry>/cluster-tester:latest
          ports:
            - containerPort: 8080
          env:
            - name: APP_KEY
              valueFrom: { secretKeyRef: { name: cluster-tester, key: app-key } }
            # --- database tool ---
            - name: DB_CONNECTION
              value: pgsql
            - name: DB_HOST
              value: postgres.default.svc.cluster.local
            - name: DB_PORT
              value: "5432"
            - name: DB_DATABASE
              value: clustertest
            - name: DB_USERNAME
              value: postgres
            - name: DB_PASSWORD
              valueFrom: { secretKeyRef: { name: cluster-tester, key: db-password } }
            # --- cache tool ---
            - name: CACHE_STORE
              value: redis
            - name: REDIS_HOST
              value: redis.default.svc.cluster.local
            - name: REDIS_PORT
              value: "6379"
          volumeMounts:
            - name: storage                # mounts the PVC at the local disk root
              mountPath: /app/storage/app/private
          readinessProbe:
            httpGet: { path: /, port: 8080 }
          livenessProbe:
            httpGet: { path: /, port: 8080 }
      volumes:
        - name: storage
          persistentVolumeClaim:
            claimName: cluster-tester-storage
---
apiVersion: v1
kind: Service
metadata:
  name: cluster-tester
spec:
  selector: { app: cluster-tester }
  ports:
    - port: 80
      targetPort: 8080

Local development

composer install
bun install        # or npm install
cp .env.example .env && php artisan key:generate
php artisan migrate
composer run dev    # serves app + vite + queue + logs

Run the tests:

php artisan test