Zanskar is an open-source, agentless access gateway for machines and managed databases. Users open a browser, pick a target, and get a terminal (SSH, WinRM), a desktop (RDP, VNC), or a database session (PostgreSQL, MySQL, MariaDB) — without installing anything on the target. Every session is policy-controlled, recorded, and audited, and access can be standing or granted just-in-time on approval.
Zanskar is named after the Zanskar Valley in Ladakh, in the Himalayas of northern India. The logo is a shell prompt redrawn as a summit and a cursor.
Most access gateways assume a fixed set of servers. Zanskar treats autoscaling groups as first-class targets: enroll an AWS Auto Scaling group with a read-only IAM role, Zanskar tracks the healthy pool, and when the instance you are on is terminated you are offered a switch to another healthy instance instead of a dead terminal.
- Terminals — SSH and Windows (WinRM), streamed to the browser over WebSocket and recorded as asciicast.
- Desktops — RDP and VNC through a guacd sidecar, with session recording and live shadowing.
- Managed databases —
psql,mysqlormariadbsessions to PostgreSQL, MySQL and MariaDB (Amazon RDS or self-managed) through an ephemeral, per-session client container. The database credential is held by a sidecar (pgbouncer, or the gateway's own relay) and never reaches the user's client; TLS to the database is per target, up toverify-fullwith your CA bundle. - Autoscaling groups as targets — enroll an AWS Auto Scaling group with a read-only cross-account role. The gateway knows its own AWS principal, prints the CLI script or CloudFormation template that creates the role, and tests the role before saving. Zanskar then tracks the healthy pool and offers failover when the instance you are on goes away.
- Just-in-time access — a policy can grant eligibility instead of standing access: a user requests a target with a reason and a duration, an administrator approves, and the grant is time-boxed, can be extended, and expires on its own. Policies carry per-target protocol rules, session limits and a recording retention of their own.
- File transfer and clipboard — SFTP for SSH and drive redirection for RDP, each gated by policy.
- Keyless SSH — an SSH certificate authority is the recommended way to reach Linux targets: Zanskar
generates the authority, prints the one
TrustedUserCAKeysline each target needs, mints a minutes-long certificate per session naming the Zanskar user in the target's auth log, and rotates the authority in two steps without breaking a host that has not learned the new key yet. - Identity, kept separate — local accounts (Argon2id + TOTP, onboarding with a one-time password replaced at first sign-in), OIDC and LDAP/AD sign-in.
- Recorded and audited — every session is recorded; recordings and command transcripts can be
downloaded, with every view and download audited; the audit log is hash-chained with a
verifycommand and can be streamed to a SIEM. - Operated from the console — HTTPS out of the box with a gateway-managed certificate you replace on the Settings page, runtime settings applied live, a restart-required banner when the environment file drifts, recording storage moved to an S3-compatible bucket without a restart, and the gateway's recent log lines on a Logs page.
- Agentless. Targets are reached over SSH, RDP, VNC or WinRM; a managed database needs only a reachable endpoint. There is no agent to install on the target.
- The browser never touches the target. Only the gateway does, so targets need no inbound internet exposure.
- Two authentications, kept separate. Who you are to Zanskar (local, OIDC, LDAP/AD, MFA) is distinct from how Zanskar authenticates to a target (password, SSH key, SSH certificate, domain credentials).
- Three roles.
adminconfigures and reviews,auditorreviews only,userconnects. Every view of a recording or the audit log is itself audited. - Least standing privilege. Sensitive targets can be made eligible-only, so no one holds standing access — it exists only as a time-boxed, approved, audited grant.
- Secure by default. Envelope-encrypted secrets, a hash-chained audit log, MFA, and signed releases.
cp .env.example .env
export ZANSKAR_MASTER_KEY=$(go run ./cmd/zanskar keygen)
go run ./cmd/zanskar migrate
go run ./cmd/zanskar admin create --username admin --name "Your Name" # prompts for a password
make build # builds the web UI and a single binary with it embedded
./bin/zanskar serve # SQLite, plain HTTP on 127.0.0.1:8443Open http://127.0.0.1:8443, sign in, and enroll your authenticator when prompted. For UI work run
make web-dev (Vite on :5173, proxying to the API) beside make run. zanskar audit verify
checks the audit chain from the command line. If the only admin loses their authenticator,
zanskar admin reset-mfa --username <name> on the gateway host clears it and audits the reset;
the next login enrolls a new one. zanskar key status, key rotate and key rotate-master
manage the key ring and the master key; zanskar dbproxy is the MySQL/MariaDB relay the gateway
runs beside a database session, not something to start by hand.
Requires Go 1.27+ and Node 22+ to build.
Run the single-instance stack (gateway on SQLite, guacd, Caddy TLS) on one box:
docker compose -f deploy/docker-compose.yml up -d. For a Postgres-backed
development stack instead, use deploy/docker-compose.dev.yml.
The product site at https://albatroxxx.github.io/zanskar/ has the installation guide, the how-to guide and release notes in one place.
Zanskar runs as a single instance: one gateway, embedded SQLite or PostgreSQL, and a guacd sidecar for RDP/VNC. High availability is planned. Two supported install paths, both from the releases page:
- Packages (recommended):
.deb/.rpmfor amd64 and arm64, thensudo zanskar initwrites the configuration, serves HTTPS on 443 with a certificate it manages (upload yours on the Settings page), and prints the next steps. It asks which address people will reach the gateway by: a cloud instance's public address is translated upstream, so nothing can guess it, and a certificate without it means a browser warning and no HTTP-to-HTTPS redirect.zanskar init -behind-proxykeeps the gateway on loopback behind your own TLS proxy. Plain tarballs are there too. - Container:
ghcr.io/albatroxxx/zanskar:latest, or a pinned:<version>, withdeploy/docker-compose.yml(gateway + guacd + Caddy TLS).ZANSKAR_VERSIONindeploy/.envpins it; it defaults tolatest. The same image is the MySQL/MariaDB relay sidecar, so a gateway that serves database targets needs Docker or Podman.
Checksums and the image are signed with Sigstore; the release notes carry the cosign verify
commands. cosign is not in the Ubuntu, Debian or RHEL repositories, so install it from
its own release first (the
install page has the commands). The Helm chart in deploy/helm/zanskar is a preview: it deploys one gateway pod. Zanskar
runs as a single instance; high availability is planned. Topology,
upgrades, backups, TLS, recording storage, database access, AWS enrolment, the certificate
authority and the security checklist are in docs/deploy.md.
cmd/zanskar/ entrypoint
internal/ application code (not importable by other modules)
migrations/ SQL migrations, one set per database driver
docs/ threat model, API spec, design decisions (ADRs), wireframes
deploy/ Dockerfile, docker-compose, Helm chart
web/ React + TypeScript frontend, embedded into the binary at build time
Every badge above is computed from this repository by an open-source tool and links to its evidence.
| Badge | What it measures | Source |
|---|---|---|
| CI | Build, go vet, race tests on SQLite and PostgreSQL, golangci-lint, govulncheck, gosec, gitleaks, OSV-Scanner, Trivy on the source tree and the built container image, third-party-notice check, all on every push and PR |
ci.yml |
| CodeQL | Static analysis of the Go server and TypeScript UI with the security-extended query suite; alerts appear in the Security tab |
codeql.yml |
| OpenSSF Scorecard | Supply-chain hygiene scored 0 to 10 by the OpenSSF: pinned dependencies, token permissions, branch protection, SAST, vulnerability status, and more. Weekly and on every push to main | scorecard.yml |
| OpenSSF Best Practices | The OpenSSF Best Practices criteria for FLOSS projects: documented contribution and vulnerability-reporting process, tests and CI, static and dynamic analysis, published cryptography, secure delivery. Answers are public and linked to their evidence | project 14924 |
| Test coverage | Statement coverage of the gateway's own code (every package but the hack/ test tools) from the CI test run, written to the badges branch after each push to main |
ci.yml |
| Go version | Read from go.mod |
shields.io |
The published image ghcr.io/albatroxxx/zanskar:latest is also re-scanned by Trivy every week,
because new advisories appear after a release; findings land in the Security tab
(image-scan.yml).
Vulnerability handling and the current advisory triage are in SECURITY.md.
Contributions are welcome. To report a bug or suggest something, open an issue — the bug report and feature request forms will walk you through what to include. Please do not file security problems as public issues; see Security below.
To work on the code, CONTRIBUTING.md has the setup, the checks that must pass, and the project conventions. The short version:
make all # runs the linters, the race-detector tests, builds the UI + binary, and runs the console testsHow the project is run, who holds which role and how decisions are made is in GOVERNANCE.md; everyone taking part follows the code of conduct. The high-level design is in docs/architecture.md, every command of the console's command line in docs/console-cli.md, and the answers behind the project's OpenSSF Best Practices Silver badge are in docs/best-practices.md.
Zanskar is an access gateway, so security reports matter. See SECURITY.md for how to report a vulnerability privately — never open a public issue for a security problem. The threat model describes what Zanskar defends against.
Apache License 2.0. See LICENSE. The third-party components compiled into
the binary and their license texts are in
THIRD_PARTY_NOTICES.md (generated by hack/gen-notices.sh);
bundled non-code assets are listed in THIRD_PARTY_LICENSES.md.