21 Commits

Author SHA1 Message Date
c6097b1b6e fix: collapse python3 binary patch to single line
Docker parses each new line in a RUN command as a potential instruction.
The multi-line python3 -c "..." caused 'unknown instruction: data' errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 06:59:26 +01:00
4d4e6cba75 fix: let install subprocess start pured daemon to avoid ETXTBSY
Pre-starting pured in the entrypoint caused ETXTBSY when the install
subprocess (triggered by createRootProcessForMissingComponents) tried
to overwrite the running daemon binary.

- Remove pured pre-start from entrypoint; daemon starts via
  `systemctl start pured` inside the install subprocess instead
- systemctl stop: use pkill -9 + sleep 1 for reliable termination
- systemctl start: wait up to 15s for :9485 instead of blind sleep 2

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 19:13:15 +01:00
f7fffc0ac3 fix: binary patch purevpn-cli to use correct pured daemon download URL
The purevpn-cli binary hardcodes /cross-platform/linux-cli/production/pured-linux-x64.gz
which returns HTTP 403. Correct URL is /cross-platform/linux-daemon/1.4.1/pured-linux-x64.gz.

- Pre-download pured daemon from correct URL during build
- Binary patch (same-length, 54 bytes) replaces hardcoded wrong path in-place
- Daemon already present so first run doesn't trigger broken download

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 19:08:27 +01:00
1c2d903a95 fix: fake systemctl for pured.service + pre-install service file
purevpn-cli checks `systemctl is-active pured.service` to determine if
components are installed. Without systemd this always returns inactive,
triggering endless sudo/reinstall loop and ETXTBSY when trying to overwrite
the running daemon binary.

Fake systemctl returns "active" when pured is listening on :9485, "inactive"
otherwise. Also handles start/stop/disable/daemon-reload as no-ops.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 18:59:40 +01:00
06e24a3776 fix: pre-download pured daemon + start it before purevpn-cli
The purevpn-cli binary hardcodes a wrong S3 path for the daemon download
which returns HTTP 403. The correct URL (from the installer script) is:
  /cross-platform/linux-daemon/1.4.1/pured-linux-x64.gz

purevpn-cli is a client that talks to the pured daemon on :9485.
Pre-download the daemon during Docker build and start it in the entrypoint
before any purevpn-cli invocations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 18:55:50 +01:00
a2a1ba3c37 fix: run purevpn-cli as non-root vpnuser with real sudo
purevpn-cli is designed to run as non-root and calls sudo internally for
privileged VPN setup. Running as root skips this flow and crashes.

- Add vpnuser (home=/root so login tokens are shared with root setup)
- Configure sudoers secure_path to include /opt/purevpn-cli/bin
- Wrap all purevpn-cli calls in entrypoint with pvpn() helper (su vpnuser)
- Keep iptables/danted running as root

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 18:44:03 +01:00
34b5c4a8cd fix: replace fake sudo with real sudo package
Real sudo uses env_reset by default, which naturally clears PKG_EXECPATH.
This lets the child binary's pkg bootstrap start fresh and load the embedded
main module correctly — no more 'Cannot find module' crash.

Removes the sudo-wrapper.sh hack entirely; the real sudo package handles
all edge cases (environment cleanup, privilege semantics) correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 18:31:57 +01:00
91674ea056 fix: env -u PKG_EXECPATH in sudo wrapper + pre-install components at build
PKG_EXECPATH inherited from parent caused pkg bootstrap to treat argv[1] as
a module path. Fix: env -u unsets only PKG_EXECPATH so bootstrap starts fresh
while all auth/session vars are preserved. Depth guard prevents loops.

Also pre-run component installation during Docker build so the sudo code path
is never hit at runtime.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 18:02:18 +01:00
60cdd60327 fix: strip --install-missing-components + env -u PKG_EXECPATH in sudo wrapper
The real issue: PKG_EXECPATH inherited from parent makes pkg bootstrap treat
argv[1] as a module path regardless of arg order. Fix: unset only PKG_EXECPATH
(env -u) so bootstrap starts fresh and loads embedded main. Strip
--install-missing-components since it's not a commander.js flag. Keep all other
env vars for auth/session. Parent handles actual connection after child exits.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 16:53:46 +01:00
88b2db93d2 fix: remove env -i, add recursion depth guard in sudo wrapper
env -i was stripping auth/session env vars the child process needs
to complete the VPN connection. Replace with PUREVPN_SUDO_DEPTH counter
that stops recursion at depth 2 while preserving parent environment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 16:03:50 +01:00
9c65d19b81 fix: reorder --install-missing-components to argv[1] in sudo wrapper
pkg bootstrap crashes when argv[1]='--connect' and --install-missing-components
is present — it tries require('/--connect'). Moving --install-missing-components
to argv[1] lets pkg handle it as its own bootstrap flag. Extracted wrapper to
sudo-wrapper.sh for readability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 07:38:54 +01:00
173bd87437 feat: manual connect mode + env -i sudo wrapper to fix pkg bootstrap crash
- MANUAL_CONNECT=true: container waits for tun0, user connects via docker exec
- MANUAL_CONNECT=false: auto mode (current), now with env -i in sudo wrapper
- sudo wrapper logs inherited env key names so we can see what parent injects
- monitor_loop extracted as shared function used by both modes
- auto mode connect logic cleaned up into a single while-true rotation loop
2026-03-12 07:23:19 +01:00
c68f3325bb fix: stub openvpn-systemd-resolved to prevent missing-components sudo call + binary inspection 2026-03-11 10:56:34 +01:00
48498c1f43 fix: sudo wrapper strips --install-missing-components and reruns command as root 2026-03-11 10:44:03 +01:00
7a739d97b3 fix: fake sudo intercepts --install-missing-components to avoid pkg/Node.js bootstrap crash 2026-03-11 10:34:00 +01:00
f5010baa44 fix: add fake sudo passthrough for purevpn-cli --install-missing-components 2026-03-11 10:23:35 +01:00
cf7cc642be fix: correct purevpn-cli PATH (/opt/purevpn-cli/bin) and pre-install VPN deps 2026-03-11 10:11:01 +01:00
ed4076abca fix: add build-time binary search + runtime path-finder for purevpn-cli 2026-03-11 10:08:44 +01:00
fa5918a36d fix: haproxy cfg — server-template must be on a single line (no backslash continuation) 2026-03-11 10:05:25 +01:00
d104249fbb fix: replace microsocks with dante-server (apt package, no compilation)
- Removes gcc/make/git and the microsocks git clone+build step
- Installs dante-server from apt — zero compilation required
- danted uses 'external: tun0' to explicitly route all proxied traffic
  through the VPN interface, more reliable than iptables-based routing
- Config is generated at runtime after tun0 is confirmed up
2026-03-11 09:58:44 +01:00
505da89144 feat: initial vpndock stack
HAProxy SOCKS5 entry point + scalable purevpn-cli/microsocks exit nodes.
Supports up to 10 simultaneous connections (PureVPN limit), random location
selection from a predefined pool, and automatic reconnect to an unused
location on server-side drop.
2026-03-11 09:45:42 +01:00