Karthik R
12/10/2025, 6:52 PMMarvin
12/10/2025, 6:52 PMMarvin
12/10/2025, 7:00 PM# 1) Resource group + ACA env
RG=prefect-rg
LOCATION=eastus
ENV_NAME=prefect-env
APP_NAME=prefect-server
az group create --name $RG --location $LOCATION
az containerapp env create \
--name $ENV_NAME \
--resource-group $RG \
--location $LOCATION
# 2) (Optional) Create PostgreSQL Flexible Server
# Replace passwords, sizing, and version to your standards
PG_SERVER=prefect-db-$RANDOM
PG_USER=prefect
PG_PASS='UseASecurePassword123!'
PG_DB=prefect
az postgres flexible-server create \
--name $PG_SERVER \
--resource-group $RG \
--location $LOCATION \
--admin-user $PG_USER \
--admin-password $PG_PASS \
--sku-name Standard_B2s \
--storage-size 32 \
--version 15
# Connection string (Azure Postgres requires SSL by default; include sslmode if needed)
DB_URL="postgresql+asyncpg://${PG_USER}:${PG_PASS}@${PG_SERVER}.<http://postgres.database.azure.com:5432/${PG_DB}?sslmode=require|postgres.database.azure.com:5432/${PG_DB}?sslmode=require>"
# 3) Deploy Prefect server to ACA
# Explicitly start the server on 0.0.0.0:4200
az containerapp create \
--name $APP_NAME \
--resource-group $RG \
--environment $ENV_NAME \
--image prefecthq/prefect:3-latest \
--command "prefect server start --host 0.0.0.0 --port 4200" \
--target-port 4200 \
--ingress external \
--cpu 2 \
--memory 4Gi \
--min-replicas 1 \
--max-replicas 3 \
--env-vars \
PREFECT_API_DATABASE_CONNECTION_URL="$DB_URL" \
PREFECT_SERVER_API_HOST="0.0.0.0" \
PREFECT_SERVER_API_PORT="4200" \
PREFECT_SERVER_API_AUTH_STRING="admin:AdminPassword123!"
# 4) Discover your ACA FQDN and point the UI at /api
FQDN=$(az containerapp show \
--name $APP_NAME \
--resource-group $RG \
--query properties.configuration.ingress.fqdn -o tsv)
# Set PREFECT_UI_API_URL so the UI JS calls the right API endpoint
az containerapp update \
--name $APP_NAME \
--resource-group $RG \
--set-env-vars PREFECT_UI_API_URL="https://${FQDN}/api"
echo "Prefect UI: https://${FQDN}"
echo "API URL: https://${FQDN}/api"
# 5) Run DB migrations once (especially before scaling beyond 1 replica)
az containerapp exec \
--name $APP_NAME \
--resource-group $RG \
--command "prefect server database upgrade -y"
# 6) (Optional) If using a custom domain, add it in ACA, then set PREFECT_UI_API_URL to that domain’s /api
# e.g. PREFECT_UI_API_URL=<https://prefect.yourdomain.com/api>
Health checks and scaling
- Health endpoint: /api/health (HTTP 200 when healthy)Marvin
12/10/2025, 7:00 PMexport PREFECT_API_URL="https://<your-aca-fqdn>/api"
# If you set Basic Auth on the server:
export PREFECT_API_AUTH_STRING="admin:AdminPassword123!"
prefect worker start --pool my-pool
Notes and best practices
- Only one container is needed; Prefect serves the UI and API together on port 4200.
- Do not set PREFECT_API_URL in the server container; that’s for clients/workers.
- Store passwords in ACA secrets rather than plain env vars (the CLI above shows env vars for brevity).
- Azure Postgres typically enforces SSL; append sslmode=require (or equivalent) to your DB URL if needed.
- Use managed TLS via ACA external ingress. Set PREFECT_UI_API_URL with https://<fqdn>/api.
- If you serve the UI/API under a subpath via a reverse proxy, set PREFECT_UI_API_URL accordingly and ensure the proxy routes / and /api/*.
Want me to tailor this for your environment?
- Do you already have a PostgreSQL server you want to use?
- Single replica (dev) or multi-replica (HA) to start?
- Do you want to enable HTTP Basic Auth on the API now?