mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-02 13:39:41 +02:00
codeman tui supersedes the sc bash chooser: it reaches sessions 10+, carries the server's real states instead of a static list, and leaves an attach with one key. Every place that told a user to run sc now names the tui equivalent, including the two wiki pages and install.sh's next-steps banner. Both wiki pages also carried the wrong detach chord (Ctrl+A D; the socket's prefix is C-b), which the tui makes moot. Source comments that explained themselves as "the sc -l replacement" now just say what they do. docs/tui-plan.md and CHANGELOG.md are historical records and keep their references.
213 lines
9.7 KiB
Markdown
213 lines
9.7 KiB
Markdown
# Remote Access
|
|
|
|
Reaching your Codeman from a phone, a laptop on the other side of the house, or a hotel
|
|
network. This is the page to read carefully, because Codeman's dashboard is a
|
|
remote-code-execution surface by design: it starts agents with permission prompts skipped,
|
|
so whoever can reach it can run code on your machine.
|
|
|
|
## Start from the default
|
|
|
|
`codeman web` binds `127.0.0.1`. It is reachable from the machine running it and nothing
|
|
else, which is why the no-password default is safe out of the box. Every option below is a
|
|
deliberate step away from that.
|
|
|
|
Two rules that make the rest of this page simple:
|
|
|
|
1. **Never expose Codeman on a network without `CODEMAN_PASSWORD`.** Binding a non-loopback
|
|
host without one starts, but prints a loud warning with the fixes.
|
|
2. **Prefer keeping the loopback bind** and putting an authenticated tunnel in front of it,
|
|
over binding wide and relying on a password alone.
|
|
|
|
## Pick an approach
|
|
|
|
| Approach | Good for | Cost |
|
|
| --------------------- | ----------------------------------------------------- | --------------------------------------------------------- |
|
|
| **Tailscale** | Phone access, permanently. The recommended setup. | Install Tailscale on both devices. |
|
|
| **Cloudflare tunnel** | A public URL, quickly, from anywhere. | Public URL, so a password is mandatory. |
|
|
| **LAN + password** | Home network only, no extra software. | Every device on your LAN can reach the login page. |
|
|
| **SSH port forward** | You already SSH to the box. | Manual, per session, terminal-bound. |
|
|
|
|
## Tailscale (recommended)
|
|
|
|
Your devices join a private network, and Codeman stays bound to loopback. Nothing is
|
|
published to the internet, and you get real HTTPS with a real certificate.
|
|
|
|
The installer sets this up for you, including installing Tailscale, logging in, enabling
|
|
tailnet HTTPS, and verifying the result end to end. To retrofit it onto an existing
|
|
install:
|
|
|
|
```bash
|
|
install.sh tailscale
|
|
```
|
|
|
|
By hand:
|
|
|
|
```bash
|
|
tailscale serve --bg 3000
|
|
tailscale serve status
|
|
```
|
|
|
|
Then open `https://<machine>.<tailnet>.ts.net` from any device on your tailnet.
|
|
|
|
Notes:
|
|
|
|
- Keep the loopback bind. `tailscale serve` connects to `127.0.0.1:3000` locally, so
|
|
binding wider adds exposure and buys nothing.
|
|
- Your tailnet is the authentication boundary. Setting `CODEMAN_PASSWORD` as well is
|
|
reasonable defence in depth, especially if other people have devices on your tailnet.
|
|
- Codeman's Host-header allowlist already accepts `.ts.net`, so no extra configuration is
|
|
needed.
|
|
- The installer never resets or rewrites `serve` mappings other than the one pointing at
|
|
Codeman's port, so unrelated serve configuration is left alone.
|
|
|
|
## Cloudflare tunnel
|
|
|
|
A free [quick tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/)
|
|
gives you a public HTTPS URL with no port forwarding, no DNS, and no static IP:
|
|
|
|
```
|
|
Browser → Cloudflare edge (HTTPS) → cloudflared → localhost:3000
|
|
```
|
|
|
|
Prerequisites: [`cloudflared`](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/)
|
|
installed, and `CODEMAN_PASSWORD` set.
|
|
|
|
```bash
|
|
./scripts/tunnel.sh start # starts the tunnel, prints the public URL
|
|
./scripts/tunnel.sh url
|
|
./scripts/tunnel.sh status
|
|
./scripts/tunnel.sh stop
|
|
```
|
|
|
|
The quick-tunnel URL is a random `*.trycloudflare.com` address that changes every time the
|
|
tunnel restarts. For a stable hostname, `./scripts/tunnel.sh named setup` walks through a
|
|
named tunnel.
|
|
|
|
To survive reboots:
|
|
|
|
```bash
|
|
systemctl --user enable codeman-tunnel
|
|
loginctl enable-linger $USER
|
|
```
|
|
|
|
There is also a toggle in **App Settings → System → Remote access**.
|
|
|
|
**The tunnel refuses to start without a password.** That is on purpose: a public URL with no
|
|
authentication is a terminal on your machine handed to the internet. Acknowledging the risk
|
|
explicitly is possible from the UI toggle, and only from there; the API will not do it for
|
|
you.
|
|
|
|
## LAN plus password
|
|
|
|
```bash
|
|
export CODEMAN_PASSWORD='something long'
|
|
codeman web -H 0.0.0.0 --https
|
|
```
|
|
|
|
Every device on your local network can now reach the login page. `--https` generates a
|
|
self-signed certificate into `~/.codeman/certs/`, which your browser will warn about once.
|
|
|
|
`CODEMAN_USERNAME` defaults to `admin`.
|
|
|
|
The installer offers this path and prompts for the password. On re-runs it preserves
|
|
whichever binding you already chose.
|
|
|
|
## SSH port forward
|
|
|
|
No configuration at all, if you already have SSH access:
|
|
|
|
```bash
|
|
ssh -L 3000:localhost:3000 you@your-box
|
|
```
|
|
|
|
Then open `http://localhost:3000` on the local machine. Codeman keeps its loopback bind and
|
|
sees a local connection. Good for occasional access, awkward as a permanent arrangement
|
|
because it dies with the SSH session.
|
|
|
|
## Logging in from a phone
|
|
|
|
Typing a long password on a phone keyboard is miserable, so Codeman issues **single-use QR
|
|
tokens**. The desktop dashboard shows a QR code; scan it and the phone is authenticated.
|
|
|
|
How it behaves:
|
|
|
|
- The code rotates every 60 seconds, with a 90 second grace window so scanning during a
|
|
rotation still works.
|
|
- Each token is **single use**. The moment a phone consumes it, a new one is generated.
|
|
- The URL contains a 6-character lookup code, not the secret, so it does not leak through
|
|
browser history, `Referer` headers, or the tunnel provider's logs.
|
|
- The desktop shows a toast naming the device and browser that just authenticated, with a
|
|
one-click revoke.
|
|
- QR attempts are rate limited separately from password attempts, so a mistyped password
|
|
cannot lock out your QR login and vice versa.
|
|
|
|
Someone holding only the tunnel URL still meets the normal password prompt. The QR is the
|
|
fast path, not a bypass.
|
|
|
|
Design detail and the threat analysis it is built against:
|
|
[`docs/qr-auth-plan.md`](https://github.com/Ark0N/Codeman/blob/master/docs/qr-auth-plan.md).
|
|
|
|
## Behind a reverse proxy
|
|
|
|
Codeman enforces a Host-header allowlist on every request to block DNS rebinding, and the
|
|
same allowlist gates the cross-site Origin check. It accepts `localhost`, IP literals, the
|
|
bind host, `.ts.net`, `.trycloudflare.com`, `.cfargotunnel.com`, and the active managed
|
|
tunnel.
|
|
|
|
**Your own domain is not on that list.** Add it:
|
|
|
|
```bash
|
|
CODEMAN_ALLOWED_HOSTS='codeman.example.com,.internal.example.com'
|
|
```
|
|
|
|
A bare entry matches that exact host; a leading dot matches subdomains. Without this, a
|
|
correctly configured proxy still gets `403 host not allowed`, which reads like a proxy bug
|
|
and is not one.
|
|
|
|
Also make sure the proxy forwards WebSocket upgrades. The terminal is a WebSocket, and the
|
|
upgrade runs the same Host and Origin checks, closing with code `4003` on failure.
|
|
|
|
## Session cookies and rate limits
|
|
|
|
The first request prompts for HTTP Basic credentials. On success the server issues an opaque
|
|
`codeman_session` cookie (24 hour lifetime, extended on activity, validated server-side so
|
|
it cannot be forged offline). Ten failed attempts from one IP produce a `429` with a 15
|
|
minute decay.
|
|
|
|
A valid cookie or a correct password recovers immediately even while an attacker is hammering
|
|
the same IP, which matters because all tunnel traffic arrives from one loopback address.
|
|
|
|
## Terminal alternatives
|
|
|
|
You do not have to use a browser. `codeman tui` is a full-screen session dashboard that
|
|
works well in SSH clients like Termius or Blink:
|
|
|
|
```bash
|
|
codeman tui # the dashboard
|
|
codeman tui 2 # attach straight to session 2
|
|
codeman tui --list # numbered list, then exit
|
|
```
|
|
|
|
`Enter` attaches into the pane and `F1` comes back. Under 72 columns it drops the preview
|
|
and becomes a single-column list, so it stays usable on a phone. The sessions are the same
|
|
ones the dashboard shows. See [docs/tui.md](https://github.com/Ark0N/Codeman/blob/master/docs/tui.md)
|
|
for the full guide.
|
|
|
|
## Common problems
|
|
|
|
| Symptom | Cause and fix |
|
|
| ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
| `403 host not allowed` | Your domain is not in the allowlist. Set `CODEMAN_ALLOWED_HOSTS`. |
|
|
| Phone shows the login page but the terminal never connects | The proxy is not forwarding WebSocket upgrades. |
|
|
| Browser warns about the certificate | Expected with `--https` and its self-signed certificate. Tailscale gives you a real one instead. |
|
|
| LAN IP does not respond, but a tunnel to the same box works | The server is bound to loopback. That is the default. A tunnel reaches it; a LAN browser cannot. |
|
|
| Hooks stopped working after switching to HTTPS | Hook callbacks need `-k` for the self-signed certificate. Recent versions self-heal existing cases; if yours predates that, recreate the case's hooks. |
|
|
| Everything is slow over the tunnel | Quick tunnels route through Cloudflare's edge. Tailscale is usually a direct connection and much faster. |
|
|
|
|
## Read next
|
|
|
|
- [Security](Security) - the whole model, and the hardening checklist.
|
|
- [Mobile Guide](Mobile-Guide) - once you can reach it from the phone.
|
|
- [Running As A Service](Running-As-A-Service) - keeping server and tunnel up across reboots.
|
|
- [`docs/security-architecture.md`](https://github.com/Ark0N/Codeman/blob/master/docs/security-architecture.md) - the full model.
|