cliproxyapi: 7.3.10 -> 8.0.4 (#568429)

This commit is contained in:
Sandro
2026-09-30 11:17:38 +00:00
committed by GitHub
4 changed files with 57 additions and 28 deletions

View File

@@ -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 <management-key>" \
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 <management-key>" \
-H "Content-Type: application/json" \
-d '{"redirect_url": "<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=<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.

View File

@@ -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 ];
};
};

View File

@@ -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"; } ];
};
};

View File

@@ -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";