Deploy and redeploy¶
This follows setup.sh and the compose files in
scimbe/CADS-kali-desktop directly. Nothing here
is an invented step — every command below is one setup.sh actually runs, or one its own README
documents.
documented in repo These are the repository's documented steps; this docs pass did not execute them against a live host.
Prerequisites¶
- Docker with Compose v2 (
docker compose version). - A tunnel created in the CADS-Tunnel portal, with
require_login=1and your account on its access list, then Install clicked to obtain the routing tokens.
1. Desktop credentials¶
git clone https://github.com/scimbe/CADS-kali-desktop.git && cd CADS-kali-desktop
cp .env.template .env && $EDITOR .env # set KASM_USER, KASM_PASSWORD
chmod 600 .env
KASM_PASSWORD should be a random value, deliberately not your Keycloak/gate password — see
why.
2. Derive the gate's injected credential¶
Reads .env, writes .env.gate (base64 of user:password, chmod 600, value never printed).
This is what lets the gate log the visitor in once and never show the desktop's own login prompt.
3. Tunnel configuration¶
cp .env.tunnel.template .env.tunnel && $EDITOR .env.tunnel # paste the portal's Install tokens
chmod 600 .env.tunnel
See Environment variables for what each field
means. Note CT_AGENT_ORIGIN: whatever you put here is silently overridden to kali-gate:3000
by compose.gate.yml when you bring up the full stack (step 5 below) — see
Applying or reverting the gate/revoke layer. Fine
to leave at its template default; just don't be surprised it isn't the value actually in effect.
4. Set who is allowed in¶
In compose.gate.yml, set KALI_ALLOWED_EMAIL to the same address you put on the tunnel's
access list in the portal. This is not treated as a secret in this repo (it's your own login
identity) — it stays in the compose file, in plain sight, rather than in an env file.
measured This is the one step setup.sh check cannot catch for
you if you skip it. The tracked compose.gate.yml ships with a real, non-placeholder address
already filled in (the upstream repo owner's own) — check's validation is [ -n
"$KALI_ALLOWED_EMAIL" ], non-empty only, confirmed by reading setup.sh directly. A value that
is merely non-empty always passes, whether or not it's your address. If you deploy a fork of
this repo without editing KALI_ALLOWED_EMAIL here, check and verify both report
green while the gate silently keeps admitting the original owner's identity — and yours, on the
list you configured in the portal, never gets in. There is no automated guard against this;
double-check this line by eye before up.
5. Check, then bring it up¶
./setup.sh check # validates files, secrets, permissions, hostname, compose config, Caddyfile — changes nothing
./setup.sh up # docker compose up -d --build ; first run pulls ~12 GB
setup.sh check refuses to proceed if .env, .env.tunnel, or .env.gate are missing or not
chmod 600.
By default setup.sh brings up the full stack — compose.kali.yml + compose.tunnel.yml +
compose.gate.yml + compose.revoke.yml together (see
which mode is actually live
for the distinction between this and the fallback path).
6. Verify¶
Re-measures the security properties documented in the README against the live deployment —
unauthenticated redirect, deep-path coverage, basic-auth-alone insufficiency, the logout target,
the no-store header, the revocation one-shot semantics, absence of published ports, presence of
the logout probe in the served page, and that the running finish hook and Caddyfile are the
patched ones — rather than assuming any of them.
Redeploying after a config change¶
Single-file bind mounts pin an inode
Caddyfile.gate and hooks/svc-de-finish are bind-mounted as individual files. Editing one
and then restarting the container changes nothing — Docker keeps serving the old,
already-unlinked file from the pinned inode. This is called out in the repo as having cost
real debugging time twice in one day. Always recreate, not restart:
docker compose -f compose.kali.yml -f compose.tunnel.yml -f compose.gate.yml -f compose.revoke.yml \
up -d --force-recreate kali-gate
# or, for the finish hook:
docker compose -f compose.kali.yml -f compose.tunnel.yml -f compose.gate.yml -f compose.revoke.yml \
up -d --force-recreate kali
setup.sh verify includes a check that the file actually present inside the running
container is the patched one, specifically because of this failure mode.
Applying or reverting the gate/revoke layer¶
# Full stack (gate + revoke on top of desktop + tunnel):
docker compose -f compose.kali.yml -f compose.tunnel.yml -f compose.gate.yml -f compose.revoke.yml up -d
# Revert to the fallback path (desktop + tunnel only, edge-only gating):
docker compose -f compose.kali.yml -f compose.tunnel.yml up -d