|
Download server/ACCESS_SETUP.md from Snapkitty/kotlin-command-center: direct link, hf CLI and curl.
- Browser
- Download file 2.65 kB
-
https://huggingface.co/Snapkitty/kotlin-command-center/resolve/main/server/ACCESS_SETUP.md
- Command line
-
hf download hf://Snapkitty/kotlin-command-center/server/ACCESS_SETUP.md
-
curl -L -o ACCESS_SETUP.md https://huggingface.co/Snapkitty/kotlin-command-center/resolve/main/server/ACCESS_SETUP.md
2.65 kB
| # Cloudflare Access setup β service-token auth for the app | |
| Both tunnel hostnames must sit behind Cloudflare Access so the open internet | |
| cannot reach Ollama or SSH. The Kotlin app authenticates with a **service | |
| token** (Client ID + Client Secret) β programmatic, no browser login on the | |
| phone. | |
| ## 1. Create the Access applications | |
| Cloudflare dashboard β **Zero Trust β Access β Applications β Add an application β Self-hosted**. | |
| Create one for each hostname (replace `yourdomain.com` with your domain): | |
| | Application name | Domain | | |
| |---|---| | |
| | command-center-ollama | `ollama-internal.yourdomain.com` | | |
| | command-center-ssh | `ssh.yourdomain.com` | | |
| Session duration: 24h is fine (service tokens are not interactive sessions). | |
| ## 2. Create the service token | |
| **Zero Trust β Access β Service Tokens β Create Service Token.** | |
| - Name: `kotlin-command-center` | |
| - It shows a **Client ID** and **Client Secret** exactly once. Copy both now β | |
| the secret cannot be retrieved later (generate a new token if lost). | |
| ## 3. Attach the Allow policy to both applications | |
| For each application β **Policies β Add a policy**: | |
| - Policy name: `app-service-token` | |
| - Action: **Allow** | |
| - Configure rules β **Add require β Service Token** β select `kotlin-command-center` | |
| - (Optional but recommended) Add an `AND` rule: **IP ranges** limited to the | |
| egress ranges you actually use, if they are stable. | |
| Result: any request without a valid `CF-Access-Client-Id` / | |
| `CF-Access-Client-Secret` pair is rejected at the edge before it ever touches | |
| your tunnel. | |
| ## 4. Wire the secrets into the stack | |
| | Secret | Where it goes | | |
| |---|---| | |
| | Client ID + Client Secret | `worker/` via `wrangler secret put CF_CLIENT_ID` / `CF_CLIENT_SECRET` (Worker attaches them when calling the tunnel) | | |
| | Client ID + Client Secret | Kotlin app config (`CC_CF_CLIENT_ID`, `CC_CF_CLIENT_SECRET`) β used on the **SSH WebSocket handshake** (`wss://ssh.yourdomain.com`) | | |
| | `APP_SECRET` (you invent) | `wrangler secret put APP_SECRET` and the app's `CC_APP_SECRET` β authenticates the phone to the Worker | | |
| The phone never talks to `ollama-internal.yourdomain.com` directly; only the | |
| Worker holds the service token for that hostname. The phone uses the service | |
| token only for the SSH WebSocket handshake. | |
| ## 5. Rotation | |
| - Service token compromised or phone lost: **Access β Service Tokens β delete** | |
| the token and create a new one, then `wrangler secret put` the new values and | |
| update the app config. The old token stops working immediately. | |
| - `APP_SECRET`: pick a fresh 32+ byte random value | |
| (`openssl rand -hex 32`), rotate the same way. | |