Skip to content

Commit 3e86235

Browse files
authored
docs: add GitHub Actions Full tunnel documentation and workflows (#783)
* docs: add GitHub Actions tunnel general documentation README.md * docs: add cloudflared quick tunnel guide * Add: add cloudflared quick tunnel workflow * docs: add ngrok tunnel guide * Add: add ngrok tunnel workflow * fix: Update cloudflared-quick.md to add link to related yml file * fix: Update ngrok.md to add related file link * docs: add cloudflared named tunnel guide * Add: add cloudflared named workflow
1 parent 0e67863 commit 3e86235

7 files changed

Lines changed: 657 additions & 0 deletions

File tree

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# GitHub Actions Full Tunnel
2+
3+
A temporary, repeatable Full tunnel mode for users who cannot or prefer not to
4+
purchase a VPS. Uses GitHub Actions free hosted runners to run the official
5+
`mhrv-tunnel-node` container for 6-hour sessions at no cost.
6+
7+
## Who This Is For
8+
9+
- Users who cannot access international payment methods to purchase a VPS
10+
- Users who need Full tunnel mode occasionally — CAPTCHA-protected sites,
11+
streaming, or services that require a real browser
12+
- Users who want to test Full tunnel mode before committing to a permanent VPS
13+
- Users in networks where the standard `apps_script` mode is sufficient for
14+
daily browsing, but Full mode is needed for specific use cases
15+
16+
## How It Works
17+
18+
1. A GitHub Actions workflow starts the official `mhrv-tunnel-node` Docker
19+
container on a free hosted runner
20+
2. A tunneling service (cloudflared or ngrok) exposes the container to the
21+
internet on a public URL
22+
3. `CodeFull.gs` is configured to forward tunnel traffic to this URL
23+
4. The runner stays alive for 6 hours, then shuts down automatically
24+
5. The workflow can be re-triggered at any time for another 6-hour session
25+
26+
## Available Methods
27+
28+
Three methods are provided, ordered by setup complexity. Each is documented in
29+
its own guide with step-by-step instructions.
30+
31+
| # | Method | Guide | Account Required | URL Behavior |
32+
|---|---|---|---|---|
33+
| 1 | cloudflared Quick Tunnel | [cloudflared-quick.md][quick] | None | New URL each session |
34+
| 2 | ngrok Tunnel | [ngrok.md][ngrok] | ngrok (free) | New URL each session |
35+
| 3 | cloudflared Named Tunnel | [cloudflared-named.md][named] | Cloudflare + domain | **Permanent URL** |
36+
37+
**New to Full tunnel mode?** Start with [Method 1][quick] — no accounts
38+
needed beyond GitHub and Google.
39+
40+
**Need a stable URL that survives restarts?** Use [Method 3][named] — requires
41+
a one-time Cloudflare CLI setup but the URL never changes.
42+
43+
## Shared Requirements
44+
45+
All methods share these requirements:
46+
47+
| Requirement | Details |
48+
|---|---|
49+
| GitHub account | Free. Repository must be private to keep secrets secure. |
50+
| Google account | Free. Used to deploy `CodeFull.gs`. |
51+
| `CodeFull.gs` deployed | See the main project documentation for deployment instructions. |
52+
| `TUNNEL_AUTH_KEY` secret | A strong password shared between the workflow and `CodeFull.gs`. |
53+
54+
## After Starting the Tunnel
55+
56+
1. Run the workflow from your repository's **Actions** tab
57+
2. Copy the `TUNNEL_SERVER_URL` from the workflow log output
58+
3. Update the `TUNNEL_SERVER_URL` constant in `CodeFull.gs`
59+
4. Deploy `CodeFull.gs` (Deploy → New Deployment → Web App)
60+
5. Configure your `mhrv-rs` client to use the new deployment in Full mode
61+
62+
For methods where the URL changes each session (1 and 2), steps 2–4 must be
63+
repeated each time the workflow runs. Method 3 uses a permanent URL — configure
64+
`CodeFull.gs` once and only re-trigger the workflow when needed.
65+
66+
## Limitations
67+
68+
- **6-hour maximum per session.** GitHub Actions enforces a 360-minute timeout
69+
on hosted runners. Re-trigger the workflow for another session.
70+
- **URL changes on restart (Methods 1 & 2).** The tunnel URL is assigned at
71+
runtime. `CodeFull.gs` must be updated and redeployed each time.
72+
- **Shared IP ranges.** GitHub-hosted runners share IP ranges with other users.
73+
Some websites may already have these IPs flagged.(sometimes need re-run)
74+
- **GitHub Actions terms.** This workflow is intended for occasional personal
75+
use. Review [GitHub's Terms for Additional Products and Features][gh-terms]
76+
and ensure your usage complies.
77+
78+
## Compliance Note
79+
80+
This workflow uses GitHub-hosted runners for a purpose adjacent to, but not
81+
directly part of, software development on the repository. Usage is low-burden
82+
(a single Docker container, moderate outbound traffic for one user) and aligns
83+
with GitHub's acceptable use guidelines for development and testing
84+
infrastructure. Continuous, high-bandwidth, or commercial use is not
85+
recommended. For persistent Full mode operation, a dedicated VPS remains the
86+
recommended solution.
87+
88+
[quick]: cloudflared-quick.md
89+
[ngrok]: ngrok.md
90+
[named]: cloudflared-named.md
91+
[gh-terms]: https://docs.github.com/en/site-policy/github-terms/github-terms-for-additional-products-and-features#actions
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
# cloudflared Named Tunnel
2+
3+
Run a Full tunnel with a **permanent, unchanging URL** using a Cloudflare
4+
account and a custom domain. The tunnel URL never changes between restarts —
5+
configure `CodeFull.gs` once and only re-trigger the workflow when needed.
6+
7+
## Prerequisites
8+
9+
- A GitHub account (free)
10+
- A Cloudflare account with a domain
11+
- `cloudflared` installed on your local machine for one-time setup
12+
- `CodeFull.gs` deployed as a Google Apps Script Web App
13+
14+
## One-Time Local Setup
15+
16+
These steps are performed **once** on your local machine. They create a named
17+
tunnel on Cloudflare and route your domain to it.
18+
19+
### Step 1: Install cloudflared
20+
21+
**Linux (Debian/Ubuntu):**
22+
```bash
23+
curl -L --output cloudflared.deb \
24+
https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
25+
sudo dpkg -i cloudflared.deb
26+
```
27+
28+
**macOS:**
29+
```bash
30+
brew install cloudflared
31+
```
32+
33+
**Windows:**
34+
Download the installer from the [cloudflared releases page](https://github.com/cloudflare/cloudflared/releases).
35+
36+
### Step 2: Authenticate with Cloudflare
37+
38+
```bash
39+
cloudflared tunnel login
40+
```
41+
42+
This opens a browser window. Select your domain and authorize.
43+
44+
### Step 3: Create a Named Tunnel
45+
46+
```bash
47+
cloudflared tunnel create my-tunnel
48+
```
49+
50+
This outputs a tunnel ID (a UUID) and creates a credentials file at:
51+
```
52+
~/.cloudflared/<TUNNEL_ID>.json
53+
```
54+
55+
Copy the tunnel ID — you will need it later.
56+
57+
### Step 4: Route Your Domain
58+
59+
```bash
60+
cloudflared tunnel route dns my-tunnel tunnel.yourdomain.com
61+
```
62+
63+
Replace `tunnel.yourdomain.com` with the actual subdomain you want to use.
64+
This creates a DNS record on Cloudflare pointing to your tunnel.
65+
66+
### Step 5: Get the Credentials File
67+
68+
```bash
69+
cat ~/.cloudflared/<TUNNEL_ID>.json
70+
```
71+
72+
Copy the entire JSON output. You will use this as the
73+
`CLOUDFLARE_TUNNEL_CREDENTIALS` secret in GitHub Actions.
74+
75+
## GitHub Setup
76+
77+
### Step 6: Create the Repository
78+
79+
If you already have a repository from another method, you can reuse it.
80+
Otherwise:
81+
82+
1. Go to [github.com](https://github.com) and sign in
83+
2. Click the **+** icon in the top-right corner, then **New repository**
84+
3. Enter a repository name (e.g., `my-tunnel`)
85+
4. Select **Private** (recommended — keeps your secrets secure)
86+
5. Click **Create repository**
87+
88+
### Step 7: Add the Secrets
89+
90+
1. In your repository, go to **Settings > Secrets and variables > Actions**
91+
2. Click **New repository secret** and add each of the following:
92+
93+
| Name | Value |
94+
|---|---|
95+
| `TUNNEL_AUTH_KEY` | A strong password. You will also set this in `CodeFull.gs`. |
96+
| `CLOUDFLARE_TUNNEL_ID` | The tunnel ID from Step 3. |
97+
| `CLOUDFLARE_TUNNEL_HOSTNAME` | The subdomain you configured in Step 4 (e.g., `tunnel.yourdomain.com`). |
98+
| `CLOUDFLARE_TUNNEL_CREDENTIALS` | The entire JSON contents of the credentials file from Step 5. |
99+
100+
3. Click **Add secret** for each
101+
102+
### Step 8: Add the Workflow
103+
104+
1. In your repository, go to the **Actions** tab
105+
2. Click **New workflow**
106+
3. Click the **set up a workflow yourself** link
107+
4. Delete the default content and paste the contents of `cloudflared-named.yml` [[here]]
108+
5. Click **Commit changes...**, add a commit message, then click **Commit changes**
109+
110+
The workflow file will be saved to `.github/workflows/cloudflared-named.yml`.
111+
112+
### Step 9: Run the Workflow
113+
114+
1. Go to the **Actions** tab
115+
2. Select **Full Tunnel (cloudflared Named)** from the left sidebar
116+
3. Click **Run workflow > Run workflow**
117+
118+
The workflow will start immediately.
119+
120+
### Step 10: Configure CodeFull.gs
121+
122+
Open `CodeFull.gs` in the Google Apps Script editor and update these constants:
123+
124+
```javascript
125+
const TUNNEL_SERVER_URL = "https://tunnel.yourdomain.com";
126+
const TUNNEL_AUTH_KEY = "the-secret-you-set-in-step-7";
127+
```
128+
129+
Deploy: **Deploy > New Deployment > Web App**.
130+
Copy the new Deployment ID and update your `mhrv-rs` config.
131+
132+
**This step is performed only once.** The tunnel URL never changes between
133+
restarts.
134+
135+
### Step 11: Verify
136+
137+
Use `mhrv-rs test` or visit `https://ipleak.net` through your proxy.
138+
You should see a Cloudflare IP address.
139+
140+
## How It Works
141+
142+
1. GitHub Actions starts a Docker container running `mhrv-tunnel-node` on port
143+
`8080`
144+
2. `cloudflared` connects to Cloudflare using the named tunnel credentials
145+
3. Cloudflare routes traffic from your custom domain to the runner through a
146+
secure, persistent tunnel
147+
4. `CodeFull.gs` forwards tunnel operations to your custom domain over HTTPS
148+
5. The runner stays alive for 6 hours, then shuts down automatically
149+
6. On restart, the same domain routes to the new runner — no configuration
150+
changes needed
151+
152+
## Restarting the Tunnel
153+
154+
The tunnel shuts down after 6 hours. To start a new session:
155+
156+
1. Go to the **Actions** tab
157+
2. Select **Full Tunnel (cloudflared Named)**
158+
3. Click **Run workflow > Run workflow**
159+
160+
That is all — the URL is permanent so `CodeFull.gs` does not need to be updated.
161+
162+
For automatic restarts every 6 hours, add a `schedule` trigger to the workflow:
163+
164+
```yaml
165+
on:
166+
workflow_dispatch:
167+
schedule:
168+
- cron: '0 */6 * * *'
169+
```
170+
171+
## Limitations
172+
173+
- Requires a one-time local setup with `cloudflared` CLI
174+
- Requires a Cloudflare account with a domain
175+
- 6-hour maximum per session (GitHub Actions limit)
176+
177+
## Troubleshooting
178+
179+
| Problem | Solution |
180+
|---|---|
181+
| `cloudflared tunnel login` fails | Ensure your browser can reach `dash.cloudflare.com`. You may need to use a proxy or alternative network for this step. |
182+
| `cloudflared tunnel create` fails | Verify you are authenticated. Run `cloudflared tunnel login` again. |
183+
| Workflow fails at Docker step | GitHub Actions may be pulling the image for the first time. Wait 2-3 minutes and retry. |
184+
| `cloudflared` fails to connect | Verify all four secrets are set correctly. Check that `CLOUDFLARE_TUNNEL_CREDENTIALS` contains valid JSON. |
185+
| `CodeFull.gs` returns 502 or timeout | Verify the workflow is still running. Check that `TUNNEL_AUTH_KEY` matches in both the secret and `CodeFull.gs`. Ensure the DNS record was created in Step 4. |
186+
187+
[here]: cloudflared-named.yml
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Full Tunnel (cloudflared Named)
2+
3+
on:
4+
workflow_dispatch:
5+
6+
permissions:
7+
contents: read
8+
9+
jobs:
10+
tunnel:
11+
runs-on: ubuntu-latest
12+
timeout-minutes: 360
13+
steps:
14+
- name: Start mhrv-tunnel-node
15+
run: |
16+
docker run -d --name mhrv-tunnel \
17+
-p 8080:8080 \
18+
-e TUNNEL_AUTH_KEY="${{ secrets.TUNNEL_AUTH_KEY }}" \
19+
ghcr.io/therealaleph/mhrv-tunnel-node:latest
20+
sleep 5
21+
curl -s http://localhost:8080/health || sleep 5
22+
23+
- name: Install cloudflared
24+
run: |
25+
curl -L --output cloudflared.deb \
26+
https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
27+
sudo dpkg -i cloudflared.deb
28+
29+
- name: Configure tunnel
30+
run: |
31+
mkdir -p ~/.cloudflared
32+
echo "${{ secrets.CLOUDFLARE_TUNNEL_CREDENTIALS }}" > ~/.cloudflared/credentials.json
33+
cat > ~/.cloudflared/config.yml << EOF
34+
tunnel: ${{ secrets.CLOUDFLARE_TUNNEL_ID }}
35+
credentials-file: /home/runner/.cloudflared/credentials.json
36+
ingress:
37+
- hostname: ${{ secrets.CLOUDFLARE_TUNNEL_HOSTNAME }}
38+
service: http://localhost:8080
39+
- service: http_status:404
40+
EOF
41+
42+
- name: Run tunnel
43+
run: |
44+
cloudflared tunnel --config ~/.cloudflared/config.yml run &
45+
echo "TUNNEL_SERVER_URL = https://${{ secrets.CLOUDFLARE_TUNNEL_HOSTNAME }}"
46+
sleep 21000
47+
48+
- name: Cleanup
49+
if: always()
50+
run: |
51+
docker stop mhrv-tunnel || true
52+
pkill cloudflared || true

0 commit comments

Comments
 (0)