HeadlessX Deployment Notes
This service runs the modular HeadlessX browserless API behind the internal gateway. The manifests live in k8s/applications/web/headlessx and stay aligned with the original docker-compose configuration.
Build and Image
- The Dockerfile at
images/headlessx/Dockerfilebuilds HeadlessX from source using the upstream repository athttps://github.com/saifyxpro/HeadlessX. - The build uses a three-stage Dockerfile pattern matching the official HeadlessX Dockerfile:
- Source stage: Clones the HeadlessX repository at the specified version
- Website builder stage: Builds the HeadlessX web interface for production
- Runtime stage: Uses the official Playwright base image (
mcr.microsoft.com/playwright:v1.56.0-noble) with all browser dependencies pre-installed
- The CI workflow in
.github/workflows/image-build.yamlautomatically builds and pushes the image toghcr.io/theepicsaxguy/headlessx:1.2.0when changes are made to the Dockerfile. - The runtime image includes a
HEALTHCHECKthat probes/api/healthevery 30 seconds.
Namespace
- Namespace:
headlessx. No extra quota or limit range is defined here—reuse the cluster defaults.
Configuration and Secrets
- Runtime knobs (
PORT,NODE_ENV,UV_THREADPOOL_SIZE,NODE_OPTIONS) are set directly on the Deployment. AUTH_TOKENcomes fromes-headlessx-auth-token, which pullsapp-headlessx-auth-tokenout of Bitwarden through External Secrets.
Storage Layout
- Logs persist to
headlessx-logs, a 10Gi Longhorn-backed PVC mounted at/app/logs. /tmpuses anemptyDirto mimic the compose bind mount.
Deployment Highlights
- Single replica Deployment with requests set to 1 CPU / 1Gi and limits to 4 CPU / 4Gi.
- Probes hit
GET /api/healthon port 3000 with a 15s initial delay, 30s period, and 10s timeout. - Pod security:
runAsNonRoot,runAsUser/runAsGroup1000, default seccomp, no privilege escalation, and all capabilities dropped.
Networking
- Service
headlessxexposes port 3000 internally. HTTPRoutebindsheadlessx.pc-tips.seto theinternalGateway and forwards all paths to the Service.NetworkPolicyonly permits ingress from namespaces labeledname=gateway, and limits egress to DNS plus outbound HTTP/HTTPS.- Publish
headlessx.pc-tips.seinside the private DNS zone so the Gateway’s internal address resolves for callers.
Verification Checklist
- Wait for the Deployment to become
Availableand confirm probes stay green. kubectl port-forwardor exec into the pod and curlhttp://localhost:3000/api/health→ HTTP 200.- Resolve
headlessx.pc-tips.sefrom an internal network and curl through the Gateway → HTTP 200. - Inspect
/app/logsto verify log files reach the PVC. Tune retention or ship to centralized logging before the volume fills.