Tutorial

OpenHands: autonomous AI coding agent on your VPS

Artificial Intelligence11 min read8 steps

GitHub Copilot Workspace and Codex cloud resolve issues, write tests and submit pull requests — but they process your code on servers you don't control. OpenHands (formerly OpenDevin) does the same from your own infrastructure: an AI agent that picks up an issue, clones the repo, writes changes, runs tests, and opens a PR — all inside an isolated Docker sandbox on your VPS. With 89,000 GitHub stars, an MIT license, and version v1.23.0 released on September 23, 2026, OpenHands has become the open-source reference for agentic software engineering. This guide covers full installation, LLM backend configuration, Docker socket hardening, and concrete use cases.

Contents· OpenHands — the AI agent that codes in the terminal on your behalf1/8
  1. 01OpenHands — the AI agent that codes in the terminal on your behalf
  2. 02What OpenHands can do on its own
  3. 03Numbered prerequisites before installation
  4. 04Install OpenHands on a VPS in 8 steps
  5. 05Configure the AI backend: Claude, GPT-4, or Ollama
  6. 06Concrete use cases
  7. 07Troubleshooting — common errors
  8. 08OpenHands vs Codex cloud vs Devin

OpenHands — the AI agent that codes in the terminal on your behalf

OpenHands is built on a simple architecture: a web server that orchestrates one or more LLM agents, each running inside an ephemeral Docker sandbox. The agent has a shell, filesystem access to the project, a GitHub API connection, and a reasoning loop that alternates between reading code, planning, and executing.

The SWE-bench Verified benchmark measures an agent's ability to resolve real GitHub issues without human assistance. In April 2025, OpenHands paired with Claude Sonnet reached 60.6% on this benchmark in a single trajectory, and 66.4% with five attempts and a critic model. For reference, an experienced junior developer resolves roughly 15 to 20% of these issues — today's agents significantly outperform humans on well-documented tasks.

OpenHands is distributed under the MIT license: you can host it, modify it, and integrate it into your internal tools with no commercial restrictions. The project is actively maintained — v1.23.0 was released on September 23, 2026, featuring remote MCP server support and Git Sync for organization admins.

What OpenHands can do on its own

  • Fix a documented bug: the agent reads the GitHub issue, locates the faulty code, writes the fix, runs existing tests, and opens a PR with an explanatory commit message.
  • Add a test suite: starting from an uncovered module, the agent generates unit or integration tests aligned with the existing framework (pytest, PHPUnit, Jest…).
  • Refactor code: extract a function, rename variables to follow conventions, move a module toward a cleaner architecture.
  • Complete documentation: generate or update docstrings, README files, and API usage examples from the source code.
  • Analyze an unfamiliar repository: produce a structure report, identify critical dependencies, map data flows between modules.
  • Open and describe a pull request: generate the title, the PR body explaining changes, passing tests, and review instructions for the team.

Numbered prerequisites before installation

OpenHands is a lightweight orchestrator, but it spawns sandbox containers per task. Requirements vary based on the chosen LLM backend.

Minimum hardware (cloud API — Claude, GPT-4, Gemini):
- RAM: 4 GB minimum, 8 GB recommended for concurrent tasks
- CPU: 2 vCPU minimum, 4 vCPU for a smooth experience
- Storage: 20 GB free (Docker images + project workspaces)
- OS: Linux with Docker 24+ (Ubuntu 22.04 LTS or Debian 12 recommended)

Hardware if paired with local Ollama LLM:
- RAM: 16 GB minimum (8 GB for a quantized 7B model + 4 GB for the OS + headroom)
- GPU VRAM: optional but strongly recommended — without GPU, inference is 10–30× slower
- Storage: 40 GB free (Ollama models + Docker)

Software versions:
- Docker Engine 24.0 or later (check with docker --version)
- Docker Compose v2 (bundled with Docker Desktop and Docker Engine 24+)
- Linux kernel 5.4+ (required for sandbox isolation namespaces)

Port 3000 must be reachable from your browser or VPN. Never expose it directly to the internet — use an Nginx reverse proxy with HTTPS.

Install OpenHands on a VPS in 8 steps

  1. Install Docker Engine on your VPS

    On Ubuntu 22.04 or Debian 12, install Docker with the official script:

    curl -fsSL https://get.docker.com | sh
    sudo usermod -aG docker $USER
    newgrp docker

    Verify the installation:

    docker --version
    # Docker version 27.x.x
    docker compose version
    # Docker Compose version v2.x.x
  2. Create the working directory

    Create a dedicated folder for OpenHands and its persistent data:

    mkdir -p /opt/openhands/.openhands
    cd /opt/openhands

    The .openhands folder stores persistent configuration: API keys, conversation history, agent settings.

  3. Launch OpenHands with Docker

    Start OpenHands with the official command:

    docker run -it --rm --pull=always \
      -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:latest \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v /opt/openhands/.openhands:/.openhands \
      -p 127.0.0.1:3000:3000 \
      --add-host host.docker.internal:host-gateway \
      --name openhands-app \
      docker.all-hands.dev/all-hands-ai/openhands:latest

    The --pull=always flag ensures you run the latest stable image. OpenHands is available at http://localhost:3000.

    For a permanent deployment (auto-restart), add --restart unless-stopped and remove -it --rm.

  4. Alternative: deploy with Docker Compose

    For simpler management, create a compose.yml file in /opt/openhands:

    services:
      openhands:
        image: docker.all-hands.dev/all-hands-ai/openhands:latest
        container_name: openhands-app
        pull_policy: always
        ports:
          - "127.0.0.1:3000:3000"
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          - ./.openhands:/.openhands
        extra_hosts:
          - host.docker.internal:host-gateway
        restart: unless-stopped

    Start the stack:

    docker compose up -d
    docker compose logs -f
  5. Configure the LLM backend in the UI

    Open http://localhost:3000 (or your HTTPS domain). On first launch, OpenHands asks for:

    1. LLM provider: choose Anthropic, OpenAI, Google, or openai-compatible for Ollama
    2. Model: claude-sonnet-4-5 (best quality/cost ratio) or claude-opus-4-5 for complex tasks
    3. API key: paste your Anthropic or OpenAI key

    These settings are saved to ~/.openhands/config.toml and persist across restarts.

  6. Connect OpenHands to GitHub

    To let OpenHands clone private repos, read issues, and open PRs, configure a GitHub Personal Access Token:

    1. On GitHub: Settings → Developer settings → Personal access tokens → Fine-grained tokens
    2. Grant permissions: Contents (read/write), Pull requests (read/write), Issues (read)
    3. In the OpenHands UI: Settings → Git → paste the token

    With this token, simply paste a GitHub issue URL into the task field and OpenHands takes over.

  7. Set up the Nginx reverse proxy with HTTPS

    Never expose port 3000 directly. Use Nginx as a reverse proxy:

    server {
        listen 443 ssl;
        server_name openhands.your-domain.com;
    
        ssl_certificate /etc/letsencrypt/live/openhands.your-domain.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/openhands.your-domain.com/privkey.pem;
    
        location / {
            proxy_pass http://127.0.0.1:3000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_http_version 1.1;
            proxy_read_timeout 600s;
        }
    }

    Obtain the certificate:

    certbot --nginx -d openhands.your-domain.com
  8. Test with a first task

    Open the interface, paste a GitHub issue URL (e.g. https://github.com/your-org/your-repo/issues/42) into the task field, and click Start.

    OpenHands will:
    1. Read the issue and plan the approach
    2. Clone the repository into the sandbox
    3. Explore the code, write changes
    4. Run the tests (pytest, npm test, etc.)
    5. Display a summary and offer to open a PR

    Follow the execution in real time in the Trajectory tab — every agent action (file read, shell command, code write) is traced.

Configure the AI backend: Claude, GPT-4, or Ollama

OpenHands supports any provider compatible with the OpenAI API, plus native Anthropic, Google, and Azure providers. The model choice is the single biggest factor determining output quality.

Claude Sonnet (Anthropic) — recommended for production
Claude claude-sonnet-4-5 offers a leading quality/cost ratio for agentic software engineering. Its 200,000-token context window lets it analyze large codebases without chunking. Expect a few cents per task depending on complexity. Set LLM_MODEL=anthropic/claude-sonnet-4-5.

Claude Opus (Anthropic) — for complex tasks
claude-opus-4-5 delivers better performance on architectural problems and large-scale refactors, but costs 5–10× more than Sonnet. Reserve it for tasks that exceed Sonnet's capabilities.

Ollama (local LLM) — for full sovereignty
If your code is particularly sensitive or you want zero external dependency, pair OpenHands with Ollama on the same VPS. Set LLM_BASE_URL=http://host.docker.internal:11434 and LLM_MODEL=openai/qwen2.5-coder:32b. The qwen2.5-coder 32B models deliver top open-weights results on coding benchmarks. Downside: CPU inference is 10–30× slower than an API call — expect 1 to 5 minutes per subtask.

Key environment variables:

LLM_MODEL=anthropic/claude-sonnet-4-5
LLM_API_KEY=sk-ant-...
LLM_BASE_URL=         # empty for Anthropic, Ollama URL for local
AGENT=CodeActAgent    # default agent, best SWE-bench performer

Securing docker.sock — socket proxy and rootless mode. Mounting /var/run/docker.sock inside a container is equivalent to granting full root access to the host machine: any container with access to this socket can create new containers, mount arbitrary volumes, and escalate privileges.

Two approaches to reduce this attack surface:

Option 1 — Socket proxy (Tecnativa/docker-socket-proxy): interpose a proxy that filters Docker API calls. OpenHands only needs POST /containers/create, GET /containers/{id}/json, POST /containers/{id}/start and DELETE /containers/{id}. The socket proxy blocks everything else.

services:
  socket-proxy:
    image: tecnativa/docker-socket-proxy
    environment:
      CONTAINERS: 1
      POST: 1
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: unless-stopped

  openhands:
    image: docker.all-hands.dev/all-hands-ai/openhands:latest
    environment:
      - DOCKER_HOST=tcp://socket-proxy:2375
    depends_on:
      - socket-proxy
    restart: unless-stopped

Option 2 — Rootless Docker: run Docker in rootless mode (your system user, not root). The socket is then at /run/user/1000/docker.sock and belongs to your user. Compromising this socket does not escalate beyond that user's privileges. Enable it with dockerd-rootless-setuptool.sh install.

Concrete use cases

Use case 1 — Resolve a documented GitHub issue
Paste the URL of a well-described issue (expected behavior, observed behavior, stack trace if available) into OpenHands. The agent reads the issue, searches the relevant files with grep and the code explorer, writes the fix, runs the test suite, and proposes a PR. For isolated, well-documented bugs, the success rate is high without human intervention.

Use case 2 — Generate tests for an uncovered module
Specify the target: Write unit tests for the module src/payments/stripe.py, aiming for 80% coverage with pytest. Mocks should use unittest.mock. The agent analyzes the module, identifies edge cases, and generates a test suite consistent with existing patterns in the project.

Use case 3 — Analyze an open source repository before forking
Before integrating a dependency or forking a project, ask OpenHands: Analyze the repository https://github.com/org/repo. Identify critical dependencies, tight coupling points, missing tests, and known CVEs in direct dependencies. The agent produces a structured report in a few minutes.

Use case 4 — Update a major dependency
Major version migrations (Django 4 → 5, React 18 → 19, Laravel 10 → 11) touch many files. OpenHands can read the official changelog, identify breaking changes, apply mechanical updates, and rerun tests to identify what still needs manual attention.

Troubleshooting — common errors

permission denied while trying to connect to the Docker daemon socket
The user running OpenHands is not in the docker group. Fix with:

sudo usermod -aG docker $USER && newgrp docker

If mounting the socket inside a container, verify that the socket's GID matches what OpenHands expects.

Container exited with OOM kill (exit code 137)
The sandbox ran out of memory. Increase available RAM on the VPS or limit concurrent tasks. Add --memory=4g to the sandbox container in the OpenHands configuration.

LLM timeout after 120s
On large codebases, the agent sends large contexts to the LLM. Two solutions: (a) increase LLM_TIMEOUT in the configuration, (b) switch to a model with a larger context window or reduce the task scope.

No such container: openhands-sandbox-xxx
The sandbox container was removed between two actions. This happens when Docker is restarted during a task. Restart the task from the beginning — OpenHands does not resume tasks interrupted by a Docker restart.

Rate limit exceeded (Anthropic/OpenAI)
OpenHands makes many LLM calls on complex tasks. If you hit rate limits, add LLM_NUM_RETRIES=5 and LLM_RETRY_MIN_WAIT=30 to the configuration to let OpenHands retry automatically.

OpenHands vs Codex cloud vs Devin

Scroll the table

CriterionOpenHands self-hostedGitHub Copilot WorkspaceDevin (Cognition)
Monthly cost$0 (+ LLM API cost)$19/month (Copilot Pro)$500/month (Team plan)
Code sent externallyNo (code stays on VPS)Yes (GitHub/Microsoft)Yes (Cognition)
Configurable LLM backendYes (Claude, GPT, Ollama…)No (Microsoft model)No (Cognition model)
SWE-bench Verified score66.4% (5 attempts, Claude)Not published~49% (last publication)
LicenseMIT (open source)ProprietaryProprietary (SaaS)
VPS requiredYes (4 GB RAM min)NoNo
Full autonomy (auto PR)YesPartialYes

Deploy OpenHands on a ServOrbit VPS

A ServOrbit VPS gives you full root access, Docker-ready infrastructure, and a dedicated IPv4. OpenHands runs entirely on your infrastructure — your source code never leaves your server. Choose the 8 GB RAM plan for optimal comfort with cloud API LLM models.

Need help?

Browse our help center and FAQ, or reach our team — callback, WhatsApp or email. Support in French, English and Arabic.

Message us on WhatsAppopens in a new tab