Deploy your LangChain agent to a VPS
You built an agent. It works on your machine. Now it needs to answer at 3am while you are asleep, keep answering after a reboot, and live at an address you can actually give people. This guide takes you from a folder of Python on your laptop to a service running on your own server, with HTTPS, in about half an hour.
First, the thing that confuses almost everyone
You cannot “install LangChain” on a server the way you install PostgreSQL or WordPress. LangChain is a library, not a service — there is no LangChain process to start and no LangChain page to visit. What you deploy is your application, which happens to import LangChain, the same way it imports requests.
That is good news: it means you do not need a special “LangChain host”. Any server with Python will do, and the steps below are the same whether your agent uses LangChain, LangGraph, CrewAI, or nothing but the OpenAI SDK.
How big a server do you need?
Smaller than people expect. The model itself runs on someone else’s hardware — your server holds a Python process, your dependencies, and whatever you cache. It is mostly waiting on network calls.
For a sense of scale, here is what we measured on real servers when we ran comparable self-hosted agents ourselves, taken 30 seconds after a live model request:
| Agent | Memory at idle | Ran fine on |
|---|---|---|
| OpenClaw | 278 MB | 1 vCPU / 1 GB |
| Hermes Agent | 120 MB | 1 vCPU / 1 GB |
| OpenHands (web workspace) | 846 MB | 1 vCPU / 2 GB |
A typical LangChain agent sits at the light end of that range. Start at 1 GB. You need more when you run models locally, parse large documents, or hold big vector stores in memory — not because you added another chain.
Step 1 — Get a server with Python on it
Any Ubuntu 22.04 box works. On AgentOcean, choose the Python 3.12 preset at checkout and the runtime, pip and venv are already there when the server boots. On a bare server, install them yourself:
sudo apt update
sudo apt install -y python3.12 python3.12-venv python3-pip gitStep 2 — Put your code on the server
Git is the least painful route, and it makes updates one command later. Push your project to GitHub (a private repo is fine), then clone it:
sudo mkdir -p /opt/agent && sudo chown $USER /opt/agent
git clone https://github.com/you/your-agent.git /opt/agent
cd /opt/agentNo repo? scp -r ./your-agent root@your-server:/opt/agent copies a folder up directly. It works, but you will be doing it again every time you change something.
Step 3 — Install dependencies in a virtualenv
A virtualenv keeps your project’s packages away from the system Python, so an upgrade in one cannot break the other. If you do not have a requirements.txt, run pip freeze > requirements.txt on your laptop first.
cd /opt/agent
python3.12 -m venv .venv
.venv/bin/pip install --upgrade pip
.venv/bin/pip install -r requirements.txtNote the .venv/bin/pip paths. Calling the virtualenv’s binaries directly means you never have to remember whether it is “activated” — which matters in Step 5, where systemd has no shell to activate anything in.
Step 4 — Keep your API keys out of your code
Put secrets in a file the service reads at startup, and make sure only root can read it. A key pasted into a Python file gets committed to git eventually — that is not a hypothetical, it is the single most common way agent keys leak.
sudo tee /opt/agent/.env > /dev/null <<'EOF'
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
LANGSMITH_API_KEY=
EOF
sudo chmod 600 /opt/agent/.envAlso add .env to your .gitignore before your next push.
Step 5 — Run it as a service that survives reboots
Starting your agent with python main.py in an SSH session lasts exactly as long as that session. systemd restarts it when it crashes and starts it again when the server reboots.
sudo tee /etc/systemd/system/agent.service > /dev/null <<'EOF'
[Unit]
Description=LangChain agent
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=/opt/agent
EnvironmentFile=/opt/agent/.env
ExecStart=/opt/agent/.venv/bin/python main.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now agent
systemctl status agent --no-pagerRestart=always plus RestartSec=5 is what turns a crash into a five-second gap instead of a dead agent you notice on Monday.
Step 6 — If it serves HTTP, put HTTPS in front
Skip this if your agent only polls or listens on Telegram. If it exposes an API — LangServe, FastAPI, a webhook receiver — bind it to localhost only and let Caddy handle the public side and the certificate.
# In your app: bind to 127.0.0.1, never 0.0.0.0
uvicorn.run(app, host="127.0.0.1", port=8000)sudo tee /etc/caddy/Caddyfile > /dev/null <<'EOF'
agent.yourdomain.com {
reverse_proxy 127.0.0.1:8000
}
EOF
sudo systemctl reload caddyCaddy fetches and renews the TLS certificate on its own. Point an A record at your server’s IP first, or the certificate request will fail.
One trap worth knowing, because we measured it
If any part of your stack runs in Docker, a published port bypasses your firewall. Docker writes its own iptables rules ahead of UFW’s, so -p 8000:8000 is reachable from the internet even when ufw status insists the port is blocked. We confirmed this from outside on live servers. Always write -p 127.0.0.1:8000:8000 and let the reverse proxy be the only thing listening publicly.
More in our VPS security guide.
Step 7 — Logs, and shipping changes
Anything your agent prints goes to the journal, so you do not need a logging library to start debugging:
# follow live
journalctl -u agent -f
# last 200 lines, including previous crashes
journalctl -u agent -n 200 --no-pagerDeploying a change is three commands:
cd /opt/agent
git pull
.venv/bin/pip install -r requirements.txt
sudo systemctl restart agentWhen this stops being enough
This setup carries a single agent a long way. The honest limits: one server means one point of failure, git pull plus a restart is a few seconds of downtime, and there is no rollback beyond checking out the previous commit. If you need zero-downtime deploys or several instances behind a load balancer, you have outgrown one box — but you will know when, and it is later than you think.
Related guides
- Secure your VPS: firewall, SSH keys & fail2ban — do this before you put an API key on the box.
- Managed vs self-hosted AI agents — what running your own box actually costs, measured.
- VPS hosting for AI agents — compare agent systems on real, measured infrastructure numbers.