Files
proxy/README.md
T

146 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# proxyctl
`proxyctl` is a keyboard-driven Linux TUI for coordinating one **Active Profile** across independently switchable proxy **Targets**. It manages proxy configuration surfaces; it does not run a proxy server.
## Supported systems
The v1 binaries target Linux on amd64 and arm64. General TUI behavior and the Shell Target are distribution-independent. The supported Target boundaries are:
- **Shell:** Bash and Zsh only.
- **APT:** Debian-family systems with `apt-config` and `apt.conf.d`.
- **Docker daemon:** Docker installations managed by systemd.
- **Docker containers/builds:** the standard per-user Docker client `config.json` model.
- **GNOME:** sessions exposing the expected `org.gnome.system.proxy` settings schemas.
Unavailable Targets are hidden from the main panel; `?` opens contextual, scrollable Help over the current page and includes every built-in Target and its detection evidence.
## Install
### Verified release binary
Download the binary for your architecture together with `SHA256SUMS`, then verify it before installing:
```sh
grep 'proxyctl-linux-amd64$' SHA256SUMS | sha256sum -c - # substitute arm64 when needed
chmod +x proxyctl-linux-amd64 # use proxyctl-linux-arm64 on arm64
install -m 0755 proxyctl-linux-amd64 "$HOME/.local/bin/proxyctl"
proxyctl version
proxyctl version --short # exact value only, for scripts
```
Release output is two single binaries, not packages or archives. The project does not publish deb, rpm, AUR, Snap, Flatpak, or similar packages.
### Install from source with Go
Go 1.24 or newer is required. From a source checkout:
```sh
go install ./cmd/proxyctl
```
The executable is placed in `GOBIN`, or in `$(go env GOPATH)/bin` when `GOBIN` is unset. Ensure that directory is on `PATH`. Source builds report `dev` unless a release version is injected by release automation.
## First use and Profiles
Start the Target panel with no arguments:
```sh
proxyctl
```
Press `m` for Proxy Profile management, then `n` to create a Profile, enter a name and proxy URL, and press Ctrl+S to save. The editor supports cursor movement, Home, End, Delete, Backspace, insertion, paste, and horizontal scrolling; Tab or the arrow keys move between fields, and Escape cancels without saving. Validation stays beside each field. The management page supports reviewing obscured connection details, editing, and safe deletion; Active Profile switching remains a separate dashboard picker workflow rather than a management action. Single mode applies one URL to HTTP, HTTPS, and ALL/SOCKS. Ctrl+T selects advanced mode for separate values without discarding values entered in either mode. A bare `host:port` is accepted and normalized to `http://`. The Single proxy URL field visibly offers Protocol Probe with Ctrl+D; it runs only on that explicit keypress, and its credential-safe progress and HTTP/SOCKS5 result stay with the initiating URL context rather than global status. When one endpoint supports both protocols, the probe switches the form to advanced mode, retains a read-only Single URL probe source row, and fills HTTP/HTTPS with `http://` and ALL/SOCKS with `socks5://`. Bypass accepts comma- or newline-delimited hostnames, domain suffixes, IPv4, IPv6, and CIDR entries; the editor previews normalized, deduplicated values and identifies invalid items before save.
The dashboard shows the Active Profile. Press `p` to open the searchable Active Profile picker, type to filter, use arrows to select, and press Enter to activate; Escape cancels without changing the Active Profile. Use arrows or `j`/`k` to select an Available Target and Space to run its contextual action: Enable, Disable, Apply Profile, or Resolve. Drift Resolution explicitly offers Reapply Active Profile and Restore Original; restoration refuses safely if proxyctl no longer has sufficient ownership evidence. Press `r` to refresh detection, `u` to show unavailable Targets, and `?` on any page or dialog for contextual Help. Help scrolls with arrows, `j`/`k`, Page Up/Page Down, Home, and End; `q` or Escape closes it without changing the page, focus, selection, or viewport beneath it. Applying or reapplying requires an Active Profile, while Restore Original remains available without one.
Escape closes the top dialog or returns one page level. `q` returns from child pages and exits only from the unobscured dashboard (in the searchable Profile picker it remains search input). Ctrl+C requests exit everywhere. If a system mutation is running, either dashboard `q` or Ctrl+C visibly defers exit until the mutation completes safely; Target browsing and Help remain available while conflicting changes are disabled.
## TUI keyboard, responsive, and accessibility behavior
The dashboard is keyboard-only. Up/Down or `j`/`k` moves within the focused region, Tab moves between the Target list and details, Page Up/Page Down scrolls long details, and the fixed footer lists the actions currently accepted. Focus always has a text marker such as `[focused]`, not color alone. Confirmation dialogs start on Cancel; Left/Right or Tab changes the choice and Enter activates it. Errors remain visible until acknowledged or directly resolved and can be expanded with `e`; progress appears both on the affected Target row and in the status area.
At 100×28 and larger, Targets and details are side by side. From 60–99 columns, the same workflow uses a single-column layout. Below 60×16, proxyctl shows only a minimum-size warning; resizing back restores the current page, selection, focus, scroll position, dialog, and in-flight operation. The TUI uses the terminal alternate screen and restores the prior shell screen after normal or safely deferred exit.
State is always communicated by a standard Unicode/ASCII-safe symbol and an explicit word (`● Enabled`, `○ Disabled`, `◇ External`, `! Drifted`, `… Checking`); no Nerd Font is required. Styling adapts to light and dark terminal backgrounds. Set `NO_COLOR` to disable color without losing state, focus, progress, warning, disabled-action, or error meaning.
Profiles are human-readable under the user's XDG configuration directory (normally `~/.config/proxyctl/profiles.json`) and are stored owner-only because proxy URLs may contain credentials.
## Shell integration
A child TUI cannot change its parent Shell. Install the one-time Bash/Zsh startup hook:
```sh
proxyctl shell install
```
Restart or source the startup file once. Thereafter the wrapper reloads proxy exports and unsets after `proxyctl` exits. The Shell Target emits conventional upper- and lower-case `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, and `NO_PROXY` forms. Remove the hook with:
```sh
proxyctl shell uninstall
```
Fish and other Shells are intentionally unsupported in v1.
## What each Target affects
1. **Shell** — commands started by integrated Bash/Zsh sessions. It does not change existing processes, system services, Docker, or desktop settings.
2. **APT** — persistent APT package operations across Shell and privilege boundaries through a tool-owned `apt.conf.d` overlay. It does not configure other package managers and requires no service restart.
3. **Docker daemon** — daemon operations such as registry access. It does not set container networking or container/build defaults. Every change reloads systemd and immediately restarts Docker; confirm only when disruption to running work is acceptable.
4. **Docker containers/builds** — proxy variables and build arguments for future containers and builds via the owning user's Docker client configuration. It does not affect existing containers, the Docker CLI connection, or the daemon.
5. **GNOME** — GNOME system proxy settings used by compatible desktop applications. It does not rewrite browser-specific profiles or configure non-GNOME desktops. GNOME settings cannot express `socks5h` remote-DNS semantics, and the Protocol Probe fills `socks5h` for SOCKS-only endpoints; switch to advanced mode and enter `socks5` when a SOCKS endpoint must work through the GNOME Target.
proxyctl prefers isolated, tool-owned overlays. Where that is impossible it records original values and a last-applied fingerprint so disable/reset can restore prior state safely.
## Target states
- **Enabled:** actual managed configuration matches the Active Profile.
- **Disabled:** no managed or positively recognized external proxy configuration was detected.
- **External:** a recognized proxy configuration exists but is not owned by proxyctl.
- **Drifted:** managed configuration exists but no longer matches the Active Profile, including partial failures or configuration left when the final Profile is deleted.
External detection is best-effort; Disabled does not claim that every possible configuration source was exhaustively searched.
## Permissions, sudo, and restarts
User Targets normally need only user-file permissions. APT and Docker daemon files generally require authority to write system locations, and Docker daemon operations require authority to reload/restart its systemd service.
proxyctl **never** runs `sudo`, `pkexec`, or another elevation mechanism. Permission failures are reported normally. If system Targets are wanted, the user must explicitly start `sudo proxyctl`; under sudo, the invoking user remains the owner of Profiles, Shell, Docker client, and GNOME configuration while current root authority is available to system Targets. In a direct root login, root is the owner. Review the Docker restart warning before confirming any daemon change.
## Diagnose, reset, and remove
Run read-only diagnostics for Profile validity, storage permissions, required commands, Target availability/state, and Target-specific authority:
```sh
proxyctl doctor
```
Before removal, restore every managed Target. The command asks for confirmation and does nothing when declined:
```sh
proxyctl reset
proxyctl shell uninstall
```
Inspect failures and rerun until reset reports no failed managed Target. Then remove the installed executable and, after retaining any desired logs, remove empty proxyctl configuration/state directories. Do not delete recovery state before a successful reset because it may be needed to restore original settings.
## Privacy and safety boundaries
proxyctl has no telemetry, automatic update checks, or automatic proxy-connectivity tests. It does not contact the network on its own; the only network traffic it generates is the user-initiated Protocol Probe (Ctrl+D in the Profile form), a handshake check that never forwards traffic through the proxy and never contacts anything beyond the endpoint itself. Local diagnostic logs are credential-redacted and bounded in size. Every TUI frame defensively redacts credentials from Profile values, Target evidence, progress, notices, errors and command output, and confirmation copy immediately before rendering, including malformed credential-bearing URLs. Profile form frames mask the entire URL userinfo while retaining the underlying value for saving. Proxy credentials remain present where a selected Target requires them, so normal local file security still matters.
proxyctl does **not** manage or supervise proxy processes such as Clash, sing-box, or Xray. It does not manage subscriptions, nodes, latency, routing rules, transparent proxying, TUN/iptables/nftables, arbitrary services or commands, plugins, or a complete headless Profile/Target CLI.
Deferred integrations include DNF, Git-specific settings, npm/pip, arbitrary systemd services, Firefox policies, Chromium launch flags, KDE and other desktops, Snap/Ubuntu Core, Fish, Windows, macOS, distribution packages, mouse interaction, and cross-Target rollback. Conventional Shell variables may already cover some deferred command-line tools.
Support is limited to the Linux architectures and Target boundaries above. When reporting an issue, include `proxyctl version`, redacted `proxyctl doctor` output, distribution/desktop/Shell details, and the affected Target/state. Never include unredacted proxy credentials.
## Build and verification
Create reproducible Linux binaries and checksums without packages or archives:
```sh
VERSION=v1.0.0 ./scripts/build-release.sh
sha256sum -c dist/SHA256SUMS
file dist/proxyctl-linux-amd64 dist/proxyctl-linux-arm64
```
`./scripts/test-release.sh` builds twice, compares binaries and checksum manifests, verifies both checksums, and checks ELF architectures. `./scripts/verify-clean-machine.sh` uses an isolated identity and XDG roots to exercise `go install`, Profile and hermetic Target workflows, doctor, reset cancellation, Shell install/uninstall, removal, and unchanged host-state snapshots.