wildtunnel 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wildtunnel-0.1.0/.github/workflows/publish.yml +18 -0
- wildtunnel-0.1.0/.gitignore +256 -0
- wildtunnel-0.1.0/.pre-commit-config.yaml +12 -0
- wildtunnel-0.1.0/.python-version +1 -0
- wildtunnel-0.1.0/LICENSE +21 -0
- wildtunnel-0.1.0/PKG-INFO +199 -0
- wildtunnel-0.1.0/README.md +183 -0
- wildtunnel-0.1.0/pyproject.toml +64 -0
- wildtunnel-0.1.0/scripts/__init__.py +0 -0
- wildtunnel-0.1.0/scripts/new_provider.py +202 -0
- wildtunnel-0.1.0/src/wildtunnel/__init__.py +3 -0
- wildtunnel-0.1.0/src/wildtunnel/cli.py +37 -0
- wildtunnel-0.1.0/src/wildtunnel/frpc_cli.py +303 -0
- wildtunnel-0.1.0/src/wildtunnel/frpc_config.py +31 -0
- wildtunnel-0.1.0/src/wildtunnel/frpc_toml.py +39 -0
- wildtunnel-0.1.0/src/wildtunnel/paths.py +53 -0
- wildtunnel-0.1.0/src/wildtunnel/prompts.py +14 -0
- wildtunnel-0.1.0/src/wildtunnel/providers/__init__.py +0 -0
- wildtunnel-0.1.0/src/wildtunnel/providers/aws_ec2/__init__.py +0 -0
- wildtunnel-0.1.0/src/wildtunnel/providers/aws_ec2/app.py +90 -0
- wildtunnel-0.1.0/src/wildtunnel/providers/aws_ec2/assets/user_data.sh +41 -0
- wildtunnel-0.1.0/src/wildtunnel/providers/aws_ec2/cli.py +263 -0
- wildtunnel-0.1.0/src/wildtunnel/providers/aws_ec2/config.py +60 -0
- wildtunnel-0.1.0/src/wildtunnel/providers/aws_ec2/tunnel_stack.py +191 -0
- wildtunnel-0.1.0/src/wildtunnel/providers/aws_lightsail/__init__.py +0 -0
- wildtunnel-0.1.0/src/wildtunnel/providers/aws_lightsail/assets/user_data.sh +23 -0
- wildtunnel-0.1.0/src/wildtunnel/providers/aws_lightsail/cli.py +252 -0
- wildtunnel-0.1.0/src/wildtunnel/providers/aws_lightsail/config.py +268 -0
- wildtunnel-0.1.0/src/wildtunnel/server/assets/server-setup.sh +132 -0
- wildtunnel-0.1.0/src/wildtunnel/services.py +43 -0
- wildtunnel-0.1.0/src/wildtunnel/systemd_unit.py +19 -0
- wildtunnel-0.1.0/src/wildtunnel/token.py +12 -0
- wildtunnel-0.1.0/tests/__init__.py +0 -0
- wildtunnel-0.1.0/tests/providers/__init__.py +0 -0
- wildtunnel-0.1.0/tests/providers/aws_ec2/__init__.py +0 -0
- wildtunnel-0.1.0/tests/providers/aws_ec2/test_cli.py +569 -0
- wildtunnel-0.1.0/tests/providers/aws_ec2/test_config.py +64 -0
- wildtunnel-0.1.0/tests/providers/aws_ec2/test_tunnel_stack.py +272 -0
- wildtunnel-0.1.0/tests/providers/aws_lightsail/__init__.py +0 -0
- wildtunnel-0.1.0/tests/providers/aws_lightsail/test_cli.py +434 -0
- wildtunnel-0.1.0/tests/providers/aws_lightsail/test_config.py +151 -0
- wildtunnel-0.1.0/tests/scripts/__init__.py +0 -0
- wildtunnel-0.1.0/tests/scripts/test_new_provider.py +147 -0
- wildtunnel-0.1.0/tests/test_cli.py +22 -0
- wildtunnel-0.1.0/tests/test_frpc_cli.py +658 -0
- wildtunnel-0.1.0/tests/test_frpc_config.py +66 -0
- wildtunnel-0.1.0/tests/test_frpc_toml.py +88 -0
- wildtunnel-0.1.0/tests/test_paths.py +34 -0
- wildtunnel-0.1.0/tests/test_prompts.py +39 -0
- wildtunnel-0.1.0/tests/test_server_setup.py +48 -0
- wildtunnel-0.1.0/tests/test_services.py +60 -0
- wildtunnel-0.1.0/tests/test_systemd_unit.py +16 -0
- wildtunnel-0.1.0/tests/test_token.py +18 -0
- wildtunnel-0.1.0/uv.lock +1195 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment: pypi
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: astral-sh/setup-uv@v3
|
|
17
|
+
- run: uv build
|
|
18
|
+
- run: uv publish
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
|
|
2
|
+
# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,linux,dotenv,macos,python
|
|
3
|
+
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,linux,dotenv,macos,python
|
|
4
|
+
|
|
5
|
+
### dotenv ###
|
|
6
|
+
.env
|
|
7
|
+
|
|
8
|
+
### Linux ###
|
|
9
|
+
*~
|
|
10
|
+
|
|
11
|
+
# temporary files which can be created if a process still has a handle open of a deleted file
|
|
12
|
+
.fuse_hidden*
|
|
13
|
+
|
|
14
|
+
# KDE directory preferences
|
|
15
|
+
.directory
|
|
16
|
+
|
|
17
|
+
# Linux trash folder which might appear on any partition or disk
|
|
18
|
+
.Trash-*
|
|
19
|
+
|
|
20
|
+
# .nfs files are created when an open file is removed but is still being accessed
|
|
21
|
+
.nfs*
|
|
22
|
+
|
|
23
|
+
### macOS ###
|
|
24
|
+
# General
|
|
25
|
+
.DS_Store
|
|
26
|
+
.AppleDouble
|
|
27
|
+
.LSOverride
|
|
28
|
+
|
|
29
|
+
# Icon must end with two \r
|
|
30
|
+
Icon
|
|
31
|
+
|
|
32
|
+
# Thumbnails
|
|
33
|
+
._*
|
|
34
|
+
|
|
35
|
+
# Files that might appear in the root of a volume
|
|
36
|
+
.DocumentRevisions-V100
|
|
37
|
+
.fseventsd
|
|
38
|
+
.Spotlight-V100
|
|
39
|
+
.TemporaryItems
|
|
40
|
+
.Trashes
|
|
41
|
+
.VolumeIcon.icns
|
|
42
|
+
.com.apple.timemachine.donotpresent
|
|
43
|
+
|
|
44
|
+
# Directories potentially created on remote AFP share
|
|
45
|
+
.AppleDB
|
|
46
|
+
.AppleDesktop
|
|
47
|
+
Network Trash Folder
|
|
48
|
+
Temporary Items
|
|
49
|
+
.apdisk
|
|
50
|
+
|
|
51
|
+
### macOS Patch ###
|
|
52
|
+
# iCloud generated files
|
|
53
|
+
*.icloud
|
|
54
|
+
|
|
55
|
+
### Python ###
|
|
56
|
+
# Byte-compiled / optimized / DLL files
|
|
57
|
+
__pycache__/
|
|
58
|
+
*.py[cod]
|
|
59
|
+
*$py.class
|
|
60
|
+
|
|
61
|
+
# C extensions
|
|
62
|
+
*.so
|
|
63
|
+
|
|
64
|
+
# Distribution / packaging
|
|
65
|
+
.Python
|
|
66
|
+
build/
|
|
67
|
+
develop-eggs/
|
|
68
|
+
dist/
|
|
69
|
+
downloads/
|
|
70
|
+
eggs/
|
|
71
|
+
.eggs/
|
|
72
|
+
lib/
|
|
73
|
+
lib64/
|
|
74
|
+
parts/
|
|
75
|
+
sdist/
|
|
76
|
+
var/
|
|
77
|
+
wheels/
|
|
78
|
+
share/python-wheels/
|
|
79
|
+
*.egg-info/
|
|
80
|
+
.installed.cfg
|
|
81
|
+
*.egg
|
|
82
|
+
MANIFEST
|
|
83
|
+
|
|
84
|
+
# PyInstaller
|
|
85
|
+
# Usually these files are written by a python script from a template
|
|
86
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
87
|
+
*.manifest
|
|
88
|
+
*.spec
|
|
89
|
+
|
|
90
|
+
# Installer logs
|
|
91
|
+
pip-log.txt
|
|
92
|
+
pip-delete-this-directory.txt
|
|
93
|
+
|
|
94
|
+
# Unit test / coverage reports
|
|
95
|
+
htmlcov/
|
|
96
|
+
.tox/
|
|
97
|
+
.nox/
|
|
98
|
+
.coverage
|
|
99
|
+
.coverage.*
|
|
100
|
+
.cache
|
|
101
|
+
nosetests.xml
|
|
102
|
+
coverage.xml
|
|
103
|
+
*.cover
|
|
104
|
+
*.py,cover
|
|
105
|
+
.hypothesis/
|
|
106
|
+
.pytest_cache/
|
|
107
|
+
cover/
|
|
108
|
+
|
|
109
|
+
# Translations
|
|
110
|
+
*.mo
|
|
111
|
+
*.pot
|
|
112
|
+
|
|
113
|
+
# Django stuff:
|
|
114
|
+
*.log
|
|
115
|
+
local_settings.py
|
|
116
|
+
db.sqlite3
|
|
117
|
+
db.sqlite3-journal
|
|
118
|
+
|
|
119
|
+
# Flask stuff:
|
|
120
|
+
instance/
|
|
121
|
+
.webassets-cache
|
|
122
|
+
|
|
123
|
+
# Scrapy stuff:
|
|
124
|
+
.scrapy
|
|
125
|
+
|
|
126
|
+
# Sphinx documentation
|
|
127
|
+
docs/_build/
|
|
128
|
+
|
|
129
|
+
# PyBuilder
|
|
130
|
+
.pybuilder/
|
|
131
|
+
target/
|
|
132
|
+
|
|
133
|
+
# Jupyter Notebook
|
|
134
|
+
.ipynb_checkpoints
|
|
135
|
+
|
|
136
|
+
# IPython
|
|
137
|
+
profile_default/
|
|
138
|
+
ipython_config.py
|
|
139
|
+
|
|
140
|
+
# pyenv
|
|
141
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
142
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
143
|
+
# .python-version
|
|
144
|
+
|
|
145
|
+
# pipenv
|
|
146
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
147
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
148
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
149
|
+
# install all needed dependencies.
|
|
150
|
+
#Pipfile.lock
|
|
151
|
+
|
|
152
|
+
# poetry
|
|
153
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
154
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
155
|
+
# commonly ignored for libraries.
|
|
156
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
157
|
+
#poetry.lock
|
|
158
|
+
|
|
159
|
+
# pdm
|
|
160
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
161
|
+
#pdm.lock
|
|
162
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
163
|
+
# in version control.
|
|
164
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
165
|
+
.pdm.toml
|
|
166
|
+
|
|
167
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
168
|
+
__pypackages__/
|
|
169
|
+
|
|
170
|
+
# Celery stuff
|
|
171
|
+
celerybeat-schedule
|
|
172
|
+
celerybeat.pid
|
|
173
|
+
|
|
174
|
+
# SageMath parsed files
|
|
175
|
+
*.sage.py
|
|
176
|
+
|
|
177
|
+
# Environments
|
|
178
|
+
.venv
|
|
179
|
+
env/
|
|
180
|
+
venv/
|
|
181
|
+
ENV/
|
|
182
|
+
env.bak/
|
|
183
|
+
venv.bak/
|
|
184
|
+
|
|
185
|
+
# Spyder project settings
|
|
186
|
+
.spyderproject
|
|
187
|
+
.spyproject
|
|
188
|
+
|
|
189
|
+
# Rope project settings
|
|
190
|
+
.ropeproject
|
|
191
|
+
|
|
192
|
+
# mkdocs documentation
|
|
193
|
+
/site
|
|
194
|
+
|
|
195
|
+
# mypy
|
|
196
|
+
.mypy_cache/
|
|
197
|
+
.dmypy.json
|
|
198
|
+
dmypy.json
|
|
199
|
+
|
|
200
|
+
# Pyre type checker
|
|
201
|
+
.pyre/
|
|
202
|
+
|
|
203
|
+
# pytype static type analyzer
|
|
204
|
+
.pytype/
|
|
205
|
+
|
|
206
|
+
# Cython debug symbols
|
|
207
|
+
cython_debug/
|
|
208
|
+
|
|
209
|
+
# PyCharm
|
|
210
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
211
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
212
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
213
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
214
|
+
#.idea/
|
|
215
|
+
|
|
216
|
+
### Python Patch ###
|
|
217
|
+
# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
|
|
218
|
+
poetry.toml
|
|
219
|
+
|
|
220
|
+
# ruff
|
|
221
|
+
.ruff_cache/
|
|
222
|
+
|
|
223
|
+
# LSP config files
|
|
224
|
+
pyrightconfig.json
|
|
225
|
+
|
|
226
|
+
### VisualStudioCode ###
|
|
227
|
+
.vscode/*
|
|
228
|
+
!.vscode/settings.json
|
|
229
|
+
!.vscode/tasks.json
|
|
230
|
+
!.vscode/launch.json
|
|
231
|
+
!.vscode/extensions.json
|
|
232
|
+
!.vscode/*.code-snippets
|
|
233
|
+
|
|
234
|
+
# Local History for Visual Studio Code
|
|
235
|
+
.history/
|
|
236
|
+
|
|
237
|
+
# Built Visual Studio Code Extensions
|
|
238
|
+
*.vsix
|
|
239
|
+
|
|
240
|
+
### VisualStudioCode Patch ###
|
|
241
|
+
# Ignore all local history of files
|
|
242
|
+
.history
|
|
243
|
+
.ionide
|
|
244
|
+
|
|
245
|
+
# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,linux,dotenv,macos,python
|
|
246
|
+
|
|
247
|
+
# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
|
|
248
|
+
|
|
249
|
+
# Claude Code runtime state (not project content)
|
|
250
|
+
.claude/scheduled_tasks.lock
|
|
251
|
+
|
|
252
|
+
# CDK (real cache lives under $XDG_CACHE_HOME/wildtunnel/aws_ec2/,
|
|
253
|
+
# outside the repo; these just catch stray local `cdk` invocations from here)
|
|
254
|
+
cdk.out/
|
|
255
|
+
cdk.context.json
|
|
256
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.16.8
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff-check
|
|
6
|
+
args: [--output-format, github, --fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
- repo: https://github.com/igorshubovych/markdownlint-cli
|
|
9
|
+
rev: v0.49.1
|
|
10
|
+
hooks:
|
|
11
|
+
- id: markdownlint
|
|
12
|
+
stages: [manual] # Only run in CI
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
wildtunnel-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dasbd72
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: wildtunnel
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Expose a local service to the internet at a wildcard subdomain, tunneled through a VPS running frps. Ships with AWS EC2 and AWS Lightsail providers.
|
|
5
|
+
Author-email: dasbd72 <twbd723@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.12
|
|
9
|
+
Requires-Dist: boto3>=1.34
|
|
10
|
+
Requires-Dist: click>=8.1
|
|
11
|
+
Provides-Extra: aws-ec2
|
|
12
|
+
Requires-Dist: aws-cdk-cli>=2.1143.0; extra == 'aws-ec2'
|
|
13
|
+
Requires-Dist: aws-cdk-lib>=2.160; extra == 'aws-ec2'
|
|
14
|
+
Requires-Dist: constructs>=10.3; extra == 'aws-ec2'
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# Wildtunnel
|
|
18
|
+
|
|
19
|
+
This tool makes a home-network service available at `<name>.<domain>`. It does not open an inbound port at home.
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
Browser -> DNS (Cloudflare) -> VPS (Caddy + frps) -> tunnel -> home PC (frpc) -> your app
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
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.
|
|
26
|
+
|
|
27
|
+
## Setup and usage
|
|
28
|
+
|
|
29
|
+
### Step 1: Install the CLI
|
|
30
|
+
|
|
31
|
+
Install frpc on a different machine first: [github.com/fatedier/frp/releases](https://github.com/fatedier/frp/releases)
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
# For the AWS EC2 provider:
|
|
35
|
+
uv tool install 'wildtunnel[aws-ec2]'
|
|
36
|
+
|
|
37
|
+
# For the AWS Lightsail provider (no extra needed, no CDK toolchain):
|
|
38
|
+
uv tool install wildtunnel
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
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:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
source <(wildtunnel completion bash) # ~/.bashrc
|
|
45
|
+
source <(wildtunnel completion zsh) # ~/.zshrc
|
|
46
|
+
wildtunnel completion fish | source # ~/.config/fish/config.fish
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Step 2: Deploy the server
|
|
50
|
+
|
|
51
|
+
Pick one provider.
|
|
52
|
+
|
|
53
|
+
#### Step 2a: Deploy to AWS EC2
|
|
54
|
+
|
|
55
|
+
Creates an EC2 host, frps, Caddy, an Elastic IP, and an IAM role, via CDK.
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
wildtunnel aws-ec2 config --domain dasbd72.com # reads the region from your AWS CLI config
|
|
59
|
+
wildtunnel aws-ec2 deploy
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Options for `aws-ec2 config`:
|
|
63
|
+
|
|
64
|
+
- `--domain`: base domain for the tunnel subdomains, e.g. `dasbd72.com`.
|
|
65
|
+
- `--region`: AWS region for the stack. Defaults to your AWS CLI region.
|
|
66
|
+
- `--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.
|
|
67
|
+
- `--yes`: skips confirmation prompts.
|
|
68
|
+
|
|
69
|
+
Record the `ElasticIp` output. Check status anytime with `wildtunnel aws-ec2 status`.
|
|
70
|
+
|
|
71
|
+
Get the frpc client's data (server address, base domain, token, and a ready `frpc config` command):
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
wildtunnel aws-ec2 info
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### Step 2b: Deploy to AWS Lightsail
|
|
78
|
+
|
|
79
|
+
Creates a `nano_3_0` Lightsail instance, frps, Caddy, and a static IP, via direct Lightsail API calls. No CDK, no CloudFormation.
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
wildtunnel aws-lightsail config --domain dasbd72.com # reads the region from your AWS CLI config
|
|
83
|
+
wildtunnel aws-lightsail deploy
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`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`.
|
|
87
|
+
|
|
88
|
+
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.
|
|
89
|
+
|
|
90
|
+
```sh
|
|
91
|
+
wildtunnel aws-lightsail info
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
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.
|
|
95
|
+
|
|
96
|
+
### Step 3: Point your DNS at the server address
|
|
97
|
+
|
|
98
|
+
Get the server address: the `ElasticIp` from `aws-ec2 info`, or the static IP from `aws-lightsail info`.
|
|
99
|
+
|
|
100
|
+
At your DNS provider (for example Cloudflare), add a wildcard `A` record, `*.dasbd72.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.
|
|
101
|
+
|
|
102
|
+
### Step 4: Configure the frpc client
|
|
103
|
+
|
|
104
|
+
#### Step 4.1: Add a service
|
|
105
|
+
|
|
106
|
+
frpc does not read the deployed server automatically. Copy the values, or the ready command, from `aws-ec2 info` / `aws-lightsail info`.
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
wildtunnel frpc config \
|
|
110
|
+
--server-addr 1.2.3.4 \
|
|
111
|
+
--base-domain dasbd72.com \
|
|
112
|
+
--token <token>
|
|
113
|
+
wildtunnel frpc add openwebui 192.168.50.10:8080
|
|
114
|
+
# -> https://openwebui.dasbd72.com
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`frpc config` options `--server-addr`, `--base-domain`, and `--token` are all required.
|
|
118
|
+
|
|
119
|
+
`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`):
|
|
120
|
+
|
|
121
|
+
```sh
|
|
122
|
+
frpc add wireguard 127.0.0.1:51820 --proto udp --remote-port 51820
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`frpc list` shows configured tunnels. `frpc del <name>` removes one.
|
|
126
|
+
|
|
127
|
+
#### Step 4.2: Run frpc on a different machine
|
|
128
|
+
|
|
129
|
+
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:
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
wildtunnel frpc render \
|
|
133
|
+
--server-addr 1.2.3.4 \
|
|
134
|
+
--base-domain dasbd72.com \
|
|
135
|
+
--token <token>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Upgrade from aws-reverse-tunnel
|
|
139
|
+
|
|
140
|
+
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:
|
|
141
|
+
|
|
142
|
+
```sh
|
|
143
|
+
mv ~/.config/aws-reverse-tunnel ~/.config/wildtunnel
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Cost
|
|
147
|
+
|
|
148
|
+
### AWS EC2
|
|
149
|
+
|
|
150
|
+
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.
|
|
151
|
+
|
|
152
|
+
| Resource | ap-northeast-1 (Tokyo) | us-east-1 |
|
|
153
|
+
| --- | --- | --- |
|
|
154
|
+
| t4g.nano (730 h) | ~$3.87 | ~$3.07 |
|
|
155
|
+
| EBS gp3, 8 GiB | ~$0.77 | ~$0.64 |
|
|
156
|
+
| Public IPv4 (Elastic IP) | ~$3.65 | ~$3.65 |
|
|
157
|
+
| SSM parameter and KMS | free | free |
|
|
158
|
+
| **Total (idle)** | **~$8.30** | **~$7.35** |
|
|
159
|
+
|
|
160
|
+
- 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.
|
|
161
|
+
- 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.
|
|
162
|
+
- The SSM parameter uses the AWS-managed KMS key, which has no monthly fee.
|
|
163
|
+
- A one-year Compute Savings Plan or Reserved Instance lowers the host cost by about 30–40%.
|
|
164
|
+
|
|
165
|
+
### AWS Lightsail
|
|
166
|
+
|
|
167
|
+
The `nano_3_0` bundle is a flat $5/month (check [aws.amazon.com/lightsail/pricing](https://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.
|
|
168
|
+
|
|
169
|
+
## Development
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
uv sync --all-extras
|
|
173
|
+
uv run pytest
|
|
174
|
+
uv run mypy src tests
|
|
175
|
+
uv run pre-commit run --all-files
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Code layout
|
|
179
|
+
|
|
180
|
+
- `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.
|
|
181
|
+
- `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.
|
|
182
|
+
- `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.
|
|
183
|
+
|
|
184
|
+
### Add a new provider
|
|
185
|
+
|
|
186
|
+
`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.
|
|
187
|
+
|
|
188
|
+
```sh
|
|
189
|
+
uv run python scripts/new_provider.py hetzner
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Known limitations
|
|
193
|
+
|
|
194
|
+
- 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.
|
|
195
|
+
- 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.
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Wildtunnel
|
|
2
|
+
|
|
3
|
+
This tool makes a home-network service available at `<name>.<domain>`. It does not open an inbound port at home.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
Browser -> DNS (Cloudflare) -> VPS (Caddy + frps) -> tunnel -> home PC (frpc) -> your app
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
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.
|
|
10
|
+
|
|
11
|
+
## Setup and usage
|
|
12
|
+
|
|
13
|
+
### Step 1: Install the CLI
|
|
14
|
+
|
|
15
|
+
Install frpc on a different machine first: [github.com/fatedier/frp/releases](https://github.com/fatedier/frp/releases)
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
# For the AWS EC2 provider:
|
|
19
|
+
uv tool install 'wildtunnel[aws-ec2]'
|
|
20
|
+
|
|
21
|
+
# For the AWS Lightsail provider (no extra needed, no CDK toolchain):
|
|
22
|
+
uv tool install wildtunnel
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
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:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
source <(wildtunnel completion bash) # ~/.bashrc
|
|
29
|
+
source <(wildtunnel completion zsh) # ~/.zshrc
|
|
30
|
+
wildtunnel completion fish | source # ~/.config/fish/config.fish
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Step 2: Deploy the server
|
|
34
|
+
|
|
35
|
+
Pick one provider.
|
|
36
|
+
|
|
37
|
+
#### Step 2a: Deploy to AWS EC2
|
|
38
|
+
|
|
39
|
+
Creates an EC2 host, frps, Caddy, an Elastic IP, and an IAM role, via CDK.
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
wildtunnel aws-ec2 config --domain dasbd72.com # reads the region from your AWS CLI config
|
|
43
|
+
wildtunnel aws-ec2 deploy
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Options for `aws-ec2 config`:
|
|
47
|
+
|
|
48
|
+
- `--domain`: base domain for the tunnel subdomains, e.g. `dasbd72.com`.
|
|
49
|
+
- `--region`: AWS region for the stack. Defaults to your AWS CLI region.
|
|
50
|
+
- `--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.
|
|
51
|
+
- `--yes`: skips confirmation prompts.
|
|
52
|
+
|
|
53
|
+
Record the `ElasticIp` output. Check status anytime with `wildtunnel aws-ec2 status`.
|
|
54
|
+
|
|
55
|
+
Get the frpc client's data (server address, base domain, token, and a ready `frpc config` command):
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
wildtunnel aws-ec2 info
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### Step 2b: Deploy to AWS Lightsail
|
|
62
|
+
|
|
63
|
+
Creates a `nano_3_0` Lightsail instance, frps, Caddy, and a static IP, via direct Lightsail API calls. No CDK, no CloudFormation.
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
wildtunnel aws-lightsail config --domain dasbd72.com # reads the region from your AWS CLI config
|
|
67
|
+
wildtunnel aws-lightsail deploy
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`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`.
|
|
71
|
+
|
|
72
|
+
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.
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
wildtunnel aws-lightsail info
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
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.
|
|
79
|
+
|
|
80
|
+
### Step 3: Point your DNS at the server address
|
|
81
|
+
|
|
82
|
+
Get the server address: the `ElasticIp` from `aws-ec2 info`, or the static IP from `aws-lightsail info`.
|
|
83
|
+
|
|
84
|
+
At your DNS provider (for example Cloudflare), add a wildcard `A` record, `*.dasbd72.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.
|
|
85
|
+
|
|
86
|
+
### Step 4: Configure the frpc client
|
|
87
|
+
|
|
88
|
+
#### Step 4.1: Add a service
|
|
89
|
+
|
|
90
|
+
frpc does not read the deployed server automatically. Copy the values, or the ready command, from `aws-ec2 info` / `aws-lightsail info`.
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
wildtunnel frpc config \
|
|
94
|
+
--server-addr 1.2.3.4 \
|
|
95
|
+
--base-domain dasbd72.com \
|
|
96
|
+
--token <token>
|
|
97
|
+
wildtunnel frpc add openwebui 192.168.50.10:8080
|
|
98
|
+
# -> https://openwebui.dasbd72.com
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`frpc config` options `--server-addr`, `--base-domain`, and `--token` are all required.
|
|
102
|
+
|
|
103
|
+
`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`):
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
frpc add wireguard 127.0.0.1:51820 --proto udp --remote-port 51820
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`frpc list` shows configured tunnels. `frpc del <name>` removes one.
|
|
110
|
+
|
|
111
|
+
#### Step 4.2: Run frpc on a different machine
|
|
112
|
+
|
|
113
|
+
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:
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
wildtunnel frpc render \
|
|
117
|
+
--server-addr 1.2.3.4 \
|
|
118
|
+
--base-domain dasbd72.com \
|
|
119
|
+
--token <token>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Upgrade from aws-reverse-tunnel
|
|
123
|
+
|
|
124
|
+
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:
|
|
125
|
+
|
|
126
|
+
```sh
|
|
127
|
+
mv ~/.config/aws-reverse-tunnel ~/.config/wildtunnel
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Cost
|
|
131
|
+
|
|
132
|
+
### AWS EC2
|
|
133
|
+
|
|
134
|
+
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.
|
|
135
|
+
|
|
136
|
+
| Resource | ap-northeast-1 (Tokyo) | us-east-1 |
|
|
137
|
+
| --- | --- | --- |
|
|
138
|
+
| t4g.nano (730 h) | ~$3.87 | ~$3.07 |
|
|
139
|
+
| EBS gp3, 8 GiB | ~$0.77 | ~$0.64 |
|
|
140
|
+
| Public IPv4 (Elastic IP) | ~$3.65 | ~$3.65 |
|
|
141
|
+
| SSM parameter and KMS | free | free |
|
|
142
|
+
| **Total (idle)** | **~$8.30** | **~$7.35** |
|
|
143
|
+
|
|
144
|
+
- 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.
|
|
145
|
+
- 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.
|
|
146
|
+
- The SSM parameter uses the AWS-managed KMS key, which has no monthly fee.
|
|
147
|
+
- A one-year Compute Savings Plan or Reserved Instance lowers the host cost by about 30–40%.
|
|
148
|
+
|
|
149
|
+
### AWS Lightsail
|
|
150
|
+
|
|
151
|
+
The `nano_3_0` bundle is a flat $5/month (check [aws.amazon.com/lightsail/pricing](https://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.
|
|
152
|
+
|
|
153
|
+
## Development
|
|
154
|
+
|
|
155
|
+
```sh
|
|
156
|
+
uv sync --all-extras
|
|
157
|
+
uv run pytest
|
|
158
|
+
uv run mypy src tests
|
|
159
|
+
uv run pre-commit run --all-files
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Code layout
|
|
163
|
+
|
|
164
|
+
- `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.
|
|
165
|
+
- `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.
|
|
166
|
+
- `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.
|
|
167
|
+
|
|
168
|
+
### Add a new provider
|
|
169
|
+
|
|
170
|
+
`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.
|
|
171
|
+
|
|
172
|
+
```sh
|
|
173
|
+
uv run python scripts/new_provider.py hetzner
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Known limitations
|
|
177
|
+
|
|
178
|
+
- 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.
|
|
179
|
+
- 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.
|
|
180
|
+
|
|
181
|
+
## License
|
|
182
|
+
|
|
183
|
+
MIT. See [LICENSE](LICENSE).
|