Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/jaypopat/cf_ai_duet/llms.txt

Use this file to discover all available pages before exploring further.

Duet can be deployed using Docker for easy setup and portability. The Docker image includes all necessary dependencies for pair programming sessions.

Dockerfile Overview

The Duet Dockerfile uses a multi-stage build:
  1. Build stage - Compiles the Go binary
  2. Run stage - Creates a minimal runtime environment with development tools

What’s Included

The Docker image includes:
  • Neovim - Text editor for collaborative coding
  • Node.js & npm - JavaScript runtime and package manager
  • OpenSSH - SSH server and key management
  • Go binary - Compiled Duet server

Quick Start

1

Build the Docker image

docker build -t duet .
2

Run the container

docker run -p 2222:2222 duet
3

Connect via SSH

ssh <username>@localhost -p 2222

Configuration

Environment Variables

The Docker container accepts configuration through command-line arguments:
docker run -p 2222:2222 duet /app/duet \
  -addr :2222 \
  -hostkey /app/.ssh/id_ed25519 \
  -worker https://your-worker.workers.dev

Port Mapping

The Dockerfile exposes port 2222 by default:
EXPOSE 2222
Map it to a different host port:
docker run -p 22:2222 duet  # Maps host port 22 to container port 2222

Volume Mounts

Persist workspaces across container restarts:
docker run -p 2222:2222 \
  -v $(pwd)/workspaces:/app/workspaces \
  duet
Each room gets its own subdirectory under /app/workspaces.

Custom Worker URL

To use your own Cloudflare Worker:
docker run -p 2222:2222 duet \
  /app/duet -addr :2222 \
  -hostkey /app/.ssh/id_ed25519 \
  -worker https://duet-cf-worker.<subdomain>.workers.dev

Docker Compose

Create a docker-compose.yml file:
version: '3.8'

services:
  duet:
    build: .
    ports:
      - "2222:2222"
    volumes:
      - ./workspaces:/app/workspaces
    command: [
      "/app/duet",
      "-addr", ":2222",
      "-hostkey", "/app/.ssh/id_ed25519",
      "-worker", "https://your-worker.workers.dev"
    ]
    restart: unless-stopped
Run with:
docker-compose up -d

Production Deployment

Fly.io

Duet includes a fly.toml configuration for deployment on Fly.io:
app = 'duet-morning-meadow-5890'
primary_region = 'lhr'

[build]

[http_service]
  internal_port = 2222
  force_https = true
  auto_stop_machines = 'stop'
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

[[services]]
  protocol = 'tcp'
  internal_port = 2222

  [[services.ports]]
    port = 22

[[vm]]
  memory = '1gb'
  cpu_kind = 'shared'
  cpus = 1
1

Install Fly CLI

curl -L https://fly.io/install.sh | sh
2

Login to Fly.io

fly auth login
3

Deploy the application

fly deploy
4

Set secrets

If you need to configure the Worker URL via secrets:
fly secrets set WORKER_URL=https://your-worker.workers.dev

Resource Configuration

The default Fly.io configuration uses:
  • Memory: 1GB
  • CPU: 1 shared CPU
  • Auto-scaling: Machines stop when idle, start on demand
  • Minimum running: 0 (cost-effective for low traffic)
The auto_stop_machines and auto_start_machines settings help reduce costs by stopping idle machines.

Security Considerations

SSH Host Keys

The Dockerfile generates SSH host keys at build time:
RUN mkdir -p /app/.ssh && \
    ssh-keygen -t ed25519 -f /app/.ssh/id_ed25519 -N "" && \
    chown -R duet:duet /app/.ssh
For production, consider mounting a persistent host key to avoid key changes on container restarts:
docker run -p 2222:2222 \
  -v $(pwd)/ssh-keys:/app/.ssh \
  duet

Non-Root User

The container runs as a non-root user duet for security:
RUN adduser -D duet
USER duet

Troubleshooting

Check Container Logs

docker logs <container-id>

Interactive Shell

Access the container:
docker exec -it <container-id> /bin/sh

Verify SSH Key

Check if the host key exists:
docker exec <container-id> ls -la /app/.ssh

Common Issues

  • Connection refused: Verify port mapping is correct
  • Permission denied: Check SSH host key permissions
  • Worker not responding: Verify Worker URL is accessible from container

Build docs developers (and LLMs) love