[{"data":1,"prerenderedAt":186},["ShallowReactive",2],{"seo-verification":3,"blog-self-host-mlflow-vps-experiment-tracking-en":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-self-host-mlflow-vps-experiment-tracking-en",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":28,"featuredImage":30,"bgImage":31,"posterImage":32,"relatedSolution":33,"intro":36,"sections":37,"ctaTitle":120,"ctaBody":121,"ctaButton":122,"ctaUrl":123,"relatedPosts":124},567,"self-host-mlflow-vps-experiment-tracking",{"fr":12,"en":10,"ar":13,"es":14},"self-host-mlflow-vps","استضافة-mlflow-على-vps-تتبع-تجارب-تعلم-الآلة","autoalojar-mlflow-vps-seguimiento-experimentos","MLflow on a VPS: ML Experiment Tracking and Model Registry","Install MLflow on a VPS: machine learning experiment tracking, a model registry and LLM tracing, password-protected and served over HTTPS.",6,0,false,"2026-11-05T00:00:00+00:00","2026-11-06T16:13:06+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},1,"Artificial Intelligence","intelligence-artificielle","bg-purple-500\u002F10 text-purple-400","ia",[29],{"id":23,"name":24,"slug":25,"color":26,"icon":27},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fself-host-mlflow-vps-poster.svg",{"categorySlug":34,"appSlug":35},"artificial-intelligence","mlflow","A machine learning project quickly produces dozens of attempts: a learning rate changed here, a dataset cleaned there, and a metric jotted down in a notebook corner. Three weeks later, nobody knows which model scored highest, or with which code. MLflow is the open-source platform (Apache-2.0 licensed) that keeps all of it on a central server: parameters, metrics and files of every run, versioned models, and traces of LLM applications. This guide installs it on a VPS with Docker Compose, protects it with a password, connects your Python code, then sets up accounts, backups and updates.",[38,42,52,79,82,98,102,105,108,111,114,117],{"type":39,"title":40,"body":41},"h2","Why an MLflow server","Run locally, MLflow writes its results to an `mlruns` folder on your machine: nobody else sees them, and they disappear with the machine. A tracking server changes that. Every notebook, every training script and every team member sends their runs to the same place, and the interface compares them side by side.\n\nThe same server holds the model registry — the list of validated, versioned models, with an alias for the one in production — and, for generative AI, the traces of your calls to language models.",{"type":43,"title":44,"items":45},"ul","What MLflow brings",[46,47,48,49,50,51],"**Experiment tracking** — parameters, metrics and artifacts of every run, filtered and compared in the interface.","**Model registry** — versions, aliases and history, so you know exactly what runs in production.","**LLM tracing** — inputs, outputs, latency and steps of every request of your generative AI applications.","**Artifacts served by the server** — files, charts and models uploaded over HTTPS, no S3 storage to configure.","**Automatic logging** — `autolog()` for scikit-learn, PyTorch, Transformers, XGBoost, OpenAI or LangChain.","**Accounts and permissions** — one account per person, permissions granted experiment by experiment.",{"type":53,"title":54,"headers":55,"rows":58},"comparison","MLflow versus tracking by hand",[5,56,57],"MLflow server","Notebooks and spreadsheet",[59,63,67,71,75],[60,61,62],"Run history","Every run recorded automatically","Whatever someone remembered to write down",[64,65,66],"Comparing two models","One screen, metrics side by side","Copying numbers",[68,69,70],"Produced files","Stored with the run that created them","Scattered across laptops",[72,73,74],"Model in production","A version and an alias in the registry","A file named \"final_v3\"",[76,77,78],"Teamwork","A shared server, accounts","Sending files around",{"type":39,"title":80,"body":81},"Prerequisites","An Ubuntu 24.04 VPS with **2 GB of RAM** is enough to start; plan 4 GB and more disk if you store many models, since artifacts take up the space. You need Docker with the Compose plugin, and a **domain name** pointing to the VPS, with nginx and an HTTPS certificate: your scripts and your team will connect to it.",{"type":83,"title":84,"steps":85},"steps","Install MLflow with Docker Compose",[86,89,92,95],{"title":87,"body":88},"Prepare the directory and the secrets","Create the application directory and a `.env` file holding the `admin` account's password, the session key and your domain.\n```bash\nmkdir -p \u002Fopt\u002Fmlflow && cd \u002Fopt\u002Fmlflow\ncat > .env \u003C\u003CEOF\nADMIN_PASSWORD=$(openssl rand -hex 16)\nSECRET_KEY=$(openssl rand -hex 24)\nDOMAIN=mlflow.example.ma\nEOF\nchmod 600 .env\n```",{"title":90,"body":91},"Write the docker-compose.yml","The `-full` image is the official variant that ships the authentication module. At startup, the command writes the `basic_auth.ini` file that declares the `admin` account; `--allowed-hosts` only accepts your domain and the loopback. The port is only published on the loopback: only nginx reaches it. `MLFLOW_SERVER_ENABLE_JOB_EXECUTION=false` turns off the background job runner, which is memory-hungry and not needed for tracking.\n```yaml\nservices:\n  mlflow:\n    image: ghcr.io\u002Fmlflow\u002Fmlflow:v3.18.0-full\n    restart: unless-stopped\n    ports:\n      - \"127.0.0.1:5000:5000\"\n    environment:\n      ADMIN_PASSWORD: ${ADMIN_PASSWORD}\n      DOMAIN: ${DOMAIN}\n      MLFLOW_FLASK_SERVER_SECRET_KEY: ${SECRET_KEY}\n      MLFLOW_AUTH_CONFIG_PATH: \u002Fmlflow\u002Fbasic_auth.ini\n      MLFLOW_SERVER_ENABLE_JOB_EXECUTION: \"false\"\n    entrypoint: [\"\u002Fbin\u002Fsh\", \"-c\"]\n    command:\n      - >-\n        mkdir -p \u002Fmlflow\u002Fartifacts &&\n        printf '[mlflow]\\ndefault_permission = NO_PERMISSIONS\\ndatabase_uri = sqlite:\u002F\u002F\u002F\u002Fmlflow\u002Fbasic_auth.db\\nadmin_username = admin\\nadmin_password = %s\\nauthorization_function = mlflow.server.auth:authenticate_request_basic_auth\\n' \"$$ADMIN_PASSWORD\" > \u002Fmlflow\u002Fbasic_auth.ini &&\n        exec mlflow server --app-name basic-auth --host 0.0.0.0 --port 5000 --workers 2\n        --backend-store-uri sqlite:\u002F\u002F\u002F\u002Fmlflow\u002Fmlflow.db --artifacts-destination \u002Fmlflow\u002Fartifacts\n        --allowed-hosts \"$$DOMAIN,localhost:*,127.0.0.1:*\"\n    volumes:\n      - mlflow-data:\u002Fmlflow\n\nvolumes:\n  mlflow-data: {}\n```",{"title":93,"body":94},"Start and check","Startup takes about fifteen seconds. `\u002Fhealth` answers without authentication; the API returns 401 without credentials.\n```bash\ndocker compose up -d\ncurl -fsS http:\u002F\u002F127.0.0.1:5000\u002Fhealth\ncurl -s -o \u002Fdev\u002Fnull -w '%{http_code}\\n' http:\u002F\u002F127.0.0.1:5000\u002Fapi\u002F2.0\u002Fmlflow\u002Fexperiments\u002Fsearch\n```",{"title":96,"body":97},"Publish over HTTPS with nginx","In your domain's vhost (certificate obtained with certbot), proxy to the local port and pass the `Host` header. Raise `client_max_body_size`: a model uploaded as an artifact quickly exceeds the default limit.\n```nginx\nlocation \u002F {\n    proxy_pass http:\u002F\u002F127.0.0.1:5000;\n    proxy_set_header Host $host;\n    proxy_set_header X-Forwarded-Proto $scheme;\n    client_max_body_size 512m;\n}\n```",{"type":99,"title":100,"body":101},"tip","Without --app-name basic-auth, the server is open","By default, `mlflow server` has no authentication: anyone who reaches the address can read your experiments, download your models and delete everything. Keep `--app-name basic-auth`, never publish port 5000 on the public IP, and keep `--allowed-hosts` set to your domain only: it is MLflow's protection against DNS rebinding.",{"type":39,"title":103,"body":104},"Send your experiments from Python","Install the client (`pip install mlflow`) on the training machine, then point it to your server. Credentials are passed through environment variables:\n```python\nimport os\nimport mlflow\n\nos.environ[\"MLFLOW_TRACKING_USERNAME\"] = \"admin\"\nos.environ[\"MLFLOW_TRACKING_PASSWORD\"] = \"YOUR_PASSWORD\"\nmlflow.set_tracking_uri(\"https:\u002F\u002Fmlflow.example.ma\")\nmlflow.set_experiment(\"churn-model\")\n\nwith mlflow.start_run():\n    mlflow.log_param(\"learning_rate\", 0.01)\n    mlflow.log_metric(\"accuracy\", 0.93)\n    mlflow.log_artifact(\"confusion_matrix.png\")\n```\nThe run appears in the interface right away, with its parameters, metrics and the uploaded file. `mlflow.sklearn.autolog()` or `mlflow.pytorch.autolog()` record all of that without an extra line.",{"type":39,"title":106,"body":107},"Trace an LLM application","For an assistant or an agent, tracing records every request with its model calls, its steps and their duration. Turn on your library's automatic logging, or decorate your own functions:\n```python\nimport mlflow\n\nmlflow.set_experiment(\"support-assistant\")\nmlflow.openai.autolog()   # every OpenAI client call becomes a trace\n\n@mlflow.trace\ndef answer(question: str) -> str:\n    ...\n```\nTraces show up in the experiment's tab: you see which call was slow, which context was sent and what the model answered.",{"type":39,"title":109,"body":110},"The model registry","When a run is validated, register its model: it gets a version number, and you can give it an alias such as `production`.\n```python\nmlflow.register_model(f\"runs:\u002F{run_id}\u002Fmodel\", \"churn-model\")\n```\nYour inference service then loads `models:\u002Fchurn-model@production`: switching models means moving the alias, without touching the code.",{"type":39,"title":112,"body":113},"Accounts and permissions","The `admin` account creates the other accounts through the API:\n```bash\ncurl -u admin:YOUR_PASSWORD -X POST https:\u002F\u002Fmlflow.example.ma\u002Fapi\u002F2.0\u002Fmlflow\u002Fusers\u002Fcreate \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"username\": \"sara\", \"password\": \"A_LONG_PASSWORD\"}'\n```\nA new account sees **no** experiment until one is shared with it: permissions (read, edit, manage) are granted experiment by experiment and model by model. Change the `admin` password through the `users\u002Fupdate-password` API (passing the old one in `current_password`); the new one is kept across restarts.",{"type":39,"title":115,"body":116},"Backup and updates","All of MLflow's state lives in the `mlflow-data` volume: the experiment database, the accounts database and the artifacts folder. Back it up with the container stopped, then copy the archive off the VPS:\n```bash\ncd \u002Fopt\u002Fmlflow\ndocker compose stop\ndocker run --rm -v mlflow_mlflow-data:\u002Fdata -v \"$PWD\":\u002Fbackup alpine \\\n  tar czf \u002Fbackup\u002Fmlflow-$(date +%F).tar.gz -C \u002Fdata .\ndocker compose start\n```\nTo update, read the release notes first — an update can migrate the database schema —, change the image tag in `docker-compose.yml`, then:\n```bash\ncd \u002Fopt\u002Fmlflow\ndocker compose pull && docker compose up -d\ndocker compose logs --tail 20\n```",{"type":39,"title":118,"body":119},"1-click install with ServOrbit","ServOrbit's 1-click apps install MLflow on your VPS without a command line: it deploys the official container, generates the `admin` account's password and the session key, enables authentication on the interface and the API, limits the accepted host names to your address and publishes the server over HTTPS on a subdomain of your domain or on the VPS's free subdomain (mlflow.{dns_slug}.servorbit-dns.com). The password is shown in your client area; all that is left is to connect your notebooks.","Your ML experiments on your own server","A ServOrbit Ubuntu 24.04 VPS with 2 GB of RAM is enough to start MLflow. 1-click install from your client area, HTTPS on your domain or on the VPS's free subdomain, password generated for you.","Install MLflow","\u002Fapplications\u002Fartificial-intelligence\u002Fmlflow",[125,144,168],{"id":126,"slug":127,"slugs":128,"title":132,"excerpt":133,"readTime":134,"views":135,"isPinned":19,"publishedAt":136,"updatedAt":137,"category":138,"categories":139,"featuredImage":30,"bgImage":31,"posterImage":141,"relatedSolution":142},177,"self-host-langfuse-on-a-vps-llm-observability-no-saas-bill",{"fr":129,"en":127,"ar":130,"es":131},"self-host-langfuse-vps","استضافة-langfuse-على-vps-مراقبة-llm-بلا-فاتورة-saas","alojar-langfuse-en-un-vps","Self-Host Langfuse on a VPS: LLM Observability, No SaaS Bill","Self-host Langfuse on a VPS — trace every AI call, evaluate prompts, track LLM costs. Full guide: installation, nginx, TLS, Python\u002FJS SDK integration, troubleshooting.",11,2,"2026-07-12T00:00:00+00:00","2026-11-04T16:30:26+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[140],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fself-host-langfuse-vps-poster.svg",{"categorySlug":34,"appSlug":143},"langfuse",{"id":145,"slug":146,"slugs":147,"title":151,"excerpt":152,"readTime":153,"views":18,"isPinned":19,"publishedAt":154,"updatedAt":155,"category":156,"categories":162,"featuredImage":30,"bgImage":31,"posterImage":164,"relatedSolution":165},552,"self-host-marimo-vps-python-notebooks",{"fr":148,"en":146,"ar":149,"es":150},"self-host-marimo-vps","استضافة-marimo-على-vps-دفاتر-python","autoalojar-marimo-vps-notebooks-python","marimo on a VPS: self-hosted reactive Python notebooks","Install marimo on a VPS: reactive Python notebooks saved as .py files, a password-protected web editor, pandas and polars included.",8,"2026-11-01T00:00:00+00:00","2026-11-04T16:30:29+00:00",{"id":157,"name":158,"slug":159,"color":160,"icon":161},7,"Self-hosting","self-hosting","bg-indigo-500\u002F10 text-indigo-400","cloud",[163],{"id":157,"name":158,"slug":159,"color":160,"icon":161},"\u002Fblog\u002Fcovers\u002Fself-host-marimo-vps-poster.svg",{"categorySlug":166,"appSlug":167},"development","marimo",{"id":134,"slug":169,"slugs":170,"title":174,"excerpt":175,"readTime":176,"views":177,"isPinned":19,"publishedAt":178,"updatedAt":179,"category":180,"categories":181,"featuredImage":30,"bgImage":31,"posterImage":183,"relatedSolution":184},"how-to-host-ollama-on-a-vps",{"fr":171,"en":169,"ar":172,"es":173},"heberger-ollama-vps","كيفية-استضافة-ollama-على-خادم-vps","como-alojar-ollama-en-un-vps","Hosting Ollama on a VPS: advanced operational guide","Advanced Ollama VPS setup: model management, nginx reverse proxy, API security, Q4_K_M\u002FQ8 quantization, CVE-2026-45672 Open WebUI and secure coupling.",9,3,"2026-06-09T00:00:00+00:00","2026-11-04T16:30:24+00:00",{"id":23,"name":24,"slug":25,"color":26,"icon":27},[182],{"id":23,"name":24,"slug":25,"color":26,"icon":27},"\u002Fblog\u002Fcovers\u002Fheberger-ollama-vps-poster.svg",{"categorySlug":34,"appSlug":185},"ollama",1793982270401]