At a glance
--hostonly controls which interface MLflow binds to;--allowed-hostsdecides which Host headers get in.- Setting
--allowed-hostsreplaces the default of localhost plus private IPs. - Basic auth needs
mlflow[auth],MLFLOW_FLASK_SERVER_SECRET_KEYand an admin password of 12 or more characters. - Clients need
MLFLOW_TRACKING_URI, plus a username and password when auth is on.
Start the server
If you want one MLflow server on a remote box that training jobs on other machines can log to, start mlflow server. In MLflow 3.17.2, released on 2026-10-21 under Apache-2.0, mlflow ui prints the same help and runs the same tracking server (UI plus REST API), so older advice that mlflow ui is only a local viewer no longer applies.
pip install mlflow
mlflow server --backend-store-uri sqlite:///mlflow.db --artifacts-destination ./mlartifacts --port 5000Out of the box, mlflow server binds to 127.0.0.1 on port 5000 with 4 workers. Runs and metrics go to sqlite:///mlflow.db (it reuses an existing ./mlruns store if one is present), and artifacts land in ./mlartifacts. Artifact serving is on, so clients upload and download files through the server.
Backend store and artifact store
A remote server has two storage locations. The backend store holds experiments, runs, parameters and metrics, and --backend-store-uri takes a SQLAlchemy URL such as postgresql://user:password@host:5432/mlflow; install a PostgreSQL driver like psycopg2-binary for that. The artifact destination holds files such as checkpoints and plots, and --artifacts-destination takes a local path or a bucket like s3://my-bucket, with boto3 installed on the server.
Because the server proxies artifacts, your training machines never need credentials for the bucket. These are the flags you'll actually touch.
| Flag | Default in MLflow 3.17.2 | What to set on a remote server |
|---|---|---|
--host | 127.0.0.1 | Keep it for an SSH tunnel or a local reverse proxy; 0.0.0.0 to listen on every interface |
--port | 5000 | Any free port |
--backend-store-uri | sqlite:///mlflow.db | A PostgreSQL URL for a shared server |
--artifacts-destination | ./mlartifacts | A local path or a bucket such as s3://my-bucket |
--serve-artifacts | On | Leave it on so clients upload through the server |
--allowed-hosts | localhost plus private IPs | Every hostname your clients use, with the port if their URL has one |
--workers | 4 | Leave it unless many clients log at once |
--app-name | Not set | basic-auth to require a login |
Reach the UI through an SSH tunnel
With --host at its default, nothing outside the box can reach port 5000. If you only need the UI from your own laptop, an SSH tunnel is the simplest safe way in.
ssh -N -L 5000:localhost:5000 user@mlflow-boxThen open http://localhost:5000 in your browser. It reaches the server's 127.0.0.1:5000 over SSH without a firewall change, and localhost is on the default allow list.
Open it to your network: --host 0.0.0.0 and --allowed-hosts
When training jobs on other machines must reach the server directly, bind it to every interface with --host 0.0.0.0. Don't mistake that for access control: the help text says --host "is NOT a security setting - it only controls network binding. To restrict which clients can connect, use --allowed-hosts."
Since MLflow 3.5.0, a security middleware checks the Host header of every request to block DNS rebinding. By default it lets in localhost and private IP ranges, so a lab network or VPC works without changes. A public hostname gets 403 and "Invalid Host header - possible DNS rebinding attack detected" until you add it.
mlflow server \
--host 0.0.0.0 \
--port 5000 \
--backend-store-uri postgresql://mlflow:DB_PASSWORD@localhost:5432/mlflow \
--artifacts-destination s3://my-mlflow-artifacts \
--allowed-hosts "mlflow.example.com,mlflow.example.com:5000,localhost:5000,10.*"Two details caught us in testing. Setting --allowed-hosts replaces the defaults, so localhost:5000 and 127.0.0.1:5000 were rejected until we listed them. And mlflow.example.com doesn't cover mlflow.example.com:5000, so list the name with the port your clients put in their URL, or use a wildcard such as 10.*, which matched addresses with any port.
Add a login with basic auth
If the server is reachable over a network, turn on MLflow's built-in basic auth. Install the extra first, because without Flask-WTF the server refuses to start with auth enabled.
pip install "mlflow[auth]"
openssl rand -hex 32 > ~/.mlflow_secret
export MLFLOW_FLASK_SERVER_SECRET_KEY="$(cat ~/.mlflow_secret)"
export MLFLOW_AUTH_ADMIN_PASSWORD="choose-a-long-password"
mlflow server --app-name basic-auth --host 0.0.0.0 --port 5000 --allowed-hosts "mlflow.example.com:5000"Both variables are required. Without MLFLOW_FLASK_SERVER_SECRET_KEY the server stops with an error about CSRF protection, and MLflow ships no default admin password, so without MLFLOW_AUTH_ADMIN_PASSWORD (or admin_password in a config file named by MLFLOW_AUTH_CONFIG_PATH) it won't start. Passwords under 12 characters are rejected. The admin user is admin, and in our test the users were stored in basic_auth.db in the working directory.
Basic auth sends the password with every request, so put TLS in front with a reverse proxy before you expose the server beyond a private network.
Point your training scripts at the server
On the machines that run training, set MLFLOW_TRACKING_URI, or call mlflow.set_tracking_uri() in Python. With basic auth on, add MLFLOW_TRACKING_USERNAME and MLFLOW_TRACKING_PASSWORD; without them, every call fails with a 401.
export MLFLOW_TRACKING_URI=http://mlflow.example.com:5000
export MLFLOW_TRACKING_USERNAME=admin
export MLFLOW_TRACKING_PASSWORD="choose-a-long-password"import mlflow
with mlflow.start_run():
mlflow.log_param("lr", 3e-4)
mlflow.log_metric("loss", 0.42, step=1)MLflow records runs, it does not watch them
Once your scripts log to the server, you have one place for metrics, parameters and artifacts. What you don't get is an alert when a training run crashes, hangs or finishes: MLflow's webhooks cover Model Registry and Prompt Registry events and AI Gateway budgets, not training runs.
Runpeek doesn't store metrics or history, and its links expire 30 minutes after the last update, so it complements the tracking server rather than replacing it. Keep the stall window at 30 minutes or less.
FAQ
What is the difference between mlflow ui and mlflow server?
In MLflow 3.17.2 they run the same tracking server, with the same help text and defaults: 127.0.0.1, port 5000 and a SQLite backend. Older MLflow versions described mlflow ui as a local viewer, so mlflow server is the clearer name to use in scripts and service files.
Why does my MLflow server return Invalid Host header?
The security middleware added in MLflow 3.5.0 rejects requests whose Host header isn't allowed, to block DNS rebinding. Add your hostname to --allowed-hosts, including the port if clients use one in the URL. Setting the flag replaces the default list of localhost and private IPs.
What is the default MLflow admin password?
There isn't one. MLflow 3.17 refuses to start basic auth until you set MLFLOW_AUTH_ADMIN_PASSWORD or an admin_password in the auth config file, and the password must be at least 12 characters. The admin username is admin.
How do I log to a remote MLflow server from a training script?
Set MLFLOW_TRACKING_URI to the server URL before the script starts, or call mlflow.set_tracking_uri() at the top. If the server uses basic auth, also set MLFLOW_TRACKING_USERNAME and MLFLOW_TRACKING_PASSWORD. Artifacts go through the server, so clients need no bucket credentials.
Can MLflow alert me when a training run fails?
Not on its own. MLflow's webhooks cover registry events and AI Gateway budgets, not training runs. To hear about a crash or a hang, add an alert that watches the running job, such as a stall alert that fires when progress stops.
Check on long runs from your phone
Change one import and every tqdm bar prints a link you can open on any device. Get a Discord or Slack message when the run finishes, fails or stalls.
pip install tqdm-liveSources
- MLflow tracking server architecture mlflow.org
- MLflow network security (allowed hosts, CORS) mlflow.org
- MLflow basic HTTP authentication mlflow.org
- MLflow CLI reference mlflow.org
- MLflow changelog (3.5.0 security middleware) github.com
- MLflow 3.17.2 on PyPI pypi.org