{"id":51895846,"url":"https://github.com/dedene/vpngrok","last_synced_at":"2026-07-26T09:30:46.341Z","repository":{"id":370835716,"uuid":"1297287375","full_name":"dedene/vpngrok","owner":"dedene","description":"Run xAI's Grok CLI from any project, with all traffic routed through a VPN (Docker + gluetun, Mullvad by default)","archived":false,"fork":false,"pushed_at":"2026-07-11T09:30:36.000Z","size":18,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-11T11:06:45.156Z","etag":null,"topics":["ai-agents","cli","docker","docker-compose","gluetun","grok","mullvad","vpn","wireguard","xai"],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dedene.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-11T09:01:55.000Z","updated_at":"2026-07-11T10:15:36.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dedene/vpngrok","commit_stats":null,"previous_names":["dedene/vpngrok"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/dedene/vpngrok","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dedene%2Fvpngrok","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dedene%2Fvpngrok/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dedene%2Fvpngrok/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dedene%2Fvpngrok/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dedene","download_url":"https://codeload.github.com/dedene/vpngrok/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dedene%2Fvpngrok/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35910592,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-26T02:00:06.503Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","cli","docker","docker-compose","gluetun","grok","mullvad","vpn","wireguard","xai"],"created_at":"2026-07-26T09:30:45.872Z","updated_at":"2026-07-26T09:30:46.332Z","avatar_url":"https://github.com/dedene.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vpnGrok\n\nRun xAI's Grok CLI from any project on your machine, with all its traffic routed through a VPN.\n\nGrok isn't available in every region. This repo puts the Grok CLI in a small Ubuntu container whose only network path is a [gluetun](https://github.com/qdm12/gluetun) VPN tunnel, then gives you a `vpngrok` command that works from any directory. If the tunnel drops, the container loses network entirely instead of leaking your real IP.\n\nMullvad is the default provider, but gluetun supports [40+ providers](https://github.com/qdm12/gluetun-wiki/tree/main/setup/providers) (NordVPN, ProtonVPN, Surfshark, PIA, ...) — see [Other VPN providers](#other-vpn-providers).\n\n## Requirements\n\n- Docker Desktop (or any Docker with compose v2)\n- A VPN subscription with WireGuard or OpenVPN support\n- macOS or Linux\n\n## Setup\n\n1. Clone the repo:\n\n   ```bash\n   git clone https://github.com/dedene/vpngrok.git\n   cd vpngrok\n   ```\n\n2. Copy the env template and fill in your VPN credentials:\n\n   ```bash\n   cp .env.example .env\n   ```\n\n   For Mullvad: generate a WireGuard config at\n   \u003chttps://mullvad.net/en/account/wireguard-config\u003e and copy the `PrivateKey`\n   and IPv4 `Address` values into `.env`. Careful: Mullvad rotates the keypair\n   on every config download, so the values in `.env` die the next time you\n   regenerate a config.\n\n   Also set `WORKSPACE_ROOT` to the directory where your projects live, unless\n   that's `~/Development` (the default). `vpngrok` only works inside this tree —\n   see [Workspace root](#workspace-root) for why.\n\n3. Start the stack and check that traffic exits through the VPN:\n\n   ```bash\n   make up\n   make verify\n   ```\n\n4. Install the `vpngrok` wrapper on your PATH:\n\n   ```bash\n   make install\n   ```\n\n## Usage\n\n```bash\ncd ~/Development/some-project\nvpngrok\n```\n\nThat's it. The wrapper starts the VPN and dev containers if they aren't running, installs the Grok CLI on first use, and drops you into Grok with your current directory as the working directory. Host paths map 1:1 inside the container.\n\nFirst run asks you to log in. If the browser flow doesn't cooperate from inside the container, set `XAI_API_KEY` in `.env` instead. Login state persists in `.docker/dev-home`, so you only do this once.\n\nYour personal skills work too: the container mounts `~/.agents`, `~/.grok/skills`, and `~/.claude/skills` read-only, which covers every home-level directory Grok scans for skills. Project-level skills (`.grok/`, `.agents/`, `.claude/`, `.cursor/` inside a repo) come along with the workspace mount. If you don't have these directories, Docker creates them empty — harmless.\n\nSessions are shared with the host: `~/.grok/sessions` is mounted read-write, and because host paths map 1:1 inside the container, `/resume` shows the same sessions whether you run Grok natively or through `vpngrok`. Just don't resume the *same* session from both at the same time.\n\n`vpngrok` works in any directory under `WORKSPACE_ROOT` — see below.\n\n## Workspace root\n\nThe container mounts one directory tree from your machine, and `vpngrok` only works inside it. It defaults to `~/Development`; set `WORKSPACE_ROOT` in `.env` if your projects live somewhere else:\n\n```bash\nWORKSPACE_ROOT=/Users/alice/Projects\n```\n\nWhy not mount all of `$HOME`? Because whatever is mounted is readable and writable by the container, and by the Grok agent running inside it. Mounting your whole home directory hands over `~/.ssh`, `~/.aws`, browser profiles, documents, everything. Scoping the mount to your projects tree means a misbehaving agent (or a compromised dependency it runs) can only touch code you already intended to share with it.\n\nPerformance is not the reason: Docker's VirtioFS mounts are lazy, so a broad mount costs nothing until files are actually accessed. It's purely about blast radius. If you truly want your whole home directory, set `WORKSPACE_ROOT` to its absolute path (e.g. `/Users/alice`) and own the tradeoff (Docker Desktop will show a warning, and macOS may prompt for access to personal folders).\n\nAfter changing `WORKSPACE_ROOT`, recreate the container: `docker compose up -d --force-recreate dev`.\n\n## Other VPN providers\n\nThe vpn container is plain gluetun, so switching providers is an `.env` change. Look up your provider in the [gluetun wiki](https://github.com/qdm12/gluetun-wiki/tree/main/setup/providers) and set the matching variables:\n\n```bash\n# NordVPN over OpenVPN, for example:\nVPN_SERVICE_PROVIDER=nordvpn\nVPN_TYPE=openvpn\nOPENVPN_USER=...\nOPENVPN_PASSWORD=...\n```\n\nThe compose file passes through `VPN_SERVICE_PROVIDER`, `VPN_TYPE`, `WIREGUARD_PRIVATE_KEY`, `WIREGUARD_ADDRESSES`, `OPENVPN_USER`, `OPENVPN_PASSWORD`, `SERVER_COUNTRIES`, and `SERVER_CITIES`. If your provider needs a variable that isn't in that list, add it to the `vpn` service in `compose.yaml`.\n\nAfter changing providers: `make down \u0026\u0026 make up \u0026\u0026 make verify`.\n\n## How it works\n\nTwo containers:\n\n- `vpn` runs gluetun with your provider's credentials. It owns the network.\n- `dev` is an Ubuntu box that shares the vpn container's network namespace\n  (`network_mode: \"service:vpn\"`). It has no network of its own, so everything\n  it does goes through the tunnel or nowhere.\n\nThe `vpngrok` script is a thin wrapper around `docker compose exec` that maps your current directory into the container.\n\nAll projects share one container, one Grok login, and one VPN exit server. There is no per-project isolation.\n\n## Kill-switch check\n\nWith the stack running, stop the VPN container and confirm the dev container can't reach the internet:\n\n```bash\ndocker compose stop vpn\ndocker compose exec dev curl --max-time 10 https://am.i.mullvad.net/ip\n```\n\nThe curl should time out rather than show your real IP. Bring the tunnel back with:\n\n```bash\ndocker compose up -d vpn\n```\n\n## Make targets\n\n| Target | What it does |\n|---|---|\n| `make up` | Build and start the vpn + dev containers |\n| `make verify` | Confirm traffic exits through the VPN |\n| `make install` | Symlink `vpngrok` into your PATH |\n| `make shell` | Open a shell in the dev container |\n| `make logs` | Tail the vpn container logs |\n| `make down` | Stop everything |\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdedene%2Fvpngrok","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdedene%2Fvpngrok","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdedene%2Fvpngrok/lists"}