Installation
Run Yolorouter with Docker, the one-line service installer, a release binary, or from source.
Deploy with Docker
Every release publishes a multi-arch image (amd64 / arm64) to
ghcr.io/yolorouter/yolorouter, tagged with the exact version; the newest
release also carries latest.
docker run -d --name yolorouter --restart unless-stopped \
-p 8080:8080 -v "$PWD/yolorouter:/yolorouter" \
ghcr.io/yolorouter/yolorouter:latestOr with Compose:
curl -fsSLO https://raw.githubusercontent.com/yolorouter/yolorouter/main/docker-compose.yml
docker compose up -dghcr.io can be slow or unreachable from mainland China. Pull through a GHCR
mirror and retag, for example the Nanjing University mirror:
docker pull ghcr.nju.edu.cn/yolorouter/yolorouter:latest
docker tag ghcr.nju.edu.cn/yolorouter/yolorouter:latest ghcr.io/yolorouter/yolorouter:latestOr point the image: field in docker-compose.yml straight at the mirror.
Third-party mirrors are run by their own operators; check their notices for
availability.
Where the state lives
Everything the container writes goes to the one mounted folder. After the first start it looks like this on the host:
yolorouter/
├── configs/config.yaml # generated on first start, holds the master key
└── data/ # SQLite database and request-body filesTo change configuration, edit ./yolorouter/configs/config.yaml on the host
and docker restart yolorouter. Backing up the folder backs up the whole
deployment.
Network access
-p 8080:8080 publishes the port on every host interface, so other machines
on your LAN can use the gateway and console at http://<host-ip>:8080 right
away. To restrict it to the host itself, map 127.0.0.1:8080:8080 instead.
Upgrading
docker compose pull && docker compose up -dWith plain docker run, pull the image, remove the container, and run the
same command again — the mounted folder carries everything over:
docker pull ghcr.io/yolorouter/yolorouter:latest
docker rm -f yolorouter
# then re-run the docker run command from the top of this pageThe console still checks for new releases inside a container: the About page
and the sidebar show when one is out. The one-click update button is replaced
by a pull-the-image hint, and the yolorouter update CLI says the same —
the image is immutable by design, so an in-place binary swap would be lost on
the next recreate.
PostgreSQL
The image runs on SQLite out of the box. To use PostgreSQL instead, add a database service:
services:
yolorouter:
image: ghcr.io/yolorouter/yolorouter:latest
container_name: yolorouter
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./yolorouter:/yolorouter
depends_on:
- postgres
postgres:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: yolorouter
POSTGRES_PASSWORD: change-me
POSTGRES_DB: yolorouter
volumes:
- ./postgres:/var/lib/postgresql/dataStart once so configs/config.yaml is generated, then switch its database
section over and restart:
database:
driver: postgres
host: postgres
port: 5432
user: yolorouter
password: change-me
dbname: yolorouter
sslmode: disableInstall as a service (one command)
Install yolorouter as a background service that starts on boot — systemd on Linux, launchd on macOS, a scheduled task on Windows:
# Linux / macOS
curl -fsSL https://get.yolorouter.com/install.sh | bash# Windows, PowerShell 5.1+
irm https://get.yolorouter.com/install.ps1 | iexOr straight from GitHub:
curl -fsSL https://raw.githubusercontent.com/yolorouter/yolorouter/main/scripts/install.sh | bashirm https://raw.githubusercontent.com/yolorouter/yolorouter/main/scripts/install.ps1 | iexIf GitHub is slow or unreachable from your network, use the accelerated command. It is the same installer downloaded through a Cloudflare proxy; auto-updates after installation keep using the mirror with no extra configuration:
# Linux / macOS
curl -fsSL https://gh.yolorouter.com/install.sh | bash# Windows, PowerShell 5.1+
irm https://gh.yolorouter.com/install.ps1 | iexTo switch an already installed machine to the mirror, add github_proxy: https://gh.yolorouter.com/ under the update section of config.yaml and restart the service.
The script first asks for an interface language, then detects your architecture, downloads and sha256-verifies the release, builds a self-contained app-home directory, starts the service and health-checks it.
What the Windows installer does
install.ps1 registers a scheduled task named Yolorouter rather than a Windows Service, and the privilege level of the PowerShell you run it from decides the install scope:
| Run from | Scope | App home | Starts |
|---|---|---|---|
| Elevated PowerShell | system | %ProgramFiles%\yolorouter | at boot, as SYSTEM |
| Normal PowerShell | user | %LOCALAPPDATA%\.yolorouter | at logon, as you |
Manage it with schtasks.exe; the installer prints the exact query / stop / restart commands when it finishes.
Re-run the same command to upgrade — configuration and database are preserved, and the database is backed up before the upgrade.
Optional environment overrides
| Variable | Meaning |
|---|---|
YOLO_LANG | zh or en, skips the language prompt |
YOLO_SCOPE | system or user install scope |
YOLO_VERSION | Pin a version, e.g. vX.Y.Z |
YOLO_REPO | Override owner/repo |
YOLO_MIRROR | Download mirror, e.g. https://host/ |
YOLO_UNINSTALL | 1 uninstalls instead of installing (same as passing --uninstall) |
Both installers accept the same variables.
A system-scope install needs root/sudo (an elevated PowerShell on Windows); without it the script falls back to a user-level service.
Run a release binary
Download the archive for your platform from the latest release, extract it, then:
./yolorouter serve # .\yolorouter.exe serve on WindowsReleases cover Linux, macOS and Windows on both amd64 and arm64 (.zip for Windows, .tar.gz elsewhere).
Run it from the directory where you want configs\ and data\ to appear: both are resolved against the working directory, not the location of the binary. The one-line installers avoid this entirely by pinning a self-contained app home.
Config file permissions on Windows
Yolorouter cannot enforce config file permissions on Windows: access there is governed by ACLs, and the permission bits Go reports are synthesized and do not reflect real access. The service logs a warning at startup — including a ready-to-run icacls command scoped to the current account — and continues.
To restrict it by hand:
icacls "configs\config.yaml" /inheritance:r `
/remove:g *S-1-1-0 /remove:g *S-1-5-32-545 /remove:g *S-1-5-11 `
/grant:r "${env:USERNAME}:F"
icacls "configs\config.yaml" # confirm only your own account is listed/inheritance:r only drops inherited entries and /grant:r only replaces the grant for the account it names, so the over-broad principals (Everyone, Users, Authenticated Users) are actually removed by those /remove:g flags — by SID rather than by name, because those names are localized (Everyone shows up as Jeder on German Windows). This covers the overwhelming majority of real-world cases, but cannot guarantee an empty ACL for arbitrary principals, which is why the second verification command is worth running. To rebuild the ACL from scratch, use PowerShell's Set-Acl with SetAccessRuleProtection($true, $false).
Under cmd.exe use "%USERNAME%:F" instead, and ^ as the continuation character rather than a backtick — ${env:...} is PowerShell-only syntax and %...% is cmd-only; they are not interchangeable.
First run
Automatic initialization
The first run generates configs/config.yaml (including a random AES-256 master key used to encrypt upstream keys), applies database migrations, and starts the console at http://localhost:8080. The startup log prints both the localhost and the LAN address, so you can open it from another machine.
Create an admin and add providers
After creating the first admin account, follow the guided flow: add providers and their upstream keys, create models with their provider candidates, then issue API keys.
Provider setup is preset-driven: pick a known provider from the built-in catalogue and the base URL and protocol are filled in for you. Once a key is pasted you can pull that provider's live model list instead of typing model ids by hand.
Build from source
Requires Go 1.25.7+ and Node.js 22.12+.
# Backend only — serves a placeholder page instead of the console
make build # -> ./bin/yolorouter
# Full binary with the console embedded
make build-embed # -> ./bin/yolorouter (builds and embeds the frontend)
# Cross-compile (frontend embedded)
make build-macos # -> ./bin/yolorouter-darwin-{amd64,arm64}
make build-windows # -> ./bin/yolorouter-windows-{amd64,arm64}.exe
# Fast compile check (windows only, no frontend build, no binary)
make build-windows-check