From 82966f901836ebb2ad71b739d785befd5532aff1 Mon Sep 17 00:00:00 2001 From: Anish Pallati Date: Tue, 29 Sep 2026 19:25:04 -0400 Subject: [PATCH 1/2] cliproxyapi: 7.3.10 -> 8.0.4 Signed-off-by: Anish Pallati --- pkgs/by-name/cl/cliproxyapi/package.nix | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/cl/cliproxyapi/package.nix b/pkgs/by-name/cl/cliproxyapi/package.nix index 790762b44404..9f77e1d22ca6 100644 --- a/pkgs/by-name/cl/cliproxyapi/package.nix +++ b/pkgs/by-name/cl/cliproxyapi/package.nix @@ -3,6 +3,7 @@ buildGoModule, fetchFromGitHub, nix-update-script, + nixosTests, versionCheckHook, }: @@ -10,13 +11,13 @@ buildGoModule (finalAttrs: { __structuredAttrs = true; pname = "cliproxyapi"; - version = "7.3.10"; + version = "8.0.4"; src = fetchFromGitHub { owner = "router-for-me"; repo = "CLIProxyAPI"; tag = "v${finalAttrs.version}"; - hash = "sha256-pKguqvvQA1IVIE4f3qQbZ8VOWEcY4evkyacyYt36+T8="; + hash = "sha256-CQ4kjO8XaGdVGFkO9MvbPMO9PrO3sTKCN706mbzOj9g="; }; vendorHash = "sha256-r3yWkdMcM40G9jV7MxW/qNv3E9WrHavFilW24quEf+8="; @@ -39,7 +40,10 @@ buildGoModule (finalAttrs: { versionCheckProgramArg = "--version"; doInstallCheck = true; - passthru.updateScript = nix-update-script { }; + passthru = { + tests = { inherit (nixosTests) cliproxyapi; }; + updateScript = nix-update-script { }; + }; meta = { description = "Proxy that provides OpenAI/Gemini/Claude/Codex/Grok compatible API interfaces"; From 2deb6bc2cf18e38ac61dfe96597f17c91a840a59 Mon Sep 17 00:00:00 2001 From: Anish Pallati Date: Tue, 29 Sep 2026 19:25:05 -0400 Subject: [PATCH 2/2] nixos/cliproxyapi: use v8 config layout Signed-off-by: Anish Pallati --- nixos/modules/services/misc/cliproxyapi.md | 30 ++++++++++++----- nixos/modules/services/misc/cliproxyapi.nix | 37 +++++++++++++-------- nixos/tests/cliproxyapi.nix | 8 +++-- 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/nixos/modules/services/misc/cliproxyapi.md b/nixos/modules/services/misc/cliproxyapi.md index 399e43f9ff49..dee7b7d32bc2 100644 --- a/nixos/modules/services/misc/cliproxyapi.md +++ b/nixos/modules/services/misc/cliproxyapi.md @@ -1,6 +1,6 @@ # CLIProxyAPI {#module-services-cliproxyapi} -[CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI) exposes OAuth-based subscription CLIs (Claude Code, Codex, Gemini, Qwen, Grok, Antigravity) behind OpenAI/Gemini/Anthropic-compatible HTTP APIs. +[CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI) exposes OAuth-based subscription CLIs (Claude Code, Codex, Grok, Antigravity, Kimi, Devin, Meta) behind OpenAI/Gemini/Anthropic-compatible HTTP APIs. Enable it with: @@ -10,11 +10,11 @@ Enable it with: } ``` -The service runs as a dedicated `cliproxyapi` user and keeps its configuration and OAuth tokens under `/var/lib/cliproxyapi`. +The service runs as a dedicated `cliproxyapi` user and keeps its configuration and OAuth tokens under `/var/lib/cliproxyapi`. The configuration file is regenerated from [](#opt-services.cliproxyapi.settings) at startup, which overwrites any changes made through the management API. ## Authentication {#module-services-cliproxyapi-authentication} -Provider logins use OAuth and must land in the service's `auth-dir` (`/var/lib/cliproxyapi`), which is owned by the `cliproxyapi` user. Either of the approaches below writes the token with the correct ownership, and the running service picks it up without a restart. +Provider logins use OAuth and must land in the service's `oauth.auth-dir` (`/var/lib/cliproxyapi`), which is owned by the `cliproxyapi` user. Either of the approaches below writes the token with the correct ownership, and the running service picks it up without a restart. ### Management API {#module-services-cliproxyapi-authentication-management-api} @@ -22,19 +22,31 @@ Set a management key in [](#opt-services.cliproxyapi.settings): ```nix { - services.cliproxyapi.settings.remote-management.secret-key._secret = - "/run/secrets/cliproxyapi-mgmt-key"; + services.cliproxyapi.settings.management.secret-key._secret = "/run/secrets/cliproxyapi-mgmt-key"; } ``` -Then request an authentication URL for the desired provider and open it in a browser: +Request a login URL and open it in a browser: ```bash curl -H "Authorization: Bearer " \ - http://127.0.0.1:8317/v0/management/anthropic-auth-url + "http://127.0.0.1:8317/v8/management/oauth/auth-url?provider=claude" ``` -The daemon completes the OAuth flow itself and stores the token in its `auth-dir`. Authentication endpoints are available for the `anthropic`, `codex`, `xai`, `antigravity`, and `kimi` providers. +Other values for `provider` are `codex`, `antigravity`, `kimi`, `kimi-ai`, `xai`, `devin` and `meta`. `kimi`, `kimi-ai`, `xai` and `meta` use a device code, so the login finishes once it is approved in the browser. + +For `claude`, `codex` and `antigravity`, the browser ends up on a `localhost` page that fails to load. Send that URL to the daemon to finish the login: + +```bash +curl -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{"redirect_url": ""}' \ + http://127.0.0.1:8317/v8/management/oauth/callback +``` + +Alternatively, add `is_webui=true` to the login URL request, and the daemon will listen on the callback port and finish the login itself. + +To check on a login, query `/v8/management/oauth/status?state=` with the `state` from the login URL response. It returns `wait` while the login is pending, `ok` once the token is saved and `error` if it failed. ### Command-line login {#module-services-cliproxyapi-authentication-cli} @@ -52,4 +64,4 @@ Then run the login as the service user, pointing at the managed configuration: sudo -u cliproxyapi cliproxyapi -config /var/lib/cliproxyapi/config.yaml --claude-login ``` -Other providers use their matching flags, for example `--codex-login` or `--xai-login`. On a headless host, pass `-no-browser` to print the OAuth URL instead of launching a browser. +Other providers have their own flags, such as `--codex-login` or `--xai-login`; see `cliproxyapi -help`. On a headless host, add `-no-browser` to print the login URL. The Claude, Codex, Antigravity and Devin logins then ask you to paste the `localhost` URL you were redirected to. diff --git a/nixos/modules/services/misc/cliproxyapi.nix b/nixos/modules/services/misc/cliproxyapi.nix index 8532d9aabc4d..70f6f26fea99 100644 --- a/nixos/modules/services/misc/cliproxyapi.nix +++ b/nixos/modules/services/misc/cliproxyapi.nix @@ -10,14 +10,9 @@ let format = pkgs.formats.yaml { }; stateDir = "/var/lib/cliproxyapi"; configPath = "${stateDir}/config.yaml"; - settings = { - auth-dir = stateDir; - } - // cfg.settings; secretsReplacement = utils.genJqSecretsReplacement { loadCredential = true; - } settings configPath; - port = cfg.settings.port or 8317; + } cfg.settings configPath; in { options.services.cliproxyapi = { @@ -26,14 +21,30 @@ in package = lib.mkPackageOption pkgs "cliproxyapi" { }; settings = lib.mkOption { - type = format.type; + type = lib.types.submodule { + freeformType = format.type; + options = { + server.port = lib.mkOption { + type = lib.types.port; + default = 8317; + description = "Port on which CLIProxyAPI listens."; + }; + oauth.auth-dir = lib.mkOption { + type = lib.types.str; + default = stateDir; + description = "Directory where OAuth tokens are stored."; + }; + }; + }; default = { }; example = lib.literalExpression '' { - host = "127.0.0.1"; - port = 8317; - api-keys = [ { _secret = "/run/secrets/cliproxyapi-api-key"; } ]; - remote-management.secret-key._secret = "/run/secrets/cliproxyapi-management-key"; + server = { + host = "127.0.0.1"; + port = 8317; + }; + access.api-keys = [ { _secret = "/run/secrets/cliproxyapi-api-key"; } ]; + management.secret-key._secret = "/run/secrets/cliproxyapi-management-key"; } ''; description = '' @@ -54,7 +65,7 @@ in openFirewall = lib.mkOption { type = lib.types.bool; default = false; - description = "Whether to open the firewall for the specified port."; + description = "Whether to open the firewall for {option}`services.cliproxyapi.settings.server.port`."; }; user = lib.mkOption { @@ -142,7 +153,7 @@ in }; networking.firewall = lib.mkIf cfg.openFirewall { - allowedTCPPorts = [ port ]; + allowedTCPPorts = [ cfg.settings.server.port ]; }; }; diff --git a/nixos/tests/cliproxyapi.nix b/nixos/tests/cliproxyapi.nix index 87076fb915c0..606d2c9a78de 100644 --- a/nixos/tests/cliproxyapi.nix +++ b/nixos/tests/cliproxyapi.nix @@ -10,9 +10,11 @@ services.cliproxyapi = { enable = true; settings = { - host = "127.0.0.1"; - port = 8317; - api-keys = [ { _secret = "/etc/cliproxyapi-api-key"; } ]; + server = { + host = "127.0.0.1"; + port = 8317; + }; + access.api-keys = [ { _secret = "/etc/cliproxyapi-api-key"; } ]; }; };