sshler 0.3.2__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.
- sshler-0.3.2/MANIFEST.in +2 -0
- sshler-0.3.2/PKG-INFO +245 -0
- sshler-0.3.2/README.md +205 -0
- sshler-0.3.2/pyproject.toml +85 -0
- sshler-0.3.2/setup.cfg +4 -0
- sshler-0.3.2/sshler/__init__.py +10 -0
- sshler-0.3.2/sshler/cli.py +161 -0
- sshler-0.3.2/sshler/config.py +425 -0
- sshler-0.3.2/sshler/scripts/install-sshler-task.ps1 +28 -0
- sshler-0.3.2/sshler/scripts/remove-sshler-task.ps1 +15 -0
- sshler-0.3.2/sshler/scripts/run-sshler.ps1 +24 -0
- sshler-0.3.2/sshler/ssh.py +329 -0
- sshler-0.3.2/sshler/ssh_config.py +134 -0
- sshler-0.3.2/sshler/state.py +230 -0
- sshler-0.3.2/sshler/static/base.js +305 -0
- sshler-0.3.2/sshler/static/favicon-terminal.svg +8 -0
- sshler-0.3.2/sshler/static/favicon.svg +8 -0
- sshler-0.3.2/sshler/static/file-edit.js +81 -0
- sshler-0.3.2/sshler/static/file-view.js +60 -0
- sshler-0.3.2/sshler/static/style.css +158 -0
- sshler-0.3.2/sshler/static/term.js +304 -0
- sshler-0.3.2/sshler/templates/base.html +41 -0
- sshler-0.3.2/sshler/templates/box.html +53 -0
- sshler-0.3.2/sshler/templates/docs.html +40 -0
- sshler-0.3.2/sshler/templates/file_edit.html +30 -0
- sshler-0.3.2/sshler/templates/file_view.html +31 -0
- sshler-0.3.2/sshler/templates/index.html +49 -0
- sshler-0.3.2/sshler/templates/new_box.html +42 -0
- sshler-0.3.2/sshler/templates/partials/dir_listing.html +91 -0
- sshler-0.3.2/sshler/templates/term.html +67 -0
- sshler-0.3.2/sshler/webapp.py +1897 -0
- sshler-0.3.2/sshler.egg-info/PKG-INFO +245 -0
- sshler-0.3.2/sshler.egg-info/SOURCES.txt +40 -0
- sshler-0.3.2/sshler.egg-info/dependency_links.txt +1 -0
- sshler-0.3.2/sshler.egg-info/entry_points.txt +2 -0
- sshler-0.3.2/sshler.egg-info/requires.txt +16 -0
- sshler-0.3.2/sshler.egg-info/top_level.txt +1 -0
- sshler-0.3.2/tests/test_basic.py +36 -0
- sshler-0.3.2/tests/test_config.py +102 -0
- sshler-0.3.2/tests/test_routes.py +350 -0
- sshler-0.3.2/tests/test_ssh.py +109 -0
- sshler-0.3.2/tests/test_websocket.py +139 -0
sshler-0.3.2/MANIFEST.in
ADDED
sshler-0.3.2/PKG-INFO
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sshler
|
|
3
|
+
Version: 0.3.2
|
|
4
|
+
Summary: A local FastAPI-powered SSH multiplexer for tmux-in-browser — from your laptop only.
|
|
5
|
+
Author: You
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/gabu-quest/sshler
|
|
8
|
+
Project-URL: Repository, https://github.com/gabu-quest/sshler
|
|
9
|
+
Project-URL: Issues, https://github.com/gabu-quest/sshler/issues
|
|
10
|
+
Keywords: ssh,tmux,fastapi,sftp,htmx
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Environment :: Web Environment
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: System :: Systems Administration
|
|
22
|
+
Classifier: Framework :: FastAPI
|
|
23
|
+
Requires-Python: >=3.12
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
Requires-Dist: fastapi>=0.115.0
|
|
26
|
+
Requires-Dist: uvicorn[standard]>=0.30.0
|
|
27
|
+
Requires-Dist: jinja2>=3.1
|
|
28
|
+
Requires-Dist: pyyaml>=6.0
|
|
29
|
+
Requires-Dist: asyncssh>=2.14.0
|
|
30
|
+
Requires-Dist: platformdirs>=4.2
|
|
31
|
+
Requires-Dist: pydantic>=2.7
|
|
32
|
+
Requires-Dist: python-multipart>=0.0.9
|
|
33
|
+
Requires-Dist: sqler>=1.2025.9.24
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: anyio>=4.4; extra == "dev"
|
|
36
|
+
Requires-Dist: httpx>=0.27.0; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest>=8.2; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
39
|
+
Requires-Dist: ruff>=0.5.6; extra == "dev"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# sshler / エスエスエイチラー
|
|
43
|
+
|
|
44
|
+
**English:** sshler is a lightweight, local-only web UI that lets you browse remote
|
|
45
|
+
files over SFTP and jump into tmux sessions in your browser — without installing
|
|
46
|
+
anything on the remote host.
|
|
47
|
+
|
|
48
|
+
**日本語:** sshler はローカル専用の軽量 Web UI で、リモートファイルを SFTP で閲覧したり、
|
|
49
|
+
ブラウザ上で tmux セッションに接続したりできます。リモート側に追加ソフトを
|
|
50
|
+
インストールする必要はありません。
|
|
51
|
+
|
|
52
|
+
- Runs on your Windows 11 laptop (or any OS with Python)
|
|
53
|
+
- **日本語:** Windows 11 を含む Python が動く環境ならどこでも動作します。
|
|
54
|
+
- Includes a "local" workspace card so you can browse your own filesystem and launch WSL-backed tmux sessions alongside remote hosts
|
|
55
|
+
- **日本語:** ローカルワークスペースカードを備え、ローカル/WSL のファイルや tmux も同じ UI で扱えます。
|
|
56
|
+
- Uses your existing SSH keys
|
|
57
|
+
- **日本語:** 既存の SSH 鍵をそのまま利用します。
|
|
58
|
+
- Opens `tmux new -As <session> -c <dir>` on the remote host and bridges it to the browser via WebSocket + xterm.js
|
|
59
|
+
- **日本語:** リモートで `tmux new -As <session> -c <dir>` を実行し、WebSocket と xterm.js でブラウザに橋渡しします。
|
|
60
|
+
- HTMX-based file browser with “Open Terminal Here”
|
|
61
|
+
- **日本語:** HTMX 製のファイルブラウザから「このディレクトリで端末を開く」がワンクリックで可能です。
|
|
62
|
+
- Auto-creates a starter config at first run
|
|
63
|
+
- **日本語:** 初回起動時に自動で設定ファイルを生成します。
|
|
64
|
+
- Honors your OpenSSH aliases; if DNS fails it resolves them via `ssh -G` and you can reset overrides with a single click
|
|
65
|
+
- **日本語:** OpenSSH のエイリアスを解釈し、DNS 解決に失敗した場合でも `ssh -G` で補完します。ワンクリックで上書きをリセットできます。
|
|
66
|
+
- One-click file previews: view remote files in a new tab without leaving the browser
|
|
67
|
+
- **日本語:** ワンクリックでプレビュー表示。ブラウザを離れずに内容確認できます。
|
|
68
|
+
- Inline edits for lightweight text files (≤256 KB) with a CodeMirror editor and Save button
|
|
69
|
+
- **日本語:** 256 KB 以下のテキストならブラウザ内で編集し、その場で保存できます。
|
|
70
|
+
|
|
71
|
+
## Install / インストール
|
|
72
|
+
|
|
73
|
+
### PyPI (recommended) / PyPI からのインストール
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install sshler
|
|
77
|
+
|
|
78
|
+
# launch once to create the config + systemd/service assets
|
|
79
|
+
sshler serve
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- **日本語:** `pip install sshler` で最新の安定版を取得し、`sshler serve` を実行すると初期設定ファイルが生成されます。
|
|
83
|
+
|
|
84
|
+
Requires Python **3.12+**.
|
|
85
|
+
|
|
86
|
+
### Development / 開発インストール
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
uv pip install -e .
|
|
90
|
+
# or: pip install -e .
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- **日本語:** 開発時は editable install (`-e`) を利用してください。
|
|
94
|
+
|
|
95
|
+
After cloning the repository, install the dev extras and run the usual tooling:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
uv sync --group dev
|
|
99
|
+
uv run ruff check .
|
|
100
|
+
uv run pytest
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
- **日本語:** リポジトリを取得したら `uv sync --group dev` で依存関係をそろえ、`uv run ruff check .` や `uv run pytest` で動作を確認します。
|
|
104
|
+
|
|
105
|
+
## Run / 実行
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
sshler serve
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The app will open `http://127.0.0.1:8822` in your default browser.
|
|
112
|
+
|
|
113
|
+
- **日本語:** 上記を実行するとデフォルトブラウザで `http://127.0.0.1:8822` が開きます。
|
|
114
|
+
|
|
115
|
+
## Configuration / 設定
|
|
116
|
+
|
|
117
|
+
sshler reads your existing OpenSSH config (`~/.ssh/config`) and shows every concrete `Host` entry automatically. Any favourites, default directories, or custom hosts you add through the UI are stored in a companion YAML file.
|
|
118
|
+
|
|
119
|
+
- **日本語:** OpenSSH の設定 (`~/.ssh/config`) を読み取り、すべての `Host` が自動的に一覧に表示されます。お気に入りやデフォルトディレクトリ、カスタムホストは付属の YAML に保存されます。
|
|
120
|
+
|
|
121
|
+
A config file is created on first run:
|
|
122
|
+
|
|
123
|
+
- Windows: `%APPDATA%\sshler\boxes.yaml`
|
|
124
|
+
- macOS/Linux: `~/.config/sshler/boxes.yaml`
|
|
125
|
+
|
|
126
|
+
Example:
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
boxes:
|
|
130
|
+
- name: gabu-server
|
|
131
|
+
host: example.tailnet.ts.net # literal IP/FQDN or keep as placeholder
|
|
132
|
+
ssh_alias: gabu-server # optional: resolves via `ssh -G gabu-server`
|
|
133
|
+
user: gabu
|
|
134
|
+
port: 22
|
|
135
|
+
keyfile: "C:/Users/gabu/.ssh/id_ed25519"
|
|
136
|
+
favorites:
|
|
137
|
+
- /home/gabu
|
|
138
|
+
- /home/gabu/projects
|
|
139
|
+
- /srv/codex
|
|
140
|
+
default_dir: /home/gabu
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
> Tip: Set `default_dir` if your home path isn’t `/home/<user>`.
|
|
144
|
+
> If you rely on an OpenSSH alias, add `ssh_alias:` and sshler will run `ssh -G` to expand it when DNS fails.
|
|
145
|
+
|
|
146
|
+
- **日本語のヒント:** ホームディレクトリが `/home/<user>` 以外なら `default_dir` を設定してください。OpenSSH のエイリアスを利用する場合は `ssh_alias:` を追加すると、DNS 失敗時に `ssh -G` で解決します。
|
|
147
|
+
|
|
148
|
+
### Resetting overrides / 上書き設定のリセット
|
|
149
|
+
|
|
150
|
+
Boxes imported from SSH config show a highlighted border and “Refresh” button. If you change something in `~/.ssh/config`, hit Refresh to drop any stored overrides (host/user/port/key) so the new settings take effect without editing `boxes.yaml`.
|
|
151
|
+
|
|
152
|
+
- **日本語:** SSH 設定から取り込まれたボックスは枠が強調表示され、「Refresh」ボタンで上書き設定を削除できます。`~/.ssh/config` を更新した際はボタンを押すだけで最新状態になります。
|
|
153
|
+
|
|
154
|
+
### Adding custom boxes / カスタムボックスの追加
|
|
155
|
+
|
|
156
|
+
Hit “Add Box” in the UI to define a host that isn’t in your SSH config (for example, a throwaway Docker container). Fields you leave blank fall back to your SSH defaults.
|
|
157
|
+
|
|
158
|
+
- **日本語:** UI の “Add Box” から SSH 設定に存在しないホストも追加できます(例: 一時的な Docker コンテナ)。未入力の項目は SSH のデフォルト値が使われます。
|
|
159
|
+
|
|
160
|
+
### Security model (important)
|
|
161
|
+
|
|
162
|
+
- sshler is designed for **single-user localhost** use. By default `sshler serve` binds to `127.0.0.1` and prints a random `X-SSHLER-TOKEN` that every state-changing request must send.
|
|
163
|
+
- File uploads are capped at 50 MB (tunable via `--max-upload-mb`). Uploaded content is never executed server-side.
|
|
164
|
+
- SSH connections still honour your system `known_hosts`. Only set `known_hosts: ignore` if you fully understand the risk.
|
|
165
|
+
- If you expose sshler beyond localhost, opt-in via `--allow-origin` and add `--auth user:pass` (basic auth). Use it only on networks you trust and put TLS in front (nginx, Caddy, etc.).
|
|
166
|
+
- There is no telemetry, analytics, or call-home behaviour.
|
|
167
|
+
|
|
168
|
+
### CLI options
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
sshler serve \
|
|
172
|
+
--bind 127.0.0.1 \
|
|
173
|
+
--port 8822 \
|
|
174
|
+
--max-upload-mb 50 \
|
|
175
|
+
--allow-origin http://workstation:8822 \
|
|
176
|
+
--auth coder:supersecret \
|
|
177
|
+
--no-ssh-alias \
|
|
178
|
+
--log-level info
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
- `--bind` (alias `--host`) keeps the server on localhost by default.
|
|
182
|
+
- `--allow-origin` can be repeated to expand CORS; combine it with `--auth` if you expose the UI to the LAN.
|
|
183
|
+
- `--max-upload-mb` lets you raise/lower the upload ceiling.
|
|
184
|
+
- `--no-ssh-alias` disables the `ssh -G` fallback when DNS fails.
|
|
185
|
+
- `--token` lets you supply your own `X-SSHLER-TOKEN` (otherwise a secure random value is generated).
|
|
186
|
+
- `--log-level` feeds directly into uvicorn.
|
|
187
|
+
|
|
188
|
+
The server prints the token (and, if enabled, the basic auth username) on startup so you can copy it into API clients or browser extensions.
|
|
189
|
+
|
|
190
|
+
- **日本語:** サーバー起動時にトークン(および Basic 認証を有効にした場合はユーザー名)を表示するので、API クライアントやブラウザ拡張に貼り付けて利用できます。
|
|
191
|
+
|
|
192
|
+
## Autostart / 自動起動
|
|
193
|
+
|
|
194
|
+
### Windows (Task Scheduler)
|
|
195
|
+
|
|
196
|
+
1. Run `where sshler` to locate the installed executable (for example, `%LOCALAPPDATA%\Programs\Python\Python312\Scripts\sshler.exe`).
|
|
197
|
+
2. Open **Task Scheduler → Create Task…**.
|
|
198
|
+
3. Under **Triggers**, add “At log on”.
|
|
199
|
+
4. Under **Actions**, choose “Start a program” and point to the `sshler.exe` path. Add arguments such as `serve --no-browser` and set **Start in** to a writable directory.
|
|
200
|
+
5. Tick “Run with highest privileges” if you need WSL access, then save. sshler will now launch automatically every time you sign in.
|
|
201
|
+
|
|
202
|
+
- **日本語:** Task Scheduler で「ログオン時」をトリガーにし、`sshler.exe serve --no-browser` を実行するタスクを作成すると、サインイン時に自動起動します。
|
|
203
|
+
|
|
204
|
+
### Linux / macOS (systemd user service)
|
|
205
|
+
|
|
206
|
+
Create `~/.config/systemd/user/sshler.service`:
|
|
207
|
+
|
|
208
|
+
```ini
|
|
209
|
+
[Unit]
|
|
210
|
+
Description=sshler – local tmux bridge
|
|
211
|
+
After=network.target
|
|
212
|
+
|
|
213
|
+
[Service]
|
|
214
|
+
Type=simple
|
|
215
|
+
ExecStart=%h/.local/bin/sshler serve --bind 127.0.0.1 --no-browser
|
|
216
|
+
Restart=on-failure
|
|
217
|
+
|
|
218
|
+
[Install]
|
|
219
|
+
WantedBy=default.target
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Reload and enable:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
systemctl --user daemon-reload
|
|
226
|
+
systemctl --user enable --now sshler.service
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
- **日本語:** 上記の systemd ユーザーサービスを作成し、`systemctl --user enable --now sshler.service` を実行するとサインイン時に自動起動します。
|
|
230
|
+
|
|
231
|
+
### Dependencies & licenses
|
|
232
|
+
|
|
233
|
+
- FastAPI, uvicorn, asyncssh, platformdirs, yaml (PyPI packages, permissive licenses)
|
|
234
|
+
- HTMX (MIT) and xterm.js (MIT) are loaded from unpkg
|
|
235
|
+
- CodeMirror (MIT) powers the editor
|
|
236
|
+
|
|
237
|
+
All assets are used under their respective MIT/BSD-style licenses. sshler itself ships under the MIT license.
|
|
238
|
+
|
|
239
|
+
- **日本語:** 依存ライブラリはいずれも寛容なライセンス (MIT/BSD) で提供されています。sshler 本体も MIT ライセンスで配布されます。
|
|
240
|
+
|
|
241
|
+
## Why “sshler”? / 名前の由来
|
|
242
|
+
|
|
243
|
+
**English:** Because sometimes you want less VS Code, more terminal — but still in a nice browser tab.
|
|
244
|
+
|
|
245
|
+
**日本語:** VS Code だけに頼らず、ブラウザタブの中で軽快にターミナルを扱いたい──そんな願いからこの名前になりました。
|
sshler-0.3.2/README.md
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
|
|
2
|
+
# sshler / エスエスエイチラー
|
|
3
|
+
|
|
4
|
+
**English:** sshler is a lightweight, local-only web UI that lets you browse remote
|
|
5
|
+
files over SFTP and jump into tmux sessions in your browser — without installing
|
|
6
|
+
anything on the remote host.
|
|
7
|
+
|
|
8
|
+
**日本語:** sshler はローカル専用の軽量 Web UI で、リモートファイルを SFTP で閲覧したり、
|
|
9
|
+
ブラウザ上で tmux セッションに接続したりできます。リモート側に追加ソフトを
|
|
10
|
+
インストールする必要はありません。
|
|
11
|
+
|
|
12
|
+
- Runs on your Windows 11 laptop (or any OS with Python)
|
|
13
|
+
- **日本語:** Windows 11 を含む Python が動く環境ならどこでも動作します。
|
|
14
|
+
- Includes a "local" workspace card so you can browse your own filesystem and launch WSL-backed tmux sessions alongside remote hosts
|
|
15
|
+
- **日本語:** ローカルワークスペースカードを備え、ローカル/WSL のファイルや tmux も同じ UI で扱えます。
|
|
16
|
+
- Uses your existing SSH keys
|
|
17
|
+
- **日本語:** 既存の SSH 鍵をそのまま利用します。
|
|
18
|
+
- Opens `tmux new -As <session> -c <dir>` on the remote host and bridges it to the browser via WebSocket + xterm.js
|
|
19
|
+
- **日本語:** リモートで `tmux new -As <session> -c <dir>` を実行し、WebSocket と xterm.js でブラウザに橋渡しします。
|
|
20
|
+
- HTMX-based file browser with “Open Terminal Here”
|
|
21
|
+
- **日本語:** HTMX 製のファイルブラウザから「このディレクトリで端末を開く」がワンクリックで可能です。
|
|
22
|
+
- Auto-creates a starter config at first run
|
|
23
|
+
- **日本語:** 初回起動時に自動で設定ファイルを生成します。
|
|
24
|
+
- Honors your OpenSSH aliases; if DNS fails it resolves them via `ssh -G` and you can reset overrides with a single click
|
|
25
|
+
- **日本語:** OpenSSH のエイリアスを解釈し、DNS 解決に失敗した場合でも `ssh -G` で補完します。ワンクリックで上書きをリセットできます。
|
|
26
|
+
- One-click file previews: view remote files in a new tab without leaving the browser
|
|
27
|
+
- **日本語:** ワンクリックでプレビュー表示。ブラウザを離れずに内容確認できます。
|
|
28
|
+
- Inline edits for lightweight text files (≤256 KB) with a CodeMirror editor and Save button
|
|
29
|
+
- **日本語:** 256 KB 以下のテキストならブラウザ内で編集し、その場で保存できます。
|
|
30
|
+
|
|
31
|
+
## Install / インストール
|
|
32
|
+
|
|
33
|
+
### PyPI (recommended) / PyPI からのインストール
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install sshler
|
|
37
|
+
|
|
38
|
+
# launch once to create the config + systemd/service assets
|
|
39
|
+
sshler serve
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- **日本語:** `pip install sshler` で最新の安定版を取得し、`sshler serve` を実行すると初期設定ファイルが生成されます。
|
|
43
|
+
|
|
44
|
+
Requires Python **3.12+**.
|
|
45
|
+
|
|
46
|
+
### Development / 開発インストール
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
uv pip install -e .
|
|
50
|
+
# or: pip install -e .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- **日本語:** 開発時は editable install (`-e`) を利用してください。
|
|
54
|
+
|
|
55
|
+
After cloning the repository, install the dev extras and run the usual tooling:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
uv sync --group dev
|
|
59
|
+
uv run ruff check .
|
|
60
|
+
uv run pytest
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- **日本語:** リポジトリを取得したら `uv sync --group dev` で依存関係をそろえ、`uv run ruff check .` や `uv run pytest` で動作を確認します。
|
|
64
|
+
|
|
65
|
+
## Run / 実行
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
sshler serve
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The app will open `http://127.0.0.1:8822` in your default browser.
|
|
72
|
+
|
|
73
|
+
- **日本語:** 上記を実行するとデフォルトブラウザで `http://127.0.0.1:8822` が開きます。
|
|
74
|
+
|
|
75
|
+
## Configuration / 設定
|
|
76
|
+
|
|
77
|
+
sshler reads your existing OpenSSH config (`~/.ssh/config`) and shows every concrete `Host` entry automatically. Any favourites, default directories, or custom hosts you add through the UI are stored in a companion YAML file.
|
|
78
|
+
|
|
79
|
+
- **日本語:** OpenSSH の設定 (`~/.ssh/config`) を読み取り、すべての `Host` が自動的に一覧に表示されます。お気に入りやデフォルトディレクトリ、カスタムホストは付属の YAML に保存されます。
|
|
80
|
+
|
|
81
|
+
A config file is created on first run:
|
|
82
|
+
|
|
83
|
+
- Windows: `%APPDATA%\sshler\boxes.yaml`
|
|
84
|
+
- macOS/Linux: `~/.config/sshler/boxes.yaml`
|
|
85
|
+
|
|
86
|
+
Example:
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
boxes:
|
|
90
|
+
- name: gabu-server
|
|
91
|
+
host: example.tailnet.ts.net # literal IP/FQDN or keep as placeholder
|
|
92
|
+
ssh_alias: gabu-server # optional: resolves via `ssh -G gabu-server`
|
|
93
|
+
user: gabu
|
|
94
|
+
port: 22
|
|
95
|
+
keyfile: "C:/Users/gabu/.ssh/id_ed25519"
|
|
96
|
+
favorites:
|
|
97
|
+
- /home/gabu
|
|
98
|
+
- /home/gabu/projects
|
|
99
|
+
- /srv/codex
|
|
100
|
+
default_dir: /home/gabu
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
> Tip: Set `default_dir` if your home path isn’t `/home/<user>`.
|
|
104
|
+
> If you rely on an OpenSSH alias, add `ssh_alias:` and sshler will run `ssh -G` to expand it when DNS fails.
|
|
105
|
+
|
|
106
|
+
- **日本語のヒント:** ホームディレクトリが `/home/<user>` 以外なら `default_dir` を設定してください。OpenSSH のエイリアスを利用する場合は `ssh_alias:` を追加すると、DNS 失敗時に `ssh -G` で解決します。
|
|
107
|
+
|
|
108
|
+
### Resetting overrides / 上書き設定のリセット
|
|
109
|
+
|
|
110
|
+
Boxes imported from SSH config show a highlighted border and “Refresh” button. If you change something in `~/.ssh/config`, hit Refresh to drop any stored overrides (host/user/port/key) so the new settings take effect without editing `boxes.yaml`.
|
|
111
|
+
|
|
112
|
+
- **日本語:** SSH 設定から取り込まれたボックスは枠が強調表示され、「Refresh」ボタンで上書き設定を削除できます。`~/.ssh/config` を更新した際はボタンを押すだけで最新状態になります。
|
|
113
|
+
|
|
114
|
+
### Adding custom boxes / カスタムボックスの追加
|
|
115
|
+
|
|
116
|
+
Hit “Add Box” in the UI to define a host that isn’t in your SSH config (for example, a throwaway Docker container). Fields you leave blank fall back to your SSH defaults.
|
|
117
|
+
|
|
118
|
+
- **日本語:** UI の “Add Box” から SSH 設定に存在しないホストも追加できます(例: 一時的な Docker コンテナ)。未入力の項目は SSH のデフォルト値が使われます。
|
|
119
|
+
|
|
120
|
+
### Security model (important)
|
|
121
|
+
|
|
122
|
+
- sshler is designed for **single-user localhost** use. By default `sshler serve` binds to `127.0.0.1` and prints a random `X-SSHLER-TOKEN` that every state-changing request must send.
|
|
123
|
+
- File uploads are capped at 50 MB (tunable via `--max-upload-mb`). Uploaded content is never executed server-side.
|
|
124
|
+
- SSH connections still honour your system `known_hosts`. Only set `known_hosts: ignore` if you fully understand the risk.
|
|
125
|
+
- If you expose sshler beyond localhost, opt-in via `--allow-origin` and add `--auth user:pass` (basic auth). Use it only on networks you trust and put TLS in front (nginx, Caddy, etc.).
|
|
126
|
+
- There is no telemetry, analytics, or call-home behaviour.
|
|
127
|
+
|
|
128
|
+
### CLI options
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
sshler serve \
|
|
132
|
+
--bind 127.0.0.1 \
|
|
133
|
+
--port 8822 \
|
|
134
|
+
--max-upload-mb 50 \
|
|
135
|
+
--allow-origin http://workstation:8822 \
|
|
136
|
+
--auth coder:supersecret \
|
|
137
|
+
--no-ssh-alias \
|
|
138
|
+
--log-level info
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
- `--bind` (alias `--host`) keeps the server on localhost by default.
|
|
142
|
+
- `--allow-origin` can be repeated to expand CORS; combine it with `--auth` if you expose the UI to the LAN.
|
|
143
|
+
- `--max-upload-mb` lets you raise/lower the upload ceiling.
|
|
144
|
+
- `--no-ssh-alias` disables the `ssh -G` fallback when DNS fails.
|
|
145
|
+
- `--token` lets you supply your own `X-SSHLER-TOKEN` (otherwise a secure random value is generated).
|
|
146
|
+
- `--log-level` feeds directly into uvicorn.
|
|
147
|
+
|
|
148
|
+
The server prints the token (and, if enabled, the basic auth username) on startup so you can copy it into API clients or browser extensions.
|
|
149
|
+
|
|
150
|
+
- **日本語:** サーバー起動時にトークン(および Basic 認証を有効にした場合はユーザー名)を表示するので、API クライアントやブラウザ拡張に貼り付けて利用できます。
|
|
151
|
+
|
|
152
|
+
## Autostart / 自動起動
|
|
153
|
+
|
|
154
|
+
### Windows (Task Scheduler)
|
|
155
|
+
|
|
156
|
+
1. Run `where sshler` to locate the installed executable (for example, `%LOCALAPPDATA%\Programs\Python\Python312\Scripts\sshler.exe`).
|
|
157
|
+
2. Open **Task Scheduler → Create Task…**.
|
|
158
|
+
3. Under **Triggers**, add “At log on”.
|
|
159
|
+
4. Under **Actions**, choose “Start a program” and point to the `sshler.exe` path. Add arguments such as `serve --no-browser` and set **Start in** to a writable directory.
|
|
160
|
+
5. Tick “Run with highest privileges” if you need WSL access, then save. sshler will now launch automatically every time you sign in.
|
|
161
|
+
|
|
162
|
+
- **日本語:** Task Scheduler で「ログオン時」をトリガーにし、`sshler.exe serve --no-browser` を実行するタスクを作成すると、サインイン時に自動起動します。
|
|
163
|
+
|
|
164
|
+
### Linux / macOS (systemd user service)
|
|
165
|
+
|
|
166
|
+
Create `~/.config/systemd/user/sshler.service`:
|
|
167
|
+
|
|
168
|
+
```ini
|
|
169
|
+
[Unit]
|
|
170
|
+
Description=sshler – local tmux bridge
|
|
171
|
+
After=network.target
|
|
172
|
+
|
|
173
|
+
[Service]
|
|
174
|
+
Type=simple
|
|
175
|
+
ExecStart=%h/.local/bin/sshler serve --bind 127.0.0.1 --no-browser
|
|
176
|
+
Restart=on-failure
|
|
177
|
+
|
|
178
|
+
[Install]
|
|
179
|
+
WantedBy=default.target
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Reload and enable:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
systemctl --user daemon-reload
|
|
186
|
+
systemctl --user enable --now sshler.service
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
- **日本語:** 上記の systemd ユーザーサービスを作成し、`systemctl --user enable --now sshler.service` を実行するとサインイン時に自動起動します。
|
|
190
|
+
|
|
191
|
+
### Dependencies & licenses
|
|
192
|
+
|
|
193
|
+
- FastAPI, uvicorn, asyncssh, platformdirs, yaml (PyPI packages, permissive licenses)
|
|
194
|
+
- HTMX (MIT) and xterm.js (MIT) are loaded from unpkg
|
|
195
|
+
- CodeMirror (MIT) powers the editor
|
|
196
|
+
|
|
197
|
+
All assets are used under their respective MIT/BSD-style licenses. sshler itself ships under the MIT license.
|
|
198
|
+
|
|
199
|
+
- **日本語:** 依存ライブラリはいずれも寛容なライセンス (MIT/BSD) で提供されています。sshler 本体も MIT ライセンスで配布されます。
|
|
200
|
+
|
|
201
|
+
## Why “sshler”? / 名前の由来
|
|
202
|
+
|
|
203
|
+
**English:** Because sometimes you want less VS Code, more terminal — but still in a nice browser tab.
|
|
204
|
+
|
|
205
|
+
**日本語:** VS Code だけに頼らず、ブラウザタブの中で軽快にターミナルを扱いたい──そんな願いからこの名前になりました。
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
|
|
2
|
+
[build-system]
|
|
3
|
+
requires = ["setuptools>=69", "wheel"]
|
|
4
|
+
build-backend = "setuptools.build_meta"
|
|
5
|
+
|
|
6
|
+
[project]
|
|
7
|
+
name = "sshler"
|
|
8
|
+
version = "0.3.2"
|
|
9
|
+
description = "A local FastAPI-powered SSH multiplexer for tmux-in-browser — from your laptop only."
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
requires-python = ">=3.12"
|
|
12
|
+
authors = [{name = "You"}]
|
|
13
|
+
license = "MIT"
|
|
14
|
+
dependencies = [
|
|
15
|
+
"fastapi>=0.115.0",
|
|
16
|
+
"uvicorn[standard]>=0.30.0",
|
|
17
|
+
"jinja2>=3.1",
|
|
18
|
+
"pyyaml>=6.0",
|
|
19
|
+
"asyncssh>=2.14.0",
|
|
20
|
+
"platformdirs>=4.2",
|
|
21
|
+
"pydantic>=2.7",
|
|
22
|
+
"python-multipart>=0.0.9",
|
|
23
|
+
"sqler>=1.2025.9.24",
|
|
24
|
+
]
|
|
25
|
+
classifiers = [
|
|
26
|
+
"Development Status :: 3 - Alpha",
|
|
27
|
+
"Environment :: Console",
|
|
28
|
+
"Environment :: Web Environment",
|
|
29
|
+
"Intended Audience :: Developers",
|
|
30
|
+
"Operating System :: OS Independent",
|
|
31
|
+
"Programming Language :: Python :: 3",
|
|
32
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
33
|
+
"Programming Language :: Python :: 3.10",
|
|
34
|
+
"Programming Language :: Python :: 3.11",
|
|
35
|
+
"Programming Language :: Python :: 3.12",
|
|
36
|
+
"Topic :: System :: Systems Administration",
|
|
37
|
+
"Framework :: FastAPI",
|
|
38
|
+
]
|
|
39
|
+
keywords = ["ssh", "tmux", "fastapi", "sftp", "htmx"]
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
Homepage = "https://github.com/gabu-quest/sshler"
|
|
43
|
+
Repository = "https://github.com/gabu-quest/sshler"
|
|
44
|
+
Issues = "https://github.com/gabu-quest/sshler/issues"
|
|
45
|
+
|
|
46
|
+
[project.optional-dependencies]
|
|
47
|
+
dev = [
|
|
48
|
+
"anyio>=4.4",
|
|
49
|
+
"httpx>=0.27.0",
|
|
50
|
+
"pytest>=8.2",
|
|
51
|
+
"pytest-asyncio>=0.23",
|
|
52
|
+
"ruff>=0.5.6",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[dependency-groups]
|
|
56
|
+
dev = [
|
|
57
|
+
"anyio>=4.4",
|
|
58
|
+
"httpx>=0.27.0",
|
|
59
|
+
"pytest>=8.2",
|
|
60
|
+
"pytest-asyncio>=0.23",
|
|
61
|
+
"ruff>=0.5.6",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[project.scripts]
|
|
65
|
+
sshler = "sshler.cli:main"
|
|
66
|
+
|
|
67
|
+
[tool.setuptools]
|
|
68
|
+
include-package-data = true
|
|
69
|
+
|
|
70
|
+
[tool.setuptools.package-data]
|
|
71
|
+
sshler = ["templates/*.html", "templates/partials/*.html", "static/*", "scripts/*.ps1"]
|
|
72
|
+
|
|
73
|
+
[tool.ruff]
|
|
74
|
+
target-version = "py310"
|
|
75
|
+
line-length = 100
|
|
76
|
+
|
|
77
|
+
[tool.ruff.lint]
|
|
78
|
+
select = ["E", "F", "W", "B", "I", "UP", "N"]
|
|
79
|
+
ignore = ["E203", "B008"]
|
|
80
|
+
|
|
81
|
+
[tool.ruff.format]
|
|
82
|
+
quote-style = "double"
|
|
83
|
+
indent-style = "space"
|
|
84
|
+
skip-magic-trailing-comma = false
|
|
85
|
+
line-ending = "lf"
|
sshler-0.3.2/setup.cfg
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Package metadata export for sshler."""
|
|
2
|
+
|
|
3
|
+
from importlib import metadata
|
|
4
|
+
|
|
5
|
+
__all__ = ["__version__"]
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
__version__ = metadata.version("sshler")
|
|
9
|
+
except metadata.PackageNotFoundError: # pragma: no cover - fallback for editable installs
|
|
10
|
+
__version__ = "0.0.0"
|