Create secure tunnels for webhooks, integration testing, and PR preview environments using LocalXpose.
- π Zero Setup - Start tunneling in seconds
- π― Cross-Platform - Works on Ubuntu, Windows, and macOS runners
- π Secure - End-to-end encryption with authentication
- π Global Regions - Supports US, EU, and AP entrypoints
- π¬ PR Comments - Automatic preview URLs in pull requests
- β‘ Fast & Reliable - Production-ready tunnel infrastructure
- β Zero Boilerplate - Be online in one step. No wait-for-it.sh, no copypasta.
Expose a local port to the internet on an ephemeral url:
- name: Start LocalXpose tunnel
uses: localxpose/localxpose-action@v1
id: tunnel
with:
port: 3000
token: ${{ secrets.LX_ACCESS_TOKEN }}
- name: Use tunnel URL
run: echo "Service available at ${{ steps.tunnel.outputs.url }}"Automatically comment tunnel URLs on pull requests:
name: PR Preview
on:
pull_request:
types: [opened, synchronize]
jobs:
preview:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Start your app
run: npm start &
- name: Create preview tunnel
uses: localxpose/localxpose-action@v1
with:
port: 3000
token: ${{ secrets.LX_ACCESS_TOKEN }}
pr-comment: true| Input | Description | Required | Default |
|---|---|---|---|
port |
Local port to expose | Yes | - |
token |
LocalXpose authentication token | No* | ${{ env.LX_ACCESS_TOKEN }} |
type |
Tunnel type (currently only http is supported) |
No | http |
region |
Tunnel region (us, eu, ap) |
No | us |
subdomain |
Request specific subdomain (requires subscription) | No | - |
pr-comment |
Post tunnel URL as PR comment | No | false |
pr-comment-name |
Display name for this tunnel in PR comment | No | - |
github-token |
GitHub token for PR comments | No | ${{ github.token }} |
*All usage requires auth token. Get yours from the LocalXpose dashboard
| Output | Description |
|---|---|
url |
Public tunnel URL |
hostname |
Tunnel hostname (without protocol) |
status |
Tunnel status (running or failed) |
- name: Start API server
run: npm run start:api &
- name: Expose API for webhook testing
id: api-tunnel
uses: localxpose/localxpose-action@v1
with:
port: 8080
token: ${{ secrets.LX_ACCESS_TOKEN }}
- name: Run webhook tests
env:
WEBHOOK_URL: ${{ steps.api-tunnel.outputs.url }}/webhook
run: npm run test:webhooksRun multiple services with separate tunnels:
- name: API tunnel
id: api
uses: localxpose/localxpose-action@v1
with:
port: 3000
token: ${{ secrets.LX_ACCESS_TOKEN }}
- name: Frontend tunnel
id: frontend
uses: localxpose/localxpose-action@v1
with:
port: 8080
token: ${{ secrets.LX_ACCESS_TOKEN }}
- name: Display URLs
run: |
echo "API: ${{ steps.api.outputs.url }}"
echo "Frontend: ${{ steps.frontend.outputs.url }}"When running multiple instances, all tunnels are displayed in a single, organized PR comment:
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
# Frontend tunnel
- name: Frontend tunnel
uses: localxpose/localxpose-action@v1
with:
port: 3000
pr-comment: true
pr-comment-name: Frontend
github-token: ${{ secrets.GITHUB_TOKEN }}
# API tunnel
- name: API tunnel
uses: localxpose/localxpose-action@v1
with:
port: 8080
pr-comment: true
pr-comment-name: API
github-token: ${{ secrets.GITHUB_TOKEN }}This creates a single PR comment that shows all active tunnels, grouped by workflow run.
PR Comment Features:
- Single comment updated with all tunnels
- Shows tunnel status (active/expired)
- Groups tunnels by workflow run
- Automatically removes expired tunnels (>20 minutes)
- Shows remaining time for tunnels nearing expiry
- name: Create tunnel for E2E tests
id: e2e-tunnel
uses: localxpose/localxpose-action@v1
with:
port: 3000
token: ${{ secrets.LX_ACCESS_TOKEN }}
region: eu # Select a region for improved latency
- name: Start your application with a dynamic url
env:
BASE_URL: ${{ steps.e2e-tunnel.outputs.url }}
run: docker-compose up -d
- name: Run E2E tests
env:
BASE_URL: ${{ steps.e2e-tunnel.outputs.url }}
run: |
# Note: Free tier tunnels limited to 15 min
npm run test:e2e --timeout=10m- Sign up at localxpose.io
- Copy your access token from the dashboard
Note: Free Tier Limitations
- Only HTTP tunnels are supported (no HTTPS/TCP/TLS)
- Tunnels automatically close after 15 minutes
- First-time visitors see a warning page before accessing your content
# In your repository settings
Settings β Secrets and variables β Actions β New repository secret
Name: LX_ACCESS_TOKEN
Value: <your-token>The action will automatically use the LX_ACCESS_TOKEN environment variable if no token input is provided.
LocalXpose creates secure tunnels from your local services to public URLs, perfect for:
- Webhook Development - Test webhooks from services like Stripe, GitHub, or Slack
- Mobile App Testing - Access local backends from mobile devices
- Client Demos - Share work-in-progress without deployment
- Integration Testing - Test with real external services
- Debugging & Troubleshooting - Easily reach hard-to-reach containers and devices
- End-to-end encryption - Your data is secure in transit
- Custom subdomains - Consistent URLs for your services
- Request inspection - Debug webhooks with full request details
- No vendor lock-in - Simple migration from other tunnel services
| Platform | Status | Notes |
|---|---|---|
| Ubuntu | β Supported | Full functionality |
| macOS | β Supported | Full functionality |
| Windows | β Supported | Full functionality |
| FreeBSD | β Supported | Not actively tested |
Authentication Failed
# Ensure token is set correctly
- uses: localxpose/localxpose-action@v1
with:
port: 3000
token: ${{ secrets.LX_ACCESS_TOKEN }} # Check secret namePort Already in Use
# Make sure your service is running on the specified port
- run: npm start & # Start your service first
- uses: localxpose/localxpose-action@v1
with:
port: 3000 # Must match your service portPR Comments Not Appearing
# Add required permissions
permissions:
contents: read
pull-requests: write # Required for PR commentsWarning Page on First Visit (Free Accounts)
- Free tier tunnels show a warning page to first-time visitors
- Users must click through to access your content
- Consider this when writing automated tests
Tunnel Expires After 15 Minutes (Free Accounts)
# Plan your workflows to complete within 15 minutes
- uses: localxpose/localxpose-action@v1
with:
port: 3000
token: ${{ secrets.LX_ACCESS_TOKEN }}
# Run time-sensitive tasks immediately
- name: Quick tests
run: npm run test:integration
timeout-minutes: 10 # Leave buffer before expiryNote on Tunnel Types
This action currently only supports HTTP tunnels. LocalXpose also offers TLS, TCP, and UDP tunnel types, which may be supported in future versions of this action.
For advanced scenarios, you can use LocalXpose configuration files:
- name: Create config
run: |
cat > loclx.yml << EOF
tunnels:
api:
proto: http
addr: 3000
subdomain: my-api
metrics:
proto: tcp
addr: 9090
EOF
- name: Run with config
run: loclx start --config loclx.ymlWe welcome contributions! Please see our Contributing Guide for details.
This project is licensed under the MIT License - see the LICENSE file for details.
No credit card required β’ Generous free tier β’ Cancel anytime
Download LocalXpose β’ Documentation β’ Pricing