|
| 1 | +# Self-Hosted Sharing Server |
| 2 | + |
| 3 | +> **Opt-in & self-hosted** — This feature is entirely optional. Nothing is shared unless |
| 4 | +> you deploy your own server and explicitly enable the setting in VS Code. No data is |
| 5 | +> sent to any third-party service. |
| 6 | +
|
| 7 | +The sharing server lets you aggregate Copilot token usage across a team on infrastructure |
| 8 | +you own. It is a lightweight Node.js API backed by SQLite — run it with Docker on any |
| 9 | +machine, point your team's VS Code extensions at it, and get a shared dashboard without |
| 10 | +needing an Azure account. |
| 11 | + |
| 12 | +## What it does |
| 13 | + |
| 14 | +``` |
| 15 | +┌──────────────────┐ ┌──────────────────┐ ┌────────────────┐ |
| 16 | +│ VS Code / CLI │──POST──▶│ Sharing Server │──read──▶│ Web Dashboard │ |
| 17 | +│ (auto-uploads) │ Bearer │ (your infra) │ SQLite │ (GitHub login)│ |
| 18 | +└──────────────────┘ token └──────────────────┘ └────────────────┘ |
| 19 | +``` |
| 20 | + |
| 21 | +1. **Upload** — The VS Code extension already holds a GitHub OAuth token (the same one |
| 22 | + used by Copilot). When you enable the sharing server setting, the extension |
| 23 | + automatically uploads daily usage rollups to your server. No new login, no API keys. |
| 24 | +2. **Store** — The server validates the GitHub token, identifies the user, and upserts |
| 25 | + the rollup into a local SQLite database. |
| 26 | +3. **View** — Team members sign in to the web dashboard with GitHub OAuth and see their |
| 27 | + own usage — input/output tokens, interactions, days active, editor breakdown, and |
| 28 | + usage trends over time. |
| 29 | + |
| 30 | +## Dashboard preview |
| 31 | + |
| 32 | + |
| 33 | + |
| 34 | +The web dashboard shows per-user usage summaries with time-range filters (Today / |
| 35 | +Last 7 Days / Last 30 Days), an editor breakdown chart, and a token usage trend graph |
| 36 | +grouped by editor or model. |
| 37 | + |
| 38 | +--- |
| 39 | + |
| 40 | +## Setup guide |
| 41 | + |
| 42 | +### Prerequisites |
| 43 | + |
| 44 | +- Docker (or Node.js ≥ 22.5 if running without Docker) |
| 45 | +- A [GitHub OAuth App](https://github.com/settings/developers) — needed for the web |
| 46 | + dashboard login |
| 47 | + |
| 48 | +### 1. Create a GitHub OAuth App |
| 49 | + |
| 50 | +1. Go to **GitHub → Settings → Developer settings → OAuth Apps → New OAuth App** |
| 51 | +2. Fill in: |
| 52 | + - **Application name**: `Copilot Token Tracker` (or any name you like) |
| 53 | + - **Homepage URL**: `https://your-server.example.com` |
| 54 | + - **Authorization callback URL**: `https://your-server.example.com/auth/github/callback` |
| 55 | +3. Copy the **Client ID** and generate a **Client Secret** |
| 56 | + |
| 57 | +### 2. Deploy with Docker Compose |
| 58 | + |
| 59 | +Create a `docker-compose.yml`: |
| 60 | + |
| 61 | +```yaml |
| 62 | +services: |
| 63 | + sharing-server: |
| 64 | + image: ghcr.io/rajbos/copilot-sharing-server:latest |
| 65 | + ports: |
| 66 | + - "3000:3000" |
| 67 | + environment: |
| 68 | + - GITHUB_CLIENT_ID=your_client_id |
| 69 | + - GITHUB_CLIENT_SECRET=your_client_secret |
| 70 | + - SESSION_SECRET=a_long_random_string_min_32_chars |
| 71 | + - BASE_URL=https://your-server.example.com |
| 72 | + # Optional: restrict to members of a specific GitHub org |
| 73 | + # - ALLOWED_GITHUB_ORG=your-org-name |
| 74 | + volumes: |
| 75 | + - sharing_data:/data |
| 76 | + restart: unless-stopped |
| 77 | + |
| 78 | +volumes: |
| 79 | + sharing_data: |
| 80 | +``` |
| 81 | +
|
| 82 | +> **Tip**: Generate `SESSION_SECRET` with `openssl rand -hex 32`. |
| 83 | + |
| 84 | +Start the server: |
| 85 | + |
| 86 | +```bash |
| 87 | +docker compose up -d |
| 88 | +``` |
| 89 | + |
| 90 | +Verify it's running: |
| 91 | + |
| 92 | +```bash |
| 93 | +curl https://your-server.example.com/health |
| 94 | +# → {"status":"ok","timestamp":"..."} |
| 95 | +``` |
| 96 | + |
| 97 | +### 3. Configure the VS Code extension |
| 98 | + |
| 99 | +Add these settings in VS Code (JSON): |
| 100 | + |
| 101 | +```json |
| 102 | +{ |
| 103 | + "aiEngineeringFluency.backend.sharingServer.enabled": true, |
| 104 | + "aiEngineeringFluency.backend.sharingServer.endpointUrl": "https://your-server.example.com" |
| 105 | +} |
| 106 | +``` |
| 107 | + |
| 108 | +Or search for **AI Engineering Fluency: Sharing Server** in the Settings UI. |
| 109 | + |
| 110 | +That's it. The extension starts uploading daily rollups automatically — no extra |
| 111 | +authentication prompt, no API keys. It reuses your existing GitHub session from VS Code. |
| 112 | + |
| 113 | +--- |
| 114 | + |
| 115 | +## Environment variables |
| 116 | + |
| 117 | +| Variable | Required | Default | Description | |
| 118 | +|---|---|---|---| |
| 119 | +| `GITHUB_CLIENT_ID` | ✅ | — | GitHub OAuth App client ID | |
| 120 | +| `GITHUB_CLIENT_SECRET` | ✅ | — | GitHub OAuth App client secret | |
| 121 | +| `SESSION_SECRET` | ✅ | — | Random secret for signing session cookies (≥ 32 chars) | |
| 122 | +| `BASE_URL` | ✅ | — | Public URL of the server (no trailing slash) | |
| 123 | +| `PORT` | ❌ | `3000` | HTTP listen port | |
| 124 | +| `DB_PATH` | ❌ | `/data/sharing.db` | SQLite database file path | |
| 125 | +| `ALLOWED_GITHUB_ORG` | ❌ | *(any user)* | Restrict uploads and dashboard to members of this GitHub org | |
| 126 | + |
| 127 | +--- |
| 128 | + |
| 129 | +## How authentication works |
| 130 | + |
| 131 | +The sharing server does **not** issue its own API keys. |
| 132 | + |
| 133 | +- **Data uploads** (from the VS Code extension) use a **Bearer token** — the same |
| 134 | + GitHub OAuth token already held by VS Code. The server validates it by calling |
| 135 | + `GET https://api.github.com/user` and caches the result for 10 minutes. |
| 136 | +- **Web dashboard** login uses a standard **GitHub OAuth flow** (the OAuth App you |
| 137 | + created in step 1). Users sign in via the browser and receive a signed session cookie. |
| 138 | + |
| 139 | +If `ALLOWED_GITHUB_ORG` is set, both uploads and dashboard access are restricted to |
| 140 | +members of that GitHub organization. |
| 141 | + |
| 142 | +--- |
| 143 | + |
| 144 | +## Privacy & data |
| 145 | + |
| 146 | +- **Opt-in only** — No data is uploaded unless you explicitly enable the setting and |
| 147 | + provide a server URL. |
| 148 | +- **Self-hosted** — The server runs on your infrastructure. Data never leaves your |
| 149 | + network (unless you expose the server publicly). |
| 150 | +- **Identified mode** — Every upload is linked to a GitHub user ID. There is no |
| 151 | + anonymous or pseudonymous mode (unlike the Azure Storage backend). |
| 152 | +- **Workspace/machine names** — Included or excluded based on the extension's |
| 153 | + `shareWorkspaceMachineNames` setting (off by default). |
| 154 | +- **Rollups only** — The extension sends daily aggregates (tokens, interactions, model |
| 155 | + names), not raw prompts or completions. |
| 156 | + |
| 157 | +--- |
| 158 | + |
| 159 | +## Backup |
| 160 | + |
| 161 | +The entire server state lives in a single SQLite file (`/data/sharing.db` by default). |
| 162 | +Back it up with any file copy tool or: |
| 163 | + |
| 164 | +```bash |
| 165 | +sqlite3 /data/sharing.db .dump > backup.sql |
| 166 | +``` |
| 167 | + |
| 168 | +--- |
| 169 | + |
| 170 | +## Running without Docker |
| 171 | + |
| 172 | +See the [sharing server README](../../sharing-server/README.md) for instructions on |
| 173 | +building from source and running locally with Node.js. |
0 commit comments