# 🐳 Docker Guide — OmniRoute (Yorùbá) 🌐 **Languages:** 🇺🇸 [English](../../../../guides/DOCKER_GUIDE.md) · 🇪🇹 [am](../../../am/docs/guides/DOCKER_GUIDE.md) · 🇸🇦 [ar](../../../ar/docs/guides/DOCKER_GUIDE.md) · 🇦🇿 [az](../../../az/docs/guides/DOCKER_GUIDE.md) · 🇧🇬 [bg](../../../bg/docs/guides/DOCKER_GUIDE.md) · 🇧🇩 [bn](../../../bn/docs/guides/DOCKER_GUIDE.md) · 🇧🇦 [bs](../../../bs/docs/guides/DOCKER_GUIDE.md) · 🇨🇿 [cs](../../../cs/docs/guides/DOCKER_GUIDE.md) · 🇩🇰 [da](../../../da/docs/guides/DOCKER_GUIDE.md) · 🇩🇪 [de](../../../de/docs/guides/DOCKER_GUIDE.md) · 🇬🇷 [el](../../../el/docs/guides/DOCKER_GUIDE.md) · 🇪🇸 [es](../../../es/docs/guides/DOCKER_GUIDE.md) · 🇪🇪 [et](../../../et/docs/guides/DOCKER_GUIDE.md) · 🇮🇷 [fa](../../../fa/docs/guides/DOCKER_GUIDE.md) · 🇫🇮 [fi](../../../fi/docs/guides/DOCKER_GUIDE.md) · 🇫🇷 [fr](../../../fr/docs/guides/DOCKER_GUIDE.md) · 🇮🇪 [ga](../../../ga/docs/guides/DOCKER_GUIDE.md) · 🇮🇳 [gu](../../../gu/docs/guides/DOCKER_GUIDE.md) · 🇳🇬 [ha](../../../ha/docs/guides/DOCKER_GUIDE.md) · 🇮🇱 [he](../../../he/docs/guides/DOCKER_GUIDE.md) · 🇮🇳 [hi](../../../hi/docs/guides/DOCKER_GUIDE.md) · 🇭🇷 [hr](../../../hr/docs/guides/DOCKER_GUIDE.md) · 🇭🇺 [hu](../../../hu/docs/guides/DOCKER_GUIDE.md) · 🇦🇲 [hy](../../../hy/docs/guides/DOCKER_GUIDE.md) · 🇮🇩 [id](../../../id/docs/guides/DOCKER_GUIDE.md) · 🇳🇬 [ig](../../../ig/docs/guides/DOCKER_GUIDE.md) · 🇮🇹 [it](../../../it/docs/guides/DOCKER_GUIDE.md) · 🇯🇵 [ja](../../../ja/docs/guides/DOCKER_GUIDE.md) · 🇬🇪 [ka](../../../ka/docs/guides/DOCKER_GUIDE.md) · 🇰🇭 [km](../../../km/docs/guides/DOCKER_GUIDE.md) · 🇮🇳 [kn](../../../kn/docs/guides/DOCKER_GUIDE.md) · 🇰🇷 [ko](../../../ko/docs/guides/DOCKER_GUIDE.md) · 🇱🇹 [lt](../../../lt/docs/guides/DOCKER_GUIDE.md) · 🇱🇻 [lv](../../../lv/docs/guides/DOCKER_GUIDE.md) · 🇮🇳 [ml](../../../ml/docs/guides/DOCKER_GUIDE.md) · 🇮🇳 [mr](../../../mr/docs/guides/DOCKER_GUIDE.md) · 🇲🇾 [ms](../../../ms/docs/guides/DOCKER_GUIDE.md) · 🇲🇹 [mt](../../../mt/docs/guides/DOCKER_GUIDE.md) · 🇲🇲 [my](../../../my/docs/guides/DOCKER_GUIDE.md) · 🇳🇵 [ne](../../../ne/docs/guides/DOCKER_GUIDE.md) · 🇳🇱 [nl](../../../nl/docs/guides/DOCKER_GUIDE.md) · 🇳🇴 [no](../../../no/docs/guides/DOCKER_GUIDE.md) · 🇮🇳 [or](../../../or/docs/guides/DOCKER_GUIDE.md) · 🇮🇳 [pa](../../../pa/docs/guides/DOCKER_GUIDE.md) · 🇵🇭 [phi](../../../phi/docs/guides/DOCKER_GUIDE.md) · 🇵🇱 [pl](../../../pl/docs/guides/DOCKER_GUIDE.md) · 🇵🇹 [pt](../../../pt/docs/guides/DOCKER_GUIDE.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/guides/DOCKER_GUIDE.md) · 🇷🇴 [ro](../../../ro/docs/guides/DOCKER_GUIDE.md) · 🇷🇺 [ru](../../../ru/docs/guides/DOCKER_GUIDE.md) · 🇱🇰 [si](../../../si/docs/guides/DOCKER_GUIDE.md) · 🇸🇰 [sk](../../../sk/docs/guides/DOCKER_GUIDE.md) · 🇸🇮 [sl](../../../sl/docs/guides/DOCKER_GUIDE.md) · 🇷🇸 [sr](../../../sr/docs/guides/DOCKER_GUIDE.md) · 🇸🇪 [sv](../../../sv/docs/guides/DOCKER_GUIDE.md) · 🇰🇪 [sw](../../../sw/docs/guides/DOCKER_GUIDE.md) · 🇮🇳 [ta](../../../ta/docs/guides/DOCKER_GUIDE.md) · 🇮🇳 [te](../../../te/docs/guides/DOCKER_GUIDE.md) · 🇹🇭 [th](../../../th/docs/guides/DOCKER_GUIDE.md) · 🇹🇷 [tr](../../../tr/docs/guides/DOCKER_GUIDE.md) · 🇺🇦 [uk-UA](../../../uk-UA/docs/guides/DOCKER_GUIDE.md) · 🇵🇰 [ur](../../../ur/docs/guides/DOCKER_GUIDE.md) · 🇺🇿 [uz](../../../uz/docs/guides/DOCKER_GUIDE.md) · 🇻🇳 [vi](../../../vi/docs/guides/DOCKER_GUIDE.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/guides/DOCKER_GUIDE.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/guides/DOCKER_GUIDE.md) --- > Ìtọ́kasí pípé fún ìmúṣiṣẹ́ Docker. Fún ìbẹ̀rẹ̀ kíákíá, wo [abala Docker nínú README](../README.md#-docker). ## Àtòjọ Àwọn Àkóónú - [Ṣíṣe Kíákíá](#quick-run) - [Pẹ̀lú Fáìlì Àyíká](#with-environment-file) - [Docker Compose](#docker-compose) - [Àwọn Profile Tó Wà](#available-profiles) - [Ṣíṣètò àwọn irinṣẹ́ CLI ti host nígbà tí OmniRoute bá ń ṣiṣẹ́ nínú Docker](#configuring-host-cli-tools-when-omniroute-runs-in-docker) - [Redis Sidecar](#redis-sidecar) - [Compose Fún Production](#production-compose) - [Àwọn Ìpele Dockerfile](#dockerfile-stages) - [Àwọn Variable Àyíká Tó Ṣe Pàtàkì](#critical-environment-variables) - [Docker Compose pẹ̀lú Caddy (HTTPS)](#docker-compose-with-caddy-https-auto-tls) - [Cloudflare Quick Tunnel](#cloudflare-quick-tunnel) - [Àwọn Tag Image](#image-tags) - [Àwọn ìmúdójúìwọ̀n Dashboard nínú Docker](#dashboard-updates-in-docker) - [Wíwà-lárọ̀ọ́wọ́tó: SQLite àìyípadà jẹ́ replica kan ṣoṣo](#availability-default-sqlite-is-single-replica) - [Àwọn àṣìṣe agbègbè Gemini nínú Docker](#gemini-regional-errors-inside-docker) - [Àwọn Àkíyèsí Pàtàkì](#important-notes) --- ## Ṣíṣe Kíákíá > **Ṣe o fẹ́ gbàlejò fúnra rẹ pẹ̀lú àṣẹ kan ṣoṣo?** Wo > [Ìtọ́sọ́nà Self-Host](../getting-started/SELF_HOST_GUIDE.md) — > `docker compose -f docker-compose.selfhost.yml up -d` (image tí a tẹ̀ jáde + > Redis, loopback nìkan, kò sí yíyan profile). Quick Run tó wà nísàlẹ̀ jẹ́ ọ̀nà > container kan ṣoṣo fún àwọn olumulo tí wọ́n ti ń ṣiṣẹ́ Redis níbòmíràn. ```bash docker run -d \ --name omniroute \ --restart unless-stopped \ --stop-timeout 40 \ -p 20128:20128 \ -v omniroute-data:/app/data \ diegosouzapw/omniroute:latest ``` ## Pẹ̀lú Fáìlì Àyíká ```bash # Kọ́kọ́ ṣe ẹ̀dà .env kí o sì ṣàtúnṣe rẹ̀ cp .env.example .env docker run -d \ --name omniroute \ --restart unless-stopped \ --stop-timeout 40 \ --env-file .env \ -p 20128:20128 \ -v omniroute-data:/app/data \ diegosouzapw/omniroute:latest ``` ## Docker Compose ```bash # Profile ìpìlẹ̀ (kò ní àwọn irinṣẹ́ CLI) docker compose --profile base up -d # Profile CLI (Claude Code, Codex, OpenClaw wà nínú rẹ̀) docker compose --profile cli up -d # Profile host (Linux ní àkọ́kọ́; ó so àwọn binary CLI host pọ̀ gẹ́gẹ́ bí kíkà-nìkan) docker compose --profile host up -d # Profile wẹ́ẹ̀bù (Chromium/Playwright fún àwọn provider session wẹ́ẹ̀bù) docker compose --profile web up -d # Darapọ̀ CLI + CLIProxyAPI sidecar docker compose --profile cli --profile cliproxyapi up -d ``` ## Àwọn Profile Tó Wà OmniRoute ní àwọn profile Compose fún àwọn ìrísí ìmúṣiṣẹ́ pàtàkì. Yan èyí tó bá àyíká rẹ mu. | Profile | Service | Ìgbà tí o yẹ kí o lò ó | Àṣẹ | | ----------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | | `base` (àìyípadà) | `omniroute-base` | Server aláìní interface / runtime kékeré jù, kò sí àwọn CLI provider tí a fi sínú rẹ̀ | `docker compose --profile base up -d` | | `cli` | `omniroute-cli` | Àwọn workflow agentic tó ń pe `omniroute providers/setup/doctor` àti àwọn CLI tí a fi sínú rẹ̀ (Codex, Claude Code, Droid, OpenClaw) | `docker compose --profile cli up -d` | | `host` | `omniroute-host` | Àwọn host Linux tó fẹ́ ààyè ìráyèṣe bíi `network_mode` sí àwọn CLI host nípa sísopọ̀ `~/.local/bin`, `~/.codex`, `~/.claude`, àti bẹ́ẹ̀ bẹ́ẹ̀ lọ gẹ́gẹ́ bí kíkà-nìkan | `docker compose --profile host up -d` | | `cliproxyapi` | `cliproxyapi` | Ṣiṣẹ́ [CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI) sidecar lórí port `8317` fún proxy CLI upstream | `docker compose --profile cliproxyapi up -d` | | `web` | `omniroute-web` | Àwọn provider session wẹ́ẹ̀bù tó nílò browser: `gemini-web`, `claude-web`, `claude-turnstile` (ó build `runner-web`, Chromium wà nínú rẹ̀) | `docker compose --profile web up -d` | > A lè darapọ̀ ọ̀pọ̀ profile: `docker compose --profile cli --profile cliproxyapi up -d`. ## Ṣíṣètò àwọn irinṣẹ́ CLI ti host nígbà tí OmniRoute bá ń ṣiṣẹ́ nínú Docker `omniroute setup-codex`, `setup-claude`, `config set ` àti bọ́tìnì **Fi àtòjọ-ẹ̀rọ pamọ́** ti dashboard, gbogbo wọn ni wọ́n ń kọ fáìlì bíi `~/.codex/*.config.toml`. Àwọn path wọ̀nyẹn ní ìtumọ̀ lórí ẹ̀rọ tí CLI náà ti ń ṣiṣẹ́ nìkan. Tí o bá ṣiṣẹ́ wọn nínú container, ohun tí a kọ yóò lọ sínú home ti container náà fúnra rẹ̀ (`/home/node` — image náà ń ṣiṣẹ́ pẹ̀lú `USER node`), níbi tí CLI host kankan kò ti ní kà á láéláé, tí a ó sì pa á rẹ́ ní kété tí a bá tún container náà ṣẹ̀dá. OmniRoute máa ń ṣàwárí èyí, yóò sì kọ̀ láti kọ ọ́, nípa fífún ọ ní ìtọ́nisọ́nà dípò jíjàbọ̀ àṣeyọrí tí o kò lè lò: CLI náà yóò jáde pẹ̀lú `2`, API náà yóò sì dáhùn `422` pẹ̀lú `containerEphemeralTarget: true`. ### Ohun tí a dámọ̀ràn: ṣiṣẹ́ CLI lórí host, kí OmniRoute sì ṣiṣẹ́ nínú Docker Container náà ń pèsè API; CLI náà ń ṣètò àwọn irinṣẹ́ host rẹ. ```bash docker compose --profile base up -d npm install -g omniroute omniroute connect http://localhost:20128 # darí CLI sí container náà omniroute setup-codex # kọ ~/.codex gidi sí host rẹ ``` Èyí ni àṣàyàn tó tọ́ nígbà tí Codex, Claude Code, Cursor tàbí irú wọn bá ń ṣiṣẹ́ lórí laptop rẹ — èyí sì ni ìṣètò tí ó wọ́pọ̀. ### Àṣàyàn mìíràn: bind-mount àwọn directory àtòjọ-ẹ̀rọ host (profile `host`) Tí o bá fẹ́ kí container náà fúnra rẹ̀ kọ àtòjọ-ẹ̀rọ host rẹ, mount àwọn directory náà sínú rẹ̀, kí o sì darí `CLI_CONFIG_HOME` sí root mount náà. Profile `host` ti ṣe èyí tẹ́lẹ̀: ```yaml environment: - CLI_CONFIG_HOME=/host-home - CLI_ALLOW_CONFIG_WRITES=true volumes: - ~/.codex:/host-home/.codex:rw - ~/.claude:/host-home/.claude:rw ``` Bind mount ni ó mú kí path náà ṣeé fọkàn tán: OmniRoute máa ń ka `/proc/self/mountinfo`, yóò sì gba kí a kọ sí àwọn path tí a mount (àti sí àwọn directory tí àwọn ọmọ wọn jẹ́ mount, èyí tí ó bá ìrísí `/host-home` lókè mu gan-an), nígbà tí ó ṣì ń kọ̀ láti kọ sí àwọn tí a kò mount. ### Ọ̀nà àbáyọ: ṣètò àwọn CLI inú container fúnra rẹ̀ (má ṣe lò ó ju bó ṣe yẹ lọ) Nígbà tí àwọn CLI bá ń gbé inú container náà ní ti gidi (profile `cli`), ìkọ̀wé náà jẹ́ èyí tí a mọ̀ọ́mọ̀ ṣe. Fi `--allow-container-write` ránṣẹ́ sí àṣẹ `setup-*` èyíkéyìí, tàbí ṣètò `OMNIROUTE_ALLOW_CONTAINER_CONFIG_WRITE=true` fún server náà. Ìkọ̀wé náà yóò tẹ̀síwájú pẹ̀lú ìkìlọ̀ pé kò ní wà lẹ́yìn tí container náà bá parí. > **Ìkìlọ̀ ààbò — profile `cli` + mount `docker.sock`.** > Profile `cli` máa ń bind-mount `/var/run/docker.sock` kí auto-updater inú container > lè tún stack náà ṣẹ̀dá láti daemon host > (`src/lib/system/autoUpdate.ts` máa ń yẹ socket náà wò, yóò sì fò ipa-ọ̀nà > Docker tí kò bá sí). Socket yẹn jẹ́ **ààlà ìgbẹ́kẹ̀lé root host**: > ohunkóhun tó bá lè dé ọ̀dọ̀ rẹ̀ lè darí daemon Docker host gẹ́gẹ́ bí > root — ó lè ṣẹ̀dá, yẹ̀wò, dá dúró, kí ó sì yọ container èyíkéyìí lórí host. > Àwọn àbájáde rẹ̀: > > 1. **Má ṣe fi port profile `cli` hàn sí network láéláé.** Publish > rẹ̀ lórí `127.0.0.1` (`ports: "127.0.0.1:${DASHBOARD_PORT:-20128}:..."`) > — profile `cli` tí LAN lè dé sí yóò sọ RCE ipele-dashboard èyíkéyìí di > ìfọ́wọ́kọ host pátápátá. > 2. **Má ṣe bind directory host àfikún kankan sínú profile `cli`.** > Socket Docker pẹ̀lú mount míì yóò fún container náà ní agbára kíkà/kíkọ > pátápátá sí filesystem àti àtòjọ-ẹ̀rọ host rẹ. Tí o bá nílò kí irinṣẹ́ kan > rí project kan, ṣiṣẹ́ rẹ̀ lórí ẹ̀rọ rẹ pẹ̀lú binary CLI — má ṣe mount rẹ̀ > sínú container `cli`. > > Tí o kò bá nílò auto-update inú container, má ṣe tan profile `cli` > (`COMPOSE_PROFILES=core,redis` tàbí èyí tó kúrú síi). Àwọn profile yòókù kò > mount socket Docker. > > Wo `docs/security/MITM-TPROXY-DECRYPT.md` (git; a kò compile rẹ̀ sínú `/docs`) fún threat model tó ní í ṣe pẹ̀lú > MITM, àti `docs/security/SUPPLY_CHAIN.md` fún > provenance chain binary `codex`/`claude-code`/`droid`/`openclaw`. ## Redis Sidecar OmniRoute gbára lé Redis láti ṣe àtìlẹ́yìn fún olùdínwọ̀n ìwọ̀n lílò tí a pín káàkiri àti cache tí a pín. A máa ń ṣàlàyé iṣẹ́ `redis` **ní gbogbo ìgbà** nínú `docker-compose.yml` (kò ní ìdènà profile kankan), ó sì máa ń bẹ̀rẹ̀ pẹ̀lú profile èyíkéyìí mìíràn. | Àlàyé | Iye | | ------------------- | ------------------------------------------- | | Image | `redis:7-alpine` | | Orúkọ container | `omniroute-redis` | | Port inú | `6379` | | Port host (àtúnṣe) | `REDIS_PORT` (àkọ́kọ́ rẹ̀ ni `6379`) | | Ìsopọ̀ host (àtúnṣe) | `REDIS_BIND_HOST` (àkọ́kọ́ rẹ̀ ni `127.0.0.1`) | | Volume | `omniroute-redis-data` → `/data` | | Àyẹ̀wò ìlera | `redis-cli ping` (àárín ìṣẹ́jú-àáyá 10) | Àwọn environment variable tó ní í ṣe pẹ̀lú rẹ̀: - `REDIS_URL` — connection string tí a fi sínú app náà (`redis://redis:6379` nípa àkọ́kọ́). - `REDIS_PORT` — ìtọ́ka port ní ẹ̀gbẹ́ host fún container Redis. - `REDIS_BIND_HOST` — interface host tí a tẹ port náà jáde sí. Àkọ́kọ́ rẹ̀ ni `127.0.0.1`. > **Ìdí tí loopback fi jẹ́ àkọ́kọ́:** sidecar náà ń ṣiṣẹ́ láìsí `requirepass`, àwọn > container app sì ń dé ọ̀dọ̀ rẹ̀ lórí compose network (`redis:6379`) — port tí a tẹ̀ jáde > wà fún àwọn irinṣẹ́ ẹ̀gbẹ́ host nìkan (`redis-cli`, `npm run dev` ti agbègbè). Títẹ̀ ẹ́ jáde lórí > `0.0.0.0` yóò fi Redis tí kò ní ìfàṣẹsí hàn sí gbogbo host lórí LAN rẹ. Tí o bá ṣètò > `REDIS_BIND_HOST=0.0.0.0`, tún fi `--requirepass` kun `command:` iṣẹ́ náà. A kò dámọ̀ràn **pípa Redis** (olùdínwọ̀n ìwọ̀n lílò yóò sọ̀kalẹ̀ sí àṣàyàn àfirọ́pò inú memory). Tí o bá ní láti ṣe bẹ́ẹ̀, yọ tàbí sọ block iṣẹ́ `redis:` di comment nínú `docker-compose.yml`, tàbí ṣe scale rẹ̀ sí òdo: ```bash docker compose up -d --scale redis=0 ``` ## Production Compose Fún snapshot production tí a yà sọ́tọ̀, tí yóò máa ṣiṣẹ́ lẹ́gbẹ̀ẹ́ dev, lo `docker-compose.prod.yml`. | Àlàyé | Iye | | -------------------- | ------------------------------------------------------------------------------------ | | Fáìlì | `docker-compose.prod.yml` | | Port dashboard àkọ́kọ́ | `PROD_DASHBOARD_PORT=20130` (tí a tọ́ka sí `${DASHBOARD_PORT:-20128}` inú) | | Port API àkọ́kọ́ | `PROD_API_PORT=20131` | | Image | `omniroute:prod` (tí a kọ láti target `runner-cli`) | | Container Redis | `omniroute-redis-prod` (`redis:8.6.2`, volume `redis-prod-data` àdáni) | | Volume data | `omniroute-prod-data` (tí a fún ní orúkọ, tí ó sì dúró láàárín àwọn àtúnkọ́) | | Àwọn àyẹ̀wò ìlera | `node healthcheck.mjs` + `redis-cli ping`, pẹ̀lú `depends_on` tí ìlera Redis ń ṣàkóso | Bí a ṣe ń lò ó: ```bash # Kọ́ stack production náà kí o sì bẹ̀rẹ̀ rẹ̀ docker compose -f docker-compose.prod.yml up -d --build # Ṣàn àwọn log docker compose -f docker-compose.prod.yml logs -f # Dá a dúró (pa àwọn volume mọ́) docker compose -f docker-compose.prod.yml down ``` Stack prod náà ń ṣiṣẹ́ ní ìṣọ̀kan pẹ̀lú compose dev (àwọn orúkọ container, port, àti volume wọn yàtọ̀), nítorí náà o lè máa bá ìmúdójúìwọ̀n agbègbè lọ nígbà tí production ṣì ń ṣiṣẹ́. ## Àwọn Ìpele Dockerfile Ibi ìpamọ́ náà ní Dockerfile onípele-púpọ̀ (`Dockerfile`). Ìpele mẹ́rin ni a ṣí sílẹ̀; yan `target` tó tọ́ fún ọ̀nà ìlò rẹ. | Ìpele | Àwòrán ìpìlẹ̀ | Ète | | ------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `builder` | `node:26-trixie-slim` | Ó ń fi àwọn ìgbẹ́kẹ̀lé sílẹ̀ (`npm ci --legacy-peer-deps`) ó sì ń ṣiṣẹ́ `npm run build` (Turbopack ni àìyẹsẹ̀ — wo Àwọn ohun àmúlò àkókò ìkọ́ ni ìsàlẹ̀) | | `runner-base` | `node:26-trixie-slim` | Àyíká ìṣiṣẹ́ ìmújáde pẹ̀lú àbájáde standalone Next.js. **Kò sí CLI olùpèsè kankan nínú rẹ̀.** | | `runner-cli` | `runner-base` | Ó ṣàfikún `git`, `docker.io`, `docker-compose` àti àwọn CLI àgbáyé: `@openai/codex`, `@anthropic-ai/claude-code`, `droid`, `openclaw`. **Yan èyí fún àwọn ìṣàn-iṣẹ́ aṣojú.** | | `runner-web` | `runner-base` | Ó ṣàfikún Playwright + aṣàwákiri Chromium (`--with-deps`) fún àwọn olùpèsè sáà wẹ́ẹ̀bù: `gemini-web`, `claude-web`, `claude-turnstile`. **Yan èyí nígbà tí o bá ń lo àwọn olùpèsè wọ̀nyẹn** — àwòrán lásán yóò kùnà ní àkókò ìbéèrè láìsí i (wo àkọsílẹ̀ `-web` lábẹ́ Àwọn Ikanni Ìtújáde). | Kọ́ target kan pàtó lọ́wọ́: ```bash docker build --target runner-base -t omniroute:base . docker build --target runner-cli -t omniroute:cli . docker build --target runner-web -t omniroute:web . ``` ### Àwọn ohun àmúlò àkókò ìkọ́ Àwọn build arg mẹ́ta ló ń ṣàkóso iye ohun àmúlò tí ìpele `builder` ń ná. Wọ́n jẹ́ ti àkókò ìkọ́ nìkan — `OMNIROUTE_MEMORY_MB` (ní ìsàlẹ̀) jẹ́ ìṣètò míì tí ó yàtọ̀ fún àkókò ìṣiṣẹ́. | Build arg | Àìyẹsẹ̀ | Ipa | | --------------------------- | ------ | --------------------------------------------------------------------------------------------------------------- | | `OMNIROUTE_USE_TURBOPACK` | `0` | `0` ń kọ́ pẹ̀lú webpack: ìrántí gíga jù lọ kéré sí i, ṣùgbọ́n ó lọra. `1` ń mú Turbopack ṣiṣẹ́. | | `OMNIROUTE_BUILD_MEMORY_MB` | `6144` | Ààlà òkè heap V8 (`--max-old-space-size`) fún `next build` tí a dá sílẹ̀. | | `OMNIROUTE_BUILD_WORKERS` | `2` | Ó ń fi iye ránṣẹ́ sí `CIRCLE_NODE_TOTAL`; Next ń yọ `workers = N - 1` jáde láti inú rẹ̀ fún ìkójọpọ̀ dátà ojú-ìwé. | `OMNIROUTE_BUILD_WORKERS` ni ohun tí o yẹ kí o pọ̀ sí i lórí builder ńlá, ó sì tún jẹ́ ohun tí o yẹ kí o fura sí nígbà tí ìkọ́ tó ní ààlà bá dáwọ́ dúró **lẹ́yìn** `✓ Compiled successfully`. Olúkúlùkù worker dátà ojú-ìwé jẹ́ process tirẹ̀, bẹ́ẹ̀ náà sì ni `next build` àkọ́kọ́ fúnra rẹ̀; àtúnṣe ìṣẹ̀lẹ̀ lórí VPS gidi kan (issue #7518) wọ́n RSS gíga jù lọ ti process kọ̀ọ̀kan sí ~4.5 GB láìka àmì heap `NODE_OPTIONS` sí (Turbopack ń ṣe ìṣàkójọ sínú ìrántí abinibi/Rust níta heap V8). Àìyẹsẹ̀ `2` (→ worker 1, process 2 lápapọ̀) ni a ṣe ìwọ̀n rẹ̀ fún àwọn runner tí GitHub ń gbàlejò tó ní 16 GB / 4 vCPU, èyí tí ìlànà ìtẹ̀jáde ń lò. Ní `8` (→ worker 7), ìrántí runner náà tán, buildkit sì mú ìgbésẹ̀ náà kùnà pẹ̀lú `ResourceExhausted: ... cannot allocate memory`; `3` (→ worker 2) kò tíì bá àyè mu lẹ́yìn tí a wọ́n RSS fún process kọ̀ọ̀kan taara dípò ṣíṣe àfojúsùn rẹ̀. `tests/unit/docker-build-memory-budget.test.ts` ń ṣe ìṣírò náà pẹ̀lú iye tí a wọ́n, ó sì ń kùnà bí èyíkéyìí lára àwọn ìṣètò méjèèjì bá ju agbára runner náà lọ. Turbopack ń ṣe ìṣàkójọ sínú ìrántí Rust abinibi tí ó wà **níta** heap V8, nítorí náà `OMNIROUTE_BUILD_MEMORY_MB` kò fi ààlà sí i. Lórí host tó ní ààlà ìrántí, OOM killer yóò fi SIGKILL pa ìkọ́ náà láìsí ọ̀rọ̀ àṣìṣe kankan — ó kàn dáwọ́ dúró láàárín `Creating an optimized production build`, èyí tó dà bí ẹni pé ó dì dípò pé ìrántí ti tán. Ìdí nìyẹn tí `Dockerfile` fi ń lo webpack gẹ́gẹ́ bí àìyẹsẹ̀ (`OMNIROUTE_USE_TURBOPACK=0`), kò dà bí `npm run dev` / `npm run build`, níbi tí Turbopack ti jẹ́ àìyẹsẹ̀ kóòdù: `docker build .` lásán láìsí build arg kankan (èyí tí Railway àti àwọn host onítẹ̀-kan míì ń ṣiṣẹ́) kò gbọdọ̀ dáwọ́ dúró ní ìdákẹ́jẹ lórí builder tó ní ààlà ìrántí. Àwọn àwòrán tí a tẹ̀jáde ti ń fi `OMNIROUTE_USE_TURBOPACK=0` ránṣẹ́ ní kedere nínú `docker-publish.yml`. Lórí builder tó ní RAM púpọ̀, mú Turbopack ṣiṣẹ́ fún ìkọ́ tó yára sí i: ```bash docker build --target runner-base \ --build-arg OMNIROUTE_USE_TURBOPACK=1 \ -t omniroute:base . ``` `webpackBuildWorker` ti ṣiṣẹ́, nítorí náà `next build` ń ṣiṣẹ́ process àkọ́kọ́ **àti** process worker kan, ọ̀kọ̀ọ̀kan sì ń tẹ̀lé `OMNIROUTE_BUILD_MEMORY_MB` lọ́tọ̀ọ̀tọ̀. Ṣètò ààlà container sí ohun tó ju ìlọ́po méjì iye náà lọ ní àfojúsùn, kì í ṣe ìgbà kan ṣoṣo. Àwọn ìwọ̀n lórí igi yìí (`--target runner-base`, `OMNIROUTE_BUILD_MEMORY_MB=6144`): | Bundler | Ààlà container | Àbájáde | | --------- | -------------- | ---------------------------------- | | Turbopack | 8 GiB / 16 GiB | OOM pa á ní méjèèjì, láìsí ìkìlọ̀ | | webpack | 8 GiB | SIGKILL pa build worker náà | | webpack | 12 GiB | ó ṣàṣeyọrí, ó ga jù lọ ní 11.1 GiB | ### Àwọn àìyẹsẹ̀ àkókò ìṣiṣẹ́ Àwọn àìyẹsẹ̀ tí `runner-base` ń ṣe export: `PORT=20128`, `HOSTNAME=0.0.0.0`, `OMNIROUTE_MEMORY_MB=1024`, `NODE_OPTIONS=--max-old-space-size=1024`, `DATA_DIR=/app/data`, `OMNIROUTE_MIGRATIONS_DIR=/app/migrations`. Ìhùwàsí ìrántí nínú Docker: - Àwòrán náà ṣètò `OMNIROUTE_MEMORY_MB=1024`, ó sì ṣe àgbéjáde `NODE_OPTIONS=--max-old-space-size=1024` láti inú rẹ̀. - Olùpilẹ̀ṣẹ̀ standalone ló ń bẹ̀rẹ̀ process server gangan; ó máa ń ka `OMNIROUTE_MEMORY_MB`, ó sì máa ń fi `--max-old-space-size=` kún un. - Node máa ń lo iye `--max-old-space-size` tí ó kẹ́yìn nínú àwọn iye tí a tún sọ, nítorí náà ṣíṣètò `OMNIROUTE_MEMORY_MB` ló ń ṣàkóso ààlà heap Docker tó ń ṣiṣẹ́ gangan. - Nítorí pé àwòrán náà máa ń ṣètò rẹ̀ ní gbogbo ìgbà, fallback tí olùpilẹ̀ṣẹ̀ fúnra rẹ̀ ṣètúnṣe gẹ́gẹ́ bí RAM kò lè ṣiṣẹ́ lábẹ́ Docker. Gbé iye rẹ̀ sókè ní tààrà fún workload náà (tábìlì ní ìsàlẹ̀). `2048` ṣì kéré jù fún `/v1/responses` ti aṣojú kóòdù. ### RAM àsìkò-ṣiṣe fún àwọn aṣojú kóòdù Àìpé Docker 1 GiB jẹ́ ìwọ̀n tó kéré jù fún dashboard/ìfọ̀rọ̀wérọ̀ fẹ́ẹ́rẹ́, kì í ṣe ìwọ̀n fún production. Àwọn body `POST /v1/responses` gígùn (ọgọ́rọ̀ọ̀rún messages, ọ̀pọ̀ mẹ́wàá tools) máa ń dá ọ̀pọ̀ graph inú-memory dúró nígbà compression. Àwọn request méjì tó ń ṣiṣẹ́ papọ̀, tí ọ̀kọ̀ọ̀kan jẹ́ ~3 MiB / ~750k-token, ti mú kí V8 dáwọ́ dúró ní old-space **12 GiB** (`FATAL ERROR: Reached heap limit`), wọ́n sì tún ti dé OOM cgroup 16 GiB. Wo [#7849](https://github.com/diegosouzapw/OmniRoute/issues/7849). Ṣètò **cgroup `--memory` sí iye tó ga ju heap lọ** — native buffers, SQLite, àti àwọn intermediate compression wà níta V8. | Workload | `OMNIROUTE_MEMORY_MB` | Container / cgroup | Àwọn àkíyèsí | | -------------------------------------- | ---------------------- | --------------------------- | ---------------------------------------------------------------------------------------------- | | Dashboard, ìfọ̀rọ̀wérọ̀ fẹ́ẹ́rẹ́ kan | `1024` (àìpé àwòrán) | ≥2 GiB | | | Aṣojú kóòdù kan (Claude/Codex/Grok) | `8192` | ≥10 GiB | `/v1/responses` session kan tí ó wọ́pọ̀ | | `/v1/responses` gígùn méjì lẹ́ẹ̀kan náà | `10240`–`12288` | ≥12–16 GiB | A díwọ̀n ìdádúró V8 ní heap ~12 GiB | | Àwọn context gígùn mẹ́ta tàbí jù bẹ́ẹ̀ lọ | má ṣe lórí process kan | ṣe lọ́kọ̀ọ̀kan / RAM púpọ̀ sí i | Àìpé admission heavyweight jẹ́ 1 in-flight; gbígbé e sókè láìsí RAM yóò tún mú ìdádúró náà padà | `omniroute serve` lórí bare metal máa ń ṣètúnṣe sí ~35% ti RAM (tí a fi ààlà `[512, 4096]` sí) nígbà tí a **kò bá ṣètò** `OMNIROUTE_MEMORY_MB`. Docker máa ń ṣètò `1024` ní gbogbo ìgbà, nítorí náà ìṣètúnṣe yẹn kì í ṣiṣẹ́ láélá nínú àwòrán official. ```bash docker run -d --name omniroute --restart unless-stopped --stop-timeout 40 \ -e OMNIROUTE_MEMORY_MB=8192 --memory=10g \ -p 127.0.0.1:20128:20128 -v omniroute-data:/app/data diegosouzapw/omniroute:latest ``` ## Àwọn Àyípadà Àyíká Pàtàkì Ní àfikún sí àwọn iye àìyípadà tí a ṣàkọsílẹ̀ sínú [ENVIRONMENT.md](../reference/ENVIRONMENT.md), àwọn àyípadà wọ̀nyí ṣe pàtàkì jù lọ nígbà tí a bá ń ṣiṣẹ́ lábẹ́ Docker: | Àyípadà | Ète | Iye àìyípadà | | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | | `OMNIROUTE_WS_BRIDGE_SECRET` | Àṣírí tí a pín fún afárá WebSocket. **Ó jẹ́ dandan ní production** — ṣètò rẹ̀ sí okùn aláìlétò tó lágbára. | kò tíì ṣètò (a gbọ́dọ̀ pèsè rẹ̀) | | `REDIS_URL` | Okùn ìsopọ̀ fún olùdínwọ̀n ìwọ̀n ìbéèrè / ibi ìpamọ́ cache | `redis://redis:6379` | | `REDIS_PORT` | Port ẹ̀gbẹ́ host fún container Redis tó wà nínú àkójọpọ̀ | `6379` | | `REDIS_BIND_HOST` | Interface host tí a tẹ̀jáde port Redis tó wà nínú àkójọpọ̀ sí (loopback àyàfi tí o bá fi AUTH kún un) | `127.0.0.1` | | `AUTO_UPDATE_HOST_REPO_DIR` | Path host tí a mount sínú profile `cli` ní `/workspace/omniroute` fún àwọn ìṣàn-iṣẹ́ ìmúdójúìwọ̀n ara-ẹni | `.` (directory lọ́wọ́lọ́wọ́) | | `OMNIROUTE_MEMORY_MB` | Òpin heap Node ní àkókò iṣẹ́ fún server Docker standalone; ó borí iye àìyípadà image tó wà lókè. Àwọn agent tó ń kọ code: `8192`+ (wo [RAM ní àkókò iṣẹ́](#runtime-ram-for-coding-agents)). | `1024` | | `DASHBOARD_PORT` / `API_PORT` | Borí àwọn port tí a ṣí síta fún dashboard (20128) àti API (20129) | `20128` / `20129` | | `APP_BIND_HOST` | Interface host tí docker-compose ń tẹ̀jáde dashboard/API/àwọn port live-WS sí. Pẹ̀lú `REQUIRE_API_KEY=false` (iye àìyípadà), `0.0.0.0` ń ṣí proxy `/v1` aláìlórúkọ sí LAN — mú un gbòòrò nìkan pẹ̀lú `REQUIRE_API_KEY=true` tàbí reverse proxy ní iwájú. | `127.0.0.1` | | `CLIPROXY_BIND_HOST` | Interface host tí docker-compose ń tẹ̀jáde sidecar `cliproxyapi` sí — data volume rẹ̀ ni àwọn ẹ̀rí ìdánimọ̀ provider wà. | `127.0.0.1` | | `OMNIROUTE_PLUGINS_DIR` | Directory tí scanner plugin ní àkókò iṣẹ́ ń kà, tí ó sì ń fi àwọn plugin sí. Ṣètò rẹ̀ nígbà tí a bá bind-mount àwọn plugin: iye àìyípadà ń tẹ̀lé `HOME`, èyí tí image kan lè má ṣe export. | `~/.omniroute/plugins` | | `OMNIROUTE_BASE_PATH` | Subpath URL nígbà tí a bá tẹ̀jáde app lẹ́yìn reverse proxy (fún àpẹẹrẹ, `/omniroute`) | _(òfo = root)_ | | `NEXT_PUBLIC_BASE_URL` | Origin browser gbogbogbò tó ní subpath nínú (fún àpẹẹrẹ, `https://host/omniroute`) | kò tíì ṣètò | | `PROD_DASHBOARD_PORT` | Port dashboard ẹ̀gbẹ́ host fún `docker-compose.prod.yml` | `20130` | | `CLIPROXYAPI_PORT` | Port ẹ̀gbẹ́ host fún sidecar `cliproxyapi` | `8317` | ## Aṣojú Ìyípadà lórí Ọ̀nà Abẹ́ (Traefik / nginx) Next.js `basePath` jẹ́ ohun tí a kó sínú àkójọpọ̀ standalone. OmniRoute máa ń ṣàkọsílẹ̀ iye tí a ti kó sínú rẹ̀ nínú fáìlì sentinel kan ní gbòǹgbò app náà (tí a kọ nígbà `npm run build`; tí `scripts/docker/ensure-docker-base-path.mjs` sì ń kà) ó sì máa ń fi wé `OMNIROUTE_BASE_PATH` nígbà tí container bá bẹ̀rẹ̀. Nígbà tí wọ́n bá yàtọ̀ tí image náà sì jẹ́ èyí tí a kọ́ fún gbòǹgbò domain, entrypoint máa ń tún àwọn manifest standalone kọ, àwọn iye `basePath`/`assetPrefix` tí a fi sínú rẹ̀ (Next 16 máa ń ṣe àfihàn àwọn URL asset SSR láti inú `assetPrefix` nìkan — patcher náà máa ń da ọ̀nà abẹ́ náà sínú rẹ̀ pẹ̀lú), àwọn URL asset `/_next/static` tí a ti kó sínú rẹ̀ (àwọn manifest client-reference, àwọn import media, àwọn ojú-ìwé àṣìṣe tí a ti prerender) àti shim `process.env` ti client kí `node dev/run-standalone.mjs` tó ṣiṣẹ́. ### Kíkọ́ pẹ̀lú Compose (a ṣe àbá rẹ̀) Ṣètò àwọn variable méjèèjì nínú `.env`, lẹ́yìn náà tún un kọ́ kí image àti runtime lè bára mu: ```bash # .env OMNIROUTE_BASE_PATH=/omniroute NEXT_PUBLIC_BASE_URL=https://myhostname.example.com/omniroute ``` ```bash docker compose --profile base up -d --build ``` `docker-compose.yml` máa ń fi `OMNIROUTE_BASE_PATH` ránṣẹ́ gẹ́gẹ́ bí Docker build-arg àti gẹ́gẹ́ bí variable environment runtime. ### Image gbòǹgbò tí a ti kọ́ tẹ́lẹ̀ + ọ̀nà abẹ́ runtime Àwọn image `diegosouzapw/omniroute:*` tí a tẹ̀ jáde ni a kọ́ fún gbòǹgbò domain. O ṣì lè ṣètò `OMNIROUTE_BASE_PATH` ní runtime; container náà máa ń patch àkójọpọ̀ náà lẹ́ẹ̀kan nígbà ìbẹ̀rẹ̀. So ó pọ̀ mọ́ origin gbangba tó bá a mu: ```yaml services: omniroute: image: diegosouzapw/omniroute:latest environment: OMNIROUTE_BASE_PATH: /omniroute NEXT_PUBLIC_BASE_URL: https://myhostname.example.com/omniroute ``` Ṣètò aṣojú ìyípadà náà láti fi ọ̀nà ìta **kíkún** ránṣẹ́ síwájú (má ṣe yọ prefix náà kúrò). Traefik gbọ́dọ̀ darí `PathPrefix(`/omniroute`)` sí container náà láìsí `StripPrefix`, kí Next.js lè gba `/omniroute/...` kí ó sì pèsè àwọn asset láti `/omniroute/_next/...`. Healthcheck Docker máa ń yẹ endpoint lifecycle `/healthz` tó fẹ́ẹ́rẹ́ wò, pẹ̀lú `OMNIROUTE_BASE_PATH` tó ń ṣiṣẹ́ gẹ́gẹ́ bí prefix. `/api/monitoring/health` ṣì wà fún àwọn àyẹ̀wò ìṣòro ènìyàn/dashboard; láti darí HEALTHCHECK container padà sí i (fún àpẹẹrẹ fún fífi ìlera jíjinlẹ̀ múlẹ̀), ṣètò `OMNIROUTE_HEALTHCHECK_PATH=/api/monitoring/health`. Ọ̀nà yẹn jẹ́ àyẹ̀wò **jíjinlẹ̀** (DB + àkótán monitoring) — ó yẹ fún `HEALTHCHECK` Docker tí kì í sábà ṣẹlẹ̀ bí o bá yàn láti tún lo ó, ṣùgbọ́n **kò** yẹ fún àwọn àárín àsìkò `livenessProbe` Kubernetes. Fún àwọn orchestrator (Kubernetes, Nomad, àti bẹ́ẹ̀ bẹ́ẹ̀ lọ): | Probe | Ohun tí a fẹ́ràn jù | Ohun tí a yẹra fún | | --------------- | --------------------------------------------------------------------- | -------------------------------------------- | | Liveness | HTTP `GET /livez`, tàbí TCP lórí port àkọ́kọ́ (`PORT`, àtẹ̀jáde `20128`) | `/api/monitoring/health` gẹ́gẹ́ bí liveness | | Readiness | HTTP `GET /healthz` | Timeout kúkúrú tó ka event-loop tó dí bí òkú | | Deep / blackbox | `/api/monitoring/health` | — | `/healthz` máa ń ṣàlàyé lifecycle process (`ok` / `starting` / `stopping`). `/livez` jẹ́ fún ṣíṣe àrídájú pé process wà láàyè nìkan (200 nígbà gbogbo tí handler bá lè ṣiṣẹ́; kò dúró de readiness). Àwọn méjèèjì ṣì ń ṣiṣẹ́ lórí event loop Node kan náà pẹ̀lú ìṣàkóso request, nítorí náà iṣẹ́ catalog tàbí compression tó di CPU mú lè mú wọn pẹ́ — dí ≠ kú. Yan TCP liveness bí àwọn probe HTTP bá ń timeout. Ìtọ́sọ́nà probe kíkún: [Ìtọ́sọ́nà monitoring — àwọn àbá probe Kubernetes](../ops/MONITORING_GUIDE.md#kubernetes-probe-recommendations). ## Docker Compose pẹ̀lú Caddy (HTTPS Auto-TLS) A lè ṣí OmniRoute síta láìléwu nípa lílo ìpèsè SSL aládàáṣiṣẹ́ ti Caddy. Rí i dájú pé àkọsílẹ̀ DNS A ti domain rẹ ń tọ́ka sí àdírẹ́sì IP olupèsè rẹ. ```yaml services: omniroute: image: diegosouzapw/omniroute:latest container_name: omniroute restart: unless-stopped volumes: - omniroute-data:/app/data environment: - PORT=20128 # Orísun tí aṣàwákiri ń rí fún àwọn ìpè-padà OAuth, àwọn ìjápọ̀ dashboard, àti àwọn URL gbogbogbò tí a ṣẹ̀dá. - NEXT_PUBLIC_BASE_URL=https://your-domain.com # URL inú láti olupèsè kan sí òmíràn fún àwọn iṣẹ́ tí a ṣètò / ìgbàjáde-sí-ara-ẹni. - BASE_URL=http://omniroute:20128 - AUTH_COOKIE_SECURE=true caddy: image: caddy:latest container_name: caddy restart: unless-stopped ports: - "80:80" - "443:443" command: caddy reverse-proxy --from https://your-domain.com --to http://omniroute:20128 volumes: omniroute-data: ``` Caddy ń ṣètò àwọn àkọlé ìfiranṣẹ́-àtẹ̀jáde boṣewa fún container òkè-odò náà. OmniRoute ń lo `NEXT_PUBLIC_BASE_URL` gẹ́gẹ́ bí orísun gbogbogbò àṣẹ fún àwọn ìpè-padà OAuth àti àwọn ìjápọ̀ gbogbogbò tí a ṣẹ̀dá; àwọn ìkọ̀wé dashboard tí a ti fìdí ìdánimọ̀ múlẹ̀ ń lo àwọn ìbéèrè orísun-kan-náà pẹ̀lú ààbò CSRF tí a so mọ́ session. Ṣe `OMNIROUTE_TRUST_PROXY` ṣiṣẹ́ fún àwọn ìmúṣiṣẹ́ onípele-gíga nìkan, níbi tí o ti mọ̀ọ́mọ̀ fẹ́ kí OmniRoute pinnu orísun gbogbogbò láti inú àwọn àkọlé ìfiranṣẹ́-àtẹ̀jáde tí a fọkàn tán dípò àtúnṣe tó ṣe kedere. ## Cloudflare Quick Tunnel Àtìlẹ́yìn dashboard fún àwọn ìmúṣiṣẹ́ Docker ní **Cloudflare Quick Tunnel** tí a lè ṣiṣẹ́ pẹ̀lú títẹ̀ ẹ̀ẹ̀kan ní `Dashboard → Endpoints`. Ṣíṣe é fún ìgbà àkọ́kọ́ yóò ṣe ìgbàsílẹ̀ `cloudflared` nígbà tí a bá nílò rẹ̀ nìkan, bẹ̀rẹ̀ tunnel ìgbà díẹ̀ sí endpoint `/v1` rẹ lọ́wọ́lọ́wọ́, yóò sì fi URL `https://*.trycloudflare.com/v1` tí a ṣẹ̀dá hàn ní tààrà lábẹ́ URL gbogbogbò rẹ déédéé. A lè fi àwọn paneli tunnel endpoint (Cloudflare, Tailscale, ngrok) hàn tàbí fi wọ́n pamọ́ láti `Settings → Appearance` láìyí ipò tunnel tó ń ṣiṣẹ́ padà. ### Àwọn Àkíyèsí Tunnel - Àwọn URL Quick Tunnel jẹ́ ti ìgbà díẹ̀, wọ́n sì máa ń yí padà lẹ́yìn gbogbo ìbẹ̀rẹ̀ tuntun. - A kì í dá àwọn Quick Tunnel padà láìfọwọ́yí lẹ́yìn ìbẹ̀rẹ̀ tuntun OmniRoute tàbí container. Ṣe wọ́n ṣiṣẹ́ lẹ́ẹ̀kan sí i láti dashboard nígbà tí a bá nílò wọn. - Ìfisórí tí a ń ṣàkóso ń ṣe àtìlẹ́yìn fún Linux, macOS, àti Windows lórí `x64` / `arm64` lọ́wọ́lọ́wọ́. - Àwọn Quick Tunnel tí a ń ṣàkóso máa ń lo ìgbékalẹ̀ HTTP/2 gẹ́gẹ́ bí àtúnṣe àkọ́kọ́ láti yẹra fún àwọn ìkìlọ̀ buffer QUIC UDP aláriwo nínú àwọn àyíká container tí a ní ààlà. Ṣètò `CLOUDFLARED_PROTOCOL=quic` tàbí `auto` bí o bá fẹ́ ìgbékalẹ̀ mìíràn. - Àwọn image Docker ní àwọn gbòǹgbò CA ètò nínú, wọ́n sì ń fi wọ́n ránṣẹ́ sí `cloudflared` tí a ń ṣàkóso, èyí tó ń dènà ìkùnà ìgbẹ́kẹ̀lé TLS nígbà tí tunnel bá ń bẹ̀rẹ̀ nínú container. - Ṣètò `CLOUDFLARED_BIN=/absolute/path/to/cloudflared` bí o bá fẹ́ kí OmniRoute lo binary tó ti wà tẹ́lẹ̀ dípò ṣíṣe ìgbàsílẹ̀ tuntun. ## Àwọn Tag Image | Image | Tag | Ìwọ̀n | Àpèjúwe | | ------------------------ | -------- | ------ | ------------------------------------------------------------------- | | `diegosouzapw/omniroute` | `latest` | ~250MB | SemVer adúróṣinṣin tó ga jù tí a ti **tẹ̀jáde** (kì í ṣe git `main`) | | `diegosouzapw/omniroute` | `3.8.0` | ~250MB | Di irú tag yìí mú fún GitOps | Manifest oní-platform-púpọ̀: `linux/amd64` + `linux/arm64` abínibí (Apple Silicon, AWS Graviton, Raspberry Pi). Docker máa ń yan architecture tó bá a mu láìfọwọ́yí; fi `--platform linux/amd64` ránṣẹ́ bí o bá nílò láti fipá mú ìfarawe AMD64 lórí àwọn host ARM. ### Àwọn Channel Ìtẹ̀jáde OmniRoute ń tẹ̀jáde àwọn channel Docker ọ̀tọ̀ọ̀tọ̀ fún àwọn ìtẹ̀jáde adúróṣinṣin, ìdánwò ẹ̀ka-ìtẹ̀jáde tó ń ṣiṣẹ́, àti àwọn build ìdàgbàsókè. | Channel | Orísun | Ṣíṣeé-yípadà | Ìlò tí a dámọ̀ràn | | ------------------------------- | ---------------------------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | | `:` / `:-web` | Ìtẹ̀jáde tí a fọwọ́sí/tí ó ní ẹ̀yà | Kò ṣeé yí padà | Àwọn ìmúṣiṣẹ́ production tí ó di ìtẹ̀jáde pàtó mú | | `:latest` / `:latest-web` | SemVer adúróṣinṣin tó ga jù tí a ti **tẹ̀jáde** | Atọ́ka adúróṣinṣin tó ṣeé yí padà | Ń tẹ̀lé àwọn ìtẹ̀jáde adúróṣinṣin **lẹ́yìn** iṣẹ́ ìtẹ̀jáde SemVer — kì í tọpinpin `main` tàbí àwọn commit `release/v*` tí a kò tíì tẹ̀jáde | | `:next` / `:next-web` | Ẹ̀ka `release/v*` àìyẹsẹ̀ lọ́wọ́lọ́wọ́ | Atọ́ka ṣáájú-ìtẹ̀jáde tó ṣeé yí padà | Ìdánwò àwọn àtúnṣe tí ó ti wọ ẹ̀ka ìtẹ̀jáde tó ń ṣiṣẹ́ ṣùgbọ́n tí kò tíì wà nínú ìtẹ̀jáde adúróṣinṣin | | `:main` / `:main-web` | Ẹ̀ka `main` | Atọ́ka ìdàgbàsókè tó ṣeé yí padà | Ìdàgbàsókè àti ìdánwò ìṣọ̀kan nìkan | #### Àwọn provider session-web: àwọn image `-web` Gbogbo channel tó wà lókè tún ní tag `-web` (`:latest-web`, `:-web`, `:next-web`, `:main-web`), tí a kọ́ láti stage `runner-web` — image kan náà pẹ̀lú Playwright àti aṣàwákiri Chromium. Image lasán wá **láìsí** Chromium; `gemini-web`, `claude-web` àti `claude-turnstile` nílò rẹ̀. Ìkùnà náà ni a sún síwájú, kì í ṣẹlẹ̀ nígbà ìbẹ̀rẹ̀: àwọn provider wọ̀nyẹn máa ń ṣe àkójọ àwọn model wọn, wọ́n sì máa ń hàn bí ẹni pé wọ́n sopọ̀ nínú dashboard, ìbéèrè àkọ́kọ́ nìkan ló sì máa kùnà pẹ̀lú ``` [500]: Failed to load external module playwright: Error: Cannot find module '/app/node_modules/playwright/node_modules/playwright-core/browsers.json' ``` Bí o bá ń lo àwọn provider wọ̀nyẹn, fa tag `-web` ti channel tí o ti ń lò — kò sí ohun mìíràn tó yí padà. Lórí ìfisórí npm/CLI (láìsí image Docker), apá tó sọnù tó bá a dọ́gba ni binary aṣàwákiri: ṣiṣẹ́ `npx playwright install chromium` lórí host náà. #### Lílo channel ṣáájú-ìtẹ̀jáde A máa tún ikanni `next` kọ́ ní gbogbo ìgbà tí a bá ṣe push sí ẹ̀ka `release/v*` àiyipada tó wà lọ́wọ́lọ́wọ́, a sì ń tẹ̀ ẹ́ jáde fún AMD64 àti ARM64. Àwọn ẹ̀ka ìtọ́jú àtijọ́ kò lè kọ lé e lórí. Ikanni náà ń pèsè image tí a lè pull fún àwọn àtúnṣe tí a ti merge sínú ẹ̀ka release tó ń ṣiṣẹ́, kí a tó dá tag stable tó kàn sílẹ̀. ```bash docker pull diegosouzapw/omniroute:next docker pull diegosouzapw/omniroute:next-web ``` Fún Docker Compose, rọ́pò tag image tí profile tí a yàn ń lò, lẹ́yìn náà pull kí o sì tún service náà ṣẹ̀dá: ```yaml services: omniroute: image: diegosouzapw/omniroute:next ``` ```bash docker compose pull docker compose up -d ``` #### Ààbò àti ìpadà-sẹ́yìn `next` jẹ́ ikanni pre-release tí kò dúró lórí ẹ̀yà kan. Ó lè yí padà ní gbogbo push sí ẹ̀ka release tó ń ṣiṣẹ́, àti pé **a kò ṣe àtìlẹ́yìn fún lílò rẹ̀ ní production**. Pin digest image náà nígbà tí o bá ń ṣe àyẹ̀wò build kan pàtó: ```bash docker pull diegosouzapw/omniroute:next docker image inspect diegosouzapw/omniroute:next --format '{{index .RepoDigests 0}}' ``` Kí o tó bẹ̀rẹ̀ ìdánwò, ṣe àdàkọ afẹ́yinti volume data OmniRoute tàbí directory data tí a fi bind mount. Láti padà sẹ́yìn, dá stable version tàbí digest tí a lò tẹ́lẹ̀ padà, kí o sì tún container náà ṣẹ̀dá: ```bash docker pull diegosouzapw/omniroute: docker compose up -d ``` Build láti ẹ̀ka release kò lè yí `latest` padà láé; stable semantic version tó péye nìkan ló lè gbé pointer stable náà ga. Àwọn image `next` ṣì ń lo àyẹ̀wò image release àti ẹnubodè tó ń dí ìpalára CRITICAL dúró. **`latest` kì í ṣe ìdánilójú pé git jẹ́ tuntun.** Àwọn àtúnṣe tí a merge sí `main` tàbí sí ẹ̀ka `release/v*` tó ń ṣiṣẹ́ kò sí nínú `:latest` títí di ìgbà tí a bá tẹ image SemVer stable kan jáde tí iṣẹ́ publish sì gbé `:latest` ga (digest kan náà pẹ̀lú SemVer yẹn). Bí `latest` bá dà bí ẹni pé kò yí padà nígbà tí GitHub ti ń fi àtúnṣe náà hàn, pull `:next` láti dán ẹ̀ka release náà wò tàbí dúró de tag SemVer. | Ohun tí o fẹ́ | Ohun tí o yẹ kí o lò | | --------------------------------------------------------------------- | ------------------------------------ | | GitOps / production tí kò gbọ́dọ̀ yí padà láìròtẹ́lẹ̀ | Pin `:X.Y.Z` (tàbí digest image náà) | | Tẹ̀lé àwọn stable tí a tẹ̀ jáde, kí o sì gba àtúnṣẹ̀dá ní release kọ̀ọ̀kan | `:latest` | | Dán àwọn commit `release/v*` tí a kò tíì tẹ̀ jáde wò | `:next` (kì í ṣe fún production) | | Dán `main` wò | `:main` (kì í ṣe fún production) | ## Àwọn ìmúdójúìwọ̀n Dashboard nínú Docker Container àwòrán tí a ti tẹ̀jáde kò lè rọ́pò ara rẹ̀. Nígbà tí OmniRoute bá ṣàwárí pé òun ń ṣiṣẹ́ nínú container kan (kò sí checkout `.git`, kì í ṣe ìfisórí npm), àsìá ìmúdójúìwọ̀n dashboard ojúlé yóò fi àṣẹ host tí a ó ṣiṣẹ́ hàn dípò àwọn ìtọ́ni npm/git, pẹ̀lú bọ́tìnì ìṣàdàkọ: ```bash docker compose pull omniroute && docker compose up -d --force-recreate omniroute ``` Orúkọ service náà wá láti `AUTO_UPDATE_SERVICE` (àkọ́kọ́bẹ̀rẹ̀ jẹ́ `omniroute`, service tó wà nínú `docker-compose.selfhost.yml`). `pull` kàn ń ṣí àmì tó ń yípadà (`latest`, `next`); pẹ̀lú àmì `:X.Y.Z` tí a ti dè mọ́ ẹ̀yà kan, kọ́kọ́ ṣàtúnṣe àmì náà. ### Àwọn ìmúdójúìwọ̀n ọlọ́kan-tẹ̀ pẹ̀lú fáìlì ìmúnṣiṣẹ́ host Láti jẹ́ kí **Ṣe Ìmúdójúìwọ̀n Báyìí** máa ṣiṣẹ́ láì gbe `/var/run/docker.sock` sókè (èyí tó ń fún container ní àṣẹ root lórí host — wo ìkìlọ̀ profile `cli` lókè), ṣètò `DOCKER_UPDATE_TRIGGER_FILE` lórí service OmniRoute kí o sì ṣiṣẹ́ olùṣọ́ kan lórí host: ```yaml services: omniroute: environment: DOCKER_UPDATE_TRIGGER_FILE: /app/data/update/docker-update.request volumes: - ./data:/app/data ``` Ọ̀nà náà gbọ́dọ̀ wà nínú `DATA_DIR` (àwọn iye ìbátan máa ń yanjú ní ìbámu pẹ̀lú rẹ̀); ohunkóhun mìíràn ni a ó kọ̀. **Ṣe Ìmúdójúìwọ̀n Báyìí** yóò kọ `{ "requestedAt": "...", "targetVersion": "X.Y.Z" }` sínú fáìlì náà, dáhùn pẹ̀lú `202`, dashboard náà yóò sì máa ṣàyẹ̀wò `/api/system/version` títí ẹ̀yà tuntun yóò fi bẹ̀rẹ̀ sí í ṣiṣẹ́, lẹ́yìn náà yóò tún kojú. OmniRoute kì í ṣiṣẹ́ shell tàbí àṣẹ Docker rárá ní ipò yìí. Gẹ́gẹ́ bí gbogbo ìgbésẹ̀ ìmúdójúìwọ̀n, àwọn client loopback/LAN nìkan ni a ti ń gba ìbéèrè náà lọ́wọ́ wọn. Ìtọ́kasí data tí a so mọ́ bind ń fún host ní ọ̀nà tó dúró ṣinṣin láti máa ṣọ́. Àwọn unit `systemd` àpẹẹrẹ (ṣàtúnṣe `/srv/omniroute` sí ìtọ́kasí tó ní fáìlì compose rẹ àti `data/`): ```ini # /etc/systemd/system/omniroute-update.path [Unit] Description=Ṣọ́ àwọn ìbéèrè ìmúdójúìwọ̀n dashboard OmniRoute [Path] PathExists=/srv/omniroute/data/update/docker-update.request [Install] WantedBy=multi-user.target ``` ```ini # /etc/systemd/system/omniroute-update.service [Unit] Description=Fa container OmniRoute kalẹ̀ kí o sì tún un ṣẹ̀dá [Service] Type=oneshot WorkingDirectory=/srv/omniroute ExecStartPre=/usr/bin/rm -f /srv/omniroute/data/update/docker-update.request ExecStart=/bin/sh -c 'docker compose pull omniroute || (sleep 15 && docker compose pull omniroute)' ExecStart=/usr/bin/docker compose up -d --force-recreate omniroute ``` ```bash sudo systemctl daemon-reload sudo systemctl enable --now omniroute-update.path ``` Service náà máa ń yọ ìbéèrè náà kúrò kí ó tó fa àwòrán náà kalẹ̀, kí ìṣiṣẹ́ tó kùnà má bà á lọ sínú ìyípo. Láìsí `DOCKER_UPDATE_TRIGGER_FILE`, dashboard náà yóò tẹ̀síwájú pẹ̀lú ìlànà àṣẹ ọwọ́. ## Wíwà-nílẹ̀: SQLite àkọ́kọ́bẹ̀rẹ̀ jẹ́ replica kan ṣoṣo OmniRoute Docker / Kubernetes àkọ́kọ́ ní **process Node kan + writer SQLite kan**. Wíwà-nílẹ̀ gíga **kò ní àtìlẹ́yìn** lórí topology yẹn. | Ìdíwọ́ | Àbájáde | | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Writer kan ṣoṣo | **Má ṣe** ṣiṣẹ́ ọ̀pọ̀ replica lórí fáìlì SQLite kan náà. Èyí máa ba DB náà jẹ́. | | Ìtúnṣẹ̀dá / ìtúnṣiṣẹ́ / pípa HEALTHCHECK | **Ìdádúró pátápátá** fún SSE tó ń lọ lọ́wọ́, àwọn session dashboard, àti state inú memory. Gbogbo client tó sopọ̀ yóò já. Àwọn ìbéèrè tuntun ní àkókò tí endpoint ṣófo yóò gba **`502 Bad Gateway: Unknown error`** láti ọ̀dọ̀ reverse-proxy, kì í ṣe JSON OmniRoute — àwọn client kò lè yà èyí sọ́tọ̀ kúrò nínú ìkùnà provider (#11015). | | Event loop kan náà bí `/healthz` | Catalog tó dí tàbí tick compression lè mú kí àwọn probe pẹ́; timeout kúkúrú yóò sì tún replica **kan ṣoṣo** náà bẹ̀rẹ̀. | **Matrix probe** (tún wo [àwọn àbá probe Kubernetes](../ops/MONITORING_GUIDE.md#kubernetes-probe-recommendations)): | Probe | Ohun àfojúsùn | Má ṣe lò ó fún | | --------------- | -------------------------------------------------------------- | -------------------------------------------------- | | Liveness | TCP lórí `PORT` (àkọ́kọ́bẹ̀rẹ̀ `20128`), tàbí HTTP rírọ̀ `/healthz` | `/api/monitoring/health` | | Readiness | HTTP `GET /healthz` | Àwọn timeout tó há tó ń ka event-loop tó dí sí òkú | | Ìjìnlẹ̀ / ènìyàn | `/api/monitoring/health` | Liveness kubelet aládàáṣiṣẹ́ | **Àwọn ìgbéga:** retí pé gbogbo session yóò já. Yọ àwọn client kúrò díẹ̀díẹ̀ bí o bá lè ṣe bẹ́ẹ̀; kò sí ìmúdójúìwọ̀n rolling lórí SQLite àkọ́kọ́bẹ̀rẹ̀. Compose `restart: unless-stopped` pẹ̀lú Docker `HEALTHCHECK` yóò tún rọ́pò process kan ṣoṣo náà nígbà tí container bá jẹ́ Unhealthy — agbègbè ìpalára kan náà. Àpẹẹrẹ kóòdù Kubernetes fún **replica kan ṣoṣo** (Recreate jẹ́ dandan; má ṣe gbé `replicas` ga lórí fáìlì SQLite kan): ```yaml spec: replicas: 1 strategy: type: Recreate template: spec: terminationGracePeriodSeconds: 90 containers: - name: omniroute lifecycle: preStop: exec: command: ["/bin/sleep", "15"] readinessProbe: httpGet: path: /healthz port: 20128 periodSeconds: 5 livenessProbe: tcpSocket: port: 20128 periodSeconds: 20 ``` Ìdádúró `preStop` ń jẹ́ kí kube yọ àwọn endpoint Service kúrò kí SIGTERM tó dé, kí ìrìnnà **tuntun** má bàa máa dé sí process tí ó ń dáwọ́ dúró. SSE `/v1/responses` tí ó ti ń ṣiṣẹ́ ni a máa ń jẹ́ kí ó parí fún àkókò tí kò ju `SHUTDOWN_TIMEOUT_MS` lọ (30s ní àìyípadà) nípasẹ̀ àwọn lease ìgbàwọlé heavyweight (#11015). Àwọn ìbéèrè tuntun tí ó ṣì dé sí process náà yóò gba `503` + `Retry-After: 5`. Àlàfo endpoint-òfo ti Recreate títí tí replacement yóò fi di Ready ṣì jẹ́ ìdádúró iṣẹ́ pátápátá — topology SQLite ni ìyẹn, kì í ṣe àṣìṣe ìṣètò probe. Postgres ti ita / HA multi-writer **kì í ṣe** ọ̀nà stock tí a ti ṣàkọsílẹ̀. Tí o bá nílò HA, lo replica kan ṣoṣo tàbí ṣiṣẹ́ topology kan tí project náà ti dán wò tí ó sì ti ṣàkọsílẹ̀ lọ́tọ̀. Iṣẹ́ Postgres/MySQL wà ní [#8075](https://github.com/diegosouzapw/OmniRoute/issues/8075). Títí tí ìyẹn yóò fi jáde, ọ̀nà kan ṣoṣo tí a ṣe àtìlẹ́yìn fún láti pọ̀ sí agbára `/v1/responses` **ńlá** ni àwọn process olómìnira N (abala tó kàn), kì í ṣe `replicas > 1` lórí volume kan. ## Ìfẹ̀síwájú ní ìwọ̀n: àwọn process olómìnira N Process Node kan jẹ́ **heap V8 kan**. Àwọn coding-agent `POST /v1/responses` méjì (RTK + Caveman) tí wọ́n bò ara wọn, tí ọ̀kọ̀ọ̀kan jẹ́ ~3 MiB / ~750k-token, máa ń dá heap náà dúró ní nǹkan bí ~12 Gi (`FATAL ERROR: Reached heap limit`) wọ́n sì lè fa OOM fún cgroup 16 Gi. Wo [#7849](https://github.com/diegosouzapw/OmniRoute/issues/7849). Ìwọ̀n yẹn jẹ́ ìkìlọ̀ nípa **ìpín ìrántí**, kì í ṣe òpin líle ti ọjà sí àwọn `/v1/responses` gígùn méjì tó ń ṣiṣẹ́ lẹ́ẹ̀kan náà. Gbigba chat tó wuwo ni a ń ṣàkóso nípasẹ̀ ìpín byte ingest tí a ń ṣe ìṣírò rẹ̀ fúnra rẹ̀ (`OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES`, `src/shared/middleware/admissionBudget.ts`), tí a ṣe ìwọ̀n rẹ̀ láti inú òpin V8/cgroup kan náà — fífi iye tó ga jù kọ ọ́ lórí (tàbí ṣíṣètò òpin iye request àtijọ́ `OMNIROUTE_CHAT_MAX_HEAVY_IN_FLIGHT`) lórí process tí a ti ṣe ìwọ̀n rẹ̀ dáadáa yóò tún fa ìdádúró náà. Àwọn chat kéékèèké, `/healthz`, `/v1/models`, àti MCP **kò** sí lábẹ́ òpin yẹn. ### Process kan: ju `/v1/responses` gígùn méjì lọ Process tó **ní ìlera** (heap tó wà ní ìsàlẹ̀ `OMNIROUTE_CHAT_ADMISSION_HEAP_SHED_RATIO`, àìyípadà rẹ̀ jẹ́ `0.75`) **lè** ṣiṣẹ́ pẹ̀lú àwọn `POST /v1/responses` gígùn tó ju méjì lọ lẹ́ẹ̀kan náà nígbà tí ààyè ṣì wà nínú ìpín inflight-byte fún gbogbo process (`OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES` / #10110). Àwọn body tó tó tàbí tó ju `OMNIROUTE_CHAT_LARGE_BODY_BYTES` (àìyípadà rẹ̀ jẹ́ 256 KiB) gba lease tó wuwo kan náà bí àwọn request tó ní structure púpọ̀, wọ́n sì ń lo ọ̀nà àbáyọ [#10437](https://github.com/diegosouzapw/OmniRoute/pull/10437) `tryAcquireHealthyHeadroom` kan náà (`OMNIROUTE_CHAT_ADMISSION_HEALTHY_HEADROOM`). Ọ̀pọ̀lọpọ̀ client SSE gígùn tó ń ṣiṣẹ́ lẹ́ẹ̀kan náà (àwọn olùdarí sábà máa ń nílò 40–50) jẹ́ ìbéèrè **ìpín ìrántí** — ṣe ìwọ̀n heap + àwọn slot primary/headroom + `OMNIROUTE_CHAT_MAX_INFLIGHT_BYTES` — kì í ṣe òpin líle “ó pọ̀ jù sí 2” ti ọjà. Heap tó wà lábẹ́ ìkìmọ́ ṣì máa ń dín ẹrù kù pẹ̀lú `503` tí a lè tún gbìyànjú, kí #7849 má bàa padà. Láti **sọ àwọn heap di púpọ̀** (àwọn old-space V8 olómìnira) **lónìí**: | Ṣe | Má ṣe | | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | | Ṣiṣẹ́ **container/pod N**, kí ọ̀kọ̀ọ̀kan ní `DATA_DIR` / volume **tirẹ̀** | Ṣètò `replicas > 1` fún file SQLite kan | | Ṣe ìwọ̀n heavy in-flight + healthy-headroom láti inú heap / ìpín inflight-byte; 1–2 ni àìyípadà oníṣọ́ra #7849, kì í ṣe òpin líle ti ọjà | Fún process kan ní RAM tó pọ̀ ní ìlọ́po 8 àti òpin iye tí kò ní ààlà | | Àṣàyàn: `QUOTA_STORE_DRIVER=redis` + `QUOTA_STORE_REDIS_URL` fún **àwọn counter quota tí a pín papọ̀** | Ka Redis sí SQLite tí a pín papọ̀ — kì í ṣe bẹ́ẹ̀ | | Ṣẹ̀dá àwọn secret provider sí ẹ̀dà inú instance kọ̀ọ̀kan (tàbí gba àwọn dashboard tí a pín sọ́tọ̀) | Retí dashboard kan / call-log kan láàárín àwọn instance | | Fi load balancer èyíkéyìí sí iwájú; sticky nípasẹ̀ API key tàbí session ti tó | Béèrè middleware size-aware tó jẹ́ ti vendor kan pàtó | Hardware: iye àwọn `/v1/responses` gígùn tó lè ṣiṣẹ́ lẹ́ẹ̀kan náà fún instance kọ̀ọ̀kan jẹ́ ìbéèrè **ìpín ìrántí** (heap + inflight-byte / #10110). Àwọn `DATA_DIR` olómìnira `N` ṣì ń sọ àwọn heap di púpọ̀: RAM host gbọ́dọ̀ lè gba `N × cgroup`, kì í ṣe “pod 16 Gi kan pẹ̀lú N=8.” Má ṣe lo `replicas > 1` lórí file SQLite kan láéláé. Àpẹẹrẹ Compose (heap méjì, volume méjì — kì í ṣe `deploy.replicas: 2`): ```yaml services: omniroute-a: image: diegosouzapw/omniroute:3.8.49 environment: DATA_DIR: /app/data OMNIROUTE_MEMORY_MB: "12288" QUOTA_STORE_DRIVER: redis QUOTA_STORE_REDIS_URL: redis://redis:6379 volumes: [omniroute-a-data:/app/data] ports: ["20128:20128"] omniroute-b: image: diegosouzapw/omniroute:3.8.49 environment: DATA_DIR: /app/data OMNIROUTE_MEMORY_MB: "12288" QUOTA_STORE_DRIVER: redis QUOTA_STORE_REDIS_URL: redis://redis:6379 volumes: [omniroute-b-data:/app/data] ports: ["20138:20128"] volumes: omniroute-a-data: omniroute-b-data: ``` Ìwọ̀n density inú process (compression kúrò lórí isolate HTTP) wà ní [#11023](https://github.com/diegosouzapw/OmniRoute/issues/11023). Cluster ọgbọ́n-orí kan lórí state pípẹ́ tí a pín papọ̀ wà ní [#8075](https://github.com/diegosouzapw/OmniRoute/issues/8075). ## Àwọn àṣìṣe ẹkùn Gemini nínú Docker Google AI Studio / Gemini API lè dá HTTP 400 padà pẹ̀lú FAILED_PRECONDITION àti `User location is not supported for the API use.` Ìbéèrè tó ṣàṣeyọrí lórí host kò fi hàn pé container náà ń lo ipa-ọ̀nà àbájáde kan náà. Bí DNS ṣe to àwọn àbájáde lẹ́sẹẹsẹ, àsopọ̀ IPv4/IPv6, ìtọ́sọ́nà VPN àti àwọn proxy tí a ti ṣètò lè yàtọ̀. Ṣàyẹ̀wò [àwọn ẹkùn tí Google ń ṣe àtìlẹ́yìn fún](https://ai.google.dev/gemini-api/docs/available-regions) pẹ̀lú ipa-ọ̀nà àsopọ̀ gangan; àṣìṣe yìí nìkan kò fi hàn pé API key náà kò dára. ### Yan proxy kan pàtó fún àsopọ̀ Lo [ètò proxy fún àsopọ̀ kọ̀ọ̀kan](../ops/PROXY_GUIDE.md#4-level-proxy-system) ti OmniRoute fún àsopọ̀ Gemini tí ọ̀ràn náà kàn, lẹ́yìn náà tún **Test Connection** àti ìbéèrè kékeré kan ṣe pẹ̀lú model kan náà. Èyí ń mú kí àyípadà ìtọ́sọ́nà náà mọ sí àsopọ̀ yẹn nìkan. Ṣàrídájú pé container lè dé ọ̀dọ̀ proxy náà, àti pé àsopọ̀ náà yan án ní ti gidi. Yíyí ipa-ọ̀nà padà kò ṣe ìdánilójú pé ẹkùn náà yẹ gẹ́gẹ́ bí upstream ṣe pinnu. ### Ṣe àfiwé nẹ́tíwọ́ọ̀kì host àti container Jẹ́ kí key, model àti ìbéèrè jẹ́ ọ̀kan náà nígbà tí o bá ń fi àwọn àbájáde tí a ti fìdí ìdánimọ̀ múlẹ̀ wéra; má ṣe fi credentials, ọ̀rọ̀ aṣínà proxy tàbí authorization headers kíkún sínú issue láé. Kọ́kọ́ ṣàyẹ̀wò àwọn address families tí OS resolver ń pèsè, nípa lílo command kan náà lórí host àti nínú container: ```bash node -e 'require("node:dns").lookup("generativelanguage.googleapis.com", {all: true}, (error, addresses) => { if (error) { console.error(error.code); process.exitCode = 1; return; } console.log(addresses.map(({family}) => family)); })' docker compose exec omniroute node -e 'require("node:dns").lookup("generativelanguage.googleapis.com", {all: true}, (error, addresses) => { if (error) { console.error(error.code); process.exitCode = 1; return; } console.log(addresses.map(({family}) => family)); })' ``` Rọ́pò `omniroute` pẹ̀lú service tí o ń ṣiṣẹ́ (fún àpẹẹrẹ, `omniroute-web`). Àwọn command wọ̀nyí máa ń tẹ address families jáde láìsí credentials tàbí IP addresses. `6` tí a dá padà fi àbájáde IPv6 DNS hàn nìkan: kò **fi ìdí rẹ̀ múlẹ̀** pé ipa-ọ̀nà IPv6 tó ṣeé lò tàbí ìráyè sí API wà. Níbi tí a ti fi `curl` sí, fi `curl -4 -I https://generativelanguage.googleapis.com` wé `curl -6 -I https://generativelanguage.googleapis.com` nínú àwọn àyíká méjèèjì. Ìdáhùn HTTP fi hàn pé àsopọ̀ wà fún ìdánwò yẹn, kódà bí ó bá jẹ́ àṣìṣe tí a kò fi ìdánimọ̀ múlẹ̀; ìbéèrè model tí a fi ìdánimọ̀ múlẹ̀ nìkan ló ń dán ìyẹ̀ Gemini wò. ### Àṣàyàn ìpele host: IPv6 tó ń ṣiṣẹ́ àti ìlànà resolver Ẹni tó jabo [#12762](https://github.com/diegosouzapw/OmniRoute/issues/12762) mú ìráyè padà bọ̀ sípò nínú àyíká wọn nípa ṣíṣe IPv6 container ṣiṣẹ́ àti yíyí bí glibc ṣe ń yan address padà. Ka èyí sí àṣàyàn tó jẹ́ pàtó fún àyíká náà. Ṣàrídájú IPv6 host tó ń ṣiṣẹ́, àbájáde/ìtọ́sọ́nà container àti àwọn òfin firewall kí o tó ṣàtúnṣe àwọn ààyò resolver. Address ULA aládání kan nìkan kò fi ìdí àsopọ̀ IPv6 gbogbogbò múlẹ̀. Fún àwọn service tí a ti so mọ́ default network ti Compose tẹ́lẹ̀, àjákù yìí ń mú IPv6 ṣiṣẹ́ lórí network náà; pa ìyókù service, ports, volumes àti configuration rẹ mọ́: ```yaml networks: default: enable_ipv6: true ``` Fún named network, mú un ṣiṣẹ́ lórí network tí service náà darapọ̀ mọ́ ní ti gidi. Docker lè pín subnet ULA kan; yan subnet tó ṣe kedere, tí kò sì ní àgbélébùú pẹ̀lú òmíràn nígbà tí network rẹ bá nílò rẹ̀ nìkan. Wo [Docker IPv6 networking](https://docs.docker.com/engine/daemon/ipv6/) àti [Compose network options](https://docs.docker.com/reference/compose-file/networks/#enable_ipv6). Lórí **image tó dá lórí glibc**, `/etc/gai.conf` lè yí bí a ṣe ń yan address padà. Dockerfile repository lọ́wọ́lọ́wọ́ ń lo Debian; àwọn image àkànṣe tó dá lórí musl kò lo ọ̀nà yìí. Àtúnṣe tí a jabo yí label ULA padà láti `label fc00::/7 6` sí `label fc00::/7 1`. Bẹ̀rẹ̀ láti policy table kíkún ti image náà, kí o sì pa àwọn entry rẹ̀ yòókù mọ́: fífi entry `label` tàbí `precedence` kún un máa rọ́pò default table yẹn, nítorí náà file tó ní ìlà tí a yí padà nìkan kò tó. [Àkọsílẹ̀ ìtọ́kasí configuration glibc](https://github.com/bminor/glibc/blob/master/posix/gai.conf) ṣàlàyé àwọn ìlànà wọ̀nyẹn. Ṣe bind-mount file tí a ti ṣàyẹ̀wò gẹ́gẹ́ bí read-only sí `/etc/gai.conf` kí o sì tún service náà dá láti fi àyípadà náà sílò. Èyí ń yí bí OS ṣe ń yan address padà fún **gbogbo outbound traffic nínú container yẹn**. Kò fipá mú gbogbo application láti yan IPv6: bí Node ṣe to DNS lẹ́sẹẹsẹ àti bí ó ṣe ń yan àsopọ̀ tún ṣe pàtàkì. Ní pàtàkì, `--dns-result-order=ipv4first` fẹ́ràn IPv4 jù kò sì jẹ́ ojútùú fún ìkùnà IPv4-nìkan. Wo [Node DNS ordering](https://nodejs.org/api/dns.html#dnssetdefaultresultorderorder). Tún Gemini àti àwọn provider rẹ yòókù dán wò lẹ́yìn àyípadà èyíkéyìí ní ìpele host. Láti yí padà sí ti tẹ́lẹ̀, yọ mount `gai.conf` àkànṣe náà kúrò, dá network configuration ti tẹ́lẹ̀ padà, kí o sì tún service/network tí ọ̀ràn náà kàn dá ní àkókò maintenance window. Títún network kan dá lè dá iṣẹ́ àwọn container mìíràn tí a so mọ́ ọn dúró; má ṣe pa persistent data volume rẹ́. ## Àwọn Àkíyèsí Pàtàkì - **Ipo WAL SQLite:** Ó yẹ kí a jẹ́ kí `docker stop` parí kí OmniRoute lè ṣe checkpoint àwọn ìyípadà tuntun padà sínú `storage.sqlite`. Àwọn fáìlì Compose tí a ṣàkójọpọ̀ mọ́ ọn ti ṣètò àkókò ìdádúró-ọ̀fẹ́ sí 40s tẹ́lẹ̀. Tí o bá ń ṣiṣẹ́ image náà ní tààrà, fi `--stop-timeout 40` sílẹ̀. - **`DISABLE_SQLITE_AUTO_BACKUP`:** Ṣètò rẹ̀ sí `true` tí a bá ń ṣàkóso àwọn backup àkókò-dé-àkókò/kíkọ-ṣáájú níta. Àwọn migration fún database tó ti wà ṣì nílò snapshot ààbò tó lágbára tiwọn àti guard fún mass-migration. - **Ìtọ́jú Data:** Máa mount volume sí `/app/data` nígbà gbogbo láti tọ́jú database, àwọn key, àti àwọn configuration rẹ ní gbogbo ìgbà tí container bá tún bẹ̀rẹ̀. - **Ìṣètò Port:** Ṣàtúnṣe environment variable `PORT` láti yí port àiyipada `20128` padà. ## Tún Wo - [Ìtọ́sọ́nà Deployment VM](../ops/VM_DEPLOYMENT_GUIDE.md) — Ìṣètò VM + nginx + Cloudflare - [Ìtọ́sọ́nà Deployment Fly.io](../ops/FLY_IO_DEPLOYMENT_GUIDE.md) — Ṣe deployment sí Fly.io - [Config Environment](../reference/ENVIRONMENT.md) — Àlàyé `.env` tó péye