Skip to content

Self-Hosted Agent

Deploy the Ovvoc agent in your own infrastructure — Docker or Kubernetes.

6 min read

The self-hosted agent lets Enterprise customers run Ovvoc's data plane entirely within their own infrastructure. Your source code never leaves your VPC.

Architecture

The self-hosted model splits Ovvoc into two planes:

  • Control plane (cloud): Scheduling, rule database, dashboard, billing
  • Data plane (your infra): Clone, transform, build, test, PR creation
Architecture
┌─────────────────────────────┐     ┌──────────────────────────┐
│     ovvoc Cloud (SaaS)      │     │    Your Infrastructure   │
│                             │     │                          │
│  ┌─────────┐ ┌───────────┐ │     │  ┌────────────────────┐  │
│  │Dashboard│ │Rule Engine│ │     │  │   ovvoc Agent       │  │
│  └─────────┘ └───────────┘ │     │  │                    │  │
│  ┌─────────┐ ┌───────────┐ │◄────│  │  Clone → Transform │  │
│  │Scheduler│ │  Billing  │ │────►│  │  Build → Test → PR │  │
│  └─────────┘ └───────────┘ │     │  └────────────────────┘  │
│                             │     │                          │
└─────────────────────────────┘     └──────────────────────────┘
        HTTPS only (outbound)            No inbound ports

The agent polls the Ovvoc API over HTTPS for new jobs. No inbound ports need to be opened in your firewall.

Requirements

  • Docker 20.10+ or Kubernetes 1.24+
  • 4 vCPU, 8 GB RAM minimum
  • HTTPS outbound to api.ovvoc.com and github.com
  • GitHub App private key stored locally

Docker deployment

The simplest way to run the self-hosted agent:

docker run
docker run -d \
  --name ovvoc-agent \
  --restart unless-stopped \
  -e OVVOC_API_KEY=your-api-key \
  -e OVVOC_AGENT_ID=your-agent-id \
  -v /path/to/github-app-key.pem:/keys/github.pem:ro \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ghcr.io/ovvoc/agent:latest

Or with Docker Compose:

docker-compose.yml
version: '3.8'
services:
  ovvoc-agent:
    image: ghcr.io/ovvoc/agent:latest
    restart: unless-stopped
    environment:
      OVVOC_API_KEY: ${OVVOC_API_KEY}
      OVVOC_AGENT_ID: ${OVVOC_AGENT_ID}
      GITHUB_APP_KEY_PATH: /keys/github.pem
    volumes:
      - ./github-app-key.pem:/keys/github.pem:ro
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      resources:
        limits:
          cpus: '4'
          memory: 8G

Kubernetes deployment

k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ovvoc-agent
  labels:
    app: ovvoc-agent
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ovvoc-agent
  template:
    metadata:
      labels:
        app: ovvoc-agent
    spec:
      containers:
        - name: agent
          image: ghcr.io/ovvoc/agent:latest
          resources:
            requests:
              cpu: '2'
              memory: 4Gi
            limits:
              cpu: '4'
              memory: 8Gi
          env:
            - name: OVVOC_API_KEY
              valueFrom:
                secretKeyRef:
                  name: ovvoc-secrets
                  key: api-key
            - name: OVVOC_AGENT_ID
              valueFrom:
                configMapKeyRef:
                  name: ovvoc-config
                  key: agent-id
            - name: GITHUB_APP_KEY_PATH
              value: /keys/github.pem
          volumeMounts:
            - name: github-key
              mountPath: /keys
              readOnly: true
      volumes:
        - name: github-key
          secret:
            secretName: github-app-key

Custom migration rules

Self-hosted agents can load custom YAML migration rules for internal packages. Mount your rules directory at /rules/custom/:

Custom rule example
# /rules/custom/internal-api-v2.yaml
package: "@acme/internal-api"
from_version: "1.x"
to_version: "2.x"
rules:
  - type: function_rename
    from: "createClient"
    to: "initializeClient"
    file_pattern: "**/*.{js,ts}"
    confidence: 1.0
    priority: 1

  - type: param_signature_change
    function: "initializeClient"
    old_params: "(url)"
    new_params: "({ baseUrl: url })"
    file_pattern: "**/*.{js,ts}"
    confidence: 0.95
    priority: 2

Security

The self-hosted agent applies the same security hardening as the cloud version:

  • Ephemeral containers for every job
  • Non-root user inside containers
  • Network isolation during build and test phases
  • Short-lived GitHub installation tokens
  • No source code stored after job completion

Additionally, your GitHub App private key stays entirely on your infrastructure and is never transmitted to Ovvoc's cloud. All communication uses TLS 1.3.

Monitoring

The agent exposes Prometheus-compatible metrics and health endpoints:

  • GET /health — returns 200 if agent is running
  • GET /ready — returns 200 if agent can accept jobs
  • GET /metrics — Prometheus metrics endpoint
prometheus.yml
scrape_configs:
  - job_name: ovvoc-agent
    scrape_interval: 15s
    static_configs:
      - targets: ['ovvoc-agent:8080']
    metrics_path: /metrics

Architecture overview

The self-hosted agent is a single binary that runs on your infrastructure and connects to the Ovvoc cloud API over HTTPS. It bridges the gap between Ovvoc’s scheduling and rule engine (which runs in the cloud) and the actual code processing (which runs entirely on your machines).

The agent follows a pull-based architecture. It periodically polls the Ovvoc API for new job assignments, receives job specifications (which dependency to update, which rules to apply), runs the full pipeline in a local Docker container, and reports results back to the API. At no point does your source code leave your network — the agent clones from your GitHub instance, processes locally, and pushes branches directly to GitHub.

The agent sends a heartbeat to the Ovvoc API every 30 seconds. This heartbeat includes the agent’s status (idle, busy, degraded), current job count, available resources, and version number. If the API does not receive a heartbeat for 90 seconds, the agent is marked as offline in the dashboard and its jobs are reassigned.

System requirements

The self-hosted agent requires the following minimum resources to operate reliably:

  • Docker 24 or later — the agent manages Docker containers for job isolation. Earlier Docker versions may work but are not tested.
  • 4 CPU cores minimum (8 recommended) — each concurrent job uses approximately 1 core during build and test phases. More cores allow more parallel jobs.
  • 8 GB RAM minimum (16 GB recommended) — each job container is allocated up to 512 MB. The agent itself uses approximately 100 MB. Additional RAM allows more concurrent jobs and headroom for large builds.
  • 50 GB disk — space is needed for Docker images (the Ovvoc job image is approximately 200 MB), cloned repositories, node_modules during builds, and workspace caching. Disk usage is cleaned up automatically after each job.
  • Outbound HTTPS access — the agent needs to reach the Ovvoc API (api.ovvoc.com:443), the npm registry (registry.npmjs.org:443), and the GitHub API (api.github.com:443). No inbound ports need to be opened.
  • Operating system: Linux (Ubuntu 22.04+ recommended) or macOS. Windows support via WSL2 is experimental.

Installation

Setting up the self-hosted agent is a four-step process:

  1. Download the agent binary. Log in to your Ovvoc dashboard, navigate to Settings → Self-Hosted, and download the agent binary for your platform (Linux amd64, Linux arm64, or macOS). The binary is a single static executable with no external dependencies beyond Docker.
  2. Configure the agent. Set the required environment variables: your OVVOC_API_KEY (generated from the dashboard) and your OVVOC_AGENT_ID (assigned when you register the agent). Point GITHUB_APP_KEY_PATH to your GitHub App private key file.
  3. Run as a system service. On Linux, install the agent as a systemd service for automatic startup and restart on failure. On macOS, use launchd. The agent ships with example service configuration files.
  4. Verify the connection. The agent auto-registers with the Ovvoc API on first connection. Check the Settings → Self-Hosted page in your dashboard to confirm the agent shows as “online”.
systemd service file
# /etc/systemd/system/ovvoc-agent.service
[Unit]
Description=ovvoc Self-Hosted Agent
After=docker.service
Requires=docker.service

[Service]
Type=simple
ExecStart=/usr/local/bin/ovvoc-agent
Restart=always
RestartSec=10
Environment=OVVOC_API_KEY=your-api-key
Environment=OVVOC_AGENT_ID=your-agent-id
Environment=GITHUB_APP_KEY_PATH=/etc/ovvoc/github.pem

[Install]
WantedBy=multi-user.target

Docker-in-Docker considerations

The Ovvoc agent creates and manages Docker containers for each job. This means the agent itself needs access to the Docker daemon, which creates a Docker-in-Docker (DinD) scenario when the agent is also running inside a container.

  • Docker socket access: The simplest approach is to mount the host’s Docker socket (/var/run/docker.sock) into the agent container. This gives the agent the ability to create sibling containers on the host.
  • Rootless Docker: For additional security, consider running Docker in rootless mode. This ensures that even if a job container is compromised, it cannot escalate privileges to the host system. The agent works with rootless Docker without any configuration changes.
  • Image caching: Job container images are cached locally after the first pull, so subsequent jobs start faster. The Ovvoc job image is approximately 200 MB and includes Node.js, npm, and git. Images are updated automatically when new versions are available.

Networking

The self-hosted agent communicates only via outbound HTTPS connections. No inbound ports need to be opened in your firewall. Here are the specific endpoints the agent connects to:

  • Ovvoc API (api.ovvoc.com:443) — job polling, heartbeats, result reporting, and rule database synchronization. All communication is authenticated with your API key and encrypted with TLS 1.3.
  • npm registry (registry.npmjs.org:443) — package downloads during the install stage. If you use a private npm registry, configure the NPM_REGISTRY_URL environment variable.
  • GitHub API (api.github.com:443) — repository cloning, branch pushing, and PR creation. For GitHub Enterprise Server, configure the GITHUB_API_URL environment variable.

During the build and test stages, job containers have no network access. Network isolation is enforced at the Docker level to prevent any outbound connections during code execution. This is a critical security measure that prevents malicious install scripts from exfiltrating data.

Monitoring and health checks

The agent provides several mechanisms for monitoring its health and performance:

  • Health endpoint: The agent exposes a /health endpoint on localhost:9090 (configurable) that returns 200 when the agent is running. Use this for load balancer health checks or container orchestrator liveness probes.
  • Heartbeat monitoring: The agent sends a heartbeat to the Ovvoc API every 30 seconds. The dashboard’s Settings → Self-Hosted page shows the agent’s current status: online (heartbeat received within 90s), offline (no heartbeat for 90s+), or degraded (agent is running but reporting resource constraints).
  • Logging: The agent logs to stdout in structured JSON format. Capture these logs with journalctl (systemd), your container orchestrator’s log aggregation, or pipe them to any log management system. Log levels can be configured via the OVVOC_LOG_LEVEL environment variable (debug, info, warn, error).
  • Prometheus metrics: The /metrics endpoint exports metrics including jobs processed, job duration, container creation time, failure counts by stage, and resource utilization.

Upgrading

Upgrading the self-hosted agent is designed to be simple and low-risk:

  1. Download the new agent binary from your dashboard (or pull the latest container image)
  2. Stop the current agent service (systemctl stop ovvoc-agent)
  3. Replace the binary at /usr/local/bin/ovvoc-agent
  4. Start the service (systemctl start ovvoc-agent)
  5. The agent reconnects to the Ovvoc API automatically and resumes processing

For zero-downtime upgrades, you can run two agents briefly during the transition. Start the new agent on a different port, verify it connects and reports as online in the dashboard, then stop the old agent. The Ovvoc scheduler automatically distributes jobs across all online agents, so in-flight jobs on the old agent will complete normally before it shuts down.

Agent versions are backward-compatible with the Ovvoc API. You do not need to upgrade immediately when a new version is released, but we recommend staying within two major versions of the latest release for security patches and rule database compatibility.

Need help?

Start with one repo and see verified PRs in minutes.