Romain Vincent
11/07/2025, 10:00 AMMarvin
11/07/2025, 10:00 AMMarvin
11/07/2025, 10:07 AMPREFECT_UI_ENABLED=false (alias for server ui enabled)
- Point the UI at your API service: PREFECT_UI_API_URL=<https://your-api.example.com/api>
- If serving UI at a sub-path: PREFECT_UI_SERVE_BASE=/
- If the UI and API are on different origins, CORS is typically already permissive:
- API CORS defaults to *, but can be tightened via PREFECT_SERVER_API_CORS_ALLOWED_ORIGINS
CLI flags (verified):
- API only: prefect server start --no-ui
- Full server (web + services): prefect server start
- Only the webserver without background services: prefect server start --no-services
You can confirm with:
prefect server start --help
Kubernetes sketch
- API Deployment/Service
- Container command: prefect server start --no-ui
- Optionally keep services on one replica (and use --no-services on additional replicas) if you run multiple API instances.
- Expose as Service (ClusterIP) and Ingress at /api (or your desired host/path).
- UI Deployment/Service, option A (Prefect serves the UI)
- Container command: prefect server start --ui
- Env: PREFECT_UI_API_URL=<https://your-api.example.com/api>
- Ingress: expose only / to this service and block/omit /api so all API calls go to the API Service.
- UI Deployment/Service, option B (static web server)
- Build a tiny image that serves the Prefect UI static assets.
- Env in the UI container (if you use Prefect’s UI server): PREFECT_UI_API_URL=<https://your-api.example.com/api>
- Ingress: expose / from this static UI service.
Minimal env examples
- API pods:
- name: PREFECT_UI_ENABLED
value: "false"
- UI pods:
- name: PREFECT_UI_ENABLED
value: "true"
- name: PREFECT_UI_API_URL
value: "<https://prefect-api.example.com/api>"
Notes on the Helm chart
- The official chart deploys a single Prefect Server by default. It does not ship a predefined “UI-only” vs “API-only” split, but you can:
- Install two releases (one with UI disabled, one acting as UI), and route via Ingress as described; or
- Use custom manifests to run separate Deployments/Services.
Docs:
- Server Helm guide: Prefect Server Helm docs
- Settings reference: Prefect settings reference
- Security/CORS: Security & CORS
Would you like a concrete example with Kubernetes manifests or Helm values for your setup (Ingress hostnames/paths, single or multiple replicas, etc.)? Are you using the official Helm chart or custom YAML?Romain Vincent
11/07/2025, 10:14 AMMarvin
11/07/2025, 10:18 AMMarvin
11/07/2025, 10:22 AMhelm repo add prefect <https://prefecthq.github.io/prefect-helm>
helm repo update
kubectl create namespace prefect
Step 2) API-only release values (values-api.yaml)
- Disables the UI on these pods
- Exposes the API on port 4200
Note: Many chart versions expose env and args as env/extraArgs or similar keys. If your chart uses different keys (e.g., server.env, server.extraArgs), adjust accordingly. See the chart README for your version: prefect-helm repo.
fullnameOverride: prefect-api
replicaCount: 2
env:
- name: PREFECT_UI_ENABLED
value: "false"
- name: PREFECT_SERVER_API_HOST
value: "0.0.0.0"
- name: PREFECT_SERVER_API_PORT
value: "4200"
# If supported by your chart version, keep the API-only process explicit
extraArgs:
- server
- start
- --no-ui
service:
type: ClusterIP
port: 4200
Install:
helm upgrade --install prefect-api prefect/prefect-server -n prefect -f values-api.yaml
Step 3) UI-serving release values (values-ui.yaml)
- Serves the UI and points it at the API path that the Ingress will route to
- Avoids running background services here to prevent duplicate schedulers/etc
Option A (preferred): disable services with CLI flags (if extraArgs supported)
fullnameOverride: prefect-ui
replicaCount: 1
env:
- name: PREFECT_UI_ENABLED
value: "true"
- name: PREFECT_UI_API_URL
value: "<https://prefect.example.com/api>"
- name: PREFECT_SERVER_API_HOST
value: "0.0.0.0"
- name: PREFECT_SERVER_API_PORT
value: "4200"
extraArgs:
- server
- start
- --ui
- --no-services
service:
type: ClusterIP
port: 4200
Option B (fallback if your chart doesn’t allow extraArgs): disable services via env vars
fullnameOverride: prefect-ui
replicaCount: 1
env:
- name: PREFECT_UI_ENABLED
value: "true"
- name: PREFECT_UI_API_URL
value: "<https://prefect.example.com/api>"
# Turn off background services on the UI pods
- name: PREFECT_API_SERVICES_SCHEDULER_ENABLED
value: "false"
- name: PREFECT_API_SERVICES_LATE_RUNS_ENABLED
value: "false"
- name: PREFECT_API_SERVICES_REPOSSESSOR_ENABLED
value: "false"
- name: PREFECT_API_SERVICES_PAUSE_EXPIRATIONS_ENABLED
value: "false"
- name: PREFECT_API_SERVICES_TASK_RUN_RECORDER_ENABLED
value: "false"
- name: PREFECT_API_SERVICES_TRIGGERS_ENABLED
value: "false"
- name: PREFECT_API_SERVICES_EVENT_LOGGER_ENABLED
value: "false"
- name: PREFECT_API_SERVICES_EVENT_PERSISTER_ENABLED
value: "false"
- name: PREFECT_API_SERVICES_FOREMAN_ENABLED
value: "false"
service:
type: ClusterIP
port: 4200
Install:
helm upgrade --install prefect-ui prefect/prefect-server -n prefect -f values-ui.yaml
Step 4) Ingress that routes / to the UI release and /api to the API release
- This keeps the UI and API separate at the Service level and makes sure all API requests go to the API service (the UI service won’t be used for /api)
- Adjust host, TLS, and annotations for your environment
```
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: prefect-ingress
namespace: prefect
annotations:
kubernetes.io/ingress.class: nginx
spec:
rules:
- host: prefect.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: prefect-api
port:
number: 4200
- path: /Marvin
11/07/2025, 10:22 AMPREFECT_SERVER_API_CORS_ALLOWED_ORIGINS=<https://ui.example.com>). See Security & CORS docs.
- If you need a single static UI without a Prefect server process, you can serve the UI assets with Nginx and still set PREFECT_UI_API_URL — but that’s outside the scope of the official server chart.
- Settings reference: Prefect settings reference
- Helm chart docs: Server Helm guide and prefect-helm repo
If you share your chart version (and whether it exposes env vs extraEnv vs extraArgs), I can tailor the values.yaml to match your chart exactly and include TLS annotations for your ingress controller.