M1 · Proxies & VPNs page and the Add egress wizard

Each earning service pays once per public IP. Today, extra IPs (proxies, a second site over Tailscale) live at the bottom of Fleet, owner-only, one 9-field form per proxy, no VPN option, and a green Test only proves a TCP connection. This plan gives them their own page, a paste-many dialog, a test that checks each vendor through the proxy, and a CLI line for every action.

Mockup, dark theme, data fake (IPs from 203.0.113.0/24, ASN 64500). Colours, type and components are copied from app/static/css/style.css on origin/main. Purple numbered circles are notes for the reader, not part of the UI.

BEFORE Adding ten proxies today

Current Add a proxy form, nine fields

Fleet → scroll → “Add a proxy”

  • Lives inside Fleet below the boxes, owner-only (fleet.html:76-80). Not in the nav, not in the setup wizard.
  • One proxy = Name, Type, Host, Port, User, Password, Cap, Stop %, Reset day, Rotating, Save (fleet.html:92-110). A provider sends a list of 10: ≈ 80 inputs plus 10 Saves.
  • Types: SOCKS5, HTTP, Tailscale exit (fleet.html:93-96). No WireGuard or OpenVPN file, no provider picker.
  • Test checks the tunnel and exit IP only (tunnel/cp-probe:8-14): a proxy that 403s PacketStream still shows green, and the copy earns nothing.
  • Running a copy is a second form with three selects, one copy per submit (fleet.html:114-123).
  • Keyboard: no shortcut reaches it; Tab from the top of Fleet takes 30+ presses (screenshot 36-kbd-fleet-proxy.png).

SCREEN 1 Proxies & VPNs page, reached with g e

One row per way out to the internet, starting with the box's own line. Status means “the services can earn through it”, not “a socket opened”.

CashPilot
+ Add service$148.32S

Proxies & VPNs

Test all Copy as CLI + Add egress n

Each service pays once per public IP. Every row here is another IP your services can earn from. How egress works

IPs
4
3 earning
Copies running through egress
5
across 2 boxes
Egress traffic this month
16.4 GB
2.1 GB on capped plans
Net, this month
−$5.88
isp-1 costs more than it earns

Ways out 4

tested 6 min ago · t test selected
NameTypeStatusExit IPCountryIP typeCopiesTrafficCost vs earningsKill switch
This box's own IP
box-a
DirectWorksx.x.x.42SpainResidential6not counted
your own line
n/aTest
isp-1
203.0.113.10:1080
SOCKS5sticky
Worksx.x.x.10SpainResidential/ISP3 2.1/10 GB
resets on day 1
$3.00/GB cost~$0.20/GB earnedlosing money
OnTestPlace⋯
site-b
exit node at a second site
Tailscale exitvia box-b
Worksx.x.x.77SpainResidential214.3 GB
no cap
no cost set~$0.20/GB earned
OnTestPlace⋯
wg-mullvad
mullvad-se-sto.conf
WireGuardfrom file
Worksx.x.x.201SwedenDatacenter00 GB
no cap
$5.00/month
OnTestPlace⋯

4 of your services do not pay on datacenter IPs (Honeygain, EarnApp, IPRoyal Pawns, PacketStream). Mysterium and Storj do. Place only the ones that pay

Kill switch: a copy that runs through an egress has no route to the box's own line. If the egress drops, the copy stops instead of leaking out of your home IP.

CashPilot 2.2.0Press g then a page's first letter to jump, / to search, ? for all keys
1 2 3 4 5 6 7 8 9
  1. 1Own nav item, visible to every role. g e jumps here; the hint shows when the link has focus. Today proxies are a section of Fleet behind {% if user.r == 'owner' %} (fleet.html:76). Viewers see the table read-only; only the owner sees Add.
  2. 2One primary action, with a key. n opens the Add egress dialog from anywhere on the page. Today: scroll, find the collapsed <details>, open it (3 actions before the first field).
  3. 3The box's own IP is row one. It is the baseline every other row is compared to, and it makes the rule “one payout per IP” obvious without reading docs. Exit IPs are masked to the last octet by default (screenshots get shared); Shift-click reveals.
  4. 4“Works” means the vendors answer through it, not only that the tunnel opened (see Screen 3). Other values: Partly some vendors blocked, Down, Untested.
  5. 5Cost vs earnings. Cost per GB from the plan the user typed; earnings per GB from the copies' own balance history. Red “losing money” when cost > earnings. Today there is a cap but no cost, so a paid proxy can burn money silently.
  6. 6Kill switch shown, not assumed. Green only after the test proved the copy has no route to the home line (the probe tries the direct route and expects it to fail).
  7. 7Datacenter warning names the services. The list comes from the catalog's residential_ip: true key in services/**/*.yml; the link opens Place with only the services that pay pre-ticked.
  8. 8Totals first. How many IPs, how many earn, what egress cost this month. Net in red when negative.
  9. 9Copy as CLI (wave 3, L5) puts the equivalent commands on the clipboard: cashpilot egress ls --json, cashpilot egress test --all. The same affordance sits in every dialog footer.

STATES Empty, and the 390-wide phone layout

empty · first visit, owner

Proxies & VPNs

+ Add egress n
This box's own IP
box-a
Worksx.x.x.42SpainResidential6 services
Each service earns once per IP. Add another IP.

Paste a proxy list from your provider, drop a WireGuard or OpenVPN file, or pick a Tailscale exit node at another site. CashPilot tests each one against the services you run before placing anything.

Paste proxiesVPN fileTailscale exit node
$ cashpilot egress add 'socks5://user:pass@host:1080' --name isp-1Copy

loading

Loading egress and their last test

error · the API is unreachable

Could not read egress: the server answered 502. Nothing was changed. Retry r

390 × 844

Proxies & VPNs$148.32≡
4 IPs · 3 earning · net −$5.88
This box's own IPWorks
Direct · box-aSpainResidential6 services
isp-1Works
SOCKS5SpainResidential/ISP3 copies
2.1/10 GBlosing money
site-bWorks
Tailscale exitSpainResidential2 copies
wg-mullvadWorks
WireGuardSwedenDatacenter0 copies

4 of your services do not pay on datacenter IPs.

+ Add egress
10
  1. 10Cards, not a 11-column table, under 640 px. Same facts in two lines; Add stays reachable at the thumb.

SCREEN 2 Add egress, Paste tab: ten proxies in one paste

Every common provider format is parsed live. Bad lines are shown with their reason and skipped, never silently dropped.

CashPilot
$148.32S

Proxies & VPNs

1 2 3 4 5 6 7
  1. 1Four tabs, one dialog. Paste covers proxy lists; VPN file or provider takes a WireGuard .conf / OpenVPN .ovpn drop or a provider picker (adds a gluetun-style sidecar, no VPN client on the host); Tailscale is Screen 4; By hand is today's form. Digits switch tabs.
  2. 2Paste is the default and is focused on open, so n then Ctrl V is the whole input step. Passwords are masked in the box the moment they are parsed.
  3. 3Live preview, one row per line. The parser in app/proxies.py gains parse_proxy_line(); the API takes a list (POST /api/egress/batch). Today the API takes one proxy per call (app/proxies.py:24).
  4. 4Bad line in red with the reason, skipped, counted out of the Add button (“Add 3”, not 4). Fixing it in the textarea updates the row at once.
  5. 5Shared fields typed once. Ten proxies from one plan share cap, reset day and price. Rotation is measured, not asked (Screen 3).
  6. 6Copy as CLI (wave 3, L5) with the exact flags the dialog holds, passwords excluded (the file keeps them). An agent can do the same with one command.
  7. 7Test before Add. Enter tests all parsed lines in parallel; Add stays available but warns if a line has not passed. ten proxies: ≈ 80 inputs → 3 keys (n, Ctrl V, Enter) plus one click to add.
Keyboard n opens the dialog, focus in the paste box→ Ctrl V pastes, preview fills→ Tab reaches Test all→ Enter runs it→ Esc closes, focus returns to “+ Add egress”

SCREEN 3 Test result: what the IP is, and which vendors answer through it

The probe in tunnel/cp-probe already fetches the exit IP. It gains three checks: IP type from the ASN, rotation from three samples, and a reach test against each deployed service's own endpoints through the egress.

CashPilot
$148.32S
1 2 3 4 5 6
  1. 1IP type with the network's name. Residential, Residential/ISP, Datacenter, Mobile, from the ASN of the exit IP. Users buy “residential” proxies that turn out to be hosting ranges; this shows it before money is spent.
  2. 2Rotation is measured. Three samples. Same IP = sticky; different = rotating, and the rotating box ticks itself. Today it is a checkbox the user must know to tick (fleet.html:109).
  3. 3Vendor reach, per deployed service. One request to each vendor's endpoint (the new docker.egress list of {host, port} in the service YAML) through the egress. This is the check whose absence made copies run green and earn nothing.
  4. 4Failures say what to do, in plain words, not an HTTP dump. Ports come from the service YAML.
  5. 5Services that cannot run through any egress are greyed, with the reason the code already enforces (no host networking, ports, volumes or devices, fleet.html:121).
  6. 6Place earners pre-selects only the services that passed, on the boxes that already run them, and asks once. Today: one “Run a copy” submit per service per proxy (fleet.html:114-123).

loading · reach test running

Testing isp-1 · exit IP done · rotation 2 of 3 samples · vendors 3 of 5
Esc closes this; the test keeps running and the row updates when it ends.

error · the egress itself is unreachable

Could not connect to 203.0.113.13:1080: connection refused after 5 s. The host is up but nothing listens on that port. Check the port in your provider's panel.

Edit portRetry tRemove

SCREEN 4 Tailscale tab: connect once, pick an exit node

Today the user creates an auth key in the Tailscale admin, pastes it, and types the exit node name or its 100.x address (fleet.html:103-105). Here CashPilot signs in with Tailscale OAuth and lists the nodes that can be exits.

CashPilot
$148.32S
1 2 3 4 5
  1. 1Connect Tailscale runs an OAuth flow and stores a read-only client. The button greys after it works and the tailnet name shows, with Disconnect beside it. Self-hosted Headscale keeps the By hand tab (login server field).
  2. 2A picker instead of a typed name or 100.x address. Online dot, last seen, exit country. Already-added nodes are ticked and labelled. Arrow keys and Space work.
  3. 3Offline nodes stay listed but greyed, so the user does not wonder where “travel-router” went.
  4. 4Missing-grant state, specific. The error comes back from the tailscale sidecar; the screen names the node and the reason instead of a generic failure.
  5. 5The exact JSON to paste, with Copy, and a link that opens the admin page. CashPilot never asks for a write token to the policy file.

CLI · API Same actions without the browser

Every dialog above has a Copy as CLI line (wave 3, L5). The CLI is a thin client over the same REST endpoints (bearer token from Settings → API tokens), so a person in a terminal and an agent such as Claude Code get identical behaviour.

$ cashpilot egress import proxies.txt --default-type socks5 --cap 10GB --reset-day 1 --test added isp-2 socks5 203.0.113.10:1080 Works Residential/ISP ES sticky added isp-3 socks5 203.0.113.11:8080 Partly Residential/ISP ES rotating PacketStream blocked (403) added isp-4 http 203.0.113.12:3128 Works Datacenter DE sticky 4 services do not pay on datacenter IPs skipped line 4 203.0.113.13:dave:****** port missing 3 added, 1 skipped. Next: cashpilot copy apply --egress isp-2 --earners $ cashpilot egress test isp-1 --json { "name": "isp-1", "status": "works", "exit_ip": "203.0.113.10", "country": "ES", "ip_type": "residential_isp", "asn": 64500, "asn_name": "Example Telecom", "rotation": { "samples": 3, "distinct": 1, "verdict": "sticky" }, "kill_switch": true, "reach": [ { "service": "honeygain", "result": "ok", "http": 200, "ms": 180 }, { "service": "repocket", "result": "ok", "http": 200, "ms": 240 }, { "service": "packetstream", "result": "blocked", "http": 403 }, { "service": "traffmonetizer", "result": "port_closed" }, { "service": "earnapp", "result": "not_applicable", "reason": "uses_volume" } ], "cost": { "per_gb_usd": 3.0, "earned_per_gb_usd": 0.20, "verdict": "losing_money" } } $ cashpilot copy apply --egress isp-1 --earners --dry-run would run honeygain on box-a via isp-1 would run repocket on box-a via isp-1 exit 0 · nothing changed (--dry-run). Exit codes: 0 ok, 1 error, 2 usage, 3 auth or scope, 4 not found, 5 refused for safety, 6 box offline, 7 partial, 8 conflict.
  1. AHuman output by default, --json for agents, stable field names, documented exit codes so a script or an agent can branch without parsing prose.
  2. B--dry-run on every write and a “Next:” hint after each command. Docs page docs/egress.md carries a copy-paste block per provider format, and docs/agents.md lists the commands and exit codes for agents.