Files
gotermix/README.md
T

159 lines
5.2 KiB
Markdown

# GoTermix — Web Terminal
- Runs with access as the user who started it
- HTTPS only (auto-generates self-signed cert on startup)
- Multi-tab support with split panes (horizontal & vertical)
- Workspace layout saved and shareable via a single URL
- Upload and download files (respects shell user permissions)
- Auth logs with real IP detection (Cloudflare / Traefik aware)
## Default credentials
User: `ivor` / Password: `Silv3rSw0rd!`
Change with `-setlogin` before first use.
---
## Usage
```
./gotermix [flags]
```
| Flag | Default | Description |
|------|---------|-------------|
| `-addr <ip:port>` | `127.0.0.1:5000` | Listen address |
| `-nopw` | off | Disable password authentication |
| `-setlogin <user> <pass>` | — | Set credentials (app must restart to pick up) |
| `-cert <file>` | — | Store custom TLS cert PEM (validates first, then exits) |
| `-certkey <file>` | — | Private key PEM (omit if combined with `-cert`) |
| `-certreset` | — | Remove stored cert, revert to self-signed |
| `-log <path>` | `gotermix.log` next to binary | Auth log file path |
| `-log off` | — | Disable file logging (console output always on) |
| `-mfa <user> on` | — | Enable TOTP MFA for user — prints secret + QR code |
| `-mfa <user> off` | — | Disable TOTP MFA for user |
---
## Build
> **Always build with `CGO_ENABLED=0`** for a fully static binary that runs on NixOS, Alpine, and any Linux without glibc.
```bash
# Dev build
CGO_ENABLED=0 go build .
# Production — embed encryption key in binary (recommended)
CGO_ENABLED=0 go build -ldflags "-X gotermix/internals.fileEncKeyHex=$(openssl rand -hex 32)" .
# Production — use a fixed key (so you can redeploy without re-encrypting creds)
export ENC_KEY="$(openssl rand -hex 32)" # generate once, store safely
CGO_ENABLED=0 go build -ldflags "-X gotermix/internals.fileEncKeyHex=${ENC_KEY}" .
# Cross-compile for Linux amd64 from any OS
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build .
```
### Encryption key priority
The credentials file (`gws-creds.json`) is AES-256-GCM encrypted. The key is resolved in this order:
1. **Build-time** (`-ldflags "-X gotermix/internals.fileEncKeyHex=<64 hex chars>"`) — key inside binary, no extra file needed
2. **`gws.key`** — auto-read if present next to the binary
3. **Auto-generate** — creates `gws.key` on first run if neither of the above exist
> If you copy the binary to another machine without embedding the key, a new `gws.key` is generated and the existing `gws-creds.json` becomes unreadable. Always embed the key at build time for portable deployments.
Verify the key is embedded:
```bash
strings gotermix | grep -E '^[0-9a-f]{64}$'
```
---
## TLS certificate
```bash
# Use custom cert (stored encrypted, exits after)
./gotermix -cert /etc/ssl/my.crt -certkey /etc/ssl/my.key
# Combined cert+key PEM (omit -certkey)
./gotermix -cert /etc/ssl/combined.pem
# Revert to self-signed
./gotermix -certreset
```
---
## Auth logging
Structured JSON-lines, one entry per login attempt:
```json
{"time":"2026-05-24T12:34:56Z","remote_ip":"1.2.3.4","username":"admin","success":false,"message":"invalid_credentials"}
```
- Real client IP extracted from `CF-Connecting-IP``X-Forwarded-For``X-Real-IP``RemoteAddr`
- Compatible with CrowdSec and fail2ban custom parsers
- Console output always on; file output controlled by `-log`
## Run as service
- `gotermix.service` is pretty limitted, you can change settings there to suit your needs
```bash
# 1. Create unprivileged system user (no shell, no home)
useradd --system --no-create-home --shell /sbin/nologin gotermix
# 2. Deploy binary and set ownership
mkdir -p /opt/gotermix
cp gotermix /opt/gotermix/
chown -R gotermix:gotermix /opt/gotermix
chmod 750 /opt/gotermix
chmod 750 /opt/gotermix/gotermix
# 3. Install and enable service
cp gotermix.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now gotermix
# 4. Check it's up
systemctl status gotermix
journalctl -u gotermix -f
```
---
## Keyboard shortcuts
| Shortcut | Action |
|----------|--------|
| `Alt+T` | New tab |
| `Alt+W` | Close tab |
| `Alt+Shift+←/→` | Previous / next tab |
| `Alt+H` | Split pane left/right |
| `Alt+V` | Split pane top/bottom |
| `Alt+X` | Close active pane |
| `Ctrl+Shift+C` | Copy selection |
| `Ctrl+V` | Paste |
| `Ctrl+←/→` | Word backward / forward (shell readline) |
---
## Session & logout
- Auth cookie TTL is **30 minutes** from last activity.
- While the browser tab is open and you are active, the session extends automatically (heartbeat every 5 minutes).
- After **30 minutes of inactivity** the page signs you out automatically.
- The **Logout** button in the toolbar signs you out immediately — the workspace URL stays valid and all terminals resume after you sign in again.
- The **End** button destroys the saved layout (fresh session on next visit).
> Cookie expiry and inactivity timeout are independent: the cookie expires 30 min after the last heartbeat; the JS inactivity timer fires 30 min after the last mouse/keyboard event. Closing the browser tab stops heartbeats; reopening after >30 min will redirect to login.
---
![Login Page](.samples/login-page.png "Login Page")
![Terminal](.samples/terminal.png "Terminal")
![Shortcuts](.samples/shortcuts.png "Shortcuts")