Skip to content

Self-hosting: overview and prerequisites

Read this before installing anything. It says what a Winner AI installation is made of, what the server and your organisation must provide, and every connection that leaves your network. Installing the Winner AI server is the install itself.

Three things decide whether you can install today:

  • Sign-in is through an OpenID Connect provider over https: Auth0, or the one your organisation already runs, such as JumpCloud.
  • A publicly trusted certificate for the server's names, in one of two modes. Either the internet reaches the server on 80 and 443, where the certificate authority checks each name, or, for a server only a private network or VPN reaches, the names sit in an Amazon Route 53 public zone and the server has an AWS instance role that may write their challenge record.
  • One linux/amd64 server with Docker. Nothing else is supported.

What you run

Winner AI has no hosted service. Each organisation runs its own installation: one server that holds the organisation's coding-agent sessions, signs its people in through its identity provider, and serves the Dashboard and the product pages to its Managers. A client on each developer's laptop sends that laptop's sessions straight to the server's database. Nothing of ours connects to the server. We build and sign the releases and answer support; you run everything else.

The database holds every session your developers' coding agents ran: their prompts, the agents' replies and the tools they called. Protect the server and its disks as you would a source repository.

Part What it does
Edge Stock Caddy. Terminates https on 443 for the server's names, and on 80 redirects to https and, in the http certificate mode, answers the certificate authority.
Sign-in gate Stock oauth2-proxy. Every page passes it and signs in through your identity provider, apart from the few addresses that are public by design or that a laptop calls with its own token.
Web server Stock Caddy with one pinned plugin, behind the gate on every request: it routes to the control plane and the dashboard, admits only the installation's Managers to the dashboard, and brands its pages.
Control plane Our application: sign-in landing, the roster, laptop enrollment, the organisation's schema and database roles, the product pages, Settings, and these guides at /guide/.
Jobs service The same application's background passes: Prompt Coaching, Skills, Benchmarks, role sync, the sampling of which laptops pushed, and the heartbeat.
Dashboard The session dashboard Managers open from the control plane: browse, search and read every session of the organisation. Its container runs agentsview pg serve.
Database Postgres with pgvector. The archive of every session; laptops push to it over TLS on 5432.
Certificate helpers db-certs hands Postgres the certificate for its name; in the dns mode, dns-certs (stock lego) obtains and renews the certificate through Route 53, and edge-reload tells the edge when it changes.
AI runner Stock Ollama, on by default (the local-llm profile in COMPOSE_PROFILES). Serves the embedding model and, unless you point them elsewhere, the model calls. It runs models on CPU.
Laptop client winner and the session collector (agentsview) on each developer's laptop. Laptop client guide covers it.

How the data moves

laptop (agentsview pg push) ──5432, TLS──> database (the organisation's schema)
laptop (winner)             ──443──> edge ──> sign-in gate ──> web server ──> control plane (enrollment, reports)
browser                     ──443──> edge ──> sign-in gate ──> web server ──> control plane, dashboard ──> database
sign-in gate, control plane ──> your identity provider
control plane, jobs, dashboard ──> AI runner, or your hosted model endpoint

A laptop sends its sessions straight to the database, as a database role that belongs to that one laptop and reaches its organisation's schema and nothing else. The control plane is not in that path: it enrolls the laptop and hands it the role, and laptops keep pushing while it is down.

The supported shape

One linux/amd64 server running Docker Compose, installed from the release bundle. Before installing anything, the installer refuses anything but Linux on x86-64, and a Docker daemon that is not linux/amd64. It builds nothing on the server: the control plane's, the Dashboard's and the sign-in gate's images come out of the bundle, and the other public ones are pulled from Docker Hub at fixed, checked versions.

Not supported: an arm64 server, a container service such as Amazon ECS, Kubernetes or another orchestrator, and an installation spread over several servers. Laptops on arm64 are supported; only the server is amd64.

What you operate

  • The server and its operating system: updates, disk, monitoring, and where the server runs.
  • Hardening. Winner AI ships no firewall rule, jail or filter, and nothing on a bundle install checks which ports the server publishes.
  • Admit only 80, 443 and 5432 from outside, plus your own administration access. Docker's own rules publish container ports past host firewalls such as ufw and firewalld, so set the rule in your network or cloud firewall, or in Docker's DOCKER-USER chain, then check from outside that only those three answer.
  • 5432 is open to wherever laptops connect from, so anyone there can guess passwords against it. Only per-laptop roles are admitted from outside; banning an address after repeated refused logins slows guessing. A fail2ban jail reading the database container's log that bans after five refused logins in ten minutes, for an hour, is a starting point. Never ban the stack's own subnet (below), and give an address many laptops share (a VPN or an office's NAT) a far higher count: one laptop with a stale password writes about two refused logins a minute, and would lock out everyone behind that address (The Postgres jail).
  • DNS and the certificate: the server's names and their records.
  • The identity provider: who may sign in, and who is a Manager.
  • The model endpoint, if you use a hosted one, and its key.
  • Backups. The bundle ships the backup and restore commands, but nothing on a bundle install schedules a backup or copies one off the server.
  • Upgrades. Nothing upgrades itself: Upgrade and roll back says how to install one.
  • Telemetry: off unless you switch it on (Model endpoint and telemetry).

Prerequisites

Everything below is needed before the install. The model endpoint is optional.

The server

  • linux/amd64 (x86-64), Ubuntu, with Docker Engine 28.0 or later and the Docker Compose plugin 2.24.4 or later. The host check the install runs refuses an older one, and a Docker daemon that is not linux/amd64. Check the requirements says how to install them.
  • A user who can run docker, who runs the install.
  • ssh-keygen (OpenSSH), sha256sum and tar, to check and unpack the bundle, openssl and curl, for the install's secrets and checks, and ss (the iproute2 package), for the host check's ports; Check the requirements has the version ssh-keygen must be.
  • Disk. 5 GB free where Docker keeps its data, 15 GB with the AI runner, plus room for the unpacked bundle. No CPU or memory figure has been measured yet. The database grows with your team's sessions, and the AI runner, which runs models on CPU, is the heaviest service.
  • Ports 80, 443 and 5432 free on the server, and a clock within 5 seconds of the real time, kept by time sync, which the host check compares.
  • No network of its own at 172.16.86.0/24. The stack pins that subnet for its own containers, and the database admits every role, its superuser included, from inside it. The server's networks, routes and any VPN range laptops connect from must not use it.
  • Outbound https to Docker Hub (the install fails if a pull does), your identity provider's issuer (the sign-in gate does not start without it), a public certificate authority, the Route 53 API in the dns certificate mode, and the Ollama registry while the AI runner is on. What leaves the server lists every destination by name.

DNS, certificate and ports

  • A public DNS name for the server, and one for the database (it may be the same name), resolving to it from wherever your people and laptops are. Use names, not IP addresses; scripts/check-env.sh refuses an IP address for the database's name.
  • A certificate mode (CERTIFICATE_MODE), which decides how the certificates are taken over ACME. The edge presents one for each name, and the database presents its name's, so laptops verify it against their system trust store.
  • http, the default: 80 and 443 reachable from the internet, for both names. The certificate authority connects to the server on 80 or 443 to check each name.
  • dns, for a server nothing on the internet reaches: both names in an Amazon Route 53 public zone, and an AWS instance role on the server that may write the challenge record in it. The certificate authority reads a TXT record instead of connecting to the server, so no inbound port is needed for the certificate. Network says which mode to choose, and Private VPC: the certificate through DNS the role's policy.
  • 5432 reachable from every laptop, which pushes there over TLS: from the internet, or only from your office and VPN ranges if every laptop connects from them.
  • An e-mail address for the certificate account (ACME_EMAIL).

Sign-in

A production installation signs in through any OpenID Connect provider whose issuer is https: Auth0, or the provider your organisation already runs. scripts/check-env.sh, which the installer runs, refuses an issuer that is not https, and a provider other than Auth0 while Auth0 Management credentials are set.

On a provider other than Auth0, the provider needs an application for the sign-in gate, and the Managers are a group at the provider or a list of addresses in .env; the Auth0 settings hold placeholders and the Management credentials stay blank. Connect your identity provider is the checklist, and JumpCloud: before the install a worked example.

On Auth0, the tenant needs:

  • one organisation for the installation, with sign-in requiring it and without adding people to it at sign-in;
  • the post-login Action, which puts the roles and the organisation on each sign-in and refuses a sign-in to the gate through any other organisation, with its two secrets set to the installation's values;
  • a regular web application for the sign-in gate, with the server's callback and logout addresses;
  • a native application with the device-code grant and offline access, which only a winner older than the control plane's own laptop sign-in uses: a current winner signs in through the control plane;
  • with Auth0 Management credentials, which let Admin add people and read roles from Auth0, a machine-to-machine application for the Management API and the roles manager and member: with the credentials set, the control plane does not start without the roles.

Who may sign in, Fill in .env and The post-login Action say how each is set, and Configuration lists every setting.

A model endpoint

None is required. The AI runner in the bundle serves the embedding model and, by default, every model call. To use a hosted model for the rest, you need an OpenAI-compatible endpoint over https and its key, or Amazon Bedrock; Model endpoint and telemetry says what the endpoint must support, how to check it before switching Prompt Coaching on, and why the AI runner keeps serving embeddings (Embeddings).

From Winner AI

  • The release bundle, winner-ai-server-<X.Y.Z>.tar.gz, and the release key's fingerprint, which you confirm with your Winner AI contact over a different channel from the bundle; Verify the bundle's signature prints the one to confirm.
  • A licence file. A Manager uploads it on Settings, which checks it from the file alone, never with us. Until one is uploaded, the deployment runs 30 days of grace from its first start. Licence covers installing and renewing it.

What leaves the server

These are the connections Winner AI's software on the server makes, as read from its code; no capture of a running stack has been run yet. Your operating system's own traffic (package updates, time, your cloud provider's services) and any copy of a backup you set up are yours, and not listed. Every connection is outbound https, on 443 unless an address you set (the model endpoint, the heartbeat or a telemetry host) names another port. Three exceptions. Two are plain http on 80. When the edge's certificate names an OCSP responder, the edge fetches the certificate's revocation status from that address. And on AWS, whatever signs with the server's instance role reads the role's credentials from the instance metadata service at the link-local address 169.254.169.254: Amazon Bedrock signed with the instance role, the certificate helper in the dns mode, and scripts/check-dns-zone.sh and scripts/env-from-secrets.sh when you run them. The third is DNS on UDP port 53: scripts/check-dns-zone.sh, run before the first dns-mode start, asks the public zone's own name servers for its test record directly. The certificate helper itself needs no outbound port 53.

Destination When Why
Your identity provider's issuer, <OAUTH2_PROXY_OIDC_ISSUER_URL> (on Auth0, <AUTH0_DOMAIN>) Always The sign-in gate reads its configuration, tokens and keys. On Auth0, the control plane also checks an older winner's Auth0 token against its keys and, with Management credentials, calls its Management API for the roles, the roster, enrollment and role sync.
A public ACME certificate authority: Let's Encrypt (acme-v02.api.letsencrypt.org), and ZeroSSL (acme.zerossl.com, and api.zerossl.com for its account credentials) when Let's Encrypt fails At first start and around each renewal The certificates. In the http mode the authority also connects in to 80 or 443 to check each name; the dns mode uses Let's Encrypt only.
The Route 53 API Around each issue and renewal, in the dns mode The certificate helper writes the challenge record, signing with the server's instance role.
Docker Hub: registry-1.docker.io, auth.docker.io, and the storage host it redirects image data to At install and upgrade, and when you run scripts/check-dns-zone.sh The installer pulls the public images: the database, the edge and web server base, the certificate helper in the dns mode, and the AI runner while local-llm is on. The zone check looks up the certificate helper's image. Docker Hub limits pulls without a login per outbound address.
ghcr.io, GitHub's registry At install and upgrade, when trial is in COMPOSE_PROFILES The trial's sign-in provider (Dex), pulled by digest.
The Ollama registry, registry.ollama.ai, and the storage host it redirects model data to At every AI runner start, while local-llm is on The runner pulls the embedding model, and the chat model when an endpoint points at the runner.
Your hosted model endpoint, and any endpoint a Manager sets for the organisation on Settings When one is set Prompt Coaching, Skills, Benchmarks and the dashboard's insights. What each feature sends to the model lists what each sends.
raw.githubusercontent.com, openrouter.ai When the control plane sets up the organisation's schema: at first start (twice when the first attempt fails), at every later start until one succeeds, after an upgrade that changes the collector version, and when a Manager runs the migration from Admin Setting up the schema refreshes the model prices that cost figures use. There is no switch for it, and laptops make the same refresh.
FLEETVIEW_HEARTBEAT_URL After every jobs sweep, when you set it Your own dead-man's switch.
The error-report and analytics hosts you set Only when you switch telemetry on Telemetry lists each kind and every field it sends.

Allow the two redirect storage hosts by the names your proxy or firewall logs for them: they are content-delivery hosts whose names and addresses change.

There is no licence check-in and no update check. The Dashboard runs with its usage ping and update check switched off, and the control plane sets up schemas with the usage ping off.

Two other parties see traffic because of the installation, not from the server:

  • People's browsers load fonts from Google Fonts (fonts.googleapis.com, fonts.gstatic.com): Archivo and JetBrains Mono on the control plane's pages, and Archivo on the dashboard. These guides serve their own.
  • Laptops reach the control plane, the database and a few hosts of their own; What the laptop sends, and where lists them.