Shubham
07/04/2026, 11:21 AMMarvin
07/04/2026, 11:21 AMMarvin
07/04/2026, 11:23 AMbash
pip install "prefect>=3"
export PREFECT_SERVER_API_AUTH_STRING="admin:StrongPassword123!"
export PREFECT_API_AUTH_STRING="admin:StrongPassword123!"
prefect server start --host 0.0.0.0 --port 4200
Then configure any client/worker that talks to that server:
bash
export PREFECT_API_URL="http://<your-server>:4200/api"
export PREFECT_API_AUTH_STRING="admin:StrongPassword123!"
You can test it with:
bash
curl -u admin:StrongPassword123! <http://localhost:4200/api/flows>
Important notes
- For self-hosted Prefect Server, use PREFECT_API_AUTH_STRING, not PREFECT_API_KEY
- PREFECT_API_KEY is for Prefect Cloud
- If both are set, the API key can interfere, so unset it for self-hosted usage
Recommended production setup on Ubuntu
1. Put credentials in an env file:
bash
sudo mkdir -p /etc/prefect
sudo nano /etc/prefect/server.env
Contents:
bash
PREFECT_SERVER_API_AUTH_STRING="admin:StrongPassword123!"
PREFECT_API_AUTH_STRING="admin:StrongPassword123!"
PREFECT_API_URL="<http://your-server:4200/api>"
2. Create a systemd service:
bash
sudo nano /etc/systemd/system/prefect-server.service
ini
[Unit]
Description=Prefect Server
After=network.target
[Service]
Type=simple
EnvironmentFile=/etc/prefect/server.env
ExecStart=/usr/local/bin/prefect server start --host 0.0.0.0 --port 4200
Restart=on-failure
[Install]
WantedBy=multi-user.target
3. Enable it:
bash
sudo systemctl daemon-reload
sudo systemctl enable --now prefect-server
sudo systemctl status prefect-server
Security recommendation
Basic auth works, but for a real deployment you should also put Prefect behind HTTPS via NGINX or another reverse proxy, otherwise credentials travel unencrypted over HTTP.
If you want, I can give you a full Ubuntu + systemd + NGINX + HTTPS example.
Relevant docs:
- Prefect docs
- Run a self-hosted Prefect server
- Settings referenceShubham
07/04/2026, 11:37 AMShubham
07/04/2026, 11:37 AMMarvin
07/04/2026, 11:37 AMMarvin
07/04/2026, 11:39 AMprefect config view in your shell does not prove the server process is using it
It only shows what your current CLI session sees.
2. Auth is only attached when the API app starts
If PREFECT_SERVER_API_AUTH_STRING was missing when the service started, restarting the shell or setting env later won't enable it. The service must start with that env present.
3. /api/health and /api/ready are open by design
Those endpoints do not require auth.
Try this exact test against a protected endpoint:
bash
curl -i <http://192.168.29.151:4200/api/flows>
If auth is working, that should return 401 Unauthorized.
Then test with auth:
bash
curl -i -u admin:StrongPassword123! <http://192.168.29.151:4200/api/flows>
If that succeeds, auth is working correctly.
Check whether systemd actually passed the env to the service
bash
sudo systemctl show prefect-server --property=Environment
You should see PREFECT_SERVER_API_AUTH_STRING=... there.
Also inspect the service file:
bash
sudo systemctl cat prefect-server
You want something like:
ini
[Service]
EnvironmentFile=/etc/prefect/server.env
ExecStart=/home/prefect/.venv/bin/prefect server start --host 0.0.0.0 --port 4200
Then reload and fully restart:
bash
sudo systemctl daemon-reload
sudo systemctl restart prefect-server
sudo systemctl status prefect-server
Common gotcha
If your env file contains quotes or bad formatting, systemd may not load it as expected. Prefer:
bash
PREFECT_SERVER_API_AUTH_STRING=admin:StrongPassword123!
not necessarily:
bash
PREFECT_SERVER_API_AUTH_STRING="admin:StrongPassword123!"
Best next check
Please run these and paste the output:
bash
curl -i <http://192.168.29.151:4200/api/flows>
sudo systemctl show prefect-server --property=Environment
sudo systemctl cat prefect-server
If you want, I can help you debug the exact systemd service line-by-line.Shubham
07/04/2026, 11:45 AMMarvin
07/04/2026, 11:45 AMMarvin
07/04/2026, 11:45 AMephemeral is Prefect’s temporary local profile that gets used when you haven’t explicitly selected another profile.
In practice, it usually means:
- Prefect is running in a local/self-hosted context
- settings may be coming from your shell env and temporary local defaults
- it is not the same thing as a named persistent profile like default, dev, or prod
From your output:
bash
PREFECT_PROFILE='ephemeral'
PREFECT_API_URL='<http://192.168.29.151:4200/api>' (from profile)
PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='true' (from profile)
that means Prefect created/used a temporary profile context for local usage.
Important: this is not the reason auth is bypassed.
The auth behavior depends on the server process settings at startup, especially:
bash
PREFECT_SERVER_API_AUTH_STRING
So even if your CLI says profile = ephemeral, the real question is whether the systemd service started with that variable set.
If you want to see your available profiles:
bash
prefect profile ls
To inspect the active one:
bash
prefect profile inspect
To create and use a normal persistent profile:
bash
prefect profile create selfhosted
prefect profile use selfhosted
prefect config set PREFECT_API_URL="<http://192.168.29.151:4200/api>"
If you want, I can also explain:
- ephemeral profile vs default profile
- why Prefect created it on your machine
- whether you should switch to a named profile for your server setupShubham
07/04/2026, 11:52 AMMarvin
07/04/2026, 11:52 AMMarvin
07/04/2026, 11:52 AMPREFECT_SERVER_API_AUTH_STRING, Prefect protects the server endpoints with HTTP Basic Auth, and since the UI talks to that same server/API, the browser will also prompt for those credentials.
So behavior like this is normal:
- browser opens Prefect UI
- browser gets 401
- browser shows a Basic Auth login popup
- after entering username:password, UI loads
Important limitation
Prefect Server auth is very simple for self-hosting:
- one shared username/password
- no separate UI login
- no user accounts / RBAC
- UI and API use the same credentials
So you cannot natively have:
- open UI but protected API
- separate UI username/password from API credentials
- multiple users with different roles
If you want more flexible access control, the usual approach is to put Prefect behind a reverse proxy like NGINX, Traefik, or OAuth proxy and handle auth there.
Examples:
- Basic auth at NGINX
- SSO/OIDC via oauth2-proxy
- IP allowlisting for internal-only access
If you want, I can show you either:
1. keep Prefect’s built-in auth and make the browser login work cleanly, or
2. remove Prefect auth and use NGINX basic auth / HTTPS instead, which is often better for Ubuntu deployments.