From 6804fde9da85fdfd3af878f337b8eb15e5b880f1 Mon Sep 17 00:00:00 2001 From: GeiserX <9169332+GeiserX@users.noreply.github.com> Date: Sat, 7 Nov 2026 20:44:11 +0100 Subject: [PATCH 1/2] feat!: ship 2.0 with the worker boxed in, earners fenced off the LAN and proxied copies Adds the What's new in 2.0 page with an upgrade and rollback section, a 2.0 block in the README and the docs home, a 2.0 entry in UPGRADING.md, and moves the CasaOS and Runtipi packages to 2.0.0. --- README.md | 7 + UPGRADING.md | 21 ++ .../casaos/CashPilot/docker-compose.yml | 12 +- .../app-stores/runtipi/cashpilot/config.json | 4 +- .../runtipi/cashpilot/docker-compose.yml | 6 +- docs/index.md | 4 + docs/whats-new-2.0.md | 211 ++++++++++++++++++ scripts/generate_readme_tables.py | 8 +- zensical.toml | 1 + 9 files changed, 263 insertions(+), 11 deletions(-) create mode 100644 docs/whats-new-2.0.md diff --git a/README.md b/README.md index 46a1eae3..96c2aefc 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,13 @@ CashPilot is a self-hosted platform that runs passive income services on your ow ![The CashPilot dashboard: the balance first, a short list of what needs attention (an offline box, a stopped container, a balance it could not read, a payout to confirm), which service runs on which box, earnings per day, and the deployed services table](https://raw.githubusercontent.com/GeiserX/CashPilot/main/docs/images/screenshots/dashboard.png) +## New in 2.0 + +- **The worker is boxed in.** It reaches Docker only through a pinned socket proxy, and only the containers, volumes and networks it created, so a compromised worker cannot read the dashboard's data or its encryption key ([security defaults](https://geiserx.github.io/CashPilot/security-defaults/#docker-socket-proxy)). +- **Earners are fenced off your LAN**, host, tailnet and cloud metadata on new installs; host-networked Mysterium is the exception ([network isolation](https://geiserx.github.io/CashPilot/isolation/)). +- **One box, several IPs.** Proxied copies run an earner through SOCKS5, HTTP CONNECT or a Tailscale exit node, and stop instead of leaking when the proxy dies ([proxied copies](https://geiserx.github.io/CashPilot/proxies/)). +- Coming from 1.x? Read [What's new in 2.0](https://geiserx.github.io/CashPilot/whats-new-2.0/#upgrading-from-1x) before you change the image tags. + ## Features - Starts a Docker service with one click from the catalog; no compose file to write, no YAML to edit. diff --git a/UPGRADING.md b/UPGRADING.md index 00fe664a..c21140b3 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -19,6 +19,27 @@ commands, and [Backing up node identities](docs/backup.md) covers the rest. --- +## 2.0: change the image tags + +**Affects everyone on 1.x.** The compose files pin a release series, so +`docker compose pull` and the in-app **Update** button never move a 1.x install +to 2.0. + +Beyond the fixes since 1.73, 2.0 changes nothing of its own, and it uses the +same database. It is the major version for the releases below, several of which need +a step from you: the socket proxy, owner isolation and its one-shot migration, +and LAN isolation for upgraded installs. + +**What to do.** Back up `/data` and your node identities, then take the 2.0 +compose file for each host (or change every `drumsergio/cashpilot:1.x` and +`drumsergio/cashpilot-worker:1.x` tag to `2.0`) and run +`docker compose up -d --force-recreate`. Coming from before 1.73, also follow +the sections below for your version. +[What's new in 2.0](docs/whats-new-2.0.md#upgrading-from-1x) has a table by +version and how to roll back. + +--- + ## Socket proxy on sockguard 2.4.6: take the new proxy line **Affects you if** your worker runs behind `cashpilot-socket-proxy`. sockguard diff --git a/contrib/app-stores/casaos/CashPilot/docker-compose.yml b/contrib/app-stores/casaos/CashPilot/docker-compose.yml index 180877fc..14bc894a 100644 --- a/contrib/app-stores/casaos/CashPilot/docker-compose.yml +++ b/contrib/app-stores/casaos/CashPilot/docker-compose.yml @@ -2,7 +2,7 @@ name: cashpilot services: cashpilot-ui: - image: drumsergio/cashpilot:1.73.0 + image: drumsergio/cashpilot:2.0.0 container_name: cashpilot-ui deploy: resources: @@ -57,7 +57,7 @@ services: # labelled one, data checked, and keeps the original as -pre-isolation. # It holds the raw socket only while it runs. cashpilot-migrate: - image: drumsergio/cashpilot-worker:1.73.0 + image: drumsergio/cashpilot-worker:2.0.0 container_name: cashpilot-migrate user: "0:0" entrypoint: ["python", "-m", "app.owner_migrate"] @@ -135,7 +135,7 @@ services: en_US: Host folders service containers may bind, comma-separated. Put the same list in the worker's CASHPILOT_PROXY_BIND_MOUNTS. cashpilot-worker: - image: drumsergio/cashpilot-worker:1.73.0 + image: drumsergio/cashpilot-worker:2.0.0 # The proxy's owner label, so the worker may read its own container. labels: cashpilot.deployed-by: worker @@ -397,13 +397,15 @@ x-casaos: index: / port_map: "8080" scheme: http - version: "1.73.0" + version: "2.0.0" update_at: "2026-11-07" release_notes: en_US: |- - - First listing in the store, on CashPilot 1.73.0. + - First listing in the store, on CashPilot 2.0.0. - The worker reaches Docker through a socket proxy that refuses every call it does not make; only the proxy holds the Docker socket. - The proxy keeps the worker away from the dashboard's data and environment: it reaches only containers, volumes and networks labelled cashpilot.deployed-by=worker. + - New installs fence the earners off your LAN, the host, a tailnet and cloud metadata; host-networked Mysterium is not covered. + - Proxied copies run an extra copy of an earner through a SOCKS5, HTTP CONNECT or Tailscale exit-node proxy, so one box earns on several IPs. - The first visit asks for the setup token printed in the cashpilot-ui log, then creates the owner account. website: https://geiserx.github.io/CashPilot/ repo: https://github.com/GeiserX/CashPilot diff --git a/contrib/app-stores/runtipi/cashpilot/config.json b/contrib/app-stores/runtipi/cashpilot/config.json index d2ac682e..a096784e 100644 --- a/contrib/app-stores/runtipi/cashpilot/config.json +++ b/contrib/app-stores/runtipi/cashpilot/config.json @@ -7,7 +7,7 @@ "dynamic_config": true, "id": "cashpilot", "tipi_version": 4, - "version": "1.73.0", + "version": "2.0.0", "categories": ["finance", "automation"], "description": "CashPilot runs passive income services (bandwidth sharing, DePIN, storage and GPU compute) on your own server and shows what they earn in one web dashboard. A worker container starts the services that run in Docker; the dashboard reads the providers' balances into one earnings history.", "short_desc": "Run passive income services and see what they earn.", @@ -17,6 +17,6 @@ "form_fields": [], "supported_architectures": ["arm64", "amd64"], "created_at": 1793750400000, - "updated_at": 1794074579901, + "updated_at": 1794080522087, "min_tipi_version": "4.8.0" } diff --git a/contrib/app-stores/runtipi/cashpilot/docker-compose.yml b/contrib/app-stores/runtipi/cashpilot/docker-compose.yml index f217b5fc..afbad50f 100644 --- a/contrib/app-stores/runtipi/cashpilot/docker-compose.yml +++ b/contrib/app-stores/runtipi/cashpilot/docker-compose.yml @@ -1,6 +1,6 @@ services: cashpilot: - image: drumsergio/cashpilot:1.73.0 + image: drumsergio/cashpilot:2.0.0 networks: - cashpilot_owned ports: @@ -24,7 +24,7 @@ services: # labelled one, data checked, and keeps the original as -pre-isolation. # It holds the raw socket only while it runs. cashpilot-migrate: - image: drumsergio/cashpilot-worker:1.73.0 + image: drumsergio/cashpilot-worker:2.0.0 container_name: cashpilot-migrate user: "0:0" entrypoint: ["python", "-m", "app.owner_migrate"] @@ -95,7 +95,7 @@ services: condition: service_completed_successfully cashpilot-worker: - image: drumsergio/cashpilot-worker:1.73.0 + image: drumsergio/cashpilot-worker:2.0.0 # The proxy's owner label, so the worker may read its own container. labels: cashpilot.deployed-by: worker diff --git a/docs/index.md b/docs/index.md index 78acce90..ad975ae9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -20,6 +20,9 @@ hide: **CashPilot** runs passive income services on your own servers and shows what they earn in one dashboard. It is a UI that holds the catalog, the credentials and the earnings history, and on each server a worker that starts and watches the service containers through a Docker socket proxy. Start with [Getting started](getting-started.md), then pick services in the [Service guides](guides/index.md). +!!! tip "New in 2.0" + The worker reaches Docker only through a socket proxy and only the containers, volumes and networks it created; earners are fenced off your LAN by default; and proxied copies let one box earn on several IPs. Upgrading from 1.x means changing the image tags: [What's new in 2.0](whats-new-2.0.md) lists what changed and how to upgrade. +
- :material-docker: **[Getting started](getting-started.md)** @@ -141,6 +144,7 @@ graph LR - Every service container runs with all Linux capabilities dropped (a few services add back only the ones they declare), `no-new-privileges` set and a PID limit. - Stored credentials are encrypted at rest with a Fernet key at `/data/.fernet_key`. Back that file up: without it nothing can be decrypted. `CASHPILOT_ENCRYPTION_KEY` is adopted only when that file is absent, so on an instance that already has a key the variable changes nothing. It is not `CASHPILOT_SECRET_KEY`, which only signs login sessions. - With the shipped compose files, only the socket proxy holds the Docker socket, and the worker reaches Docker only through it ([Security defaults](security-defaults.md)). The [app-store listings](app-stores.md) do not include the proxy yet, so there the worker mounts the socket itself. The UI is published on loopback by default, and the worker's port 8081 is never published, because either could start containers on the host. +- The proxy also limits the worker to the containers, volumes and networks it created, so a compromised worker cannot read the UI's `/data`, its encryption key or the keys in its environment ([owner isolation](security-defaults.md#docker-socket-proxy)). - [Security defaults](security-defaults.md) lists what ships enabled, [Protecting your home network](home-network-security.md) and [Network isolation](isolation.md) show how to keep the earners away from your LAN, router and host. - To report a security problem, follow the [security policy](https://github.com/GeiserX/CashPilot/blob/main/SECURITY.md) and do not open a public issue. diff --git a/docs/whats-new-2.0.md b/docs/whats-new-2.0.md new file mode 100644 index 00000000..a6259a25 --- /dev/null +++ b/docs/whats-new-2.0.md @@ -0,0 +1,211 @@ +# What's new in 2.0 + +CashPilot 2.0 adds no big feature of its own. It closes a run of releases, +1.62 to 1.73, that changed what the worker can do on your host, how +far an earner can reach into your network, and how many IPs one box can earn on. +Several of those releases need a step from you when you upgrade, so they get +a major version together. This page lists what changed, with a link to the page +that covers each part, and then [how to upgrade](#upgrading-from-1x). + +## Security + +### The worker no longer holds the Docker socket + +Whoever holds the Docker socket is root on the host. In the shipped compose +files the socket now sits with a socket proxy, +[sockguard](https://github.com/CodesWhat/sockguard) 2.4.6, pinned by digest. +The worker talks to Docker only through it. The proxy reads every request, +including its JSON body, and refuses: + +- every Docker API call the worker does not make (swarm, secrets, plugins, + builds, exec of arbitrary commands, image push, and more); +- privileged containers, host PID, IPC and user namespaces, unconfined seccomp + or AppArmor; +- binds of `/`, of the socket, or of any host folder you did not list; +- any added capability other than `NET_ADMIN`, `NET_RAW`, `SETUID` and + `SETGID`, any device other than `/dev/net/tun`, and any runtime other than + `runc` and gVisor. + +A CI job opens a pull request when sockguard ships a new release, so the pin +does not go stale. [Docker socket proxy](security-defaults.md#docker-socket-proxy) +has the full list. + +### Owner isolation keeps a compromised worker out of the dashboard + +The proxy labels every container, volume and network the worker creates with +`cashpilot.deployed-by=worker`, and refuses the worker everything without that +label. On a host that runs the dashboard and a worker together, a compromised +worker can no longer read the dashboard's `/data`. That folder holds +`.fernet_key`, the key that decrypts every login CashPilot stores. Nor can it +read the keys in the dashboard container's environment. It cannot touch containers you started by +hand either. + +It is not yet a full root boundary. If you set `CASHPILOT_COMPOSE_DIR` or +`CASHPILOT_PROXY_BIND_MOUNTS`, a symlink planted in one of those folders can +still reach the host's root, until sockguard can check binds for symlinks. +Leave both unset and that path is closed. +[Owner isolation](security-defaults.md#docker-socket-proxy) lists what a +compromised worker can still do. + +### Earners are fenced off your LAN + +On a new install the worker puts bridge-networked earners on their own Docker +network and writes one firewall table that drops traffic from them to: + +- private ranges (`10/8`, `172.16/12`, `192.168/16`); +- `100.64/10`, which covers carrier-grade NAT and your tailnet; +- `169.254/16`, cloud metadata; +- the host itself, any subnet directly attached to it, and your home's own + public IP, which most routers would loop back into the LAN. + +An upgraded install turns it on with **Turn on isolation** on the Fleet page, +and **Check isolation** starts two short-lived containers to test that it holds. + +Limits: Mysterium runs on host networking and is not covered by the fence. A +second WAN or extra public IPs are not dropped. Docker Desktop, rootless Docker, +Podman and Unraid are not tested yet. +[Network isolation](isolation.md#lan-isolation-by-default) has the details, and +[Test your isolation](isolation-check.md) has the checks by platform. + +### gVisor where it works + +If your Docker daemon has gVisor's `runsc` runtime, `CASHPILOT_CONTAINER_RUNTIME` +puts the bridge-networked earners in it, with exceptions per service. We +measured about a fifth less peak throughput and six to nine times the CPU per +byte moved. It does not run on stock Unraid. +[gVisor, optional](home-network-security.md#7-gvisor-optional) has the numbers +and the install steps. + +### Node identities are backed up before you can lose them + +Some earners keep state that has no copy anywhere else: a Mysterium keystore, +a Storj identity. CashPilot refuses to delete those volumes unless you ask for +it explicitly. The Payouts page lists them under **Back these up**, one line +per box, with an encrypted **Download backup** button. A box that has been +backed up asks again when its volume changes or after six months. +[Backing up node identities](backup.md) explains how. + +## Proxied copies: earn on more than one IP + +Providers count devices per public IP, so a second copy of an earner on the +same box usually earns nothing. A proxied copy is an extra copy of a deployed +service that leaves through a proxy instead, so one box earns on its own IP plus +one IP per proxy. + +- Three kinds of proxy: SOCKS5, HTTP CONNECT, or a Tailscale exit node on + another connection you own. +- **Test** starts a throwaway tunnel, shows the exit IP and country, and passes + only when that IP is public and, when the worker knows its own public IP, is + not the box's own. +- It fails closed. The earner has no network of its own. It shares the + namespace of a tunnel container whose firewall drops every packet that does + not go through the proxy. The earner starts only after the tunnel has seen an + exit IP within 45 seconds. If the proxy dies, the copy stops earning + and nothing leaks out of your own IP. `scripts/proxy_leak_test.sh` checks + this against a real Docker daemon. +- An optional traffic cap per proxy, in GB, stops its copies at a threshold + (90% of the cap by default) and starts them again on the reset day. + +Limits: services that need host networking, published ports, volumes, devices +or extra network capabilities cannot run through a proxy. That rules out +Mysterium, Bitping and Storj. Neither can a service whose terms forbid proxies. +UDP works only through a SOCKS5 proxy that supports it. +[Proxied copies](proxies.md) covers setup and DNS. + +## Also new since 1.62 + +- **Provider ratings.** Every provider gets a letter grade from the same ten + questions, each answer backed by a source you can open. Today none of the + graded providers earns an A or a B. [Provider ratings](ratings.md) +- **Activity.** Off by default. Once you turn it on, it shows what each earner + does on the network: connections, ports, networks, countries, and alerts for + mail ports and attempts on your LAN. It reads socket tables only, never + traffic. [Activity](activity.md) +- **Custom services.** Run any image the catalog lacks, by name and tag, with + the catalog's restrictions. [Custom services](custom-services.md) +- **Import from another tool.** Bring your logins over from money4band, + CashFactory or InternetIncome, and review them before saving. + [Moving from money4band](migrate/money4band.md) +- **Payouts.** The Payouts page lists each service, the boxes it runs on and + the address it pays to. A balance drop is offered as a payout for you to + confirm. The [service guides](guides/index.md) give each minimum payout, and + several say what a first cash-out asks for, such as a one-time registration + link or a phone check by SMS. +- **Android phones in the fleet.** The + [Android app](https://github.com/GeiserX/CashPilot-android) reports a phone's + earning apps to the [Fleet page](fleet.md#fleet-dashboard) next to your + servers. The app is waiting for review on + [F-Droid](https://gitlab.com/fdroid/fdroiddata/-/merge_requests/56196). +- **Desktop app.** [CashPilot Desktop](https://github.com/GeiserX/CashPilot-Desktop) + runs the same catalog as an app for macOS (Apple Silicon), Windows and Linux, + and pins every service image by digest. +- **App stores.** Install from Unraid Community Applications or TrueNAS SCALE. + CasaOS and Runtipi packages are in this repository and run the socket proxy. + [App stores](app-stores.md) +- **Catalog.** 40 active services and + 1 in beta: 17 run in + Docker, 24 are tracked, and + 15 have a balance collector. + [How CashPilot compares](comparison.md) sets this against five other stacks, + every cell sourced. + +## Upgrading from 1.x + +### Back up first + +- `/data` of the dashboard: `cashpilot.db` holds your earnings history and + `.fernet_key` decrypts every stored login. Without that key the logins + cannot be recovered. [Backing up and restoring](backup-restore.md) +- Node identities: use **Download backup** on the Payouts page for every box + it lists. [Backing up node identities](backup.md) + +### What to do + +The compose files pin a release series (`drumsergio/cashpilot:1.73`), so +`docker compose pull` and the in-app **Update** button stay inside 1.x. Moving +to 2.0 means changing the tags. + +1. Take the new compose file for each host: `docker-compose.yml`, + `docker-compose.fleet.yml`, or `docker-compose.worker.yml` on a worker-only + host. Keep your own changes. If you keep your old file instead, change + every `drumsergio/cashpilot:1.x` and `drumsergio/cashpilot-worker:1.x` tag + to `2.0`. +2. Run `docker compose up -d --force-recreate`, with `-f` and your file if it + is not `docker-compose.yml`. +3. Do the same on every worker host. The dashboard and every worker should run + the same version. + +What else happens depends on the version you come from: + +| You run | What 2.0 adds | +|---|---| +| 1.73 | Nothing else. Only the tag changes. | +| 1.71 or 1.72, behind the socket proxy | `cashpilot-migrate` runs once before the proxy starts. It moves your volumes onto labelled ones, checking the data before and after, and keeps every original. | +| Any version whose worker still mounts `/var/run/docker.sock` | The new compose file adds the socket proxy and runs the migration. Set `CASHPILOT_COMPOSE_DIR` in `.env` if you want the in-app update, knowing it opens the symlink path above. On a GPU host, read UPGRADING.md first: the proxy refuses to recreate a CashPilot service with a GPU. | +| 1.69 or older | Your earners stay on Docker's default bridge until you press **Turn on isolation** on the Fleet page. | + +Two things work differently after the upgrade: + +- On the host where the dashboard and a worker run together, the in-app update + updates the worker only. Update the dashboard with + `docker compose pull && docker compose up -d`. +- Earners you started by hand, or from a compose file CashPilot exported, no + longer show in the dashboard. They keep running and earning. + +[UPGRADING.md](https://github.com/GeiserX/CashPilot/blob/main/UPGRADING.md) +has every step in full, including the leftovers the migration keeps and how to +remove them. + +### Rolling back + +2.0 does not change the database: it uses the same schema as every release +since 1.67. To go back to 1.73, set the tags back to `1.73` and run +`docker compose up -d`. + +To go back further than 1.73, put your old compose file back and run +`docker compose up -d`. The migration copies and never deletes: your old +worker volumes and each `-pre-isolation` backup stay until you remove +them yourself. Keep them until 2.0 has run well for a while. A compose file +from before the socket proxy leaves the proxy running: remove it with +`docker rm -f cashpilot-socket-proxy`. Going back past 1.67, restore the +`/data` backup you took too. diff --git a/scripts/generate_readme_tables.py b/scripts/generate_readme_tables.py index ad93fd91..779ce01a 100644 --- a/scripts/generate_readme_tables.py +++ b/scripts/generate_readme_tables.py @@ -43,7 +43,13 @@ GPU = "gpu-services" #: Files whose counts are generated. The README also carries the lists above. -COUNTED_FILES = ["README.md", "docs/index.md", "docs/getting-started.md", "docs/comparison.md"] +COUNTED_FILES = [ + "README.md", + "docs/index.md", + "docs/getting-started.md", + "docs/comparison.md", + "docs/whats-new-2.0.md", +] _COUNT = re.compile(r"\d*") diff --git a/zensical.toml b/zensical.toml index 1f2ee887..8291bed4 100644 --- a/zensical.toml +++ b/zensical.toml @@ -46,6 +46,7 @@ nav = [ { Home = "index.md" }, { "Get started" = [ { "Getting started" = "getting-started.md" }, + { "What's new in 2.0" = "whats-new-2.0.md" }, { "App stores" = "app-stores.md" }, { "How it works" = "how-it-works.md" }, { FAQ = "faq.md" }, From d5b2be858ed84b2f5adc2529cda82bcfc2c93402 Mon Sep 17 00:00:00 2001 From: GeiserX <9169332+GeiserX@users.noreply.github.com> Date: Sat, 7 Nov 2026 20:51:19 +0100 Subject: [PATCH 2/2] docs(2.0): say why to upgrade, how the migrator runs, and name the companion apps --- docs/whats-new-2.0.md | 181 +++++++++++++++++++++++++++++------------- 1 file changed, 126 insertions(+), 55 deletions(-) diff --git a/docs/whats-new-2.0.md b/docs/whats-new-2.0.md index a6259a25..ddf0bfcc 100644 --- a/docs/whats-new-2.0.md +++ b/docs/whats-new-2.0.md @@ -1,11 +1,32 @@ # What's new in 2.0 CashPilot 2.0 adds no big feature of its own. It closes a run of releases, -1.62 to 1.73, that changed what the worker can do on your host, how -far an earner can reach into your network, and how many IPs one box can earn on. -Several of those releases need a step from you when you upgrade, so they get -a major version together. This page lists what changed, with a link to the page -that covers each part, and then [how to upgrade](#upgrading-from-1x). +1.62 to 1.73, that changed what the worker can do on your host, how far an +earner can reach into your network, and how many IPs one box can earn on. +Several of those releases need a step from you when you upgrade, so they get a +major version together. This page says why the upgrade is worth it, what +changed, with a link to the page that covers each part, and then +[how to upgrade](#upgrading-from-1x). + +## Why upgrade + +What an older install leaves open, by version: + +- **1.70 and older:** the worker holds the raw Docker socket. Whoever takes + over the worker is root on your host. +- **1.72 and older,** with the dashboard and a worker on one host: a + compromised worker can read `.fernet_key` and decrypt every provider login + you stored. +- **Anything deployed before 1.70:** earners carrying strangers' traffic can + reach your LAN, your router and your other machines, until you turn the + fence on. + +2.0 closes all three. It also carries the fixes since 1.73: the in-app update +works behind the socket proxy, identity backups you confirmed stay confirmed +through the migration, earners from the old pre-worker deploy path stay +visible after it, Podman workers can deploy, and traffic caps on proxies +recover after a box was offline. Releases are cut from one branch, so every +fix from now on ships in 2.x and the `1.73` tag gets no more patches. ## Security @@ -63,7 +84,8 @@ and **Check isolation** starts two short-lived containers to test that it holds. Limits: Mysterium runs on host networking and is not covered by the fence. A second WAN or extra public IPs are not dropped. Docker Desktop, rootless Docker, -Podman and Unraid are not tested yet. +and Unraid are not tested yet. On Podman the fence is not available yet: a +worker there deploys on Podman's default network and the Fleet page says so. [Network isolation](isolation.md#lan-isolation-by-default) has the details, and [Test your isolation](isolation-check.md) has the checks by platform. @@ -109,7 +131,8 @@ one IP per proxy. Limits: services that need host networking, published ports, volumes, devices or extra network capabilities cannot run through a proxy. That rules out Mysterium, Bitping and Storj. Neither can a service whose terms forbid proxies. -UDP works only through a SOCKS5 proxy that supports it. +UDP goes out only through a Tailscale exit node, never through SOCKS5 or HTTP +CONNECT. [Proxied copies](proxies.md) covers setup and DNS. ## Also new since 1.62 @@ -131,14 +154,6 @@ UDP works only through a SOCKS5 proxy that supports it. confirm. The [service guides](guides/index.md) give each minimum payout, and several say what a first cash-out asks for, such as a one-time registration link or a phone check by SMS. -- **Android phones in the fleet.** The - [Android app](https://github.com/GeiserX/CashPilot-android) reports a phone's - earning apps to the [Fleet page](fleet.md#fleet-dashboard) next to your - servers. The app is waiting for review on - [F-Droid](https://gitlab.com/fdroid/fdroiddata/-/merge_requests/56196). -- **Desktop app.** [CashPilot Desktop](https://github.com/GeiserX/CashPilot-Desktop) - runs the same catalog as an app for macOS (Apple Silicon), Windows and Linux, - and pins every service image by digest. - **App stores.** Install from Unraid Community Applications or TrueNAS SCALE. CasaOS and Runtipi packages are in this repository and run the socket proxy. [App stores](app-stores.md) @@ -149,42 +164,95 @@ UDP works only through a SOCKS5 proxy that supports it. [How CashPilot compares](comparison.md) sets this against five other stacks, every cell sourced. -## Upgrading from 1.x - -### Back up first +## Companion apps -- `/data` of the dashboard: `cashpilot.db` holds your earnings history and - `.fernet_key` decrypts every stored login. Without that key the logins - cannot be recovered. [Backing up and restoring](backup-restore.md) -- Node identities: use **Download backup** on the Payouts page for every box - it lists. [Backing up node identities](backup.md) +- **[CashPilot Desktop 1.0](https://github.com/GeiserX/CashPilot-Desktop)** + runs the same catalog as an app for macOS (Apple Silicon), Windows and + Linux. It works as a full dashboard or as a worker that joins this one, and + pins every service image by digest. +- **[CashPilot for Android 1.0](https://github.com/GeiserX/CashPilot-android)** + reports a phone's earning apps to the [Fleet page](fleet.md#fleet-dashboard) + next to your servers. It ships from GitHub releases and is waiting for + review on [F-Droid](https://gitlab.com/fdroid/fdroiddata/-/merge_requests/56196). -### What to do +## Upgrading from 1.x The compose files pin a release series (`drumsergio/cashpilot:1.73`), so `docker compose pull` and the in-app **Update** button stay inside 1.x. Moving -to 2.0 means changing the tags. +to 2.0 means taking the new compose file or changing the tags. -1. Take the new compose file for each host: `docker-compose.yml`, - `docker-compose.fleet.yml`, or `docker-compose.worker.yml` on a worker-only - host. Keep your own changes. If you keep your old file instead, change - every `drumsergio/cashpilot:1.x` and `drumsergio/cashpilot-worker:1.x` tag - to `2.0`. -2. Run `docker compose up -d --force-recreate`, with `-f` and your file if it - is not `docker-compose.yml`. -3. Do the same on every worker host. The dashboard and every worker should run - the same version. +### 1. Back up first -What else happens depends on the version you come from: - -| You run | What 2.0 adds | -|---|---| -| 1.73 | Nothing else. Only the tag changes. | -| 1.71 or 1.72, behind the socket proxy | `cashpilot-migrate` runs once before the proxy starts. It moves your volumes onto labelled ones, checking the data before and after, and keeps every original. | -| Any version whose worker still mounts `/var/run/docker.sock` | The new compose file adds the socket proxy and runs the migration. Set `CASHPILOT_COMPOSE_DIR` in `.env` if you want the in-app update, knowing it opens the symlink path above. On a GPU host, read UPGRADING.md first: the proxy refuses to recreate a CashPilot service with a GPU. | -| 1.69 or older | Your earners stay on Docker's default bridge until you press **Turn on isolation** on the Fleet page. | - -Two things work differently after the upgrade: +- **The dashboard's `/data`.** `cashpilot.db` holds your earnings history and + `.fernet_key` decrypts every stored login. Without that key the logins + cannot be recovered. [Backing up and restoring](backup-restore.md#backup) + has a script that copies both without stopping the container, and the + commands to check the copy. +- **Node identities.** On the Payouts page, use **Download backup** for every + box listed under **Back these up**. A Mysterium keystore or a Storj identity + has no other copy. [Backing up node identities](backup.md) + +The migration below keeps its own copy of every volume it touches, but a +backup you hold is the one that survives a lost disk. + +### 2. Take the 2.0 compose file + +On each host, replace your compose file with the 2.0 one: +`docker-compose.yml` where the dashboard runs, `docker-compose.fleet.yml` for a +dashboard with remote workers, or `docker-compose.worker.yml` on a worker-only +host. Carry over your own changes and keep your `.env`. If you keep your old +file, it must already have the `cashpilot-socket-proxy` and +`cashpilot-migrate` services; then change every `drumsergio/cashpilot:1.x` and +`drumsergio/cashpilot-worker:1.x` tag to `2.0`. + +If your worker still mounts `/var/run/docker.sock`, the new file is what moves +the socket to the proxy. Set `CASHPILOT_COMPOSE_DIR=/folder/with/the/compose/file` +in `.env` if you want the in-app update, which opens the symlink path +described above. On a GPU host, read +[UPGRADING.md](https://github.com/GeiserX/CashPilot/blob/main/UPGRADING.md#docker-socket-proxy-take-the-new-compose-file-once) +first: the proxy refuses to recreate a CashPilot service with a GPU. + +### 3. Start it + +```sh +docker compose up -d --force-recreate +``` + +Add `-f` and your file name if it is not `docker-compose.yml`. Do the +dashboard host first, then every worker host. The dashboard and every worker +should run the same version. + +### What the one-shot migrator does + +On an install from before 1.73, `cashpilot-migrate` runs once, before the +socket proxy starts. Docker cannot add a label to an existing volume or +network, so it moves your data onto labelled ones: + +- each volume of an earner the worker started is copied to a backup named + `-pre-isolation`, checked by digest, recreated with the label, + filled back from the backup and checked again. The earner is then recreated + as it was. A Mysterium identity keeps its address; +- the worker's own volumes are copied into new ones named + `cashpilot_worker_data_owned` and, where the dashboard runs too, + `cashpilot_fleet_owned`; +- the `cashpilot-isolated` network is rebuilt with the label, with its earners + put back on it. + +It deletes nothing. It can take a few minutes on a node with a large volume. If it stops halfway, after a reboot +or a kill, run the same command again and it finishes from where it stopped. +If it already ran on 1.73, it finds nothing to do and exits. + +### What you see when it is done + +- `docker logs cashpilot-migrate` ends with *Migration complete: everything the + worker uses carries cashpilot.deployed-by=worker.* A run that had to leave + something alone ends with *Migration done, with N thing(s) left as they + were*, and the lines above it say what and why. +- The worker's status page says *Docker access: socket proxy*. +- The dashboard shows every earner running, the Fleet page shows each worker on + 2.0, and a Mysterium node shows the same address as before. + +Two things work differently afterwards: - On the host where the dashboard and a worker run together, the in-app update updates the worker only. Update the dashboard with @@ -192,20 +260,23 @@ Two things work differently after the upgrade: - Earners you started by hand, or from a compose file CashPilot exported, no longer show in the dashboard. They keep running and earning. -[UPGRADING.md](https://github.com/GeiserX/CashPilot/blob/main/UPGRADING.md) -has every step in full, including the leftovers the migration keeps and how to -remove them. +If you came from 1.69 or older, your earners are still on Docker's default +bridge. Press **Turn on isolation** on each worker's row on the Fleet page, +then **Check isolation**. + +Once everything has run well for a while, remove what the migration left +behind. [UPGRADING.md](https://github.com/GeiserX/CashPilot/blob/main/UPGRADING.md#owner-isolation-take-the-compose-file-again-two-features-change-on-the-uis-host) +lists each leftover and the commands. ### Rolling back -2.0 does not change the database: it uses the same schema as every release -since 1.67. To go back to 1.73, set the tags back to `1.73` and run -`docker compose up -d`. +2.0 uses the same database schema as every release since 1.67. To go back to +1.73, set the tags back to `1.73` and run `docker compose up -d`. -To go back further than 1.73, put your old compose file back and run -`docker compose up -d`. The migration copies and never deletes: your old -worker volumes and each `-pre-isolation` backup stay until you remove -them yourself. Keep them until 2.0 has run well for a while. A compose file +To go back further, put your old compose file back and run +`docker compose up -d`. The migration copies and never deletes, so your old +worker volumes and each `-pre-isolation` backup are still there, +unless you removed them. That is why you keep them for a while. A compose file from before the socket proxy leaves the proxy running: remove it with `docker rm -f cashpilot-socket-proxy`. Going back past 1.67, restore the -`/data` backup you took too. +`/data` backup you took as well.