my prefect server setup prefect-metrics.waow.tech
python orchestration
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

revert: undo Traefik IngressRoute public UI approach

the native browser BasicAuth prompt fires on every SPA navigation for
unauthenticated users — unusable. restoring Prefect's own BasicAuth
and the standard Ingress setup.

keeps PREFECT_SERVER_UI_SHOW_PROMOTIONAL_CONTENT=false via server.env.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

zzstoatzz c02dfdc5 ba7ee942

+14 -108
-12
deploy/prefect-certificate.yaml
··· 1 - apiVersion: cert-manager.io/v1 2 - kind: Certificate 3 - metadata: 4 - name: prefect-server-tls 5 - namespace: prefect 6 - spec: 7 - secretName: prefect-server-tls 8 - issuerRef: 9 - name: letsencrypt-prod 10 - kind: ClusterIssuer 11 - dnsNames: 12 - - DOMAIN_PLACEHOLDER
-58
deploy/prefect-ingress-route.yaml
··· 1 - --- 2 - # BasicAuth middleware — credentials from prefect-traefik-auth secret (htpasswd format) 3 - apiVersion: traefik.io/v1alpha1 4 - kind: Middleware 5 - metadata: 6 - name: prefect-admin-auth 7 - namespace: prefect 8 - spec: 9 - basicAuth: 10 - secret: prefect-traefik-auth 11 - 12 - --- 13 - # Public IngressRoute — GETs and explicit safe read POSTs, no auth required (priority 20) 14 - apiVersion: traefik.io/v1alpha1 15 - kind: IngressRoute 16 - metadata: 17 - name: prefect-public 18 - namespace: prefect 19 - spec: 20 - entryPoints: 21 - - websecure 22 - routes: 23 - - match: Host(`DOMAIN_PLACEHOLDER`) && Method(`GET`) 24 - kind: Rule 25 - priority: 20 26 - services: 27 - - name: prefect-server 28 - port: 4200 29 - - match: "Host(`DOMAIN_PLACEHOLDER`) && Method(`POST`) && (Path(`/api/flows/filter`) || Path(`/api/flows/count`) || Path(`/api/flows/paginate`) || Path(`/api/flow_runs/filter`) || Path(`/api/flow_runs/count`) || Path(`/api/flow_runs/paginate`) || Path(`/api/flow_runs/history`) || Path(`/api/flow_runs/lateness`) || Path(`/api/task_runs/filter`) || Path(`/api/task_runs/count`) || Path(`/api/task_runs/paginate`) || Path(`/api/task_runs/history`) || Path(`/api/deployments/filter`) || Path(`/api/deployments/count`) || Path(`/api/deployments/paginate`) || Path(`/api/artifacts/filter`) || Path(`/api/artifacts/count`) || Path(`/api/artifacts/latest/filter`) || Path(`/api/artifacts/latest/count`) || Path(`/api/work_pools/filter`) || Path(`/api/work_pools/count`) || Path(`/api/work_queues/filter`) || Path(`/api/logs/filter`) || Path(`/api/events/filter`) || Path(`/api/events/count-by/day`) || Path(`/api/events/count-by/event_type`) || Path(`/api/events/count-by/resource_id`) || Path(`/api/variables/filter`) || Path(`/api/variables/count`) || Path(`/api/automations/filter`) || Path(`/api/automations/count`) || Path(`/api/block_types/filter`) || Path(`/api/block_schemas/filter`) || Path(`/api/block_documents/filter`) || Path(`/api/concurrency_limits/filter`) || Path(`/api/v2/concurrency_limits/filter`))" 30 - kind: Rule 31 - priority: 20 32 - services: 33 - - name: prefect-server 34 - port: 4200 35 - tls: 36 - secretName: prefect-server-tls 37 - 38 - --- 39 - # Admin IngressRoute — catch-all, BasicAuth required (priority 10) 40 - apiVersion: traefik.io/v1alpha1 41 - kind: IngressRoute 42 - metadata: 43 - name: prefect-admin 44 - namespace: prefect 45 - spec: 46 - entryPoints: 47 - - websecure 48 - routes: 49 - - match: Host(`DOMAIN_PLACEHOLDER`) 50 - kind: Rule 51 - priority: 10 52 - middlewares: 53 - - name: prefect-admin-auth 54 - services: 55 - - name: prefect-server 56 - port: 4200 57 - tls: 58 - secretName: prefect-server-tls
+11 -2
deploy/prefect-values.yaml
··· 2 2 replicaCount: 1 3 3 4 4 basicAuth: 5 - enabled: false # auth moves to Traefik IngressRoute 5 + enabled: true 6 + existingSecret: prefect-auth 6 7 7 8 uiConfig: 8 9 prefectUiApiUrl: "https://DOMAIN_PLACEHOLDER/api" ··· 34 35 architecture: standalone 35 36 36 37 ingress: 37 - enabled: false # replaced by IngressRoute CRDs + Certificate CR in deploy/prefect-ingress-route.yaml 38 + enabled: true 39 + className: traefik 40 + host: 41 + hostname: DOMAIN_PLACEHOLDER 42 + path: / 43 + pathType: Prefix 44 + annotations: 45 + cert-manager.io/cluster-issuer: letsencrypt-prod 46 + tls: true
+3 -36
justfile
··· 86 86 sed "s|LETSENCRYPT_EMAIL_PLACEHOLDER|$LETSENCRYPT_EMAIL|g" deploy/cluster-issuer.yaml \ 87 87 | kubectl apply -f - 88 88 89 - echo "==> creating prefect traefik auth secret (htpasswd format)" 90 - USER=$(echo "$AUTH_STRING" | cut -d: -f1) 91 - PASS=$(echo "$AUTH_STRING" | cut -d: -f2-) 92 - HASH=$(openssl passwd -apr1 "$PASS") 93 - kubectl create secret generic prefect-traefik-auth \ 89 + echo "==> creating prefect auth secret" 90 + kubectl create secret generic prefect-auth \ 94 91 --namespace prefect \ 95 - --from-literal=users="${USER}:${HASH}" \ 92 + --from-literal=auth-string="$AUTH_STRING" \ 96 93 --dry-run=client -o yaml | kubectl apply -f - 97 94 98 95 echo "==> installing prefect server" ··· 102 99 --values - \ 103 100 --set postgresql.auth.password="$POSTGRES_PASSWORD" \ 104 101 --wait --timeout 5m 105 - 106 - echo "==> applying prefect certificate" 107 - sed "s|DOMAIN_PLACEHOLDER|$DOMAIN|g" deploy/prefect-certificate.yaml \ 108 - | kubectl apply -f - 109 - 110 - echo "==> applying prefect ingress routes" 111 - sed "s|DOMAIN_PLACEHOLDER|$DOMAIN|g" deploy/prefect-ingress-route.yaml \ 112 - | kubectl apply -f - 113 102 114 103 echo "==> installing monitoring stack" 115 104 sed "s|GRAFANA_DOMAIN_PLACEHOLDER|$GRAFANA_DOMAIN|g" deploy/monitoring-values.yaml \ ··· 150 139 # deploy the kubernetes worker to the cluster 151 140 worker: 152 141 kubectl apply -f deploy/worker.yaml 153 - 154 - # re-apply public ingress config without full deploy (certificate + ingress routes + auth secret) 155 - public-ingress: 156 - #!/usr/bin/env bash 157 - set -euo pipefail 158 - : "${DOMAIN:?set DOMAIN}" 159 - : "${AUTH_STRING:?set AUTH_STRING}" 160 - USER=$(echo "$AUTH_STRING" | cut -d: -f1) 161 - PASS=$(echo "$AUTH_STRING" | cut -d: -f2-) 162 - HASH=$(openssl passwd -apr1 "$PASS") 163 - kubectl create secret generic prefect-traefik-auth \ 164 - --namespace prefect \ 165 - --from-literal=users="${USER}:${HASH}" \ 166 - --dry-run=client -o yaml | kubectl apply -f - 167 - sed "s|DOMAIN_PLACEHOLDER|$DOMAIN|g" deploy/prefect-certificate.yaml \ 168 - | kubectl apply -f - 169 - sed "s|DOMAIN_PLACEHOLDER|$DOMAIN|g" deploy/prefect-ingress-route.yaml \ 170 - | kubectl apply -f - 171 - echo "done — verify:" 172 - echo " curl -sf https://$DOMAIN/api/health | jq ." 173 - echo " curl -sf -X POST https://$DOMAIN/api/flow_runs/filter -H 'Content-Type: application/json' -d '{}' | jq 'length'" 174 - echo " curl -o /dev/null -w '%{http_code}' -X POST https://$DOMAIN/api/flow_runs/ -H 'Content-Type: application/json' -d '{}' # expect 401" 175 142 176 143 # register flow deployments (run locally with PREFECT_API_URL + PREFECT_API_AUTH_STRING) 177 144 register-flows: