This guide walks through running the Trellis server, console, and supporting services directly from the source tree. By the end you will have a local development environment equivalent to the Server Setup guides, but running processes natively instead of in containers.
What you need
- Git
- Deno (v2+)
- a Rust toolchain (
rustup) podman(for the NATS container only)systemctl --userwith Quadlet support- an OAuth application (GitHub) for local development
1. Clone the repository
git clone https://github.com/qlever-llc/trellis.git
cd trellis 2. Install dependencies
Install the Deno workspace dependencies:
cd js
deno install
cd .. Build the Trellis CLI from source:
cd rust
cargo build -p trellis-cli
cd .. The commands below use the installed trellis CLI directly.
trellis --version 3. Set up NATS
NATS still runs in a container even for in-repo development. Follow the Prepare NATS guide to get a running NATS server.
Create a workspace directory for NATS state outside the repo:
mkdir -p ~/trellis/{config,keys,nsc,nkeys}
chmod 700 ~/trellis/keys ~/trellis/nsc ~/trellis/nkeys Complete all of the steps in the Prepare NATS guide using ~/trellis as your workspace root. When you are done you should have NATS running on 127.0.0.1:4222.
4. Generate the Trellis session key
trellis keygen \
--out ~/trellis/keys/trellis.seed \
--pubout ~/trellis/keys/trellis.pub 5. Build SDKs from contracts
The service and generated SDK packages depend on contract build artifacts. Generate them before running anything:
deno task -c js/deno.json build:sdk 6. Collect the NATS values
If you still have the shell variables from the NATS guide, skip this step.
cd ~/trellis
NATS_AUTH_ISSUER_NKEY=$(./nsc.sh describe account -n AUTH --field sub | tr -d '"')
NATS_AUTH_TARGET_NKEY=$(./nsc.sh describe account -n TRELLIS --field sub | tr -d '"')
XKEY_PUB=$(./nsc.sh describe account -n AUTH -J | grep '"xkey"' | tr -d ' ",' | cut -d: -f2) Read the signing seeds:
NATS_AUTH_ISSUER_SIGNING_SEED=$(cat ~/trellis/keys/auth-issuer-signing.nk)
NATS_AUTH_TARGET_SIGNING_SEED=$(cat ~/trellis/keys/trellis-target-signing.nk)
NATS_AUTH_SXKEY_SEED=$(cat ~/trellis/nkeys/keys/X/${XKEY_PUB:1:2}/${XKEY_PUB}.nk) 7. Configure the auth runtime
Copy the example Trellis config in the source tree:
cd /path/to/trellis
cp js/services/trellis/config.example.jsonc js/services/trellis/config.jsonc Edit js/services/trellis/config.jsonc and fill in the values. When running from source, relative paths are resolved from js/services/trellis/.
{
"web": {
"origins": ["http://localhost:5173"],
"publicOrigin": "http://localhost:3000"
},
"nats": {
"servers": "localhost",
"trellis": {
"credsPath": "/home/<you>/trellis/nkeys/creds/Trellis/TRELLIS/trellis.creds"
},
"auth": {
"credsPath": "/home/<you>/trellis/nkeys/creds/Trellis/AUTH/trellis.creds"
},
"sentinelCredsPath": "/home/<you>/trellis/nkeys/creds/Trellis/AUTH/sentinel.creds",
"authCallout": {
"issuer": {
"nkey": "<value from step 6>",
"signingSeedFile": ".local/secrets/auth-issuer-signing.seed"
},
"target": {
"nkey": "<value from step 6>",
"signingSeedFile": ".local/secrets/auth-target-signing.seed"
},
"sxSeedFile": ".local/secrets/auth-sx.seed"
}
},
"sessionKeySeedFile": ".local/secrets/session-key.seed",
"client": {
"natsServers": ["ws://localhost:8080"]
},
"oauth": {
"redirectBase": "http://localhost:3000/auth/callback",
"alwaysShowProviderChooser": true,
"providers": {
"github": {
"type": "github",
"clientId": "<your GitHub OAuth app client ID>",
"clientSecretFile": ".local/secrets/github-client-secret"
}
}
}
} client.natsServers is the websocket endpoint list the auth service returns to browser clients after /auth/bind, so apps can discover the correct realtime connection settings from the instance they signed into.
Then start the runtime with the config path override:
TRELLIS_CONFIG=./config.jsonc deno task -c js/services/trellis/deno.json dev 8. Bootstrap NATS buckets
trellis bootstrap nats \
--servers 127.0.0.1 \
--trellis-creds ~/trellis/nkeys/creds/Trellis/TRELLIS/trellis.creds \
--auth-creds ~/trellis/nkeys/creds/Trellis/AUTH/trellis.creds 9. Start the Trellis runtime
cd js/services/trellis
deno task dev The runtime starts on http://localhost:3000 with file watching enabled. Code changes under js/ will trigger an automatic restart.
Test it:
curl -i http://localhost:3000/auth/login/github An HTTP 400 is expected — it confirms the runtime is serving.
10. Start the console app
In a second terminal:
cd js/apps/trellis
cp .env.example .env
deno task dev The console starts on http://localhost:5173 with Vite HMR.
11. Create the first admin
Before logging into the console, bootstrap the GitHub account that will become the first administrator:
trellis bootstrap admin \
--servers 127.0.0.1 \
--creds ~/trellis/nkeys/creds/Trellis/AUTH/trellis.creds \
--origin github \
--id github:YOUR_GITHUB_USER_ID This seeds the user projection with the default console access set: admin, trellis.catalog.read, and trellis.contract.read.
12. Log in with the CLI
trellis --nats-servers 127.0.0.1 auth login \
--auth-url http://localhost:3000 \
--provider github 13. Verify
curl http://127.0.0.1:8222/healthz
curl -i http://localhost:3000/auth/login/github
curl -I http://localhost:5173/
trellis auth status Open http://localhost:5173 in your browser and complete the OAuth login with that same GitHub account.
Development workflow
- Runtime changes — edit files under
js/services/trellis/orjs/packages/. Thedeno task devwatcher restarts the process automatically. - Console changes — edit files under
js/apps/trellis/. Vite HMR applies changes in-place. - Contract changes — run
deno task -c js/deno.json build:sdkto regenerate SDKs, then restart the affected service. - CLI changes — run
cargo build -p trellis-cliin therust/directory, then re-runtrellis ...commands from the repo root. - Type checking — run
deno task -c js/deno.json checkto type-check the full JS workspace. - Tests — run
deno task -c js/deno.json test:contractsordeno task -c js/deno.json test:auth.