Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions assets/github-actions-tunnel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# GitHub Actions Full Tunnel

A temporary, repeatable Full tunnel mode for users who cannot or prefer not to
purchase a VPS. Uses GitHub Actions free hosted runners to run the official
`mhrv-tunnel-node` container for 6-hour sessions at no cost.

## Who This Is For

- Users who cannot access international payment methods to purchase a VPS
- Users who need Full tunnel mode occasionally — CAPTCHA-protected sites,
streaming, or services that require a real browser
- Users who want to test Full tunnel mode before committing to a permanent VPS
- Users in networks where the standard `apps_script` mode is sufficient for
daily browsing, but Full mode is needed for specific use cases

## How It Works

1. A GitHub Actions workflow starts the official `mhrv-tunnel-node` Docker
container on a free hosted runner
2. A tunneling service (cloudflared or ngrok) exposes the container to the
internet on a public URL
3. `CodeFull.gs` is configured to forward tunnel traffic to this URL
4. The runner stays alive for 6 hours, then shuts down automatically
5. The workflow can be re-triggered at any time for another 6-hour session

## Available Methods

Three methods are provided, ordered by setup complexity. Each is documented in
its own guide with step-by-step instructions.

| # | Method | Guide | Account Required | URL Behavior |
|---|---|---|---|---|
| 1 | cloudflared Quick Tunnel | [cloudflared-quick.md][quick] | None | New URL each session |
| 2 | ngrok Tunnel | [ngrok.md][ngrok] | ngrok (free) | New URL each session |
| 3 | cloudflared Named Tunnel | [cloudflared-named.md][named] | Cloudflare + domain | **Permanent URL** |

**New to Full tunnel mode?** Start with [Method 1][quick] — no accounts
needed beyond GitHub and Google.

**Need a stable URL that survives restarts?** Use [Method 3][named] — requires
a one-time Cloudflare CLI setup but the URL never changes.

## Shared Requirements

All methods share these requirements:

| Requirement | Details |
|---|---|
| GitHub account | Free. Repository must be private to keep secrets secure. |
| Google account | Free. Used to deploy `CodeFull.gs`. |
| `CodeFull.gs` deployed | See the main project documentation for deployment instructions. |
| `TUNNEL_AUTH_KEY` secret | A strong password shared between the workflow and `CodeFull.gs`. |

## After Starting the Tunnel

1. Run the workflow from your repository's **Actions** tab
2. Copy the `TUNNEL_SERVER_URL` from the workflow log output
3. Update the `TUNNEL_SERVER_URL` constant in `CodeFull.gs`
4. Deploy `CodeFull.gs` (Deploy → New Deployment → Web App)
5. Configure your `mhrv-rs` client to use the new deployment in Full mode

For methods where the URL changes each session (1 and 2), steps 2–4 must be
repeated each time the workflow runs. Method 3 uses a permanent URL — configure
`CodeFull.gs` once and only re-trigger the workflow when needed.

## Limitations

- **6-hour maximum per session.** GitHub Actions enforces a 360-minute timeout
on hosted runners. Re-trigger the workflow for another session.
- **URL changes on restart (Methods 1 & 2).** The tunnel URL is assigned at
runtime. `CodeFull.gs` must be updated and redeployed each time.
- **Shared IP ranges.** GitHub-hosted runners share IP ranges with other users.
Some websites may already have these IPs flagged.(sometimes need re-run)
- **GitHub Actions terms.** This workflow is intended for occasional personal
use. Review [GitHub's Terms for Additional Products and Features][gh-terms]
and ensure your usage complies.

## Compliance Note

This workflow uses GitHub-hosted runners for a purpose adjacent to, but not
directly part of, software development on the repository. Usage is low-burden
(a single Docker container, moderate outbound traffic for one user) and aligns
with GitHub's acceptable use guidelines for development and testing
infrastructure. Continuous, high-bandwidth, or commercial use is not
recommended. For persistent Full mode operation, a dedicated VPS remains the
recommended solution.

[quick]: cloudflared-quick.md
[ngrok]: ngrok.md
[named]: cloudflared-named.md
[gh-terms]: https://docs.github.com/en/site-policy/github-terms/github-terms-for-additional-products-and-features#actions
187 changes: 187 additions & 0 deletions assets/github-actions-tunnel/cloudflared-named.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# cloudflared Named Tunnel

Run a Full tunnel with a **permanent, unchanging URL** using a Cloudflare
account and a custom domain. The tunnel URL never changes between restarts —
configure `CodeFull.gs` once and only re-trigger the workflow when needed.

## Prerequisites

- A GitHub account (free)
- A Cloudflare account with a domain
- `cloudflared` installed on your local machine for one-time setup
- `CodeFull.gs` deployed as a Google Apps Script Web App

## One-Time Local Setup

These steps are performed **once** on your local machine. They create a named
tunnel on Cloudflare and route your domain to it.

### Step 1: Install cloudflared

**Linux (Debian/Ubuntu):**
```bash
curl -L --output cloudflared.deb \
https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared.deb
```

**macOS:**
```bash
brew install cloudflared
```

**Windows:**
Download the installer from the [cloudflared releases page](https://github.com/cloudflare/cloudflared/releases).

### Step 2: Authenticate with Cloudflare

```bash
cloudflared tunnel login
```

This opens a browser window. Select your domain and authorize.

### Step 3: Create a Named Tunnel

```bash
cloudflared tunnel create my-tunnel
```

This outputs a tunnel ID (a UUID) and creates a credentials file at:
```
~/.cloudflared/<TUNNEL_ID>.json
```

Copy the tunnel ID — you will need it later.

### Step 4: Route Your Domain

```bash
cloudflared tunnel route dns my-tunnel tunnel.yourdomain.com
```

Replace `tunnel.yourdomain.com` with the actual subdomain you want to use.
This creates a DNS record on Cloudflare pointing to your tunnel.

### Step 5: Get the Credentials File

```bash
cat ~/.cloudflared/<TUNNEL_ID>.json
```

Copy the entire JSON output. You will use this as the
`CLOUDFLARE_TUNNEL_CREDENTIALS` secret in GitHub Actions.

## GitHub Setup

### Step 6: Create the Repository

If you already have a repository from another method, you can reuse it.
Otherwise:

1. Go to [github.com](https://github.com) and sign in
2. Click the **+** icon in the top-right corner, then **New repository**
3. Enter a repository name (e.g., `my-tunnel`)
4. Select **Private** (recommended — keeps your secrets secure)
5. Click **Create repository**

### Step 7: Add the Secrets

1. In your repository, go to **Settings > Secrets and variables > Actions**
2. Click **New repository secret** and add each of the following:

| Name | Value |
|---|---|
| `TUNNEL_AUTH_KEY` | A strong password. You will also set this in `CodeFull.gs`. |
| `CLOUDFLARE_TUNNEL_ID` | The tunnel ID from Step 3. |
| `CLOUDFLARE_TUNNEL_HOSTNAME` | The subdomain you configured in Step 4 (e.g., `tunnel.yourdomain.com`). |
| `CLOUDFLARE_TUNNEL_CREDENTIALS` | The entire JSON contents of the credentials file from Step 5. |

3. Click **Add secret** for each

### Step 8: Add the Workflow

1. In your repository, go to the **Actions** tab
2. Click **New workflow**
3. Click the **set up a workflow yourself** link
4. Delete the default content and paste the contents of `cloudflared-named.yml` [[here]]
5. Click **Commit changes...**, add a commit message, then click **Commit changes**

The workflow file will be saved to `.github/workflows/cloudflared-named.yml`.

### Step 9: Run the Workflow

1. Go to the **Actions** tab
2. Select **Full Tunnel (cloudflared Named)** from the left sidebar
3. Click **Run workflow > Run workflow**

The workflow will start immediately.

### Step 10: Configure CodeFull.gs

Open `CodeFull.gs` in the Google Apps Script editor and update these constants:

```javascript
const TUNNEL_SERVER_URL = "https://tunnel.yourdomain.com";
const TUNNEL_AUTH_KEY = "the-secret-you-set-in-step-7";
```

Deploy: **Deploy > New Deployment > Web App**.
Copy the new Deployment ID and update your `mhrv-rs` config.

**This step is performed only once.** The tunnel URL never changes between
restarts.

### Step 11: Verify

Use `mhrv-rs test` or visit `https://ipleak.net` through your proxy.
You should see a Cloudflare IP address.

## How It Works

1. GitHub Actions starts a Docker container running `mhrv-tunnel-node` on port
`8080`
2. `cloudflared` connects to Cloudflare using the named tunnel credentials
3. Cloudflare routes traffic from your custom domain to the runner through a
secure, persistent tunnel
4. `CodeFull.gs` forwards tunnel operations to your custom domain over HTTPS
5. The runner stays alive for 6 hours, then shuts down automatically
6. On restart, the same domain routes to the new runner — no configuration
changes needed

## Restarting the Tunnel

The tunnel shuts down after 6 hours. To start a new session:

1. Go to the **Actions** tab
2. Select **Full Tunnel (cloudflared Named)**
3. Click **Run workflow > Run workflow**

That is all — the URL is permanent so `CodeFull.gs` does not need to be updated.

For automatic restarts every 6 hours, add a `schedule` trigger to the workflow:

```yaml
on:
workflow_dispatch:
schedule:
- cron: '0 */6 * * *'
```

## Limitations

- Requires a one-time local setup with `cloudflared` CLI
- Requires a Cloudflare account with a domain
- 6-hour maximum per session (GitHub Actions limit)

## Troubleshooting

| Problem | Solution |
|---|---|
| `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. |
| `cloudflared tunnel create` fails | Verify you are authenticated. Run `cloudflared tunnel login` again. |
| Workflow fails at Docker step | GitHub Actions may be pulling the image for the first time. Wait 2-3 minutes and retry. |
| `cloudflared` fails to connect | Verify all four secrets are set correctly. Check that `CLOUDFLARE_TUNNEL_CREDENTIALS` contains valid JSON. |
| `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. |

[here]: cloudflared-named.yml
52 changes: 52 additions & 0 deletions assets/github-actions-tunnel/cloudflared-named.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Full Tunnel (cloudflared Named)

on:
workflow_dispatch:

permissions:
contents: read

jobs:
tunnel:
runs-on: ubuntu-latest
timeout-minutes: 360
steps:
- name: Start mhrv-tunnel-node
run: |
docker run -d --name mhrv-tunnel \
-p 8080:8080 \
-e TUNNEL_AUTH_KEY="${{ secrets.TUNNEL_AUTH_KEY }}" \
ghcr.io/therealaleph/mhrv-tunnel-node:latest
sleep 5
curl -s http://localhost:8080/health || sleep 5

- name: Install cloudflared
run: |
curl -L --output cloudflared.deb \
https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared.deb

- name: Configure tunnel
run: |
mkdir -p ~/.cloudflared
echo "${{ secrets.CLOUDFLARE_TUNNEL_CREDENTIALS }}" > ~/.cloudflared/credentials.json
cat > ~/.cloudflared/config.yml << EOF
tunnel: ${{ secrets.CLOUDFLARE_TUNNEL_ID }}
credentials-file: /home/runner/.cloudflared/credentials.json
ingress:
- hostname: ${{ secrets.CLOUDFLARE_TUNNEL_HOSTNAME }}
service: http://localhost:8080
- service: http_status:404
EOF

- name: Run tunnel
run: |
cloudflared tunnel --config ~/.cloudflared/config.yml run &
echo "TUNNEL_SERVER_URL = https://${{ secrets.CLOUDFLARE_TUNNEL_HOSTNAME }}"
sleep 21000

- name: Cleanup
if: always()
run: |
docker stop mhrv-tunnel || true
pkill cloudflared || true
Loading
Loading