Install — Linux
Install on Linux
Section titled “Install on Linux”Zero to working proxy in ~1-2 minutes on a fast network. Tested on Ubuntu 22.04 / 24.04, Debian 12, and Alpine 3.20. Other glibc-based distros likely work but aren’t part of the install matrix.
0. Prerequisites
Section titled “0. Prerequisites”# Check distro + glibcuname -a; ldd --version 2>&1 | head -1
# Check curl + tar (install if missing)command -v curl tarYou do NOT need: Python pre-installed, pyenv, sudo (for non-root install), Docker.
If you’re missing curl/tar:
# Debian/Ubuntusudo apt-get update && sudo apt-get install -y curl tar ca-certificates
# Alpine (busybox tar can't unzstd — install GNU tar + zstd)sudo apk add --no-cache bash ca-certificates curl tar zstd1. Install
Section titled “1. Install”curl -sSL https://worthless.sh | shThe installer drops uv and worthless into ~/.local/bin/. No
password prompts. install.sh runs entirely in $HOME — it does not
need sudo and won’t ask for it.
If you see your shell may need ~/.local/bin on PATH, add the
suggested line to your shell rc:
# bashecho 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
# zshecho 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
# fishecho 'set -gx PATH "$HOME/.local/bin" $PATH' >> ~/.config/fish/config.fishThen source it or open a new terminal.
2. Verify install
Section titled “2. Verify install”worthless --versionExpected:
worthless 0.3.33. First lock
Section titled “3. First lock”Linux uses Secret Service (GNOME Keyring / KWallet / kwallet5)
where available. On servers without a session bus, worthless falls
back to a file-backed keystore in ~/.worthless/.
cd /path/to/your/projectcat .env# OPENAI_API_KEY=<your-real-openai-key-here>
worthless- On a desktop with GNOME / KDE: a credential prompt may appear once (varies by desktop env). Grant access permanently.
- On a server with no DBus session: no prompt — worthless uses the
file-backed fallback at
~/.worthless/.fernet-key(mode 0600).
.env is rewritten (see README — what worthless lock does) and the proxy spawns on 127.0.0.1:8787.
4. Point your app at the proxy
Section titled “4. Point your app at the proxy”Your app reads .env via dotenv / direnv / your framework — no code
change. SDK picks up OPENAI_BASE_URL automatically.
For systemd-managed services that DON’T inherit .env, add the URL
to your service unit’s Environment= directive:
[Service]EnvironmentFile=/path/to/your/project/.env5. Verify
Section titled “5. Verify”See README — Verify it works for the SDK snippet. Same on every platform.
6. Daily use
Section titled “6. Daily use”| You do | What survives | What you do |
|---|---|---|
| Close terminal | Proxy keeps running | Nothing |
worthless down | Proxy stops | worthless up |
| Reboot machine | Proxy is gone | worthless up |
| Logout / login | Depends on your session manager — usually proxy dies | worthless up |
Why no auto-start? (the reboot gap)
Section titled “Why no auto-start? (the reboot gap)”WOR-175 (Linux systemd user service) ships
the install/uninstall commands in v1.1. Until then, write your own
systemd user unit. Copy-paste this into
~/.config/systemd/user/worthless-proxy.service (replace
/home/youruser with your actual $HOME):
[Unit]Description=Worthless local proxyAfter=network.target
[Service]ExecStart=/home/youruser/.local/bin/worthless upRestart=on-failureRestartSec=5s
[Install]WantedBy=default.targetThen enable it:
systemctl --user daemon-reloadsystemctl --user enable --now worthless-proxy.serviceloginctl enable-linger "$USER" # so the unit survives logoutIf you don’t want a service file (e.g. ephemeral dev machine), the
fallback is the same shell-rc opt-in pattern — but be aware silently
auto-spawning daemons from your .bashrc is a tradeoff worth knowing
about, not the recommended path.
7. Uninstall (manual, until WOR-435 ships)
Section titled “7. Uninstall (manual, until WOR-435 ships)”worthless downuv tool uninstall worthless
# Purge Secret Service entries (if used)secret-tool clear service worthless 2>/dev/null
# Wipe local state (file-backed keystore + DB)rm -rf ~/.worthlessCommon failures
Section titled “Common failures”| Symptom | Cause | Fix |
|---|---|---|
| ”command not found: worthless” | ~/.local/bin not on PATH | Add to shell rc per §1 |
Alpine: uv install fails on tar -xzst | busybox tar can’t unzstd | apk add tar zstd |
Failed to install worthless==X.Y.Z (network) | curl/uv blocked | Set HTTPS_PROXY=... and re-run |
| Proxy starts but health check fails | Port 8787 in use | lsof -i :8787 to find the squatter |
| Server with no session bus, install hangs at keychain step | keyring waiting for unavailable service | This shouldn’t happen; if it does, file an issue with keyring --list-backends output |
App in container can’t reach 127.0.0.1:8787 | Container loopback ≠ host | See docker.md |
What worthless does NOT defend against on Linux
Section titled “What worthless does NOT defend against on Linux”- A compromised user account. Same as macOS — if attacker has user shell access, they can read shard A + the file-backed keystore + query the proxy.
- Containerized apps without proper networking — see docker.md.
- Multi-user systems.
~/.worthless/is mode 0700 but other admins on the box can still read it. worthless is a per-user tool.
For AI agents
Section titled “For AI agents”Human readers can stop here — the YAML below is for AI agents.
Schema documented in agent-schema.md.
schema_version: 1platform: linuxcommands: install: "curl -sSL https://worthless.sh | sh" verify: "worthless --version" first_lock: "worthless" proxy_restart: "worthless up"expectations: install_succeeds_silently: true # Servers (no DBus): 0. GNOME/KDE desktop with keyring: 1. Strict YAML # readers should treat 0 as the headless-server default and add 1 if a # session bus is detected at runtime. first_lock_keychain_popups: 0 first_lock_requires_human_interaction: false # true on GNOME/KDE if keyring is locked subsequent_command_keychain_popups: 0 proxy_starts_automatically_on_lock: true proxy_survives_reboot: falseproxy: url_template: "http://127.0.0.1:8787/<alias>/v1" port: 8787service_install: # Agents must run all three for "survives reboot" — the unit alone isn't enough. unit_path: "~/.config/systemd/user/worthless-proxy.service" unit_text: | [Unit] Description=Worthless local proxy After=network.target
[Service] ExecStart=%h/.local/bin/worthless up Restart=on-failure RestartSec=5s
[Install] WantedBy=default.target enable_commands: - "systemctl --user daemon-reload" - "systemctl --user enable --now worthless-proxy.service" - "loginctl enable-linger \"$USER\"" # REQUIRED on headless boxes; without it the unit dies on logoutlimitations: - "Manual `worthless up` after reboot UNLESS service_install applied — WOR-175 ships managed install/uninstall in v1.1" - "service_install is per-user; if app runs as a different user, install worthless under that user too" - "On servers with no DBus session, fernet key lives at ~/.worthless/.fernet-key (mode 0600)" - "uv tool uninstall doesn't purge keystore — WOR-435"