Mohamed Zaki
08/24/2025, 5:55 PMserver:
image: prefecthq/prefect:3.4.13-python3.11
labels:
- "com.azcare.service=work-wizard-server"
- "com.azcare.domain=<http://demo-wizard.azcare.ai|demo-wizard.azcare.ai>"
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
environment:
PREFECT_API_DATABASE_CONNECTION_URL: <postgresql+asyncpg://prefect:prefect@db:5432/prefect>
PREFECT_SERVER_API_HOST: 0.0.0.0
PREFECT_UI_API_URL: "<https://demo-wizard.azcare.ai/api>"
PREFECT_MESSAGING_BROKER: prefect_redis.messaging
PREFECT_MESSAGING_CACHE: prefect_redis.messaging
PREFECT_REDIS_MESSAGING_HOST: redis
PREFECT_REDIS_MESSAGING_PORT: 6379
PREFECT_REDIS_MESSAGING_DB: 0
PREFECT_LOGGING_LEVEL: DEBUG
PREFECT_LOGGING_LOG_PRINTS: True
PREFECT_SERVER_LOGGING_LEVEL: DEBUG
PREFECT_SERVER_LOGGING_LOG_PRINTS: True
PREFECT_SERVER_API_AUTH_STRING: "admin:password"
command: prefect server start --no-services
ports:
- "4200:4200"
healthcheck:
test: [ "CMD-SHELL", "python -c 'import json,urllib.request,sys; sys.exit(0 if json.loads(urllib.request.urlopen(\"<http://localhost:4200/api/health>\", timeout=1).read()) is True else 1)' " ]
interval: 5s
timeout: 3s
retries: 30
restart: always
create-autoupdate-deployment:
image: prefect-workpool
build:
context: .
dockerfile: docker/autoupdate/Dockerfile
depends_on:
server:
condition: service_healthy
environment:
PREFECT_API_URL: <http://server:4200/api>
PREFECT_SERVER_API_AUTH_STRING: "admin:password"
# command: prefect deployment build autoupdate/pipeline/deployment.py:autoupdate_pipeline --name autoupdate-pipeline --cron "0 0 * * *" --timezone "America/New_York" --infra prefect-wizard-infra --storage-block prefect-s3-block
command: bash -c "cd /opt/prefect/autoupdate && prefect --no-prompt deploy --name autoupdate-deployment"
volumes:
- ./autoupdate:/opt/prefect/autoupdate
- ./core:/opt/prefect/autoupdate/core
env_file:
- .env
autoupdate-worker:
image: prefect-workpool
depends_on:
server:
condition: service_healthy
services:
condition: service_started
create-autoupdate-deployment:
condition: service_completed_successfully
environment:
PREFECT_API_URL: <http://localhost:4200/api>
DOCKER_HOST: <tcp://localhost:2375>
PREFECT_SERVER_API_AUTH_STRING: "admin:password"
# DOCKER_TLS_VERIFY: ${DOCKER_TLS_VERIFY:-}
# DOCKER_CERT_PATH: ${DOCKER_CERT_PATH:-}
network_mode: host
volumes:
- ./autoupdate:/opt/prefect/autoupdate
- ./core:/opt/prefect/autoupdate/core
- ${HOME}/.wizard:/logs
env_file:
- .env
restart: always
I get this auth error with create-autoupdate-deployment:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/prefect/client/base.py", line 379, in send
response.raise_for_status()
File "/usr/local/lib/python3.11/site-packages/prefect/client/base.py", line 163, in raise_for_status
raise PrefectHTTPStatusError.from_httpx_error(exc) from exc.__cause__
prefect.exceptions.PrefectHTTPStatusError: Client error '401 Unauthorized' for url '<http://server:4200/api/work_pools/auto-update-pool>'
Response: {'exception_message': 'Unauthorized'}
For more information check: <https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401>
Marvin
08/24/2025, 5:55 PMMarvin
08/24/2025, 5:57 PMserver:
environment:
PREFECT_SERVER_API_AUTH_STRING: "admin:password"
PREFECT_API_DATABASE_CONNECTION_URL: <postgresql+asyncpg://prefect:prefect@db:5432/prefect>
PREFECT_SERVER_API_HOST: 0.0.0.0
PREFECT_UI_API_URL: "<https://demo-wizard.azcare.ai/api>"
# ...other settings...
create-autoupdate-deployment:
environment:
PREFECT_API_URL: <http://server:4200/api>
PREFECT_API_AUTH_STRING: "admin:password"
PREFECT_API_KEY: "" # ensure not set from .env
# command: make sure you have '&&' not '&&' in the actual file
command: bash -c "cd /opt/prefect/autoupdate && prefect --no-prompt deploy --name autoupdate-deployment"
autoupdate-worker:
environment:
PREFECT_API_URL: <http://localhost:4200/api>
PREFECT_API_AUTH_STRING: "admin:password"
PREFECT_API_KEY: "" # ensure not set from .env
DOCKER_HOST: <tcp://localhost:2375>
# ...rest unchanged...
Docs for reference:
- Security settings (Prefect 3)
If you still see 401s after this change, please double-check:
- No PREFECT_API_KEY is leaking in via your .env.
- The password matches exactly between server and clients.
- You can curl the API with basic auth from the client container, e.g. curl -u admin:password <http://server:4200/api/health>
(should return true).Mohamed Zaki
08/24/2025, 6:13 PMMarvin
08/24/2025, 6:13 PMMarvin
08/24/2025, 6:14 PMprefect version
prefect config view | egrep -i 'api\.(url|auth_string|key)'
python - <<'PY'
from prefect.settings import get_current_settings
s = get_current_settings()
print("api.url =", s.api_url)
print("api.auth_string =", s.api_auth_string)
print("api.key =", s.api_key)
PY
2) Verify the API requires Basic auth and that your creds work:
curl -sv <http://server:4200/api/health>
curl -sv -u admin:password <http://server:4200/api/health>
- First call should 401
- Second should 200 with “true”
3) Print env to ensure nothing is overriding:
env | grep -E '^PREFECT_'
Confirm:
- PREFECT_API_URL=http://server:4200/api
- PREFECT_API_AUTH_STRING=admin:password
- PREFECT_API_KEY is empty/unset
- No stray PREFECT_CLOUD_* variables
If any of the above don’t match, that’s the smoking gun.
A couple of fixes I recommend right away:
- Ensure your client image is on the same Prefect version as the server (you’re running server 3.4.13). If your custom prefect-workpool image doesn’t pin Prefect, it could be older/newer and ignore the setting. Easiest: base it on the official image or pip-pin it.
- Example Dockerfile base: FROM prefecthq/prefect:3.4.13-python3.11
- Or ensure: pip install "prefect==3.4.13"
- In the create-autoupdate-deployment service, explicitly neutralize any API key from .env:
environment:
PREFECT_API_URL: <http://server:4200/api>
PREFECT_API_AUTH_STRING: "admin:password"
PREFECT_API_KEY: "" # make sure this wins over .env
Optional sanity check: run the deploy once with inline env to rule out compose/env_file issues:
bash -lc 'PREFECT_API_URL=<http://server:4200/api> PREFECT_API_AUTH_STRING=admin:password PREFECT_API_KEY= prefect --no-prompt deploy --name autoupdate-deployment'
If the above checks still show 401, please share:
- Output of the four commands above
- The Dockerfile for prefect-workpool
- A short snippet of the server logs around the 401 (since you have PREFECT_SERVER_LOGGING_LEVEL=DEBUG)
Reference:
- Security settings (Prefect 3) (PREFECT_SERVER_API_AUTH_STRING on the server, PREFECT_API_AUTH_STRING on clients)Mohamed Zaki
08/24/2025, 6:34 PMMohamed Zaki
08/24/2025, 6:34 PMMarvin
08/24/2025, 6:34 PMMarvin
08/24/2025, 6:37 PMprefect work-pool create "auto-update-pool" --type docker --overwrite
prefect work-pool resume "auto-update-pool"
- Inspect details:
prefect work-pool inspect "auto-update-pool"
2) Ensure a worker is running and polling the pool
- Start a worker:
prefect worker start -p "auto-update-pool"
- Check worker logs for lines like “Connected to work pool 'auto-update-pool'” and “Polling for work”.
3) Validate concurrency and pausing
- Make sure the pool is not paused (see inspect output).
- If you set a concurrency limit, make sure it’s > 0:
prefect work-pool set-concurrency-limit "auto-update-pool" 10
4) Confirm your deployment points at the pool (and queue, if any)
- Inspect the deployment:
prefect deployments inspect "<your-deployment-name>"
- Ensure it lists Work pool: auto-update-pool (and the queue name if used). If not, update and redeploy.
5) Run a quick smoke test
- Trigger a run:
prefect deployments run "<your-deployment-name>"
- You should see the worker pick it up.
In your compose specifically
- Make sure your worker service actually starts a worker. Your snippet didn’t show a command; add:
command: >
bash -lc 'prefect worker start -p "auto-update-pool"'
- Ensure the pool exists before the worker starts. Add a small init service:
create-work-pool:
image: prefecthq/prefect:3.4.13-python3.11
depends_on:
server:
condition: service_healthy
environment:
PREFECT_API_URL: <http://server:4200/api>
PREFECT_API_AUTH_STRING: "admin:password"
command: >
bash -lc 'prefect work-pool create "auto-update-pool" --type docker --overwrite &&
prefect work-pool resume "auto-update-pool" || true'
- Then depend your worker on this:
autoupdate-worker:
depends_on:
server:
condition: service_healthy
create-work-pool:
condition: service_completed_successfully
command: >
bash -lc 'prefect worker start -p "auto-update-pool"'
environment:
PREFECT_API_URL: <http://localhost:4200/api>
PREFECT_API_AUTH_STRING: "admin:password"
PREFECT_API_KEY: ""
Optional: a simple readiness gate you can run before deployments
# assumes PREFECT_API_URL and PREFECT_API_AUTH_STRING are set
prefect work-pool inspect "auto-update-pool" >/dev/null 2>&1 || exit 1
# If you pause pools in automation, also parse the output to verify not paused
Notes for your environment
- You’re using Docker: ensure your pool type is docker and the worker can reach the Docker daemon (DOCKER_HOST etc.).
- With Basic Auth: set PREFECT_API_URL and PREFECT_API_AUTH_STRING on the worker and deployment containers; ensure PREFECT_API_KEY is unset/empty so Basic Auth is used.
If you want, share:
- The output of prefect work-pool inspect "auto-update-pool"
- The worker container logs after adding the start command
Docs:
- Work pools and workers CLI commands are available via prefect work-pool --help
and prefect worker --help
.Brendan Dalpe
08/25/2025, 12:59 PMPREFECT_SERVER_EVENTS_CAUSAL_ORDERING=prefect_redis.ordering
to your environment variables to ensure correct ordering of events.
The docs got updated on Saturday so you may have not seen this. https://github.com/PrefectHQ/prefect/issues/18766#issuecomment-3215942971Brendan Dalpe
08/25/2025, 12:59 PM