Xalgorix Cloud
Autonomous AI security testing for developers and security teams: find vulnerabilities, prove each with a working exploit, and ship verified fixes with zero infrastructure setup.
翻訳待ち
Lor: temporary, approved SSH access for AI agents via a short-lived SSH CA
翻訳待ち
Loading the full README.
Read the full README ↗Lor gives AI agents temporary, approved SSH access to homelab machines. It is a small SSH certificate authority: every grant is a short-lived OpenSSH certificate, so hosts enforce the end time themselves, even if Lor is down.
An agent asks with lor request nas --for 1h --reason "..." and shares the
approval link in chat. You open it on your phone, see exactly what would be
allowed, and authorize with a passkey tap. The agent then runs
lor ssh nas -- <cmd> until the certificate expires; each command shows up in
Lor. You can also grant access before the agent asks, extend, and revoke.
Install (details at https://lor.hyperf.app):
curl -fsSL https://lor.hyperf.app/install.sh | sh # agent CLI (Linux, macOS)
curl -fsSL https://lor.hyperf.app/install.sh | sudo sh -s -- --server # lor-server (Linux, systemd)
The installer downloads the latest release
and checks it against the release's SHA256SUMS. Options: --skill (also
install the agent skill), --version vX.Y.Z, --dir DIR.
The full design is in docs/plan.md. Deviations from it are in docs/deviations.md; the operations runbook is in docs/runbook.md.
Your devices ──HTTPS──▶ Caddy ──HTTPS :8444 (pinned)──▶ lor-server (admin API + web UI)
Agent LXC ── lor CLI ──HTTPS :8443 (pinned, token + source IP)──▶ lor-server (agent API, CA)
Agent LXC ── ssh (certificate locked to the agent's IP) ──▶ targets (agent / agent-sudo)
| Path | What |
|---|---|
cmd/lor-server, cmd/lor | the server and the agent CLI |
api/admin.yaml, api/agent.yaml | OpenAPI contracts (Go and TypeScript code is generated from them) |
internal/ca | certificate signing and its refusal rules |
internal/grants | the grant state machine and sweeper |
internal/auth | passkeys, sessions, step-up, agent tokens |
internal/hosts, scripts/bootstrap.sh.tmpl | host-key scans and the host bootstrap script |
internal/server | the two HTTP listeners, CSRF, SPA serving |
web/ | the SvelteKit web UI (embedded into lor-server) |
skill/SKILL.md | the agent skill |
deploy/ | example config, systemd unit and Caddy site |
site/ | the public site and installer at lor.hyperf.app (GitHub Pages) |
test/e2e, test/integration | Playwright and Docker/OpenSSH tests |
Needs Go 1.26+ and Node 22 with pnpm (Node is only needed at build time).
make build # web UI → web/build, then CGO_ENABLED=0 go build → bin/lor-server, bin/lor
make test # go vet + go test, svelte-check, ESLint, Prettier, Vitest
make generate # regenerate code from api/*.yaml (output is committed; CI checks for drift)
lor-server embeds the web UI; go build fails if web/build/ is missing,
so always build with make build (or make web first).
Other test suites:
go build -o bin/fakessh ./test/e2e/fakessh
pnpm -C web exec playwright install chromium
make e2e # Playwright against lor-server --dev
DISTRO=ubuntu:26.04 make integration # real OpenSSH in Docker (needs Docker)
CI runs all of them, with the integration tests on Debian 12, Debian 13, Ubuntu 22.04, 24.04 and 26.04.
Pushing a tag vX.Y.Z runs .github/workflows/release.yml: make dist
builds lor (Linux and macOS, amd64 and arm64) and lor-server (Linux,
amd64 and arm64) as <binary>_<os>_<arch>.tar.gz plus SHA256SUMS, and
publishes them as a GitHub release. Asset names carry no version, so
releases/latest/download/… (which site/install.sh uses) always gets the
newest one. Tags with a - (v0.2.0-rc.1) become prereleases, which
latest skips.
site/ is deployed to GitHub Pages by .github/workflows/pages.yml whenever
it changes on main; make site assembles it in dist/site/.
make dev
This runs lor-server serve --dev on http://localhost:8444 (admin) and
https://127.0.0.1:8443 (agent API) with a throwaway data dir in
.dev-data/, plus the Vite dev server on http://localhost:5173 with hot
reload (it proxies /api to the Go server). Open
http://localhost:5173/setup and use the LOR_DEV_SETUP_CODE printed at
startup. --dev is a command-line flag only: plain HTTP, 127.0.0.1, passkey
RP ID localhost. It can't be set from the config file.
Lor runs in its own small LXC (the plan uses an Ubuntu 26.04 LXC on the NAS: 1 vCPU, 512 MB RAM). Copy the two static binaries; nothing else is needed.
Proxmox notes from the field test: unprivileged Ubuntu 26.04 LXCs (systemd
259) need features: nesting=1, or journald/networkd fail with
243/CREDENTIALS; Docker targets also need keyctl=1. pct exec runs with a
PATH that doesn't include /usr/local/bin, so call
/usr/local/bin/lor-server with its full path there.
Install the server on the Lor LXC. The installer does all of this
(curl -fsSL https://lor.hyperf.app/install.sh | sudo sh -s -- --server)
except starting the service; by hand, from a release archive or bin/:
install -m 0755 bin/lor-server /usr/local/bin/
useradd --system --home /var/lib/lor --shell /usr/sbin/nologin lor
install -d -m 0755 /etc/lor
install -m 0644 deploy/lor-server.toml /etc/lor/lor-server.toml # then edit it
install -m 0644 deploy/lor-server.service /etc/systemd/system/
systemctl daemon-reload && systemctl enable --now lor-server
In /etc/lor/lor-server.toml, set public_url (your Caddy site),
admin_listen and agent_listen (the Lor LXC's fixed LAN IP, ports
8444 and 8443), and trusted_proxy (the Caddy LXC's LAN IP).
This is the beginning of the README. Read the rest at the original. Read the full README ↗