diff --git a/blueprints/orca-server/docker-compose.yml b/blueprints/orca-server/docker-compose.yml new file mode 100644 index 00000000..a78afabb --- /dev/null +++ b/blueprints/orca-server/docker-compose.yml @@ -0,0 +1,55 @@ +version: "3.8" +services: + orca-server: + # Orca publishes no container image, so this builds one from the + # pinned upstream release AppImage, following the official headless + # Linux server guide (docs/reference/headless-linux-server.md). + build: + args: + ORCA_VERSION: v1.4.205 + dockerfile_inline: | + FROM ubuntu:24.04 + ARG ORCA_VERSION + ARG TARGETARCH + ENV DEBIAN_FRONTEND=noninteractive + RUN apt-get update && apt-get install -y --no-install-recommends \ + bash ca-certificates curl file git jq openssh-client procps \ + xvfb zlib1g-dev libgtk-3-0t64 libpango-1.0-0 libcairo2 \ + libnss3 libgbm1 libdrm2 libasound2t64 libcups2t64 libxkbcommon0 \ + libatk1.0-0t64 libatk-bridge2.0-0t64 libatspi2.0-0t64 \ + libx11-xcb1 libxcb-dri3-0 libxcomposite1 libxdamage1 libxfixes3 \ + libxrandr2 libxrender1 libxss1 libxtst6 \ + && rm -rf /var/lib/apt/lists/* + RUN if [ "$$TARGETARCH" = arm64 ]; then asset=orca-linux-arm64.AppImage; else asset=orca-linux.AppImage; fi \ + && curl -fL --retry 3 -o /tmp/orca.AppImage \ + "https://github.com/stablyai/orca/releases/download/$$ORCA_VERSION/$$asset" \ + && chmod +x /tmp/orca.AppImage \ + && cd /opt && /tmp/orca.AppImage --appimage-extract >/dev/null \ + && mv /opt/squashfs-root /opt/orca \ + && chmod -R a+rX /opt/orca \ + && rm /tmp/orca.AppImage + RUN useradd --create-home --shell /bin/bash orca + USER orca + WORKDIR /home/orca + ENV PATH=/home/orca/.local/bin:/opt/orca/resources/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \ + LIBGL_ALWAYS_SOFTWARE=1 + # Chromium cannot create its sandbox namespaces in an unprivileged + # container; the container is the isolation boundary instead. + ENTRYPOINT ["/opt/orca/AppRun", "--no-sandbox"] + restart: unless-stopped + init: true + shm_size: "1gb" + command: serve --port 6768 --pairing-address ${ORCA_PAIRING_ADDRESS} ${ORCA_SERVE_ARGS:-} + expose: + - 6768 + volumes: + - orca-home:/home/orca + healthcheck: + test: ["CMD", "bash", "-c", ": > /dev/tcp/127.0.0.1/6768"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 60s + +volumes: + orca-home: {} diff --git a/blueprints/orca-server/instructions.md b/blueprints/orca-server/instructions.md new file mode 100644 index 00000000..04f3fdd4 --- /dev/null +++ b/blueprints/orca-server/instructions.md @@ -0,0 +1,63 @@ +# Orca Server + +Runs `orca serve`, the headless Orca runtime, following the official +[headless Linux server guide](https://github.com/stablyai/orca/blob/main/docs/reference/headless-linux-server.md). +Orca publishes no container image, so the service is built from the pinned +upstream release AppImage (`v1.4.205`, amd64 or arm64) on the first deploy. +The first deployment therefore takes a few extra minutes. + +The domain serves the runtime WebSocket and its web client. Every client, +browser included, connects with a pairing link printed in the logs. + +## Pair a client + +1. Open the `orca-server` service logs in Dokploy. +2. Copy the `Pairing URL: orca://pair?code=...` line printed after + `Orca server ready`. The `Web client URL` line next to it opens the same + runtime in a browser, already paired. +3. In the Orca desktop app, open **Settings > Remote Orca Servers** and paste + the link. From a CLI: + `orca environment add --name my-server --pairing-code 'orca://pair?code=...'`. + +The pairing link is a credential: share it only with the client you are +pairing. Paired devices are stored in the persistent volume, so clients +reconnect after a redeploy or an upgrade without pairing again. + +## Pair the Orca mobile app + +The mobile app needs a mobile-scoped link, which the default link is not. +Set `ORCA_SERVE_ARGS=--mobile-pairing` in the environment and redeploy: the +logs then print a mobile pairing QR code and link instead of the desktop one. +Scan it from the app, then clear `ORCA_SERVE_ARGS` and redeploy. Devices +already paired stay paired either way. On a phone, the `Web client URL` also +works in the browser without this step. + +## HTTPS + +`ORCA_PAIRING_ADDRESS` is the address advertised to clients. It defaults to +`http://` (plain WebSocket through Traefik; the pairing channel +itself is end-to-end encrypted). Once HTTPS is enabled on the domain, set it to +`https://` in the environment and redeploy so clients dial +`wss://`. + +## Coding agents + +The image ships Orca, git and the Linux libraries it needs, but no coding +agent. Install the agents you use from an Orca terminal on this server; they +land in `/home/orca/.local/bin`, which is on `PATH` and persisted in the +`orca-home` volume together with their credentials, your repositories and +Orca's state (`/home/orca/.config`). + +Example for Claude Code: `curl -fsSL https://claude.ai/install.sh | bash`. + +## Upgrade + +`orca serve` never updates itself. To upgrade, change the `ORCA_VERSION` +build argument in the compose file and redeploy. State lives in the +volume, not in the image, and newer releases migrate it on load. + +## Logs and secrets + +D-Bus and OS keyring errors at startup are expected in a container and +harmless. Without a keyring, Orca stores its secrets unencrypted in the +`orca-home` volume: treat that volume as sensitive. diff --git a/blueprints/orca-server/meta.json b/blueprints/orca-server/meta.json new file mode 100644 index 00000000..82ba12c7 --- /dev/null +++ b/blueprints/orca-server/meta.json @@ -0,0 +1,18 @@ +{ + "id": "orca-server", + "name": "Orca Server", + "version": "v1.4.205", + "description": "Headless Orca runtime: run a fleet of parallel coding agents in isolated git worktrees on your server and drive them from the Orca desktop, web or mobile app.", + "logo": "orca-server.png", + "links": { + "github": "https://github.com/stablyai/orca", + "website": "https://www.onorca.dev", + "docs": "https://github.com/stablyai/orca/blob/main/docs/reference/headless-linux-server.md" + }, + "tags": [ + "ai", + "developer-tools", + "agents", + "self-hosted" + ] +} diff --git a/blueprints/orca-server/orca-server.png b/blueprints/orca-server/orca-server.png new file mode 100644 index 00000000..a70d317f Binary files /dev/null and b/blueprints/orca-server/orca-server.png differ diff --git a/blueprints/orca-server/template.toml b/blueprints/orca-server/template.toml new file mode 100644 index 00000000..b0f26d10 --- /dev/null +++ b/blueprints/orca-server/template.toml @@ -0,0 +1,14 @@ +[variables] +main_domain = "${domain}" + +[config] +env = [ + "ORCA_PAIRING_ADDRESS=http://${main_domain}", + "ORCA_SERVE_ARGS=", +] +mounts = [] + +[[config.domains]] +serviceName = "orca-server" +port = 6768 +host = "${main_domain}"