HTTP proxy pool powered by gluetun and Mullvad VPN. Runs 3 proxy instances with different WireGuard exit servers, providing IP rotation for applications that need it.
Each proxy is an independent gluetun container with its own WireGuard tunnel and exit IP. Traffic routed through any proxy exits through a different Mullvad server.
- Docker with Compose v2
- Mullvad VPN account
- WireGuard keys registered with Mullvad (up to 5 per account)
# 1. Copy the example env file
cp .env.example .env
# 2. Edit .env with your Mullvad WireGuard credentials
# (see "Getting WireGuard Keys" below)
nano .env
# 3. Start the proxy pool
docker compose up -d
# 4. Verify — should show a Mullvad exit IP, not your real IP
curl --proxy http://127.0.0.1:8888 https://am.i.mullvad.net/json| Proxy | Port | Default Exit |
|---|---|---|
| proxy-1 | 8888 | Los Angeles, USA |
| proxy-2 | 8889 | New York, USA |
| proxy-3 | 8890 | Frankfurt, Germany |
All proxies are plain HTTP proxies. Use them with http_proxy / https_proxy environment variables or --proxy flag with curl.
- Log in to your Mullvad account
- Go to WireGuard configuration
- Generate keys — you need one key per proxy instance (3 total)
- Each key gets a private key and an assigned address (e.g.,
10.67.50.32/32) - Copy the private key and address into your
.envfile
Alternatively, use the Mullvad CLI:
mullvad account login YOUR_ACCOUNT_NUMBER
mullvad tunnel wireguard key regenerateOr register keys via the Mullvad API:
# Generate a WireGuard keypair
wg genkey | tee privatekey | wg pubkey > publickey
# Register with Mullvad
curl -sSL https://api.mullvad.net/wg/ \
-d account=YOUR_ACCOUNT_NUMBER \
--data-urlencode pubkey=$(cat publickey)
# Returns the assigned address (e.g., 10.67.50.32/32)Each container exposes a health check on port 9999 (internal only). Docker reports container health status:
# Check all container health
docker compose ps
# Check specific proxy
docker inspect --format='{{.State.Health.Status}}' mullvad-proxy-1This proxy pool is designed to work with jupyterlab-claude and other K8s workloads that need proxy routing.
After starting the proxy pool, create a secret with the proxy URLs for your pods:
# Replace HOST with the IP/hostname where Docker Compose is running
kubectl create secret generic proxy-pool-config \
--namespace YOUR_NAMESPACE \
--from-literal=proxy_urls="http://HOST:8888,http://HOST:8889,http://HOST:8890"- Deploy this proxy pool on a host accessible from your cluster
- Create the secret in your JupyterLab namespace
- Enable the Mullvad feature in your Helm values:
mullvad:
enabled: true
proxySecretName: proxy-pool-config- Inside JupyterLab, use the
%proxymagic:
%proxy mullvad # Connect through random proxy
%proxy mullvad 2 # Connect through proxy-2 specifically
%proxy status # Show current exit IP
%proxy off # DisconnectConfigure exit servers in your .env file. See the full server list for available countries and cities.
PROXY1_COUNTRY=USA
PROXY1_CITY=Los Angeles CA
PROXY2_COUNTRY=Japan
PROXY2_CITY=Tokyo
PROXY3_COUNTRY=Switzerland
PROXY3_CITY=ZurichTo add more proxies, duplicate a service block in docker-compose.yml with a new port and key index. Each proxy requires its own WireGuard key (max 5 per Mullvad account).
MIT