servepass 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Fulvio Favilla
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,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: servepass
3
+ Version: 0.1.0
4
+ Summary: LAN file server with password protection. Like python -m http.server but with auth
5
+ Author-email: Fulvio Favilla <contact@fulvio.sh>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Fulvio Favilla
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/fulviofavilla/servepass
29
+ Project-URL: Repository, https://github.com/fulviofavilla/servepass
30
+ Project-URL: Issues, https://github.com/fulviofavilla/servepass/issues
31
+ Keywords: http,server,lan,file-sharing,auth,privacy
32
+ Classifier: Development Status :: 3 - Alpha
33
+ Classifier: Environment :: Console
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Intended Audience :: System Administrators
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Operating System :: OS Independent
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.8
40
+ Classifier: Programming Language :: Python :: 3.9
41
+ Classifier: Programming Language :: Python :: 3.10
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Classifier: Programming Language :: Python :: 3.12
44
+ Classifier: Topic :: Internet :: WWW/HTTP
45
+ Classifier: Topic :: Utilities
46
+ Requires-Python: >=3.8
47
+ Description-Content-Type: text/markdown
48
+ License-File: LICENSE
49
+ Dynamic: license-file
50
+
51
+ # servepass
52
+
53
+ Serve files on your LAN with a token. That's it.
54
+
55
+ ```
56
+ pipx install servepass
57
+ servepass
58
+ ```
59
+
60
+ ---
61
+
62
+ You know `python -m http.server`. It's great for quick file sharing on a local network. The problem is it has zero authentication, so anyone on the same network can grab whatever you're serving.
63
+
64
+ `servepass` fixes that. Same zero-config philosophy, but with a token-protected URL. Run it, get a link, share it. No accounts, no cloud, no telemetry.
65
+
66
+ ## Install
67
+
68
+ ```bash
69
+ pipx install servepass
70
+ ```
71
+
72
+ Or with pip:
73
+
74
+ ```bash
75
+ pip install servepass
76
+ ```
77
+
78
+ Requires Python 3.8+. No external dependencies.
79
+
80
+ ## Usage
81
+
82
+ ```bash
83
+ # Serve current directory
84
+ servepass
85
+
86
+ # Serve a specific path
87
+ servepass ./downloads
88
+
89
+ # Custom port
90
+ servepass --port 9090
91
+
92
+ # No authentication
93
+ servepass --no-auth
94
+ ```
95
+
96
+ Every time you run servepass, a fresh token is generated. You get a URL and an optional QR code in the terminal:
97
+
98
+ ```
99
+ Serving: /home/user/downloads
100
+ Network: http://192.168.1.42:8080/?token=a3f9b2c1
101
+ Token: a3f9b2c1
102
+
103
+ Ctrl+C to stop
104
+ ```
105
+
106
+ Open the URL in any browser on your network and you're in. Scan the QR code to open it directly on your phone.
107
+
108
+ ## QR code
109
+
110
+ The QR code is printed automatically if the `qrcode` package is installed:
111
+
112
+ ```bash
113
+ pip install qrcode
114
+ ```
115
+
116
+ Without it, servepass works normally and just shows the URL.
117
+
118
+ ## Known limitations
119
+
120
+ servepass uses a token in the URL over plain HTTP. The token is not encrypted in transit. This is fine for a trusted local network. It is not a substitute for HTTPS or VPN on public or untrusted networks.
121
+
122
+ If you're on public WiFi, use something else.
123
+
124
+ ## Who this is for
125
+
126
+ * You're on a trusted LAN (home, office, workshop) and want to share files quickly
127
+ * You want to download files on your phone without cables or cloud storage
128
+ * You don't want to expose an unauthenticated HTTP server to everyone on the network
129
+ * You want something lightweight with zero setup time
130
+
131
+ ## Comparison
132
+
133
+ | | servepass | python -m http.server | filebrowser |
134
+ |---|---|---|---|
135
+ | Authentication | Token | No | Yes |
136
+ | Install | `pipx install servepass` | Built-in | Binary + config |
137
+ | Dependencies | None | None | None |
138
+ | LAN IP detection | Yes | No | Yes |
139
+ | QR code | Optional | No | No |
140
+ | File upload | Planned | No | Yes |
141
+
142
+ ## Roadmap
143
+
144
+ - [x] Serve with token auth
145
+ - [x] Auto-detect LAN IP
146
+ - [x] QR code in terminal (optional)
147
+ - [ ] `--token` flag to set a fixed token
148
+ - [ ] HTTPS with self-signed cert
149
+ - [ ] File upload via browser
150
+
151
+ ## License
152
+
153
+ MIT
@@ -0,0 +1,103 @@
1
+ # servepass
2
+
3
+ Serve files on your LAN with a token. That's it.
4
+
5
+ ```
6
+ pipx install servepass
7
+ servepass
8
+ ```
9
+
10
+ ---
11
+
12
+ You know `python -m http.server`. It's great for quick file sharing on a local network. The problem is it has zero authentication, so anyone on the same network can grab whatever you're serving.
13
+
14
+ `servepass` fixes that. Same zero-config philosophy, but with a token-protected URL. Run it, get a link, share it. No accounts, no cloud, no telemetry.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pipx install servepass
20
+ ```
21
+
22
+ Or with pip:
23
+
24
+ ```bash
25
+ pip install servepass
26
+ ```
27
+
28
+ Requires Python 3.8+. No external dependencies.
29
+
30
+ ## Usage
31
+
32
+ ```bash
33
+ # Serve current directory
34
+ servepass
35
+
36
+ # Serve a specific path
37
+ servepass ./downloads
38
+
39
+ # Custom port
40
+ servepass --port 9090
41
+
42
+ # No authentication
43
+ servepass --no-auth
44
+ ```
45
+
46
+ Every time you run servepass, a fresh token is generated. You get a URL and an optional QR code in the terminal:
47
+
48
+ ```
49
+ Serving: /home/user/downloads
50
+ Network: http://192.168.1.42:8080/?token=a3f9b2c1
51
+ Token: a3f9b2c1
52
+
53
+ Ctrl+C to stop
54
+ ```
55
+
56
+ Open the URL in any browser on your network and you're in. Scan the QR code to open it directly on your phone.
57
+
58
+ ## QR code
59
+
60
+ The QR code is printed automatically if the `qrcode` package is installed:
61
+
62
+ ```bash
63
+ pip install qrcode
64
+ ```
65
+
66
+ Without it, servepass works normally and just shows the URL.
67
+
68
+ ## Known limitations
69
+
70
+ servepass uses a token in the URL over plain HTTP. The token is not encrypted in transit. This is fine for a trusted local network. It is not a substitute for HTTPS or VPN on public or untrusted networks.
71
+
72
+ If you're on public WiFi, use something else.
73
+
74
+ ## Who this is for
75
+
76
+ * You're on a trusted LAN (home, office, workshop) and want to share files quickly
77
+ * You want to download files on your phone without cables or cloud storage
78
+ * You don't want to expose an unauthenticated HTTP server to everyone on the network
79
+ * You want something lightweight with zero setup time
80
+
81
+ ## Comparison
82
+
83
+ | | servepass | python -m http.server | filebrowser |
84
+ |---|---|---|---|
85
+ | Authentication | Token | No | Yes |
86
+ | Install | `pipx install servepass` | Built-in | Binary + config |
87
+ | Dependencies | None | None | None |
88
+ | LAN IP detection | Yes | No | Yes |
89
+ | QR code | Optional | No | No |
90
+ | File upload | Planned | No | Yes |
91
+
92
+ ## Roadmap
93
+
94
+ - [x] Serve with token auth
95
+ - [x] Auto-detect LAN IP
96
+ - [x] QR code in terminal (optional)
97
+ - [ ] `--token` flag to set a fixed token
98
+ - [ ] HTTPS with self-signed cert
99
+ - [ ] File upload via browser
100
+
101
+ ## License
102
+
103
+ MIT
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools>=42", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "servepass"
7
+ version = "0.1.0"
8
+ description = "LAN file server with password protection. Like python -m http.server but with auth"
9
+ readme = "README.md"
10
+ license = { file = "LICENSE" }
11
+ authors = [{ name = "Fulvio Favilla", email = "contact@fulvio.sh" }]
12
+ keywords = ["http", "server", "lan", "file-sharing", "auth", "privacy"]
13
+ classifiers = [
14
+ "Development Status :: 3 - Alpha",
15
+ "Environment :: Console",
16
+ "Intended Audience :: Developers",
17
+ "Intended Audience :: System Administrators",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.8",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Topic :: Internet :: WWW/HTTP",
27
+ "Topic :: Utilities",
28
+ ]
29
+ requires-python = ">=3.8"
30
+ dependencies = []
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/fulviofavilla/servepass"
34
+ Repository = "https://github.com/fulviofavilla/servepass"
35
+ Issues = "https://github.com/fulviofavilla/servepass/issues"
36
+
37
+ [project.scripts]
38
+ servepass = "servepass.__main__:main"
39
+
40
+ [tool.setuptools.packages.find]
41
+ where = ["."]
42
+ include = ["servepass*"]
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,241 @@
1
+ """
2
+ servepass -- serve files on the LAN with token auth.
3
+
4
+ Nothing fancy. No dependencies. Just stdlib and a link.
5
+ """
6
+
7
+ import argparse
8
+ import json
9
+ import os
10
+ import secrets
11
+ import signal
12
+ import socket
13
+ import sys
14
+ from http.server import SimpleHTTPRequestHandler, HTTPServer
15
+ from pathlib import Path
16
+ from urllib.parse import urlparse, parse_qs
17
+
18
+
19
+ CONFIG_DIR = Path.home() / ".servepass"
20
+ CONFIG_FILE = CONFIG_DIR / "config"
21
+ DEFAULT_PORT = 8080
22
+
23
+
24
+ # ---------------------------------------------------------------------------
25
+ # QR code -- pure stdlib, no external deps
26
+ # ---------------------------------------------------------------------------
27
+
28
+ def _qr_terminal(url):
29
+ """
30
+ Print a QR code for the given URL using Unicode block characters.
31
+ Requires the 'qrcode' package. If not installed, silently skips.
32
+ This is intentionally optional -- the URL is always printed anyway.
33
+ """
34
+ try:
35
+ import qrcode
36
+ qr = qrcode.QRCode(border=1)
37
+ qr.add_data(url)
38
+ qr.make(fit=True)
39
+ matrix = qr.get_matrix()
40
+ print()
41
+ for i in range(0, len(matrix) - 1, 2):
42
+ row = " "
43
+ for j in range(len(matrix[i])):
44
+ top = matrix[i][j]
45
+ bot = matrix[i + 1][j] if i + 1 < len(matrix) else False
46
+ if top and bot:
47
+ row += "\u2588" # full block
48
+ elif top:
49
+ row += "\u2580" # upper half
50
+ elif bot:
51
+ row += "\u2584" # lower half
52
+ else:
53
+ row += " "
54
+ print(row)
55
+ print()
56
+ except ImportError:
57
+ # qrcode not installed, no problem -- URL is printed in the banner
58
+ pass
59
+
60
+
61
+ # ---------------------------------------------------------------------------
62
+ # Network
63
+ # ---------------------------------------------------------------------------
64
+
65
+ def get_lan_ip():
66
+ """Best-effort local IP detection. Falls back to 127.0.0.1 if it fails."""
67
+ try:
68
+ # connect to an external address but don't actually send anything
69
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
70
+ s.connect(("8.8.8.8", 80))
71
+ ip = s.getsockname()[0]
72
+ s.close()
73
+ return ip
74
+ except Exception:
75
+ return "127.0.0.1"
76
+
77
+
78
+ # ---------------------------------------------------------------------------
79
+ # Token generation
80
+ # ---------------------------------------------------------------------------
81
+
82
+ def generate_token():
83
+ """8 hex chars -- short enough to type, long enough to not guess."""
84
+ return secrets.token_hex(4)
85
+
86
+
87
+ # ---------------------------------------------------------------------------
88
+ # Request handlers
89
+ # ---------------------------------------------------------------------------
90
+
91
+ def make_token_handler(token, directory):
92
+ """Handler that checks for ?token=<token> on every request."""
93
+
94
+ class TokenHandler(SimpleHTTPRequestHandler):
95
+ def __init__(self, *args, **kwargs):
96
+ super().__init__(*args, directory=directory, **kwargs)
97
+
98
+ def do_HEAD(self):
99
+ if not self.check_token():
100
+ return
101
+ super().do_HEAD()
102
+
103
+ def do_GET(self):
104
+ if not self.check_token():
105
+ return
106
+ # strip token from path before serving so directory listing works
107
+ self.path = self._strip_token(self.path)
108
+ super().do_GET()
109
+
110
+ def check_token(self):
111
+ parsed = urlparse(self.path)
112
+ params = parse_qs(parsed.query)
113
+ supplied = params.get("token", [None])[0]
114
+ if supplied == token:
115
+ return True
116
+ self.send_response(403)
117
+ self.send_header("Content-Type", "text/plain")
118
+ self.end_headers()
119
+ self.wfile.write(b"Access denied. Missing or invalid token.")
120
+ return False
121
+
122
+ def _strip_token(self, path):
123
+ """Remove ?token=... from path so links in directory listing stay clean."""
124
+ parsed = urlparse(path)
125
+ params = parse_qs(parsed.query)
126
+ params.pop("token", None)
127
+ # rebuild query string without token
128
+ new_query = "&".join(f"{k}={v[0]}" for k, v in params.items())
129
+ return parsed.path + (f"?{new_query}" if new_query else "")
130
+
131
+ def log_message(self, format, *args):
132
+ print(f" {self.address_string()} {args[0]} {args[1]}")
133
+
134
+ return TokenHandler
135
+
136
+
137
+ def make_open_handler(directory):
138
+ """Handler with no auth, for --no-auth mode."""
139
+
140
+ class OpenHandler(SimpleHTTPRequestHandler):
141
+ def __init__(self, *args, **kwargs):
142
+ super().__init__(*args, directory=directory, **kwargs)
143
+
144
+ def log_message(self, format, *args):
145
+ print(f" {self.address_string()} {args[0]} {args[1]}")
146
+
147
+ return OpenHandler
148
+
149
+
150
+ # ---------------------------------------------------------------------------
151
+ # Banner
152
+ # ---------------------------------------------------------------------------
153
+
154
+ def print_banner(directory, ip, port, token):
155
+ url = f"http://{ip}:{port}"
156
+ if token:
157
+ full_url = f"{url}/?token={token}"
158
+ print()
159
+ print(f" Serving: {os.path.abspath(directory)}")
160
+ print(f" Network: {full_url}")
161
+ print(f" Token: {token}")
162
+ _qr_terminal(full_url)
163
+ else:
164
+ print()
165
+ print(f" Serving: {os.path.abspath(directory)}")
166
+ print(f" Network: {url}")
167
+ print(f" Auth: disabled (--no-auth)")
168
+ print()
169
+
170
+ print(" Ctrl+C to stop")
171
+ print()
172
+
173
+
174
+ # ---------------------------------------------------------------------------
175
+ # Entry point
176
+ # ---------------------------------------------------------------------------
177
+
178
+ def main():
179
+ parser = argparse.ArgumentParser(
180
+ prog="servepass",
181
+ description="Serve files on the LAN with token auth.",
182
+ formatter_class=argparse.RawDescriptionHelpFormatter,
183
+ epilog="""
184
+ examples:
185
+ servepass serve current directory
186
+ servepass ./downloads serve a specific directory
187
+ servepass --port 9090 use a custom port
188
+ servepass --no-auth serve without authentication
189
+ """,
190
+ )
191
+ parser.add_argument(
192
+ "dir",
193
+ nargs="?",
194
+ default=".",
195
+ metavar="DIR",
196
+ help="directory to serve (default: current directory)",
197
+ )
198
+ parser.add_argument(
199
+ "--port",
200
+ type=int,
201
+ default=DEFAULT_PORT,
202
+ help=f"port to listen on (default: {DEFAULT_PORT})",
203
+ )
204
+ parser.add_argument(
205
+ "--no-auth",
206
+ action="store_true",
207
+ help="disable authentication",
208
+ )
209
+
210
+ args = parser.parse_args()
211
+
212
+ directory = args.dir
213
+ if not os.path.isdir(directory):
214
+ print(f"servepass: '{directory}' is not a directory", file=sys.stderr)
215
+ sys.exit(1)
216
+
217
+ use_auth = not args.no_auth
218
+ token = generate_token() if use_auth else None
219
+ ip = get_lan_ip()
220
+
221
+ if use_auth:
222
+ handler = make_token_handler(token=token, directory=directory)
223
+ else:
224
+ handler = make_open_handler(directory=directory)
225
+
226
+ server = HTTPServer(("0.0.0.0", args.port), handler)
227
+
228
+ def handle_exit(sig, frame):
229
+ print("\n\n Stopped.\n")
230
+ server.server_close()
231
+ sys.exit(0)
232
+
233
+ signal.signal(signal.SIGINT, handle_exit)
234
+ signal.signal(signal.SIGTERM, handle_exit)
235
+
236
+ print_banner(directory, ip, args.port, token)
237
+ server.serve_forever()
238
+
239
+
240
+ if __name__ == "__main__":
241
+ main()
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: servepass
3
+ Version: 0.1.0
4
+ Summary: LAN file server with password protection. Like python -m http.server but with auth
5
+ Author-email: Fulvio Favilla <contact@fulvio.sh>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Fulvio Favilla
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/fulviofavilla/servepass
29
+ Project-URL: Repository, https://github.com/fulviofavilla/servepass
30
+ Project-URL: Issues, https://github.com/fulviofavilla/servepass/issues
31
+ Keywords: http,server,lan,file-sharing,auth,privacy
32
+ Classifier: Development Status :: 3 - Alpha
33
+ Classifier: Environment :: Console
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Intended Audience :: System Administrators
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Operating System :: OS Independent
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.8
40
+ Classifier: Programming Language :: Python :: 3.9
41
+ Classifier: Programming Language :: Python :: 3.10
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Classifier: Programming Language :: Python :: 3.12
44
+ Classifier: Topic :: Internet :: WWW/HTTP
45
+ Classifier: Topic :: Utilities
46
+ Requires-Python: >=3.8
47
+ Description-Content-Type: text/markdown
48
+ License-File: LICENSE
49
+ Dynamic: license-file
50
+
51
+ # servepass
52
+
53
+ Serve files on your LAN with a token. That's it.
54
+
55
+ ```
56
+ pipx install servepass
57
+ servepass
58
+ ```
59
+
60
+ ---
61
+
62
+ You know `python -m http.server`. It's great for quick file sharing on a local network. The problem is it has zero authentication, so anyone on the same network can grab whatever you're serving.
63
+
64
+ `servepass` fixes that. Same zero-config philosophy, but with a token-protected URL. Run it, get a link, share it. No accounts, no cloud, no telemetry.
65
+
66
+ ## Install
67
+
68
+ ```bash
69
+ pipx install servepass
70
+ ```
71
+
72
+ Or with pip:
73
+
74
+ ```bash
75
+ pip install servepass
76
+ ```
77
+
78
+ Requires Python 3.8+. No external dependencies.
79
+
80
+ ## Usage
81
+
82
+ ```bash
83
+ # Serve current directory
84
+ servepass
85
+
86
+ # Serve a specific path
87
+ servepass ./downloads
88
+
89
+ # Custom port
90
+ servepass --port 9090
91
+
92
+ # No authentication
93
+ servepass --no-auth
94
+ ```
95
+
96
+ Every time you run servepass, a fresh token is generated. You get a URL and an optional QR code in the terminal:
97
+
98
+ ```
99
+ Serving: /home/user/downloads
100
+ Network: http://192.168.1.42:8080/?token=a3f9b2c1
101
+ Token: a3f9b2c1
102
+
103
+ Ctrl+C to stop
104
+ ```
105
+
106
+ Open the URL in any browser on your network and you're in. Scan the QR code to open it directly on your phone.
107
+
108
+ ## QR code
109
+
110
+ The QR code is printed automatically if the `qrcode` package is installed:
111
+
112
+ ```bash
113
+ pip install qrcode
114
+ ```
115
+
116
+ Without it, servepass works normally and just shows the URL.
117
+
118
+ ## Known limitations
119
+
120
+ servepass uses a token in the URL over plain HTTP. The token is not encrypted in transit. This is fine for a trusted local network. It is not a substitute for HTTPS or VPN on public or untrusted networks.
121
+
122
+ If you're on public WiFi, use something else.
123
+
124
+ ## Who this is for
125
+
126
+ * You're on a trusted LAN (home, office, workshop) and want to share files quickly
127
+ * You want to download files on your phone without cables or cloud storage
128
+ * You don't want to expose an unauthenticated HTTP server to everyone on the network
129
+ * You want something lightweight with zero setup time
130
+
131
+ ## Comparison
132
+
133
+ | | servepass | python -m http.server | filebrowser |
134
+ |---|---|---|---|
135
+ | Authentication | Token | No | Yes |
136
+ | Install | `pipx install servepass` | Built-in | Binary + config |
137
+ | Dependencies | None | None | None |
138
+ | LAN IP detection | Yes | No | Yes |
139
+ | QR code | Optional | No | No |
140
+ | File upload | Planned | No | Yes |
141
+
142
+ ## Roadmap
143
+
144
+ - [x] Serve with token auth
145
+ - [x] Auto-detect LAN IP
146
+ - [x] QR code in terminal (optional)
147
+ - [ ] `--token` flag to set a fixed token
148
+ - [ ] HTTPS with self-signed cert
149
+ - [ ] File upload via browser
150
+
151
+ ## License
152
+
153
+ MIT
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ servepass/__init__.py
5
+ servepass/__main__.py
6
+ servepass.egg-info/PKG-INFO
7
+ servepass.egg-info/SOURCES.txt
8
+ servepass.egg-info/dependency_links.txt
9
+ servepass.egg-info/entry_points.txt
10
+ servepass.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ servepass = servepass.__main__:main
@@ -0,0 +1 @@
1
+ servepass
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+