apsta 0.5.5__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.
- apsta-0.5.5/PKG-INFO +403 -0
- apsta-0.5.5/README.md +385 -0
- apsta-0.5.5/apsta.egg-info/PKG-INFO +403 -0
- apsta-0.5.5/apsta.egg-info/SOURCES.txt +10 -0
- apsta-0.5.5/apsta.egg-info/dependency_links.txt +1 -0
- apsta-0.5.5/apsta.egg-info/entry_points.txt +3 -0
- apsta-0.5.5/apsta.egg-info/top_level.txt +2 -0
- apsta-0.5.5/apsta.py +1894 -0
- apsta-0.5.5/apsta_gtk.py +743 -0
- apsta-0.5.5/pyproject.toml +34 -0
- apsta-0.5.5/setup.cfg +4 -0
- apsta-0.5.5/setup.py +14 -0
apsta-0.5.5/PKG-INFO
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: apsta
|
|
3
|
+
Version: 0.5.5
|
|
4
|
+
Summary: Smart AP+STA WiFi hotspot manager for Linux
|
|
5
|
+
Author: apsta contributors
|
|
6
|
+
Maintainer: krotrn
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/krotrn/apsta
|
|
9
|
+
Keywords: wifi,hotspot,ap,sta,networkmanager,linux
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: System Administrators
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: System :: Networking
|
|
16
|
+
Requires-Python: >=3.8
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# apsta
|
|
20
|
+
|
|
21
|
+
**AP+STA WiFi hotspot manager for Linux.**
|
|
22
|
+
|
|
23
|
+
Stay connected to your WiFi network and broadcast a hotspot simultaneously — without the manual `nmcli` / `hostapd` pain, without dropping your connection, and without touching a config file.
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
$ apsta detect
|
|
27
|
+
|
|
28
|
+
apsta — Hardware Detection
|
|
29
|
+
|
|
30
|
+
→ Found 1 WiFi interface(s):
|
|
31
|
+
wlo1 [e4:c7:67:e4:30:ae] connected to HomeWiFi
|
|
32
|
+
|
|
33
|
+
Capability Report
|
|
34
|
+
→ Driver: iwlwifi
|
|
35
|
+
→ Chipset: Intel Wi-Fi 6 AX200
|
|
36
|
+
|
|
37
|
+
✔ AP mode (hotspot) supported
|
|
38
|
+
✔ STA mode (WiFi client) supported
|
|
39
|
+
✘ AP+STA simultaneous (nmcli) not supported
|
|
40
|
+
✔ AP+STA simultaneous (hostapd) supported
|
|
41
|
+
|
|
42
|
+
Verdict
|
|
43
|
+
✔ Your hardware supports AP+STA simultaneously (hostapd mode).
|
|
44
|
+
✔ apsta will use hostapd + dnsmasq to share WiFi without disconnecting.
|
|
45
|
+
→ Run: sudo apsta start
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## The Problem
|
|
51
|
+
|
|
52
|
+
On Linux, running a hotspot while staying connected to WiFi is harder than it should be:
|
|
53
|
+
|
|
54
|
+
- `nmcli device wifi hotspot` **kills your existing WiFi connection** — it takes over the interface completely
|
|
55
|
+
- Most WiFi cards don't support concurrent AP+STA mode in the way NetworkManager expects
|
|
56
|
+
- Windows handles this transparently via a virtual WiFi layer — Linux doesn't have an equivalent
|
|
57
|
+
- NetworkManager doesn't tell you _why_ it failed or _what your options are_
|
|
58
|
+
- COSMIC DE has no hotspot UI at all
|
|
59
|
+
|
|
60
|
+
`apsta` fixes all of this.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## How It Works
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
apsta detect
|
|
68
|
+
↓
|
|
69
|
+
Parse iw list → find "valid interface combinations"
|
|
70
|
+
↓
|
|
71
|
+
Level 1: AP+managed in SAME #{ } block, total >= 2?
|
|
72
|
+
YES → nmcli virtual interface (Strategy 1)
|
|
73
|
+
|
|
74
|
+
Level 2: AP and managed in SEPARATE #{ } blocks, #channels <= 1?
|
|
75
|
+
YES → hostapd virtual interface (Strategy 2) — Intel AX200, iwlwifi
|
|
76
|
+
|
|
77
|
+
Neither → explain options → suggest ethernet / USB dongle / --force
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Strategy 1 — nmcli concurrent (true hardware AP+STA):**
|
|
81
|
+
Creates a virtual `wlo1_ap` interface and runs `nmcli device wifi hotspot` on it.
|
|
82
|
+
WiFi stays on `wlo1`. Requires the driver to expose AP+managed in the same
|
|
83
|
+
interface combination block.
|
|
84
|
+
|
|
85
|
+
**Strategy 2 — hostapd concurrent (split-block AP+STA):**
|
|
86
|
+
Creates a virtual `wlo1_ap` interface, runs hostapd directly (bypassing nmcli),
|
|
87
|
+
assigns IP `192.168.42.1/24`, starts dnsmasq for DHCP, and sets up NAT so
|
|
88
|
+
hotspot clients get internet through `wlo1`'s connection. This is how Windows
|
|
89
|
+
handles the Intel AX200 — apsta now does the same on Linux.
|
|
90
|
+
|
|
91
|
+
1. Create virtual `wlo1_ap` on top of `wlo1` (`iw dev wlo1 interface add wlo1_ap type __ap`)
|
|
92
|
+
2. Assign randomized locally-administered MAC to `wlo1_ap` — keeps `wlo1` MAC unchanged so NM holds its STA connection
|
|
93
|
+
3. Tell NM to ignore `wlo1_ap` only — `wlo1` stays fully managed and connected
|
|
94
|
+
4. Run hostapd on `wlo1_ap` with channel matching `wlo1`'s current channel
|
|
95
|
+
5. Assign IP `192.168.42.1/24` to `wlo1_ap`
|
|
96
|
+
6. Start dnsmasq for DHCP — clients get `192.168.42.10–192.168.42.100`
|
|
97
|
+
7. Enable NAT via iptables MASQUERADE so `wlo1_ap` clients get internet through `wlo1`
|
|
98
|
+
|
|
99
|
+
**Strategy 3 — nmcli --force (drops WiFi):**
|
|
100
|
+
Uses the single interface as AP. WiFi disconnects. Only triggered with `--force`.
|
|
101
|
+
|
|
102
|
+
Key technical decisions:
|
|
103
|
+
|
|
104
|
+
- **Split-block detection**: parses multi-line `iw list` combinations by joining
|
|
105
|
+
continuation lines before processing — correctly identifies Intel AX200/iwlwifi
|
|
106
|
+
which exposes AP and managed in separate `#{ }` blocks with `#channels <= 1`
|
|
107
|
+
- **Channel sync**: reads live STA frequency via `iw dev link` and forces the AP
|
|
108
|
+
to the same channel — prevents `Device or resource busy` on single-radio cards
|
|
109
|
+
- **Band sync**: derives band (`a` or `bg`) from frequency — prevents `band bg channel 36` crash
|
|
110
|
+
- **DFS channels**: detects regulatory-blocked channels (52–144) and aborts with clear instructions
|
|
111
|
+
- **Virtual interface MAC**: randomises the locally-administered MAC (`02:xx:xx:xx:xx:xx`)
|
|
112
|
+
on the AP interface only — base interface MAC stays unchanged so NM keeps its STA connection
|
|
113
|
+
- **State persistence**: saves `ap_interface`, `base_interface`, `active_con_name`, and
|
|
114
|
+
`start_method` to `/etc/apsta/config.json` so teardown is exact and method-aware
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Install
|
|
119
|
+
|
|
120
|
+
### For Users
|
|
121
|
+
|
|
122
|
+
#### One command (recommended)
|
|
123
|
+
|
|
124
|
+
### 1. Official PPA (Ubuntu / Pop!\_OS) — Recommended
|
|
125
|
+
|
|
126
|
+
The easiest way to install `apsta` on Ubuntu-based distributions (22.04, 24.04, and Noble) is via the official Launchpad PPA. This ensures you get automatic updates and all system dependencies (like `hostapd` and `dnsmasq`) are handled for you.
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
sudo add-apt-repository ppa:krotrn/apsta
|
|
130
|
+
sudo apt update
|
|
131
|
+
sudo apt install apsta
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 2. Manual One-Liner (Python pipx)
|
|
135
|
+
|
|
136
|
+
If you are on a different distribution (Fedora, Arch, etc.) or prefer using `pipx`, use this one-liner to install the dependencies and the app:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
sudo apt update && sudo apt install -y pipx network-manager iw iproute2 usbutils pciutils hostapd dnsmasq python3-gi gir1.2-gtk-4.0 gir1.2-adw-1 && pipx ensurepath && pipx install git+https://github.com/krotrn/apsta.git
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 3. Development / Source Install
|
|
143
|
+
|
|
144
|
+
If you want to contribute or build from source:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
git clone https://github.com/krotrn/apsta
|
|
148
|
+
cd apsta
|
|
149
|
+
# Install the CLI and GTK UI locally
|
|
150
|
+
pipx install .
|
|
151
|
+
# Or run the manual install script
|
|
152
|
+
sudo ./install.sh
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### For Maintainers
|
|
156
|
+
|
|
157
|
+
#### Publish APT package (enables `sudo apt install apsta`)
|
|
158
|
+
|
|
159
|
+
`sudo apt install apsta` works after you publish this package in an APT repository (PPA).
|
|
160
|
+
|
|
161
|
+
Build a local Debian package:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
sudo apt update && sudo apt install -y build-essential debhelper dh-python pybuild-plugin-pyproject python3-all python3-setuptools dpkg-dev
|
|
165
|
+
dpkg-buildpackage -us -uc -b
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Install the built package locally:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
sudo apt install ../apsta_*_all.deb
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
To enable `sudo apt install apsta` for other users, publish the generated `.deb` to your APT repo and add that repo to user systems.
|
|
175
|
+
|
|
176
|
+
#### Publish: Launchpad PPA
|
|
177
|
+
|
|
178
|
+
1. Create a PPA in Launchpad.
|
|
179
|
+
2. Create the upstream orig tarball (required for `3.0 (quilt)`):
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
UPVER="$(dpkg-parsechangelog -SVersion | sed 's/-[^-]*$//')"
|
|
183
|
+
git ls-files -z | grep -zv '^debian/' | tar --null -T - -czf "../apsta_${UPVER}.orig.tar.gz" --transform "s,^,apsta-${UPVER}/,"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
3. Build source package from the repo root:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
debuild -S -sa -k<your-gpg-key-id>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
4. Upload to PPA:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
dput ppa:<launchpad-user>/<ppa-name> ../apsta_*_source.changes
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
5. Users install:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
sudo add-apt-repository ppa:<launchpad-user>/<ppa-name>
|
|
202
|
+
sudo apt update
|
|
203
|
+
sudo apt install apsta
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Required dependencies** (all default on Ubuntu/Pop!\_OS/Fedora/Arch):
|
|
207
|
+
`nmcli` · `iw` · `ip` · `lsusb` · `lspci`
|
|
208
|
+
|
|
209
|
+
**For hostapd mode** (Intel AX200 and similar split-block cards):
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
sudo apt install hostapd dnsmasq
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
apsta will prompt if these are missing when hostapd mode is needed.
|
|
216
|
+
|
|
217
|
+
**Python 3.8+** required.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## CLI Usage
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
# Show version
|
|
225
|
+
apsta --version
|
|
226
|
+
|
|
227
|
+
# Detect hardware capability (shows both nmcli and hostapd support levels)
|
|
228
|
+
apsta detect
|
|
229
|
+
|
|
230
|
+
# Detect/status as machine-readable JSON
|
|
231
|
+
apsta detect --json
|
|
232
|
+
apsta status --json
|
|
233
|
+
|
|
234
|
+
# Start hotspot (auto-detects best method — tries nmcli, then hostapd, then --force)
|
|
235
|
+
sudo apsta start
|
|
236
|
+
|
|
237
|
+
# Start even if AP+STA not supported (drops WiFi)
|
|
238
|
+
sudo apsta start --force
|
|
239
|
+
|
|
240
|
+
# Stop hotspot (method-aware: cleans up hostapd/dnsmasq/iptables if needed)
|
|
241
|
+
sudo apsta stop
|
|
242
|
+
|
|
243
|
+
# Show current state (shows connected clients in hostapd mode)
|
|
244
|
+
apsta status
|
|
245
|
+
|
|
246
|
+
# Configure SSID and password
|
|
247
|
+
apsta config --set ssid=MyHotspot
|
|
248
|
+
sudo apsta config --set password=secret123
|
|
249
|
+
|
|
250
|
+
# Scan plugged-in USB WiFi adapters
|
|
251
|
+
apsta scan-usb
|
|
252
|
+
|
|
253
|
+
# Suggest a USB adapter to buy
|
|
254
|
+
apsta recommend
|
|
255
|
+
|
|
256
|
+
# Auto-start on boot + survive sleep/wake
|
|
257
|
+
sudo apsta enable
|
|
258
|
+
sudo apsta disable
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Shell completion
|
|
262
|
+
|
|
263
|
+
Generate completion scripts directly from apsta:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
apsta completion bash
|
|
267
|
+
apsta completion zsh
|
|
268
|
+
apsta completion fish
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Install manually:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
# bash
|
|
275
|
+
apsta completion bash | sudo tee /etc/bash_completion.d/apsta >/dev/null
|
|
276
|
+
|
|
277
|
+
# zsh
|
|
278
|
+
apsta completion zsh | sudo tee /usr/local/share/zsh/site-functions/_apsta >/dev/null
|
|
279
|
+
|
|
280
|
+
# fish
|
|
281
|
+
apsta completion fish | sudo tee /etc/fish/completions/apsta.fish >/dev/null
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## GUIs
|
|
287
|
+
|
|
288
|
+
### COSMIC Panel Applet (Pop!\_OS / COSMIC DE)
|
|
289
|
+
|
|
290
|
+
Shows a WiFi icon in your panel. Click to toggle hotspot, change SSID/password, run detect.
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
cd cosmic-applet-apsta
|
|
294
|
+
just install
|
|
295
|
+
# COSMIC Settings → Desktop → Panel → Configure Panel Applets → Add → "apsta Hotspot"
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Requires: Rust 1.75+, `just`, COSMIC session.
|
|
299
|
+
|
|
300
|
+
### GTK4 / Libadwaita (GNOME, KDE, Xfce, any desktop)
|
|
301
|
+
|
|
302
|
+
Full three-page GUI: Status, Hardware, Settings. Force start toggle for single-radio cards.
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
apsta-gtk
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
`apsta-gtk` is installed by the same one-command package install.
|
|
309
|
+
|
|
310
|
+
Requires: `python3-gi`, `gir1.2-gtk-4.0`, `gir1.2-adw-1`
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
sudo apt install python3-gi gir1.2-gtk-4.0 gir1.2-adw-1
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Auto-start and Sleep/Wake Persistence
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
sudo apsta enable
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
This installs:
|
|
325
|
+
|
|
326
|
+
- **`/etc/systemd/system/apsta.service`** — starts hotspot after NetworkManager connects on boot (`nm-online -q` pre-condition, not a fragile `sleep 3`)
|
|
327
|
+
- **`/usr/lib/systemd/system-sleep/apsta-sleep`** — tears down hotspot before suspend, restores it after resume (works for both nmcli and hostapd modes)
|
|
328
|
+
|
|
329
|
+
Works on **systemd**, **OpenRC**, and **runit**. Non-systemd users get exact manual instructions and pm-utils hook installation if available.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## USB Dongle Support
|
|
334
|
+
|
|
335
|
+
If your built-in card doesn't support either AP+STA mode:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
# See what's plugged in
|
|
339
|
+
apsta scan-usb
|
|
340
|
+
|
|
341
|
+
# See what to buy
|
|
342
|
+
apsta recommend
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Recommended chipsets (in-kernel drivers, plug and play):
|
|
346
|
+
|
|
347
|
+
| Chipset | WiFi Gen | Driver | Notes |
|
|
348
|
+
| -------- | -------- | ------- | ----------------------------- |
|
|
349
|
+
| mt7921au | WiFi 6 | mt7921u | Best overall. Kernel 5.19+ |
|
|
350
|
+
| mt7612u | WiFi 5 | mt76x2u | Rock-solid, works everywhere |
|
|
351
|
+
| mt7610u | WiFi 5 | mt76x0u | AC600, great for hotspot-only |
|
|
352
|
+
| mt7925u | WiFi 7 | mt7925u | Newest. Kernel 6.7+ |
|
|
353
|
+
|
|
354
|
+
Realtek chipsets are intentionally excluded — out-of-kernel drivers, unreliable AP+STA.
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
## Compatibility
|
|
359
|
+
|
|
360
|
+
| Distro | CLI | GTK UI | COSMIC Applet |
|
|
361
|
+
| -------------------- | --- | ------ | ------------- |
|
|
362
|
+
| Pop!\_OS 22.04 | ✅ | ✅ | ✅ |
|
|
363
|
+
| Pop!\_OS COSMIC | ✅ | ✅ | ✅ |
|
|
364
|
+
| Ubuntu 22.04 / 24.04 | ✅ | ✅ | — |
|
|
365
|
+
| Fedora 39+ | ✅ | ✅ | — |
|
|
366
|
+
| Arch Linux | ✅ | ✅ | — |
|
|
367
|
+
| Alpine (OpenRC) | ✅ | ✅ | — |
|
|
368
|
+
| Artix (runit) | ✅ | ✅ | — |
|
|
369
|
+
|
|
370
|
+
**Tested hardware:**
|
|
371
|
+
|
|
372
|
+
- Intel Wi-Fi 6 AX200 (iwlwifi) — hostapd mode ✅
|
|
373
|
+
- MediaTek mt7921au USB — nmcli mode ✅
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Why This Exists
|
|
378
|
+
|
|
379
|
+
Built out of frustration with Pop!\_OS COSMIC's missing hotspot UI and the silent WiFi-disconnection behaviour of `nmcli hotspot`. The deeper problem: Windows implements a virtual WiFi multiplexing layer that makes AP+STA work on almost any card. Linux exposes raw hardware capability honestly — and for cards like the Intel AX200, that capability exists but nmcli can't use it. apsta bridges the gap using hostapd directly.
|
|
380
|
+
|
|
381
|
+
If you've ever typed:
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
nmcli device wifi hotspot ifname wlan0 ssid foo password bar
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
...and watched your SSH session drop — this is for you.
|
|
388
|
+
|
|
389
|
+
See [CHANGELOG.md](CHANGELOG.md) for the full development history.
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## Contributing
|
|
394
|
+
|
|
395
|
+
PRs welcome. The Python CLI has no dependencies beyond stdlib (plus optional hostapd/dnsmasq). The GTK UI requires PyGObject. The COSMIC applet requires Rust + libcosmic.
|
|
396
|
+
|
|
397
|
+
If you've tested on a distro or hardware not in the tables above, open an issue with your `apsta detect` output.
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## License
|
|
402
|
+
|
|
403
|
+
MIT
|