From 74a9e5c26cf2af1fc64073bc2caf53e87043699f Mon Sep 17 00:00:00 2001 From: MrLYC Date: Fri, 16 Jan 2026 01:26:13 +0800 Subject: [PATCH 1/5] feat: add Bearer token authentication support - Add --api-key command line option to enable authentication - Create auth middleware for Bearer token validation - Apply authentication to all API endpoints - Maintain backward compatibility when no API key is provided --- src/lib/auth-middleware.ts | 28 ++++++++++++++++++++++++++++ src/lib/state.ts | 3 +++ src/server.ts | 2 ++ src/start.ts | 8 ++++++++ 4 files changed, 41 insertions(+) create mode 100644 src/lib/auth-middleware.ts diff --git a/src/lib/auth-middleware.ts b/src/lib/auth-middleware.ts new file mode 100644 index 000000000..a21af5e86 --- /dev/null +++ b/src/lib/auth-middleware.ts @@ -0,0 +1,28 @@ +import type { Context, Next } from "hono" + +import { state } from "./state" + +export async function authMiddleware( + c: Context, + next: Next, +): Promise { + if (!state.apiKey) { + await next() + return c.res + } + + const authHeader = c.req.header("Authorization") + + if (!authHeader) { + return c.json({ error: "Missing Authorization header" }, 401) + } + + const token = authHeader.replace(/^Bearer\s+/i, "") + + if (token !== state.apiKey) { + return c.json({ error: "Invalid API key" }, 401) + } + + await next() + return c.res +} diff --git a/src/lib/state.ts b/src/lib/state.ts index 5ba4dc1d1..23db928b5 100644 --- a/src/lib/state.ts +++ b/src/lib/state.ts @@ -15,6 +15,9 @@ export interface State { // Rate limiting configuration rateLimitSeconds?: number lastRequestTimestamp?: number + + // API key for authentication + apiKey?: string } export const state: State = { diff --git a/src/server.ts b/src/server.ts index 462a278f3..744ddc7b2 100644 --- a/src/server.ts +++ b/src/server.ts @@ -2,6 +2,7 @@ import { Hono } from "hono" import { cors } from "hono/cors" import { logger } from "hono/logger" +import { authMiddleware } from "./lib/auth-middleware" import { completionRoutes } from "./routes/chat-completions/route" import { embeddingRoutes } from "./routes/embeddings/route" import { messageRoutes } from "./routes/messages/route" @@ -13,6 +14,7 @@ export const server = new Hono() server.use(logger()) server.use(cors()) +server.use(authMiddleware) server.get("/", (c) => c.text("Server running")) diff --git a/src/start.ts b/src/start.ts index 14abbbdff..50d05f9fc 100644 --- a/src/start.ts +++ b/src/start.ts @@ -25,6 +25,7 @@ interface RunServerOptions { claudeCode: boolean showToken: boolean proxyEnv: boolean + apiKey?: string } export async function runServer(options: RunServerOptions): Promise { @@ -46,6 +47,7 @@ export async function runServer(options: RunServerOptions): Promise { state.rateLimitSeconds = options.rateLimit state.rateLimitWait = options.rateLimitWait state.showToken = options.showToken + state.apiKey = options.apiKey await ensurePaths() await cacheVSCodeVersion() @@ -184,6 +186,11 @@ export const start = defineCommand({ default: false, description: "Initialize proxy from environment variables", }, + "api-key": { + alias: "k", + type: "string", + description: "API key for Bearer token authentication", + }, }, run({ args }) { const rateLimitRaw = args["rate-limit"] @@ -202,6 +209,7 @@ export const start = defineCommand({ claudeCode: args["claude-code"], showToken: args["show-token"], proxyEnv: args["proxy-env"], + apiKey: args["api-key"], }) }, }) From 9292ebbcd8fd0ba76d52c309db9609c4fc8c03ad Mon Sep 17 00:00:00 2001 From: MrLYC Date: Sun, 1 Feb 2026 14:22:46 +0800 Subject: [PATCH 2/5] feat: add API key support and Docker Hub CI - Add API_KEY environment variable support in entrypoint.sh - Add --api-key option documentation in README - Update release-docker.yml to push to Docker Hub - Add latest tag for main branch builds - Add pre-built image usage instructions Amp-Thread-ID: https://ampcode.com/threads/T-019c17d4-16ea-744f-9a9b-41a93568c802 Co-authored-by: Amp --- .github/workflows/release-docker.yml | 21 ++++++------ README.md | 51 +++++++++++++++++++++++++++- entrypoint.sh | 15 ++++++-- 3 files changed, 74 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release-docker.yml b/.github/workflows/release-docker.yml index 97b124ba1..3ad5a02cd 100644 --- a/.github/workflows/release-docker.yml +++ b/.github/workflows/release-docker.yml @@ -7,17 +7,16 @@ name: Docker Build and Push on: push: - # branches: [ "main" ] - # Publish semver tags as releases. + branches: [ "main" ] tags: [ 'v*.*.*' ] paths-ignore: - 'docs/**' + - '*.md' + - 'pages/**' env: - # Use docker.io for Docker Hub if empty - REGISTRY: ghcr.io - # github.repository as / - #IMAGE_NAME: ${{ github.repository }} + REGISTRY: docker.io + IMAGE_NAME: mrlyc/copilot-api jobs: @@ -56,13 +55,13 @@ jobs: # Login against a Docker registry except on PR # https://github.com/docker/login-action - - name: Log into registry ${{ env.REGISTRY }} + - name: Log into Docker Hub if: github.event_name != 'pull_request' uses: docker/login-action@v2 with: registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} # Extract metadata (tags, labels) for Docker # https://github.com/docker/metadata-action @@ -71,11 +70,13 @@ jobs: uses: docker/metadata-action@v4 with: github-token: ${{ secrets.GITHUB_TOKEN }} - images: ${{ env.REGISTRY }}/${{ github.repository }} + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | + type=raw,value=latest,enable={{is_default_branch}} type=semver,pattern=v{{version}} type=semver,pattern=v{{major}}.{{minor}} type=semver,pattern=v{{major}} + type=sha,prefix= # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action diff --git a/README.md b/README.md index 0d36c13c9..82d17c868 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,29 @@ bun install ## Using with Docker -Build image +### Using Pre-built Image + +You can use the pre-built Docker image from Docker Hub: + +```sh +# Pull the latest image +docker pull mrlyc/copilot-api:latest + +# Run the container +docker run -p 4141:4141 -v $(pwd)/copilot-data:/root/.local/share/copilot-api mrlyc/copilot-api:latest + +# Run with environment variables +docker run -p 4141:4141 -e GH_TOKEN=your_token -e API_KEY=your_secret_key mrlyc/copilot-api:latest +``` + +Available tags: +- `latest` - Latest build from main branch +- `v0.7.0` - Specific version +- `v0.7` - Latest patch of v0.7.x +- `v0` - Latest minor/patch of v0.x.x +- `` - Specific commit + +### Building from Source ```sh docker build -t copilot-api . @@ -91,6 +113,9 @@ docker build --build-arg GH_TOKEN=your_github_token_here -t copilot-api . # Run with GitHub token docker run -p 4141:4141 -e GH_TOKEN=your_github_token_here copilot-api +# Run with API key for authentication (requires Bearer token in requests) +docker run -p 4141:4141 -e GH_TOKEN=your_token -e API_KEY=your_secret_key copilot-api + # Run with additional options docker run -p 4141:4141 -e GH_TOKEN=your_token copilot-api start --verbose --port 4141 ``` @@ -106,6 +131,7 @@ services: - "4141:4141" environment: - GH_TOKEN=your_github_token_here + - API_KEY=your_secret_api_key # Optional: enables Bearer token authentication restart: unless-stopped ``` @@ -163,6 +189,7 @@ The following command line options are available for the `start` command: | --claude-code | Generate a command to launch Claude Code with Copilot API config | false | -c | | --show-token | Show GitHub and Copilot tokens on fetch and refresh | false | none | | --proxy-env | Initialize proxy from environment variables | false | none | +| --api-key | API key for Bearer token authentication | none | -k | ### Auth Command Options @@ -255,6 +282,28 @@ npx copilot-api@latest debug --json # Initialize proxy from environment variables (HTTP_PROXY, HTTPS_PROXY, etc.) npx copilot-api@latest start --proxy-env + +# Enable API key authentication (clients must send Bearer token) +npx copilot-api@latest start --api-key your_secret_key +``` + +## API Key Authentication + +You can secure your Copilot API proxy with Bearer token authentication using the `--api-key` option (or `API_KEY` environment variable in Docker). + +When enabled, all API requests must include an `Authorization` header: + +``` +Authorization: Bearer your_secret_key +``` + +Example with curl: + +```sh +curl -X POST http://localhost:4141/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer your_secret_key" \ + -d '{"model": "gpt-4.1", "messages": [{"role": "user", "content": "Hello"}]}' ``` ## Using the Usage Viewer diff --git a/entrypoint.sh b/entrypoint.sh index dfe63c902..40b73fa89 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -3,7 +3,18 @@ if [ "$1" = "--auth" ]; then # Run auth command exec bun run dist/main.js auth else - # Default command - exec bun run dist/main.js start -g "$GH_TOKEN" "$@" + # Build command with optional arguments + CMD="bun run dist/main.js start" + + if [ -n "$GH_TOKEN" ]; then + CMD="$CMD -g $GH_TOKEN" + fi + + if [ -n "$API_KEY" ]; then + CMD="$CMD --api-key $API_KEY" + fi + + # Execute with any additional arguments + exec $CMD "$@" fi From 8f5e8a569b4ab38a7b5180702d29a01122cd326c Mon Sep 17 00:00:00 2001 From: MrLYC Date: Sun, 1 Feb 2026 14:45:21 +0800 Subject: [PATCH 3/5] fix: trigger docker build on master branch Amp-Thread-ID: https://ampcode.com/threads/T-019c17d4-16ea-744f-9a9b-41a93568c802 Co-authored-by: Amp --- .github/workflows/release-docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-docker.yml b/.github/workflows/release-docker.yml index 3ad5a02cd..cc9f0a1aa 100644 --- a/.github/workflows/release-docker.yml +++ b/.github/workflows/release-docker.yml @@ -7,7 +7,7 @@ name: Docker Build and Push on: push: - branches: [ "main" ] + branches: [ "master" ] tags: [ 'v*.*.*' ] paths-ignore: - 'docs/**' From 8378a68e0e0a7a15dbfbd23c71f93e21b9d2f7c2 Mon Sep 17 00:00:00 2001 From: MrLYC Date: Sun, 1 Feb 2026 14:46:06 +0800 Subject: [PATCH 4/5] feat: add workflow_dispatch trigger for manual runs Amp-Thread-ID: https://ampcode.com/threads/T-019c17d4-16ea-744f-9a9b-41a93568c802 Co-authored-by: Amp --- .github/workflows/release-docker.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release-docker.yml b/.github/workflows/release-docker.yml index cc9f0a1aa..441e92ab0 100644 --- a/.github/workflows/release-docker.yml +++ b/.github/workflows/release-docker.yml @@ -6,6 +6,7 @@ name: Docker Build and Push # documentation. on: + workflow_dispatch: push: branches: [ "master" ] tags: [ 'v*.*.*' ] From 8a39d31172d9b6b0565cc347ebcae08f7508ed45 Mon Sep 17 00:00:00 2001 From: MrLYC Date: Sun, 1 Feb 2026 14:47:41 +0800 Subject: [PATCH 5/5] chore: trigger docker build Amp-Thread-ID: https://ampcode.com/threads/T-019c17d4-16ea-744f-9a9b-41a93568c802 Co-authored-by: Amp --- entrypoint.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/entrypoint.sh b/entrypoint.sh index 40b73fa89..6d2df1adf 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -18,3 +18,4 @@ else exec $CMD "$@" fi +