How to Self-Host OpenHands on VPS with Docker
Run OpenHands on an Ubuntu 24.04 VPS with Docker, but secure the Web UI and API secrets because Docker socket access fit mean root access.
OpenHands na wetin, and the one risk wey you need understand first
OpenHands, wey dem bin call OpenDevin before, na autonomous software-engineering agent. You go give am task with plain language, and e go plan the work, write code, run commands, read the output, and repeat the process until e finish the task. You go run am for your own server with Docker and point am to a language model. For VPS, e become coding agent wey fit work while you dey away.
One fact suppose guide your whole setup. OpenHands no just suggest code; e dey run the code too. To do this, e controller container mount the host Docker socket at /var/run/docker.sock, so e fit create sandbox containers for each task. Anything wey fit communicate with the Docker socket fit start new container wey mount the whole host filesystem. This mean say socket access practically be root access for the machine. So treat the OpenHands box like server wey dey run untrusted code, because na exactly wetin e dey do. Every hardening choice below come from this fact.
Wetin you need
You need VPS wey dey run Ubuntu 24.04 with recent Docker Engine, at least 4 GB RAM, and API key for language model (OpenAI, Anthropic, or Google), or local model wey Ollama dey serve for the same VPS. OpenHands support dozens of model backends, so na you go choose. If you never set up containers before, Docker basics for VPS cover the foundation wey this guide assume say you sabi.
Docker dey install
OpenHands dey come as two images: the application image wey you go run, and an agent-server image wey e go pull to run each task sandbox. Run am like this, but replace the tags with the current ones from the project docs:
docker run -it --rm --pull=always \
-e AGENT_SERVER_IMAGE_REPOSITORY=ghcr.io/openhands/agent-server \
-e AGENT_SERVER_IMAGE_TAG=1.26.0-python \
-e LOG_ALL_EVENTS=true \
-v /var/run/docker.sock:/var/run/docker.sock \
-v ~/.openhands:/.openhands \
-p 127.0.0.1:3000:3000 \
--add-host host.docker.internal:host-gateway \
--name openhands \
docker.openhands.dev/openhands/openhands:1.8Two details fit save you one hour of confusion. The app image and the agent-server image get different version numbers intentionally, so no try make dem match: use the agent-server tag wey the docs pair with your app version. And notice say na -p 127.0.0.1:3000:3000, no be -p 3000:3000. That one change na the difference between Web UI wey only you fit reach and one wey the whole internet fit reach. The next section dey explain this.
Make Web UI no dey public internet
OpenHands dey serve its interface for port 3000. That interface dey control an agent wey dey run code. So if you publish am to internet, anybody wey find am fit use am enter process wey dey execute commands remotely. Bind am to loopback, as the run command above do, then reach am from your laptop through SSH tunnel:
ssh -L 3000:127.0.0.1:3000 you@your-vpsThen open http://127.0.0.1:3000 for your own machine. The traffic dey pass through your existing SSH session, and nothing new dey listen for public internet. No be every agent need port: Claude Code sessions for the same VPS dey message each other through terminal, so na SSH itself be the only thing wey you ever expose. You fit use the same loopback-and-tunnel habit for every agent dashboard wey you host; reaching open-kritt's scanning UI through a tunnel work the same way, but e dey use port 5173. For setup wey go stay long-term, put am behind VPN instead. Either way, put default-deny firewall before the box so nothing expose by mistake. Remember say firewall wey cover only IPv4 go leave the same port open for IPv6. Na this be the IPv6 firewall gap wey dey catch plenty people.
Separate the model key and any repo credentials
OpenHands need API key for its model, and e often need token to clone and push go your repositories. Both fit spend money and act as you, so treat dem like passwords. Keep dem inside environment file wey only the correct account fit read. Never put dem for the run command, where dem go enter your shell history and process list. Also, never put dem inside file wey dey inside git repository. If you keep the originals for self-hosted password manager, harden that server too. A vault's weak points na its admin token and backup file, not the encrypted items themselves, as the Vaultwarden hardening process dey explain.
Run am for one box wey you fit throw away
Because controller must hold Docker socket, you no fit fully sandbox OpenHands away from the host. The honest way to reduce the risk na isolation by placement: run OpenHands for dedicated VPS wey no get anything else wey you care about, instead of server wey also dey run your database or website. Take snapshot before you start, then rebuild from that snapshot instead of trusting a box wey agent-authored code don run for one week. Cheap, disposable, single-purpose VPS na the correct place for am. Placement na the only control wey OpenHands really give you here. So if you also want control over how much the agent fit do before e stop to ask, Claude Code permission modes show wetin that second control fit look like for server wey nobody dey monitor.
Harden the box around am
The remaining work na standard server hygiene, and e matter pass usual here because this workload dey carry more risk than usual. Create one unprivileged admin user instead of working as root, following run services as an unprivileged user. Move SSH go key-only authentication. Then run the checklist below and keep am for place wey you go see am again.
If you wan understand the different parts instead of just running dem, see build your own AI agent on a VPS; for platform wey need less code, self-host Dify na easier way to start.
FAQ
OpenHands safe to run for server?
E fit safe if you handle am carefully, but e get more risk than ordinary web app because e dey write and run code, and e controller hold the host Docker socket. This one practically mean root access for the machine. Run am for dedicated, disposable VPS wey no hold any other valuable thing. Keep e Web UI for loopback behind SSH tunnel or VPN, isolate e keys, and harden the box. No run am beside your important services.
Why OpenHands need Docker socket?
OpenHands dey run each task inside fresh sandbox container. E dey ask host Docker daemon to create those containers by mounting /var/run/docker.sock inside e controller. This one give the controller container control over Docker for the host. The access powerful and risky, so you must treat the host itself as machine wey dey run untrusted code.
OpenHands fit use local model instead of paid API?
Yes. OpenHands support local models wey Ollama or vLLM serve. So you fit run am fully self-hosted without per-token cost, and no data go leave your server. You need machine wey get enough memory for capable coding model. Na the same sizing question wey the Ollama guide cover.
I suppose run OpenHands for my main server?
No. Because e dey run code wey agent write and e hold Docker socket, keep am for separate, single-purpose VPS wey you ready to rebuild. If you colocate am with database, website, or your other services, agent mistake or bug fit reach things wey e never suppose touch.