Skip to main content

Wildtunnel

PyPI Python versions Publish to PyPI License: MIT

This tool makes a home-network service available at <name>.<domain>. It does not open an inbound port at home.

Browser -> DNS (Cloudflare) -> VPS (Caddy + frps) -> tunnel -> home PC (frpc) -> your app

Wildtunnel puts the tunnel server on a VPS. It supports two providers: AWS EC2 (deployed via CDK) and AWS Lightsail (deployed via direct API calls, no CDK toolchain needed). The code separates the generic server setup (frps + Caddy) from each provider's deploy logic, so adding another provider needs no rewrite.

Setup and usage

Step 1: Install the CLI

Install frpc on a different machine first: github.com/fatedier/frp/releases

# For the AWS EC2 provider:
uv tool install 'wildtunnel[aws-ec2]'

# For the AWS Lightsail provider (no extra needed, no CDK toolchain):
uv tool install wildtunnel

Tab completion for subcommands, flags, and tunnel names (frpc del <tab>) is available for bash, zsh, and fish. Add the line for your shell to its rc file, then restart your shell:

source <(wildtunnel completion bash)   # ~/.bashrc
source <(wildtunnel completion zsh)    # ~/.zshrc
wildtunnel completion fish | source    # ~/.config/fish/config.fish

Step 2: Deploy the server

Pick one provider.

Step 2a: Deploy to AWS EC2

Creates an EC2 host, frps, Caddy, an Elastic IP, and an IAM role, via CDK.

wildtunnel aws-ec2 config --domain example.com   # reads the region from your AWS CLI config
wildtunnel aws-ec2 deploy

Options for aws-ec2 config:

  • --domain: base domain for the tunnel subdomains, e.g. example.com.
  • --region: AWS region for the stack. Defaults to your AWS CLI region.
  • --extra-port-range START-END: opens a TCP+UDP port range on the EC2 host and in frps, for frpc add --proto tcp|udp --remote-port. Not opened unless given. Run aws-ec2 deploy again to apply a change.
  • --yes: skips confirmation prompts.

Record the ElasticIp output. Check status anytime with wildtunnel aws-ec2 status.

Get the frpc client's data (server address, base domain, token, and a ready frpc config command):

wildtunnel aws-ec2 info

Step 2b: Deploy to AWS Lightsail

Creates a nano_3_0 Lightsail instance, frps, Caddy, and a static IP, via direct Lightsail API calls. No CDK, no CloudFormation.

wildtunnel aws-lightsail config --domain example.com   # reads the region from your AWS CLI config
wildtunnel aws-lightsail deploy

aws-lightsail config takes the same options as aws-ec2 config: --domain, --region, --extra-port-range, --yes. Check status anytime with wildtunnel aws-lightsail status.

Lightsail instances cannot have an IAM role, so wildtunnel writes the frp token directly into the instance's user data at deploy time, instead of fetching it from SSM at boot. One effect: wildtunnel aws-lightsail info only works on the machine that ran deploy, since the token is never stored remotely.

wildtunnel aws-lightsail info

Re-running deploy on a live instance only syncs the static IP and firewall rules (for example after changing --extra-port-range) — Lightsail cannot re-run cloud-init, so it never reinstalls frps/Caddy. Use wildtunnel aws-lightsail diff to check for firewall drift, or destroy + deploy to force a clean reinstall.

Step 3: Point your DNS at the server address

Get the server address: the ElasticIp from aws-ec2 info, or the static IP from aws-lightsail info.

At your DNS provider (for example Cloudflare), add a wildcard A record, *.example.com, pointed at that address. Keep it DNS-only — do not enable the Cloudflare proxy (grey cloud, not orange). Make sure port 80 is open: Caddy needs it to get a TLS certificate per host on demand, via Let's Encrypt HTTP-01.

Step 4: Configure the frpc client

Step 4.1: Add a service

frpc does not read the deployed server automatically. Copy the values, or the ready command, from aws-ec2 info / aws-lightsail info.

wildtunnel frpc config \
  --server-addr 1.2.3.4 \
  --base-domain example.com \
  --token <token>
wildtunnel frpc add openwebui 192.168.50.10:8080
# -> https://openwebui.example.com

frpc config options --server-addr, --base-domain, and --token are all required.

frpc add <name> <local-ip>:<local-port> adds a tunnel for a local service — HTTP/HTTPS at <name>.<base-domain> by default. For a non-HTTP service, for example WireGuard, add --proto tcp or --proto udp with --remote-port <port> (must be in the range you set with --extra-port-range):

frpc add wireguard 127.0.0.1:51820 --proto udp --remote-port 51820

frpc list shows configured tunnels. frpc del <name> removes one.

Step 4.2: Run frpc on a different machine

Use the same data as step 4.1. The render command writes an frpc.toml to stdout, without saving a file or starting a service:

wildtunnel frpc render \
  --server-addr 1.2.3.4 \
  --base-domain example.com \
  --token <token>

Upgrade from aws-reverse-tunnel

This project was renamed from aws-reverse-tunnel to wildtunnel. There is no automatic migration. To keep your existing configuration, move the config directory by hand:

mv ~/.config/aws-reverse-tunnel ~/.config/wildtunnel

Cost

AWS EC2

Runs one t4g.nano EC2 host, an 8 GiB gp3 EBS volume, and one Elastic IP. On-demand list prices below for a 730-hour month; treat as estimates, since AWS prices change.

Resource ap-northeast-1 (Tokyo) us-east-1
t4g.nano (730 h) ~$3.87 ~$3.07
EBS gp3, 8 GiB ~$0.77 ~$0.64
Public IPv4 (Elastic IP) ~$3.65 ~$3.65
SSM parameter and KMS free free
Total (idle) ~$8.30 ~$7.35
  • AWS charges $0.005/hour per public IPv4 address since February 2024 — this applies to the Elastic IP even when idle, making it the largest cost after the host.
  • The table excludes data transfer: egress scales with traffic. 100 GB/month is free, then AWS charges about $0.114/GB in Tokyo and about $0.09/GB in us-east-1.
  • The SSM parameter uses the AWS-managed KMS key, which has no monthly fee.
  • A one-year Compute Savings Plan or Reserved Instance lowers the host cost by about 30–40%.

AWS Lightsail

The nano_3_0 bundle is a flat $5/month (check aws.amazon.com/lightsail/pricing for current prices) — includes the instance, SSD storage, and a monthly data-transfer allowance. No separate EBS or per-GB egress charges like EC2, and no $0.005/hour IP surcharge (a static IP is free while attached to a running instance). Simpler pricing, at the cost of a fixed 0.5 GiB RAM (same as t4g.nano) and no Savings Plan or Reserved Instance discount.

Development

uv sync --all-extras
uv run pytest
uv run mypy src tests
uv run pre-commit run --all-files

Code layout

  • src/wildtunnel/: the CLI and the generic server installer (server/assets/server-setup.sh), which reads its input from environment variables and makes no AWS calls — so it also runs by hand on any Linux VPS.
  • src/wildtunnel/providers/aws_ec2/: all AWS EC2 code — the CDK stack, app entry point, SSM token helpers, and the aws-ec2 CLI group. Includes the stack itself, so aws-ec2 deploy needs no clone of this repo.
  • src/wildtunnel/providers/aws_lightsail/: all AWS Lightsail code — the aws-lightsail CLI group and direct boto3 calls. No CDK: Lightsail has no useful CDK L2 constructs, and the point of Lightsail is to be simpler than EC2+CloudFormation.

Add a new provider

scripts/new_provider.py is a maintainer-only scaffold, not shipped in the package and not wired into the CLI. It generates providers/<name>/ and tests/providers/<name>/, mirroring providers/aws_ec2/'s shape (a Click group, a config dataclass, matching test stubs), then prints the remaining manual steps. Refuses to run if providers/<name>/ already exists.

uv run python scripts/new_provider.py hetzner

Known limitations

  • The CDK app creates the frp token, so the plaintext token ends up in the generated CloudFormation template. AWS stores it as a SecureString, but a person with read access to the stack can still see it. Acceptable for this personal, single-account setup.
  • Lightsail instances cannot have an IAM role, so wildtunnel writes the frp token directly into the instance's user data instead of fetching it from SSM. A person who can call lightsail:GetInstance can see it there. Also, wildtunnel aws-lightsail info only works on the machine that ran deploy, since the token is never stored remotely.

License

MIT. See LICENSE.

Metadata

Release files for wildtunnel 0.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wildtunnel 0.2.3
File Size Uploaded
wildtunnel-0.2.3.tar.gz 169.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for wildtunnel 0.2.3
File Interpreter ABI Platform
wildtunnel-0.2.3-py3-none-any.whl Python 3 none any Details

Total release size: 218.6 kB

Release files / wildtunnel-0.2.3.tar.gz

Download URL wildtunnel-0.2.3.tar.gz
Size 169.9 kB
Tags Source
SHA-256 checksum
How to use checksums
98405eede8338902a18c811bfab9a9406dd2db592db1abb2842b0471b89407fa
BLAKE2b-256 checksum
How to use checksums
6306d2a10ed5f7c466f21c4cd530b3229fa9b02146b40d2ce6e249ed6f8a1ecb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / wildtunnel-0.2.3-py3-none-any.whl

Download URL wildtunnel-0.2.3-py3-none-any.whl
Size 48.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1c40c004b24e279f9e2a3ea7d4d939abeed96421ea7b248a8760cb231b4b7c32
BLAKE2b-256 checksum
How to use checksums
afd087f7fac5202aaf159b31f827b5732b5feb8dc2ca8c1b7cd8f360b8688444
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.1

2 release files

This release

0.2.3 This release

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page