wisp-vpn 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.
- wisp_vpn-0.1.0/LICENSE +21 -0
- wisp_vpn-0.1.0/PKG-INFO +241 -0
- wisp_vpn-0.1.0/README.md +200 -0
- wisp_vpn-0.1.0/pyproject.toml +100 -0
- wisp_vpn-0.1.0/setup.cfg +4 -0
- wisp_vpn-0.1.0/src/wisp/cli/__init__.py +3 -0
- wisp_vpn-0.1.0/src/wisp/cli/__main__.py +10 -0
- wisp_vpn-0.1.0/src/wisp/cli/app.py +252 -0
- wisp_vpn-0.1.0/src/wisp/cli/screens/__init__.py +15 -0
- wisp_vpn-0.1.0/src/wisp/cli/screens/base.py +53 -0
- wisp_vpn-0.1.0/src/wisp/cli/screens/config.py +713 -0
- wisp_vpn-0.1.0/src/wisp/cli/screens/deploy.py +570 -0
- wisp_vpn-0.1.0/src/wisp/cli/screens/main_menu.py +225 -0
- wisp_vpn-0.1.0/src/wisp/cli/screens/modal.py +242 -0
- wisp_vpn-0.1.0/src/wisp/cli/screens/progress.py +404 -0
- wisp_vpn-0.1.0/src/wisp/cli/screens/shutdown.py +305 -0
- wisp_vpn-0.1.0/src/wisp/cli/screens/tunnel.py +244 -0
- wisp_vpn-0.1.0/src/wisp/cli/state.py +103 -0
- wisp_vpn-0.1.0/src/wisp/cli/widgets/__init__.py +0 -0
- wisp_vpn-0.1.0/src/wisp/config/__init__.py +3 -0
- wisp_vpn-0.1.0/src/wisp/config/constants.py +171 -0
- wisp_vpn-0.1.0/src/wisp/config/credentials.py +504 -0
- wisp_vpn-0.1.0/src/wisp/config/settings.py +275 -0
- wisp_vpn-0.1.0/src/wisp/daemon/__init__.py +14 -0
- wisp_vpn-0.1.0/src/wisp/daemon/adapter.py +129 -0
- wisp_vpn-0.1.0/src/wisp/daemon/install.py +505 -0
- wisp_vpn-0.1.0/src/wisp/daemon/protocol.py +63 -0
- wisp_vpn-0.1.0/src/wisp/daemon/server.py +122 -0
- wisp_vpn-0.1.0/src/wisp/daemon/transport.py +381 -0
- wisp_vpn-0.1.0/src/wisp/daemon/windows_service.py +84 -0
- wisp_vpn-0.1.0/src/wisp/data/wireguard-server-install.sh +709 -0
- wisp_vpn-0.1.0/src/wisp/data/wisp.service.tpl +12 -0
- wisp_vpn-0.1.0/src/wisp/data/wisp.socket +11 -0
- wisp_vpn-0.1.0/src/wisp/main.py +548 -0
- wisp_vpn-0.1.0/src/wisp/providers/__init__.py +31 -0
- wisp_vpn-0.1.0/src/wisp/providers/aws/__init__.py +3 -0
- wisp_vpn-0.1.0/src/wisp/providers/aws/constants.py +9 -0
- wisp_vpn-0.1.0/src/wisp/providers/aws/provider.py +62 -0
- wisp_vpn-0.1.0/src/wisp/providers/aws/pulumi.py +267 -0
- wisp_vpn-0.1.0/src/wisp/providers/base.py +148 -0
- wisp_vpn-0.1.0/src/wisp/providers/gcp/__init__.py +5 -0
- wisp_vpn-0.1.0/src/wisp/providers/gcp/constants.py +26 -0
- wisp_vpn-0.1.0/src/wisp/providers/gcp/provider.py +84 -0
- wisp_vpn-0.1.0/src/wisp/providers/gcp/pulumi.py +271 -0
- wisp_vpn-0.1.0/src/wisp/providers/oci/__init__.py +13 -0
- wisp_vpn-0.1.0/src/wisp/providers/oci/constants.py +19 -0
- wisp_vpn-0.1.0/src/wisp/providers/oci/provider.py +99 -0
- wisp_vpn-0.1.0/src/wisp/providers/oci/pulumi.py +470 -0
- wisp_vpn-0.1.0/src/wisp/providers/pulumi_base.py +293 -0
- wisp_vpn-0.1.0/src/wisp/providers/vps.py +269 -0
- wisp_vpn-0.1.0/src/wisp/schemas.py +30 -0
- wisp_vpn-0.1.0/src/wisp/session.py +496 -0
- wisp_vpn-0.1.0/src/wisp/utils/__init__.py +38 -0
- wisp_vpn-0.1.0/src/wisp/utils/logger.py +106 -0
- wisp_vpn-0.1.0/src/wisp/utils/platform.py +68 -0
- wisp_vpn-0.1.0/src/wisp/utils/pulumi.py +130 -0
- wisp_vpn-0.1.0/src/wisp/utils/randoms.py +11 -0
- wisp_vpn-0.1.0/src/wisp/utils/watchdog.py +278 -0
- wisp_vpn-0.1.0/src/wisp/wireguard/__init__.py +17 -0
- wisp_vpn-0.1.0/src/wisp/wireguard/local_client.py +32 -0
- wisp_vpn-0.1.0/src/wisp/wireguard/remote_server.py +421 -0
- wisp_vpn-0.1.0/src/wisp_vpn.egg-info/PKG-INFO +241 -0
- wisp_vpn-0.1.0/src/wisp_vpn.egg-info/SOURCES.txt +75 -0
- wisp_vpn-0.1.0/src/wisp_vpn.egg-info/dependency_links.txt +1 -0
- wisp_vpn-0.1.0/src/wisp_vpn.egg-info/entry_points.txt +2 -0
- wisp_vpn-0.1.0/src/wisp_vpn.egg-info/requires.txt +16 -0
- wisp_vpn-0.1.0/src/wisp_vpn.egg-info/top_level.txt +1 -0
- wisp_vpn-0.1.0/tests/test_config_screen.py +218 -0
- wisp_vpn-0.1.0/tests/test_daemon.py +53 -0
- wisp_vpn-0.1.0/tests/test_daemon_install.py +515 -0
- wisp_vpn-0.1.0/tests/test_focus_order.py +126 -0
- wisp_vpn-0.1.0/tests/test_layout.py +168 -0
- wisp_vpn-0.1.0/tests/test_logger.py +81 -0
- wisp_vpn-0.1.0/tests/test_paths.py +129 -0
- wisp_vpn-0.1.0/tests/test_progress_screen.py +84 -0
- wisp_vpn-0.1.0/tests/test_settings.py +42 -0
- wisp_vpn-0.1.0/tests/test_tunnel_screen.py +201 -0
wisp_vpn-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Juan D. Perez
|
|
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.
|
wisp_vpn-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: wisp-vpn
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Wisp — ephemeral WireGuard VPNs on your own cloud
|
|
5
|
+
Author-email: dosquisd <pereznjuandiego@gmail.com>, SantiagoQP31 <santiagoqp3103@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/dosquisd/wisp-vpn
|
|
8
|
+
Project-URL: Issues, https://github.com/dosquisd/wisp-vpn/issues
|
|
9
|
+
Keywords: wireguard,vpn,ephemeral,pulumi,aws,oci,gcp,tui
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: System Administrators
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Internet
|
|
20
|
+
Classifier: Topic :: System :: Networking
|
|
21
|
+
Classifier: Topic :: System :: Systems Administration
|
|
22
|
+
Classifier: Topic :: Utilities
|
|
23
|
+
Requires-Python: >=3.14
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: boto3>=1.43.83
|
|
27
|
+
Requires-Dist: google-cloud-compute>=1.54.0
|
|
28
|
+
Requires-Dist: oci>=2.100.0
|
|
29
|
+
Requires-Dist: paramiko>=5.0.0
|
|
30
|
+
Requires-Dist: platformdirs>=4.11.7
|
|
31
|
+
Requires-Dist: pulumi<4.0.0,>=3.0.0
|
|
32
|
+
Requires-Dist: pulumi-aws<8.0.0,>=7.0.0
|
|
33
|
+
Requires-Dist: pulumi-gcp>=9.37.0
|
|
34
|
+
Requires-Dist: pulumi-oci>=4.22.0
|
|
35
|
+
Requires-Dist: pulumi-tls>=5.5.1
|
|
36
|
+
Requires-Dist: pywin32>=312; sys_platform == "win32"
|
|
37
|
+
Requires-Dist: textual>=8.2.8
|
|
38
|
+
Requires-Dist: tomli-w>=1.2.0
|
|
39
|
+
Requires-Dist: tqdm>=4.70.0
|
|
40
|
+
Dynamic: license-file
|
|
41
|
+
|
|
42
|
+
<div align="center">
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
██╗ ██╗██╗███████╗██████╗
|
|
46
|
+
██║ ██║██║██╔════╝██╔══██╗
|
|
47
|
+
██║ █╗ ██║██║███████╗██████╔╝
|
|
48
|
+
██║███╗██║██║╚════██║██╔═══╝
|
|
49
|
+
╚███╔███╔╝██║███████║██║
|
|
50
|
+
╚══╝╚══╝ ╚═╝╚══════╝╚═╝
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**A VPN for the sessions you actually need.**
|
|
54
|
+
|
|
55
|
+
A monthly subscription bills you for every minute of the month so you can use
|
|
56
|
+
thirty. Wisp spins up a WireGuard server in your own cloud account, connects
|
|
57
|
+
you, and destroys it when you're done — measured: **~30 seconds to a working
|
|
58
|
+
tunnel** on your own VPS, ~2–3 minutes on a cloud provider (the VM boot is
|
|
59
|
+
the slow part), and a typical session costs fractions of a cent on
|
|
60
|
+
pay-as-you-go pricing.
|
|
61
|
+
|
|
62
|
+
<img src="https://raw.githubusercontent.com/dosquisd/wisp-vpn/main/.github/assets/demo-tui.gif" alt="Wisp TUI — deploy, tunnel, destroy" width="100%">
|
|
63
|
+
|
|
64
|
+
[](https://github.com/dosquisd/wisp-vpn/pyproject.toml)
|
|
65
|
+
[]([LICENSE](https://github.com/dosquisd/wisp-vpn/tree/main/LICENSE))
|
|
66
|
+
[](https://github.com/dosquisd/wisp-vpn/tree/main/docs/installation.md)
|
|
67
|
+
[](#supported-providers)
|
|
68
|
+
|
|
69
|
+
[Installation](#install) · [Quick start](#quick-start) · [Documentation](https://github.com/dosquisd/wisp-vpn/tree/main/docs/README.md) · [Contributing](https://github.com/dosquisd/wisp-vpn/tree/main/docs/contributing.md)
|
|
70
|
+
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Why Wisp
|
|
76
|
+
|
|
77
|
+
| | Subscription VPN | Always-on VPS | Wisp |
|
|
78
|
+
| --- | --- | --- | --- |
|
|
79
|
+
| Billing | Flat, monthly | 24/7, whether you use it or not | Per session — fractions of a cent |
|
|
80
|
+
| Who runs the server | The provider | You | You, briefly |
|
|
81
|
+
| Upkeep | None | Patches, a box to forget | None — it's destroyed |
|
|
82
|
+
| Exit IP | Shared pool | Dedicated, tied to your account | Dedicated, tied to your account |
|
|
83
|
+
|
|
84
|
+
**Who it's for:** developers who already have a cloud account (or a spare VPS)
|
|
85
|
+
and use a VPN occasionally — a few sessions a month, not all day every day.
|
|
86
|
+
|
|
87
|
+
**Who it's not for:** if you need an anonymous exit IP, look elsewhere — Wisp's
|
|
88
|
+
exit IP belongs to *your* cloud account or *your* VPS, which is the point.
|
|
89
|
+
|
|
90
|
+
- **Designed so nothing outlives your session.** The VM is destroyed on exit —
|
|
91
|
+
`q`, `Ctrl+C`, closing the terminal — and an optional TTL watchdog tears down
|
|
92
|
+
forgotten sessions. (The watchdog timer runs on your machine: if that machine
|
|
93
|
+
is off or suspended when the TTL expires, the session survives until the next
|
|
94
|
+
`wisp gc` — and `wisp gc --destroy` cleans up anything a crash left behind.)
|
|
95
|
+
- **Nothing to clean up by hand.** Orphan detection and `wisp gc` catch
|
|
96
|
+
anything a crash left behind.
|
|
97
|
+
- **Bring your own server.** Already have a VPS? Skip the cloud entirely —
|
|
98
|
+
Wisp configures WireGuard on it over SSH and cleans up after itself.
|
|
99
|
+
- **No sudo at runtime.** The privileged daemon owns the local WireGuard
|
|
100
|
+
interface; the CLI/TUI never elevate after installation.
|
|
101
|
+
|
|
102
|
+
## Features
|
|
103
|
+
|
|
104
|
+
| | Feature | What it means |
|
|
105
|
+
| --- | --- | --- |
|
|
106
|
+
| **TUI** | Interactive terminal UI | Full deploy wizard, live progress, one-key teardown |
|
|
107
|
+
| **CLI** | Scriptable subcommands | `deploy`, `destroy`, `regions`, `gc` — JSON output, `tqdm` progress |
|
|
108
|
+
| **Multi-cloud** | AWS · OCI · GCP | Provisioned via Pulumi; RSA 4096 SSH keys per session |
|
|
109
|
+
| **BYO server** | Custom VPS | No cloud account needed — SSH into a host you own |
|
|
110
|
+
| **Ephemeral** | Session guard | `q`/`Ctrl+C`/`esc`/signals/`atexit` all release the resources, exactly once |
|
|
111
|
+
| **Watchdog** | TTL auto-destroy | Optional OS-level timer runs `wisp destroy` if the session outlives its TTL |
|
|
112
|
+
| **Garbage collection** | `wisp gc` | Finds and destroys leftover stacks from crashed sessions |
|
|
113
|
+
| **No sudo at runtime** | Privileged daemon | After installation the CLI/TUI never elevate; a local daemon owns `wg-quick` |
|
|
114
|
+
| **Live installer output** | Progress streaming | The remote WireGuard install streams into the progress bar — no frozen screens |
|
|
115
|
+
|
|
116
|
+
## How it works
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
Wisp CLI/TUI ──Pulumi──▶ Cloud VM (AWS EC2 / OCI Compute / GCP + WireGuard)
|
|
120
|
+
│ ▲ │
|
|
121
|
+
│ └──── Paramiko (SSH) ────┘ installs & configures the server
|
|
122
|
+
▼
|
|
123
|
+
wisp daemon (privileged) ──wg-quick──▶ local WireGuard interface (wg0)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The client-side privileged daemon means the unprivileged CLI/TUI never needs
|
|
127
|
+
`sudo` to bring the local tunnel up or down; it talks to the daemon over a
|
|
128
|
+
group-restricted Unix socket (Linux) or Named Pipe (Windows) instead. The
|
|
129
|
+
session guard arms *before* provisioning starts, so a crashed TUI still
|
|
130
|
+
leaves a marker behind — the next run offers to clean it up, and the optional
|
|
131
|
+
TTL watchdog handles it even if nobody reopens Wisp.
|
|
132
|
+
|
|
133
|
+
## Install (from source)
|
|
134
|
+
|
|
135
|
+
Requirements: Python **3.14+** (if you install via `uv`, it manages Python for
|
|
136
|
+
you — you never see this requirement), the
|
|
137
|
+
[Pulumi CLI](https://www.pulumi.com/docs/install/), and WireGuard tools — both
|
|
138
|
+
installed by the setup script.
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# 0. Clone and enter the repo
|
|
142
|
+
git clone https://github.com/dosquisd/wisp.git && cd wisp
|
|
143
|
+
|
|
144
|
+
# 1. Install the CLI (isolated tool venv)
|
|
145
|
+
uv tool install .
|
|
146
|
+
|
|
147
|
+
# 2. Install the privileged local daemon (needs root/administrator)
|
|
148
|
+
sudo ./setup.sh # Linux; or: sudo ./setup.sh --skip-pulumi
|
|
149
|
+
./setup.ps1 # Windows (self-elevates to administrator)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Then log out and back in (or `newgrp wisp`) so your `wisp` group membership
|
|
153
|
+
takes effect. macOS is not supported yet (the daemon adapter is not
|
|
154
|
+
implemented — see `MacOSAdapter` in
|
|
155
|
+
[`daemon/adapter.py`](https://github.com/dosquisd/wisp-vpn/src/wisp/daemon/adapter.py)). A published PyPI package
|
|
156
|
+
with a one-command installer is planned.
|
|
157
|
+
|
|
158
|
+
## Quick start
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# 1. Authenticate the Pulumi backend (the deployment state lives there)
|
|
162
|
+
pulumi login
|
|
163
|
+
|
|
164
|
+
# 2. Configure your cloud credentials (standard SDK chains — see docs)
|
|
165
|
+
aws configure # or ~/.oci/config, or [gcp] in wisp.toml
|
|
166
|
+
|
|
167
|
+
# 3. Launch the TUI (or use the CLI directly)
|
|
168
|
+
wisp
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
# CLI equivalent — deploy, tunnel, destroy:
|
|
173
|
+
wisp deploy aws --region eu-west-1 # provisions VM + WireGuard, connects you
|
|
174
|
+
wisp destroy aws --region eu-west-1 # tears it all down
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
<!-- TODO: record the CLI demo GIF — deploy + destroy, 15-20s.
|
|
178
|
+
<img src=".github/assets/demo-cli.gif" alt="wisp deploy / destroy on the CLI" width="100%">
|
|
179
|
+
-->
|
|
180
|
+
|
|
181
|
+
## CLI cheat sheet
|
|
182
|
+
|
|
183
|
+
| Command | What it does |
|
|
184
|
+
| --- | --- |
|
|
185
|
+
| `wisp` | Launch the interactive TUI |
|
|
186
|
+
| `wisp deploy <provider> [-r region]` | Deploy a VPN (add `--ttl 120`, `--wireguard-port 51820`) |
|
|
187
|
+
| `wisp deploy vps --host <ip> --ssh-user root` | Configure WireGuard on a server you own |
|
|
188
|
+
| `wisp destroy <provider> [-r region]` | Tear down the tunnel + all cloud resources |
|
|
189
|
+
| `wisp regions <provider>` | List available regions (JSON) |
|
|
190
|
+
| `wisp gc [--refresh] [--destroy]` | Find and clean up leftover stacks |
|
|
191
|
+
|
|
192
|
+
## Supported providers
|
|
193
|
+
|
|
194
|
+
| Provider | Provisioning | Credentials |
|
|
195
|
+
| --- | --- | --- |
|
|
196
|
+
| **AWS** | Pulumi (`t3.micro`, most-recent Ubuntu AMI) | Standard AWS chain (`aws configure`, env vars) |
|
|
197
|
+
| **OCI** | Pulumi (`VM.Standard.A1.Flex`, Ubuntu 24.04) | `~/.oci/config` profile |
|
|
198
|
+
| **GCP** | Pulumi (SPOT `e2-micro`, default network) | Service account key or ADC |
|
|
199
|
+
| **Custom VPS** | None — SSH into a host you already own | Your own SSH key (`[vps]` in `wisp.toml`) |
|
|
200
|
+
|
|
201
|
+
> **Note:** as of this writing, Wisp ships with support for `aws`, `oci`,
|
|
202
|
+
> `gcp`, and `vps`. The provider layer is designed to be extensible — see
|
|
203
|
+
> `ProviderEnum`
|
|
204
|
+
> ([`src/wisp/providers/base.py`](https://github.com/dosquisd/wisp-vpn/src/wisp/providers/base.py)) and
|
|
205
|
+
> `PROVIDERS_MAP`
|
|
206
|
+
> ([`src/wisp/providers/__init__.py`](https://github.com/dosquisd/wisp-vpn/src/wisp/providers/__init__.py)), or
|
|
207
|
+
> the [contributing guide](https://github.com/dosquisd/wisp-vpn/tree/main/docs/contributing.md#adding-a-cloud-provider) to
|
|
208
|
+
> add your own.
|
|
209
|
+
|
|
210
|
+
## Documentation
|
|
211
|
+
|
|
212
|
+
Full documentation lives in [`docs/`](https://github.com/dosquisd/wisp-vpn/tree/main/docs/README.md):
|
|
213
|
+
|
|
214
|
+
| | |
|
|
215
|
+
| --- | --- |
|
|
216
|
+
| [Architecture](https://github.com/dosquisd/wisp-vpn/tree/main/docs/architecture.md) | High-level design, module map, runtime data flow |
|
|
217
|
+
| [Installation](https://github.com/dosquisd/wisp-vpn/tree/main/docs/installation.md) | System requirements, `setup.sh` / `setup.ps1`, daemon |
|
|
218
|
+
| [Usage](https://github.com/dosquisd/wisp-vpn/tree/main/docs/usage.md) | Full CLI and TUI reference |
|
|
219
|
+
| [Configuration](https://github.com/dosquisd/wisp-vpn/tree/main/docs/configuration.md) | `wisp.toml`, `WispConfig`, per-provider settings |
|
|
220
|
+
| [Deployment flow](https://github.com/dosquisd/wisp-vpn/tree/main/docs/deployment-flow.md) | Step-by-step deploy and destroy |
|
|
221
|
+
| [Security model](https://github.com/dosquisd/wisp-vpn/tree/main/docs/security.md) | Keys, firewall, socket permissions, trust boundaries |
|
|
222
|
+
| [Components reference](https://github.com/dosquisd/wisp-vpn/tree/main/docs/components/README.md) | Per-module reference |
|
|
223
|
+
| [Contributing](https://github.com/dosquisd/wisp-vpn/tree/main/docs/contributing.md) | Adding a provider, style, commits |
|
|
224
|
+
|
|
225
|
+
## Security
|
|
226
|
+
|
|
227
|
+
Keys are per-session RSA 4096 pairs, stored `0600` and removed on destroy.
|
|
228
|
+
The daemon socket is group-restricted (`root:wisp`). Cloud credentials are
|
|
229
|
+
never stored by Wisp — each provider uses its standard SDK chain (the only
|
|
230
|
+
file Wisp ever touches is the optional `[gcp].credentials_path`, which you
|
|
231
|
+
point at; Wisp reads it, it does not manage it). Read the full
|
|
232
|
+
[security model](https://github.com/dosquisd/wisp-vpn/tree/main/docs/security.md).
|
|
233
|
+
|
|
234
|
+
## Contributing
|
|
235
|
+
|
|
236
|
+
PRs against `main`. The provider layer is the easiest entry point — see
|
|
237
|
+
[adding a cloud provider](https://github.com/dosquisd/wisp-vpn/tree/main/docs/contributing.md#adding-a-cloud-provider).
|
|
238
|
+
|
|
239
|
+
## License
|
|
240
|
+
|
|
241
|
+
[MIT](https://github.com/dosquisd/wisp-vpn/tree/main/LICENSE) — Copyright (c) 2026 Juan D. Perez
|
wisp_vpn-0.1.0/README.md
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
```text
|
|
4
|
+
██╗ ██╗██╗███████╗██████╗
|
|
5
|
+
██║ ██║██║██╔════╝██╔══██╗
|
|
6
|
+
██║ █╗ ██║██║███████╗██████╔╝
|
|
7
|
+
██║███╗██║██║╚════██║██╔═══╝
|
|
8
|
+
╚███╔███╔╝██║███████║██║
|
|
9
|
+
╚══╝╚══╝ ╚═╝╚══════╝╚═╝
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**A VPN for the sessions you actually need.**
|
|
13
|
+
|
|
14
|
+
A monthly subscription bills you for every minute of the month so you can use
|
|
15
|
+
thirty. Wisp spins up a WireGuard server in your own cloud account, connects
|
|
16
|
+
you, and destroys it when you're done — measured: **~30 seconds to a working
|
|
17
|
+
tunnel** on your own VPS, ~2–3 minutes on a cloud provider (the VM boot is
|
|
18
|
+
the slow part), and a typical session costs fractions of a cent on
|
|
19
|
+
pay-as-you-go pricing.
|
|
20
|
+
|
|
21
|
+
<img src="https://raw.githubusercontent.com/dosquisd/wisp-vpn/main/.github/assets/demo-tui.gif" alt="Wisp TUI — deploy, tunnel, destroy" width="100%">
|
|
22
|
+
|
|
23
|
+
[](https://github.com/dosquisd/wisp-vpn/pyproject.toml)
|
|
24
|
+
[]([LICENSE](https://github.com/dosquisd/wisp-vpn/tree/main/LICENSE))
|
|
25
|
+
[](https://github.com/dosquisd/wisp-vpn/tree/main/docs/installation.md)
|
|
26
|
+
[](#supported-providers)
|
|
27
|
+
|
|
28
|
+
[Installation](#install) · [Quick start](#quick-start) · [Documentation](https://github.com/dosquisd/wisp-vpn/tree/main/docs/README.md) · [Contributing](https://github.com/dosquisd/wisp-vpn/tree/main/docs/contributing.md)
|
|
29
|
+
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Why Wisp
|
|
35
|
+
|
|
36
|
+
| | Subscription VPN | Always-on VPS | Wisp |
|
|
37
|
+
| --- | --- | --- | --- |
|
|
38
|
+
| Billing | Flat, monthly | 24/7, whether you use it or not | Per session — fractions of a cent |
|
|
39
|
+
| Who runs the server | The provider | You | You, briefly |
|
|
40
|
+
| Upkeep | None | Patches, a box to forget | None — it's destroyed |
|
|
41
|
+
| Exit IP | Shared pool | Dedicated, tied to your account | Dedicated, tied to your account |
|
|
42
|
+
|
|
43
|
+
**Who it's for:** developers who already have a cloud account (or a spare VPS)
|
|
44
|
+
and use a VPN occasionally — a few sessions a month, not all day every day.
|
|
45
|
+
|
|
46
|
+
**Who it's not for:** if you need an anonymous exit IP, look elsewhere — Wisp's
|
|
47
|
+
exit IP belongs to *your* cloud account or *your* VPS, which is the point.
|
|
48
|
+
|
|
49
|
+
- **Designed so nothing outlives your session.** The VM is destroyed on exit —
|
|
50
|
+
`q`, `Ctrl+C`, closing the terminal — and an optional TTL watchdog tears down
|
|
51
|
+
forgotten sessions. (The watchdog timer runs on your machine: if that machine
|
|
52
|
+
is off or suspended when the TTL expires, the session survives until the next
|
|
53
|
+
`wisp gc` — and `wisp gc --destroy` cleans up anything a crash left behind.)
|
|
54
|
+
- **Nothing to clean up by hand.** Orphan detection and `wisp gc` catch
|
|
55
|
+
anything a crash left behind.
|
|
56
|
+
- **Bring your own server.** Already have a VPS? Skip the cloud entirely —
|
|
57
|
+
Wisp configures WireGuard on it over SSH and cleans up after itself.
|
|
58
|
+
- **No sudo at runtime.** The privileged daemon owns the local WireGuard
|
|
59
|
+
interface; the CLI/TUI never elevate after installation.
|
|
60
|
+
|
|
61
|
+
## Features
|
|
62
|
+
|
|
63
|
+
| | Feature | What it means |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| **TUI** | Interactive terminal UI | Full deploy wizard, live progress, one-key teardown |
|
|
66
|
+
| **CLI** | Scriptable subcommands | `deploy`, `destroy`, `regions`, `gc` — JSON output, `tqdm` progress |
|
|
67
|
+
| **Multi-cloud** | AWS · OCI · GCP | Provisioned via Pulumi; RSA 4096 SSH keys per session |
|
|
68
|
+
| **BYO server** | Custom VPS | No cloud account needed — SSH into a host you own |
|
|
69
|
+
| **Ephemeral** | Session guard | `q`/`Ctrl+C`/`esc`/signals/`atexit` all release the resources, exactly once |
|
|
70
|
+
| **Watchdog** | TTL auto-destroy | Optional OS-level timer runs `wisp destroy` if the session outlives its TTL |
|
|
71
|
+
| **Garbage collection** | `wisp gc` | Finds and destroys leftover stacks from crashed sessions |
|
|
72
|
+
| **No sudo at runtime** | Privileged daemon | After installation the CLI/TUI never elevate; a local daemon owns `wg-quick` |
|
|
73
|
+
| **Live installer output** | Progress streaming | The remote WireGuard install streams into the progress bar — no frozen screens |
|
|
74
|
+
|
|
75
|
+
## How it works
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
Wisp CLI/TUI ──Pulumi──▶ Cloud VM (AWS EC2 / OCI Compute / GCP + WireGuard)
|
|
79
|
+
│ ▲ │
|
|
80
|
+
│ └──── Paramiko (SSH) ────┘ installs & configures the server
|
|
81
|
+
▼
|
|
82
|
+
wisp daemon (privileged) ──wg-quick──▶ local WireGuard interface (wg0)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The client-side privileged daemon means the unprivileged CLI/TUI never needs
|
|
86
|
+
`sudo` to bring the local tunnel up or down; it talks to the daemon over a
|
|
87
|
+
group-restricted Unix socket (Linux) or Named Pipe (Windows) instead. The
|
|
88
|
+
session guard arms *before* provisioning starts, so a crashed TUI still
|
|
89
|
+
leaves a marker behind — the next run offers to clean it up, and the optional
|
|
90
|
+
TTL watchdog handles it even if nobody reopens Wisp.
|
|
91
|
+
|
|
92
|
+
## Install (from source)
|
|
93
|
+
|
|
94
|
+
Requirements: Python **3.14+** (if you install via `uv`, it manages Python for
|
|
95
|
+
you — you never see this requirement), the
|
|
96
|
+
[Pulumi CLI](https://www.pulumi.com/docs/install/), and WireGuard tools — both
|
|
97
|
+
installed by the setup script.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# 0. Clone and enter the repo
|
|
101
|
+
git clone https://github.com/dosquisd/wisp.git && cd wisp
|
|
102
|
+
|
|
103
|
+
# 1. Install the CLI (isolated tool venv)
|
|
104
|
+
uv tool install .
|
|
105
|
+
|
|
106
|
+
# 2. Install the privileged local daemon (needs root/administrator)
|
|
107
|
+
sudo ./setup.sh # Linux; or: sudo ./setup.sh --skip-pulumi
|
|
108
|
+
./setup.ps1 # Windows (self-elevates to administrator)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Then log out and back in (or `newgrp wisp`) so your `wisp` group membership
|
|
112
|
+
takes effect. macOS is not supported yet (the daemon adapter is not
|
|
113
|
+
implemented — see `MacOSAdapter` in
|
|
114
|
+
[`daemon/adapter.py`](https://github.com/dosquisd/wisp-vpn/src/wisp/daemon/adapter.py)). A published PyPI package
|
|
115
|
+
with a one-command installer is planned.
|
|
116
|
+
|
|
117
|
+
## Quick start
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# 1. Authenticate the Pulumi backend (the deployment state lives there)
|
|
121
|
+
pulumi login
|
|
122
|
+
|
|
123
|
+
# 2. Configure your cloud credentials (standard SDK chains — see docs)
|
|
124
|
+
aws configure # or ~/.oci/config, or [gcp] in wisp.toml
|
|
125
|
+
|
|
126
|
+
# 3. Launch the TUI (or use the CLI directly)
|
|
127
|
+
wisp
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# CLI equivalent — deploy, tunnel, destroy:
|
|
132
|
+
wisp deploy aws --region eu-west-1 # provisions VM + WireGuard, connects you
|
|
133
|
+
wisp destroy aws --region eu-west-1 # tears it all down
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
<!-- TODO: record the CLI demo GIF — deploy + destroy, 15-20s.
|
|
137
|
+
<img src=".github/assets/demo-cli.gif" alt="wisp deploy / destroy on the CLI" width="100%">
|
|
138
|
+
-->
|
|
139
|
+
|
|
140
|
+
## CLI cheat sheet
|
|
141
|
+
|
|
142
|
+
| Command | What it does |
|
|
143
|
+
| --- | --- |
|
|
144
|
+
| `wisp` | Launch the interactive TUI |
|
|
145
|
+
| `wisp deploy <provider> [-r region]` | Deploy a VPN (add `--ttl 120`, `--wireguard-port 51820`) |
|
|
146
|
+
| `wisp deploy vps --host <ip> --ssh-user root` | Configure WireGuard on a server you own |
|
|
147
|
+
| `wisp destroy <provider> [-r region]` | Tear down the tunnel + all cloud resources |
|
|
148
|
+
| `wisp regions <provider>` | List available regions (JSON) |
|
|
149
|
+
| `wisp gc [--refresh] [--destroy]` | Find and clean up leftover stacks |
|
|
150
|
+
|
|
151
|
+
## Supported providers
|
|
152
|
+
|
|
153
|
+
| Provider | Provisioning | Credentials |
|
|
154
|
+
| --- | --- | --- |
|
|
155
|
+
| **AWS** | Pulumi (`t3.micro`, most-recent Ubuntu AMI) | Standard AWS chain (`aws configure`, env vars) |
|
|
156
|
+
| **OCI** | Pulumi (`VM.Standard.A1.Flex`, Ubuntu 24.04) | `~/.oci/config` profile |
|
|
157
|
+
| **GCP** | Pulumi (SPOT `e2-micro`, default network) | Service account key or ADC |
|
|
158
|
+
| **Custom VPS** | None — SSH into a host you already own | Your own SSH key (`[vps]` in `wisp.toml`) |
|
|
159
|
+
|
|
160
|
+
> **Note:** as of this writing, Wisp ships with support for `aws`, `oci`,
|
|
161
|
+
> `gcp`, and `vps`. The provider layer is designed to be extensible — see
|
|
162
|
+
> `ProviderEnum`
|
|
163
|
+
> ([`src/wisp/providers/base.py`](https://github.com/dosquisd/wisp-vpn/src/wisp/providers/base.py)) and
|
|
164
|
+
> `PROVIDERS_MAP`
|
|
165
|
+
> ([`src/wisp/providers/__init__.py`](https://github.com/dosquisd/wisp-vpn/src/wisp/providers/__init__.py)), or
|
|
166
|
+
> the [contributing guide](https://github.com/dosquisd/wisp-vpn/tree/main/docs/contributing.md#adding-a-cloud-provider) to
|
|
167
|
+
> add your own.
|
|
168
|
+
|
|
169
|
+
## Documentation
|
|
170
|
+
|
|
171
|
+
Full documentation lives in [`docs/`](https://github.com/dosquisd/wisp-vpn/tree/main/docs/README.md):
|
|
172
|
+
|
|
173
|
+
| | |
|
|
174
|
+
| --- | --- |
|
|
175
|
+
| [Architecture](https://github.com/dosquisd/wisp-vpn/tree/main/docs/architecture.md) | High-level design, module map, runtime data flow |
|
|
176
|
+
| [Installation](https://github.com/dosquisd/wisp-vpn/tree/main/docs/installation.md) | System requirements, `setup.sh` / `setup.ps1`, daemon |
|
|
177
|
+
| [Usage](https://github.com/dosquisd/wisp-vpn/tree/main/docs/usage.md) | Full CLI and TUI reference |
|
|
178
|
+
| [Configuration](https://github.com/dosquisd/wisp-vpn/tree/main/docs/configuration.md) | `wisp.toml`, `WispConfig`, per-provider settings |
|
|
179
|
+
| [Deployment flow](https://github.com/dosquisd/wisp-vpn/tree/main/docs/deployment-flow.md) | Step-by-step deploy and destroy |
|
|
180
|
+
| [Security model](https://github.com/dosquisd/wisp-vpn/tree/main/docs/security.md) | Keys, firewall, socket permissions, trust boundaries |
|
|
181
|
+
| [Components reference](https://github.com/dosquisd/wisp-vpn/tree/main/docs/components/README.md) | Per-module reference |
|
|
182
|
+
| [Contributing](https://github.com/dosquisd/wisp-vpn/tree/main/docs/contributing.md) | Adding a provider, style, commits |
|
|
183
|
+
|
|
184
|
+
## Security
|
|
185
|
+
|
|
186
|
+
Keys are per-session RSA 4096 pairs, stored `0600` and removed on destroy.
|
|
187
|
+
The daemon socket is group-restricted (`root:wisp`). Cloud credentials are
|
|
188
|
+
never stored by Wisp — each provider uses its standard SDK chain (the only
|
|
189
|
+
file Wisp ever touches is the optional `[gcp].credentials_path`, which you
|
|
190
|
+
point at; Wisp reads it, it does not manage it). Read the full
|
|
191
|
+
[security model](https://github.com/dosquisd/wisp-vpn/tree/main/docs/security.md).
|
|
192
|
+
|
|
193
|
+
## Contributing
|
|
194
|
+
|
|
195
|
+
PRs against `main`. The provider layer is the easiest entry point — see
|
|
196
|
+
[adding a cloud provider](https://github.com/dosquisd/wisp-vpn/tree/main/docs/contributing.md#adding-a-cloud-provider).
|
|
197
|
+
|
|
198
|
+
## License
|
|
199
|
+
|
|
200
|
+
[MIT](https://github.com/dosquisd/wisp-vpn/tree/main/LICENSE) — Copyright (c) 2026 Juan D. Perez
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "wisp-vpn"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Wisp — ephemeral WireGuard VPNs on your own cloud"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.14"
|
|
7
|
+
authors = [
|
|
8
|
+
{ name="dosquisd", email="pereznjuandiego@gmail.com" },
|
|
9
|
+
{ name="SantiagoQP31", email="santiagoqp3103@gmail.com" },
|
|
10
|
+
]
|
|
11
|
+
dependencies = [
|
|
12
|
+
"boto3>=1.43.83",
|
|
13
|
+
"google-cloud-compute>=1.54.0",
|
|
14
|
+
"oci>=2.100.0",
|
|
15
|
+
"paramiko>=5.0.0",
|
|
16
|
+
"platformdirs>=4.11.7",
|
|
17
|
+
"pulumi>=3.0.0,<4.0.0",
|
|
18
|
+
"pulumi-aws>=7.0.0,<8.0.0",
|
|
19
|
+
"pulumi-gcp>=9.37.0",
|
|
20
|
+
"pulumi-oci>=4.22.0",
|
|
21
|
+
"pulumi-tls>=5.5.1",
|
|
22
|
+
"pywin32>=312 ; sys_platform == 'win32'",
|
|
23
|
+
"textual>=8.2.8",
|
|
24
|
+
"tomli-w>=1.2.0",
|
|
25
|
+
"tqdm>=4.70.0",
|
|
26
|
+
]
|
|
27
|
+
license = "MIT"
|
|
28
|
+
license-files = ["LICEN[CS]E*"]
|
|
29
|
+
keywords = ["wireguard", "vpn", "ephemeral", "pulumi", "aws", "oci", "gcp", "tui"]
|
|
30
|
+
classifiers = [
|
|
31
|
+
"Development Status :: 3 - Alpha",
|
|
32
|
+
"Environment :: Console",
|
|
33
|
+
"Intended Audience :: Developers",
|
|
34
|
+
"Intended Audience :: System Administrators",
|
|
35
|
+
"Operating System :: POSIX :: Linux",
|
|
36
|
+
"Operating System :: Microsoft :: Windows",
|
|
37
|
+
"Programming Language :: Python :: 3",
|
|
38
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
39
|
+
"Programming Language :: Python :: 3.14",
|
|
40
|
+
"Topic :: Internet",
|
|
41
|
+
"Topic :: System :: Networking",
|
|
42
|
+
"Topic :: System :: Systems Administration",
|
|
43
|
+
"Topic :: Utilities",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[project.urls]
|
|
47
|
+
Homepage = "https://github.com/dosquisd/wisp-vpn"
|
|
48
|
+
Issues = "https://github.com/dosquisd/wisp-vpn/issues"
|
|
49
|
+
|
|
50
|
+
[build-system]
|
|
51
|
+
requires = ["setuptools>=84.0.0"]
|
|
52
|
+
build-backend = "setuptools.build_meta"
|
|
53
|
+
|
|
54
|
+
[tool.setuptools.package-data]
|
|
55
|
+
wisp = ["data/*.sh", "data/*.tpl", "data/wisp.socket"]
|
|
56
|
+
|
|
57
|
+
# Use `uv tool install --editable .`
|
|
58
|
+
[project.scripts]
|
|
59
|
+
wisp = "wisp.main:main"
|
|
60
|
+
|
|
61
|
+
[tool.uv]
|
|
62
|
+
package = true
|
|
63
|
+
|
|
64
|
+
[tool.ruff]
|
|
65
|
+
exclude = [".git", ".pytest_cache", ".venv"]
|
|
66
|
+
line-length = 88
|
|
67
|
+
indent-width = 4
|
|
68
|
+
target-version = "py314"
|
|
69
|
+
|
|
70
|
+
[tool.ruff.lint]
|
|
71
|
+
select = ["E4", "E7", "E9", "F"]
|
|
72
|
+
fixable = ["ALL"]
|
|
73
|
+
extend-select = ["I"]
|
|
74
|
+
|
|
75
|
+
[tool.ruff.format]
|
|
76
|
+
quote-style = "double"
|
|
77
|
+
indent-style = "space"
|
|
78
|
+
line-ending = "auto"
|
|
79
|
+
|
|
80
|
+
[dependency-groups]
|
|
81
|
+
dev = [
|
|
82
|
+
"pytest>=8.3.4",
|
|
83
|
+
"pytest-asyncio>=0.24.0",
|
|
84
|
+
"ruff>=0.16.10",
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
[tool.pytest.ini_options]
|
|
88
|
+
asyncio_mode = "auto"
|
|
89
|
+
testpaths = ["tests"]
|
|
90
|
+
|
|
91
|
+
[[tool.uv.index]]
|
|
92
|
+
name = "testpypi"
|
|
93
|
+
url = "https://test.pypi.org/simple/"
|
|
94
|
+
publish-url = "https://test.pypi.org/legacy/"
|
|
95
|
+
explicit = true
|
|
96
|
+
|
|
97
|
+
# How to install the package from TestPyPI and PyPI:
|
|
98
|
+
# uv pip install --index-url https://test.pypi.org/simple/ \
|
|
99
|
+
# --extra-index-url https://pypi.org/simple/ \
|
|
100
|
+
# wisp-vpn
|
wisp_vpn-0.1.0/setup.cfg
ADDED