public-ingress ยท diff
git:20260615.5cc360c to git:20260825.c3e752c
65 added, 7 removed. Audit B to B.
---
name: public-ingress
description: Set up and manage ngrok-based public ingress for local assistants; do not use this in managed mode when platform callback routing is available
compatibility: "Designed for Vellum personal assistants"
metadata:
emoji: "๐"
vellum:
category: "system"
display-name: "Public Ingress"
activation-hints:
- "Local assistant needs a public webhook or OAuth callback URL"
- "ngrok tunnel setup for a non-managed assistant"
avoid-when:
- "Running in a platform-managed assistant with platform callback routing available"
---
You are setting up and managing a public ingress tunnel so that external services (Telegram webhooks, OAuth callbacks, etc.) can reach the local Vellum gateway. This skill uses ngrok to create a secure tunnel and persists the public URL as `ingress.publicBaseUrl`.
If managed platform callback routing is available, stop and do not continue with ngrok. In platform-managed deployments, Telegram/Twilio/OAuth callback routing should use the platform callback route flow instead of local public ingress.
## Overview
The Vellum gateway listens locally and needs a publicly reachable URL for:
- Telegram webhook delivery
- Google/Slack OAuth redirect callbacks
- Any other inbound webhook traffic
This skill installs ngrok, configures authentication, starts a tunnel, discovers the public URL, and saves it to the assistant's ingress config.
+ On Windows, use the PowerShell blocks instead of the POSIX ones.
+
## Step 0: Reject Managed Callback Environments
Check whether managed platform callback routing is available:
```bash
assistant platform status --json
```
If the result shows `isPlatform: true` and `available: true`, stop here. Tell the user that this assistant should use the platform callback route flow instead of ngrok, and do not install or start ngrok.
## Step 1: Check Current Ingress Status
First, check whether ingress is already configured:
```bash
assistant config get ingress.publicBaseUrl
assistant config get ingress.enabled
```
The local gateway URL is available as the `$INTERNAL_GATEWAY_BASE_URL` environment variable (defaults to `http://127.0.0.1:7830`).
The commands return:
- `ingress.publicBaseUrl` - currently configured public ingress URL (if any)
- `ingress.enabled` - whether ingress is enabled
If `publicBaseUrl` is already set and the tunnel is running (check via `curl -s http://127.0.0.1:4040/api/tunnels`), tell the user the current status and ask if they want to reconfigure or if this is sufficient.
+ On Windows, check the tunnel with:
+
+ ```powershell
+ Invoke-RestMethod http://127.0.0.1:4040/api/tunnels
+ ```
+
## Step 2: Install ngrok
Check if ngrok is installed:
```bash
ngrok version
```
If not installed, install it:
**macOS (Homebrew):**
```bash
brew install ngrok/ngrok/ngrok
```
+ **Windows (Microsoft Store via WinGet):**
+
+ ```powershell
+ winget install ngrok -s msstore
+ ```
+
**Linux (snap):**
```bash
sudo snap install ngrok
```
**Linux (apt - alternative):**
```bash
curl -sSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null
echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list
sudo apt update && sudo apt install ngrok
```
After installation, verify with `ngrok version`.
## Step 3: Authenticate ngrok
Check if ngrok already has an auth token configured:
```bash
ngrok config check
```
If not authenticated:
1. Tell the user: "You need an ngrok account to create tunnels. If you don't have one, sign up at https://dashboard.ngrok.com/signup - it's free."
2. Once they have an account, run `assistant credentials prompt` (via the bash tool) to securely collect their auth token. **Never ask the user to paste the token directly in chat.**
```bash
assistant credentials prompt --service ngrok --field authtoken \
--label "ngrok Auth Token" \
--description "Get your auth token from https://dashboard.ngrok.com/get-started/your-authtoken" \
--usage-description "ngrok authentication token for creating public tunnels"
```
3. Once the credential is stored, reveal it and apply it to ngrok:
```bash
ngrok config add-authtoken "$(assistant credentials reveal --service ngrok --field authtoken)"
```
+ On Windows:
+
+ ```powershell
+ $token = assistant credentials reveal --service ngrok --field authtoken
+ ngrok config add-authtoken $token
+ ```
+
If no value is returned, re-run `assistant credentials prompt` and try again.
Verify authentication succeeded by checking `ngrok config check` again.
## Step 4: Start the Tunnel
Before starting, check for an existing ngrok process to avoid duplicates:
```bash
curl -s http://127.0.0.1:4040/api/tunnels 2>/dev/null
```
+ On Windows:
+
+ ```powershell
+ Invoke-RestMethod http://127.0.0.1:4040/api/tunnels -ErrorAction SilentlyContinue
+ ```
+
If a tunnel is already running, check whether it points to the correct local target. If so, skip to Step 5. If it points elsewhere, stop it first:
```bash
pkill -f ngrok || true
sleep 1
```
+ On Windows:
+
+ ```powershell
+ Get-Process ngrok -ErrorAction SilentlyContinue | Stop-Process
+ Start-Sleep -Seconds 1
+ ```
+
Start ngrok in the background tunneling to the local gateway URL:
```bash
nohup ngrok http "$INTERNAL_GATEWAY_BASE_URL" --log=stdout > /tmp/ngrok.log 2>&1 &
echo $! > /tmp/ngrok.pid
```
- Wait a few seconds for the tunnel to establish:
+ On Windows:
- ```bash
- sleep 3
+ ```powershell
+ $logPath = Join-Path $env:TEMP "ngrok.log"
+ $errorLogPath = Join-Path $env:TEMP "ngrok-error.log"
+ Start-Process ngrok -ArgumentList @("http", $env:INTERNAL_GATEWAY_BASE_URL, "--log=stdout") -RedirectStandardOutput $logPath -RedirectStandardError $errorLogPath -WindowStyle Hidden
```
+ Wait a few seconds for the tunnel to establish.
+
## Step 4b: Verify Port Alignment
Before discovering the public URL, verify that ngrok is forwarding to the same port the gateway is actually listening on. A mismatch here causes silent failures - webhooks appear to be delivered but never reach the gateway.
Query the ngrok tunnel's target port and the gateway's configured port, then compare them:
```bash
curl -s http://127.0.0.1:4040/api/tunnels | python3 -c "
import sys, json, re
data = json.load(sys.stdin)
tunnels = data.get('tunnels', [])
if not tunnels:
print('ERROR: no active ngrok tunnel found')
sys.exit(1)
addr = tunnels[0].get('config', {}).get('addr', '')
match = re.search(r':(\d+)$', addr)
if not match:
print(f'ERROR: could not extract port from ngrok tunnel addr: {addr}')
sys.exit(1)
print(match.group(1))
"
```
```bash
echo "$INTERNAL_GATEWAY_BASE_URL" | grep -oE '[0-9]+$'
```
+ On Windows, resolve both ports without using the POSIX snippets:
+
+ ```powershell
+ $tunnel = (Invoke-RestMethod http://127.0.0.1:4040/api/tunnels).tunnels[0]
+ $tunnelPort = ([uri]$tunnel.config.addr).Port
+ $gatewayPort = ([uri]$env:INTERNAL_GATEWAY_BASE_URL).Port
+ @{ tunnelPort = $tunnelPort; gatewayPort = $gatewayPort }
+ ```
+
Compare the two port numbers. If they differ, warn the user:
- > **Port mismatch detected:** ngrok is forwarding to port **X** but the gateway is listening on port **Y**. Webhooks will not reach the gateway. Stop ngrok (`pkill -f ngrok`), then re-run this skill to start ngrok on the correct port.
+ > **Port mismatch detected:** ngrok is forwarding to port **X** but the gateway is listening on port **Y**. Webhooks will not reach the gateway. Stop ngrok (Step 4), then re-run this skill to start ngrok on the correct port.
If the ports match, proceed silently to Step 5.
## Step 5: Discover the Public URL
Query the ngrok local API for the tunnel's public URL:
```bash
curl -s http://127.0.0.1:4040/api/tunnels | python3 -c "
import sys, json
data = json.load(sys.stdin)
tunnels = data.get('tunnels', [])
for t in tunnels:
url = t.get('public_url', '')
if url.startswith('https://'):
print(url)
sys.exit(0)
for t in tunnels:
url = t.get('public_url', '')
if url:
print(url)
sys.exit(0)
print('ERROR: no tunnel found')
sys.exit(1)
"
```
If no tunnel is found, check `/tmp/ngrok.log` for errors and report them to the user.
+ On Windows, discover the URL and inspect the logs with:
+
+ ```powershell
+ $tunnel = (Invoke-RestMethod http://127.0.0.1:4040/api/tunnels).tunnels | Where-Object { $_.public_url -like "https://*" } | Select-Object -First 1
+ $tunnel.public_url
+ Get-Content (Join-Path $env:TEMP "ngrok.log") -ErrorAction SilentlyContinue
+ Get-Content (Join-Path $env:TEMP "ngrok-error.log") -ErrorAction SilentlyContinue
+ ```
+
## Step 6: Persist the Ingress Setting
Save the discovered public URL and enable ingress:
```bash
assistant config set ingress.publicBaseUrl "<public-url>"
assistant config set ingress.enabled true
```
Verify it was saved:
```bash
assistant config get ingress.publicBaseUrl
assistant config get ingress.enabled
```
## Step 7: Report Completion
Summarize the setup:
- **Public URL:** `<the-url>` (this is your `ingress.publicBaseUrl`)
- **Local gateway target:** `$INTERNAL_GATEWAY_BASE_URL`
- **ngrok dashboard:** http://127.0.0.1:4040
Provide useful follow-up commands:
- **Check tunnel status:** `curl -s http://127.0.0.1:4040/api/tunnels | python3 -c "import sys,json; [print(t['public_url']) for t in json.load(sys.stdin)['tunnels']]"`
- **View ngrok logs:** `cat /tmp/ngrok.log`
- **Restart tunnel:** `pkill -f ngrok; sleep 1; nohup ngrok http "$INTERNAL_GATEWAY_BASE_URL" --log=stdout > /tmp/ngrok.log 2>&1 &`
- **Stop tunnel:** `pkill -f ngrok`
- **Rotate URL:** Stop and restart ngrok (free tier assigns a new URL each time; update `ingress.publicBaseUrl` afterward)
**Important:** On ngrok's free tier, the public URL changes every time the tunnel restarts. After restarting, re-run this skill or manually update `ingress.publicBaseUrl` and any registered webhooks (e.g., Telegram).
## Troubleshooting
### ngrok not installed
Run the install commands in Step 2. On macOS, make sure Homebrew is installed first (`brew --version`).
### Auth token invalid or expired
Sign in to https://dashboard.ngrok.com, copy a fresh token from the "Your Authtoken" page, and re-run Step 3.
### ngrok API (port 4040) not responding
- The ngrok process may not be running. Check with `ps aux | grep ngrok`. If not running, start it per Step 4. If running but 4040 is unresponsive, check `/tmp/ngrok.log` for errors.
+ The ngrok process may not be running. On macOS or Linux, check with `ps aux | grep ngrok`. On Windows, use `Get-Process ngrok -ErrorAction SilentlyContinue`. If it is not running, start it per Step 4. If it is running but port 4040 is unresponsive, check `/tmp/ngrok.log` (`$env:TEMP\ngrok.log` on Windows) for errors.
### Gateway not reachable on local target
Re-check the local gateway target with `echo $INTERNAL_GATEWAY_BASE_URL`. Run `curl -s "$INTERNAL_GATEWAY_BASE_URL/healthz"` to verify it is reachable. If the gateway is not running, start the assistant first.
+ On Windows, use `$env:INTERNAL_GATEWAY_BASE_URL` and `Invoke-RestMethod "$env:INTERNAL_GATEWAY_BASE_URL/healthz"`.
+
### "Too many connections" or tunnel limit errors
ngrok's free tier allows one tunnel at a time. Stop any other ngrok tunnels before starting a new one.
### ngrok port doesn't match gateway port
**Symptom:** Webhooks return connection refused or timeouts even though both ngrok and the gateway appear to be running.
**Cause:** ngrok is forwarding to a different port than the gateway is listening on. This can happen if the gateway port was changed after ngrok was started, or if ngrok was started manually with a hardcoded port.
- **Fix:** Stop ngrok (`pkill -f ngrok`), verify the gateway URL with `echo $INTERNAL_GATEWAY_BASE_URL`, then re-run this skill to start ngrok on the correct port.
+ **Fix:** Stop ngrok (Step 4), verify the gateway URL with `echo $INTERNAL_GATEWAY_BASE_URL`, then re-run this skill to start ngrok on the correct port.
### ngrok automatically restarts with wrong port
- If after killing the ngrok process, it automatically re-spawns and is still attached to the incorrect port, check to see if there is a launch agent process configured to auto-restart it. This might exist at `~/Library/LaunchAgents/com.ngrok.tunnel.plist`. If so, it needs to be either removed or updated.
+ On macOS, if the ngrok process automatically re-spawns on the incorrect port, check for a launch agent at `~/Library/LaunchAgents/com.ngrok.tunnel.plist`. If it exists, remove or update it.