Access many HTTPS sites on a Parallel Works ACTIVATE workspace through a single local port (:443), routed by SNI.
A companion to the pw CLI: once you've authenticated with pw auth, every tunnel this proxy opens runs through pw ssh under your workspace identity, so any internal or access-controlled URL reachable from your ACTIVATE workspace is reachable from your local browser with the same permissions.
Reaching multiple HTTPS sites from your workspace normally means one SSH tunnel per site, each bound to local port 443 — but only one process can hold a port at a time:
sudo ssh -L 443:app.example.com:443 -o ProxyCommand="pw ssh --proxy-command %h" user@workspace
sudo ssh -L 443:api.example.com:443 -o ProxyCommand="pw ssh --proxy-command %h" user@workspace
# ^ can't run bothThis tool runs one SNI-aware proxy on 127.0.0.1:443 and fans out to per-site tunnels on unique local ports, so you can hit any number of workspace-side HTTPS sites at once.
Browser → /etc/hosts app.example.com → 127.0.0.1
→ SNI proxy on :443 reads TLS ClientHello SNI
→ unique local port e.g. :10443
→ pw ssh tunnel forwards to remote host:443
- Each site gets its own
pw sshtunnel on a unique local port (10443, 10444, ...) - The SNI proxy on
:443parses the TLS hostname and routes to the matching tunnel /etc/hostsentries are auto-managed so the configured domains resolve to127.0.0.1
- Install the pw CLI (docs):
curl -fsSL https://activate.parallel.works/cli/install.sh | bash - Authenticate (docs) — pick one:
This sets up
pw auth token # short-term token pw auth apikey # long-lived API key
~/.ssh/pwcliand links your workspace identity. Sanity check:pw auth whoami
- Node.js (for this proxy) and sudo (for
:443and/etc/hosts).
npm install
cp config.yaml.template config.yaml
# edit config.yaml: your pw username, workspace name, and the sites you wantssh:
identityFile: ~/.ssh/pwcli # managed by `pw auth`
user: YOUR_PW_USERNAME
jumpHost: workspace # short name of your pw workspace
proxyCommand: "pw ssh --proxy-command %h" # routes through ACTIVATE
sites:
- host: app.example.com
port: 443
localPort: 10443
- host: api.example.com
port: 443
localPort: 10444Each site needs a unique localPort. Because auth flows through ~/.ssh/pwcli, rotating credentials is a single pw auth call — no edits here. config.yaml is gitignored.
sudo node index.js
# Ctrl+C cleans up /etc/hosts and kills tunnelsOpen https://app.example.com in your browser — it resolves to 127.0.0.1, hits the SNI proxy, and is forwarded through your ACTIVATE workspace.
The proxy itself is ProxyCommand-agnostic. To use a plain SSH jumpbox instead:
ssh:
identityFile: ~/.ssh/id_rsa
user: username
jumpHost: jumpbox
proxyCommand: "ssh -W %h:%p jumpbox"- index.js — loads config, starts everything, handles shutdown
- sni-proxy.js — TCP server on
:443, parses TLS SNI to pick a tunnel - tunnel-manager.js — spawns and monitors per-site SSH processes
- hosts-manager.js — manages
/etc/hostsentries between marker comments