|
| 1 | +# orange local development quickstart |
| 2 | + |
| 3 | +Two commands cover the full local dev loop: |
| 4 | + |
| 5 | +``` |
| 6 | +orange server --local # server + bootstrap + admin REPL |
| 7 | +orange egress serve --local # envoy + redis + rls + egress REPL (standalone) |
| 8 | +ORANGE_SERVER_URL=http://localhost:3000 \ |
| 9 | + orange egress serve --local \ |
| 10 | + --bundle=<egress-id>.tar.gz # same stack, config from server |
| 11 | +``` |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## `orange server --local` |
| 16 | + |
| 17 | +Starts the orange management plane for local development. On first run it |
| 18 | +bootstraps everything from `orange.yaml`, then drops into the admin REPL. |
| 19 | +Ctrl-D / `exit` in the REPL shuts the server down. |
| 20 | + |
| 21 | +### What it does on startup |
| 22 | + |
| 23 | +1. Starts embedded Postgres under `~/.orange/data/` and loads (or generates) a |
| 24 | + local KEK at `~/.orange/kek`. |
| 25 | +2. If the database is empty **and `--no-seed` was not given**, bootstraps from |
| 26 | + `orange.yaml`: |
| 27 | + - Reads unique workspace names from the first path component of each key in |
| 28 | + the `keys:` map. Example: `demo/dio/sk-default` → workspace `demo`. |
| 29 | + - Creates org `orange.io`, project `proj1`, one workspace per derived name, |
| 30 | + user `dio@orange.io`, admin user `admin@orange.io` with an org-admin API key, |
| 31 | + and an egress record per workspace. |
| 32 | +3. Starts the HTTP/2 management plane on `:3000` (override with `--port`). |
| 33 | +4. Prints `export ORANGE_API_KEY=<key>` — save this for future `--no-purge` |
| 34 | + restarts and for `orange admin` sessions from a second terminal. |
| 35 | +5. Enters the **admin REPL** seeded with the org and project context. |
| 36 | + |
| 37 | +Re-runs on existing data skip the bootstrap and enter the REPL directly. |
| 38 | +To wipe and start fresh, add `--purge` (see Flags below). |
| 39 | + |
| 40 | +### Flags |
| 41 | + |
| 42 | +| Flag | Default | Env | Description | |
| 43 | +|---|---|---|---| |
| 44 | +| `--local` | — | — | enable local mode (required) | |
| 45 | +| `--purge` | false | — | wipe `~/.orange/data/` and `~/.orange/kek` before starting (requires `--local`) | |
| 46 | +| `--no-seed` | false | — | skip auto-bootstrap after `--purge`; start with an empty DB | |
| 47 | +| `--config` | `orange.yaml` | `ORANGE_CONFIG` | config file for workspace derivation | |
| 48 | +| `--org` | `orange.io` | — | org name | |
| 49 | +| `--project` | `proj1` | — | project name | |
| 50 | +| `--user` | `dio` | — | initial workspace member | |
| 51 | +| `--port` | `3000` | `PORT` | listen port | |
| 52 | +| `--public-url` | `http://localhost:<port>` | `ORANGE_PUBLIC_URL` | URL written into egress bundles | |
| 53 | + |
| 54 | +### First run |
| 55 | + |
| 56 | +```bash |
| 57 | +cd examples/orange |
| 58 | +orange server --local |
| 59 | +``` |
| 60 | + |
| 61 | +Output: |
| 62 | + |
| 63 | +``` |
| 64 | +# local dev server ready |
| 65 | +# admin: admin@orange.io |
| 66 | +export ORANGE_API_KEY=sk-org-<key> |
| 67 | +# user: dio@orange.io |
| 68 | +export ORANGE_USER_API_KEY=sk-<key> |
| 69 | +orange [orange.io / proj1]> |
| 70 | +``` |
| 71 | + |
| 72 | +Save both keys. `ORANGE_API_KEY` is the admin key for the management API; |
| 73 | +`ORANGE_USER_API_KEY` is the workspace-scoped key used to issue PASETO tokens |
| 74 | +and switch to the user REPL (`su $ORANGE_USER_API_KEY`). The prompt is now the |
| 75 | +admin REPL. |
| 76 | + |
| 77 | +### Admin REPL — useful commands after start |
| 78 | + |
| 79 | +``` |
| 80 | +# List what was created |
| 81 | +ws list # show workspaces |
| 82 | +egress list # show egress records per workspace |
| 83 | +member list # show workspace members |
| 84 | +
|
| 85 | +# Download the egress bundle so you can run egress serve --local --bundle |
| 86 | +egress bundle <egress-id> # writes <egress-id>.tar.gz in cwd |
| 87 | +# or interactively: |
| 88 | +ws # show ws IDs |
| 89 | +egress bundle # prompts if >1 egress |
| 90 | +
|
| 91 | +# Config snapshot is auto-published from orange.yaml on first start (--purge). |
| 92 | +# Re-publish after editing orange.yaml: |
| 93 | +config publish orange.yaml ws=<ws-id> |
| 94 | +
|
| 95 | +# User operations |
| 96 | +user list |
| 97 | +apikey list |
| 98 | +
|
| 99 | +help # full command reference |
| 100 | +exit # shut down server and exit |
| 101 | +``` |
| 102 | + |
| 103 | +### Restarting (re-attach to existing data) |
| 104 | + |
| 105 | +```bash |
| 106 | +export ORANGE_API_KEY=sk-org-<key> # from the first-run output |
| 107 | +orange server --local |
| 108 | +``` |
| 109 | + |
| 110 | +The server starts, detects existing org data, skips bootstrap, and enters the |
| 111 | +admin REPL using your existing API key. |
| 112 | + |
| 113 | +### Starting fresh |
| 114 | + |
| 115 | +```bash |
| 116 | +orange server --local --purge |
| 117 | +``` |
| 118 | + |
| 119 | +Wipes `~/.orange/data/` and `~/.orange/kek`, then re-bootstraps from |
| 120 | +`orange.yaml`. Add `--no-seed` to skip the bootstrap and start with an empty DB. |
| 121 | + |
| 122 | +--- |
| 123 | + |
| 124 | +## `orange egress serve --local` — standalone mode |
| 125 | + |
| 126 | +Runs the full local egress stack (Envoy + redis-server + in-process RLS) using |
| 127 | +a local `orange.yaml` as the config source. No orange server needed. |
| 128 | + |
| 129 | +```bash |
| 130 | +orange egress serve --local |
| 131 | +orange egress serve --local --config path/to/orange.yaml |
| 132 | +``` |
| 133 | + |
| 134 | +The REPL prompt is `egress:local>`. Hot-reload happens automatically on save. |
| 135 | + |
| 136 | +### Prerequisites |
| 137 | + |
| 138 | +```bash |
| 139 | +brew install redis # redis-server must be in PATH |
| 140 | +export ENVOY_BIN=... # or: make download-envoy in the transit repo root |
| 141 | +``` |
| 142 | + |
| 143 | +--- |
| 144 | + |
| 145 | +## `orange egress serve --local --server-url` — connected mode |
| 146 | + |
| 147 | +Runs the same local stack (Envoy + redis + RLS + REPL) but pulls config from a |
| 148 | +running orange server instead of a local yaml file. Use this after |
| 149 | +`orange server --local` has bootstrapped and published a workspace snapshot. |
| 150 | + |
| 151 | +```bash |
| 152 | +ORANGE_SERVER_URL=http://localhost:3000 \ |
| 153 | + orange egress serve --local \ |
| 154 | + --bundle <egress-id>.tar.gz |
| 155 | +``` |
| 156 | + |
| 157 | +Or with explicit flags: |
| 158 | + |
| 159 | +```bash |
| 160 | +orange egress serve --local \ |
| 161 | + --server-url http://localhost:3000 \ |
| 162 | + --bundle <egress-id>.tar.gz |
| 163 | +``` |
| 164 | + |
| 165 | +### What it does |
| 166 | + |
| 167 | +1. Loads `<egress-id>.tar.gz` for bundle credentials. |
| 168 | +2. Overrides the bundle's baked-in server URL with `ORANGE_SERVER_URL`. |
| 169 | +3. Fetches the initial config snapshot from the server and writes it to a temp |
| 170 | + yaml file. |
| 171 | +4. Starts redis, RLS, and Envoy pointing at that temp file (identical to |
| 172 | + standalone mode). |
| 173 | +5. Background poller re-fetches every `--interval` (default 30 s); when the |
| 174 | + snapshot changes the temp file is atomically replaced and the existing |
| 175 | + `WatchFile` goroutine triggers `provider.Reload` in the RLS. |
| 176 | +6. Enters the `egress:local>` REPL exactly as in standalone mode. |
| 177 | + |
| 178 | +### Flags |
| 179 | + |
| 180 | +| Flag | Default | Env | Description | |
| 181 | +|---|---|---|---| |
| 182 | +| `--server-url` | — | `ORANGE_SERVER_URL` | orange server URL (triggers connected mode) | |
| 183 | +| `--bundle` | — | `ORANGE_EGRESS_BUNDLE` | bundle path; required with `--server-url` | |
| 184 | +| `--interval` | `30s` | — | snapshot poll interval | |
| 185 | +| `--no-rls` | false | — | skip redis + RLS (Envoy only) | |
| 186 | +| `--rls-listen` | `:8081` | — | RLS gRPC listen address | |
| 187 | + |
| 188 | +### Full two-terminal workflow |
| 189 | + |
| 190 | +**Terminal 1 — server:** |
| 191 | + |
| 192 | +```bash |
| 193 | +cd examples/orange |
| 194 | +orange server --local |
| 195 | +# → export ORANGE_API_KEY=sk-org-<key> |
| 196 | +# → orange [orange.io / proj1]> |
| 197 | +``` |
| 198 | + |
| 199 | +In the admin REPL: |
| 200 | + |
| 201 | +``` |
| 202 | +egress bundle <egress-id> # write <egress-id>.tar.gz |
| 203 | +# Config snapshot was auto-published from orange.yaml on startup. |
| 204 | +# Re-publish after changes: config publish orange.yaml ws=<ws-id> |
| 205 | +``` |
| 206 | + |
| 207 | +**Terminal 2 — egress:** |
| 208 | + |
| 209 | +```bash |
| 210 | +export ORANGE_API_KEY=sk-org-<key> # from terminal 1 |
| 211 | +ORANGE_SERVER_URL=http://localhost:3000 \ |
| 212 | + orange egress serve --local \ |
| 213 | + --bundle <egress-id>.tar.gz |
| 214 | +``` |
| 215 | + |
| 216 | +Config changes pushed via `config push` in the server REPL propagate to the |
| 217 | +egress stack within one poll interval. |
0 commit comments