docs: add v0.4.0 workflow guide and release notes
This commit is contained in:
parent
db25f9011b
commit
0151076ca9
38
README.md
38
README.md
|
|
@ -22,11 +22,11 @@ port forwarding management.
|
||||||
- Password and key-passphrase auth through a PTY prompt handler, without putting
|
- Password and key-passphrase auth through a PTY prompt handler, without putting
|
||||||
secrets in command-line arguments.
|
secrets in command-line arguments.
|
||||||
- Key, SSH-agent, password, and key+passphrase auth modes.
|
- Key, SSH-agent, password, and key+passphrase auth modes.
|
||||||
- **Routes / ProxyJump** — manage bastion hosts and jump chains with human-readable display.
|
- **Routes / ProxyJump** — ordered bastion chains with stable references to sshkeeper profiles; profile renames do not break routes.
|
||||||
- **Port forwarding** — named local/remote/SOCKS forwards with type selector, validation, and OpenSSH preview.
|
- **Port forwarding** — named local/remote/SOCKS forwards with type selector, validation, and OpenSSH preview.
|
||||||
- **Tunnel management** — start/stop/list background tunnels, PID tracking, runtime state.
|
- **Tunnel management** — start/stop/list background tunnels, PID tracking, runtime state.
|
||||||
- **Tunnel vs Forward** — clear separation: forward = saved rule, tunnel = running SSH process.
|
- **Tunnel vs Forward** — clear separation: forward = saved rule, tunnel = running SSH process.
|
||||||
- Groups, tags, command templates, search by metadata/routes/forward ports, and OpenSSH config generation.
|
- First-class groups, multi-select tags, command templates, search by metadata/routes/forward ports, and OpenSSH config generation.
|
||||||
- Import from `~/.ssh/config` and simple tab-separated export.
|
- Import from `~/.ssh/config` and simple tab-separated export.
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
@ -66,11 +66,11 @@ Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
|
||||||
- Primary public repository: [github.com/mirivlad/sshkeeper](https://github.com/mirivlad/sshkeeper)
|
- Primary public repository: [github.com/mirivlad/sshkeeper](https://github.com/mirivlad/sshkeeper)
|
||||||
- Self-hosted mirror: `git@git.mirv.top:mirivlad/sshkeeper`
|
- Self-hosted mirror: `git@git.mirv.top:mirivlad/sshkeeper`
|
||||||
|
|
||||||
### Install from release (after v0.2.0 publication)
|
### Install from release
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
tar -xzf sshkeeper_v0.2.0_linux_amd64.tar.gz
|
tar -xzf sshkeeper_v0.4.0_linux_amd64.tar.gz
|
||||||
sudo install -m 0755 sshkeeper_v0.2.0_linux_amd64/sshkeeper /usr/local/bin/sshkeeper
|
sudo install -m 0755 sshkeeper_v0.4.0_linux_amd64/sshkeeper /usr/local/bin/sshkeeper
|
||||||
sshkeeper
|
sshkeeper
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -140,7 +140,8 @@ it to DEL (in xterm, `backarrowKey: false`).
|
||||||
| Ctrl+E | Edit server |
|
| Ctrl+E | Edit server |
|
||||||
| Ctrl+F | Search |
|
| Ctrl+F | Search |
|
||||||
| Ctrl+W | Manage port forwards for selected server |
|
| Ctrl+W | Manage port forwards for selected server |
|
||||||
| Ctrl+X | Action menu (connect, tunnels, forwards, route, test, edit, delete, import/export, vault actions) |
|
| Ctrl+X | Server actions (connect, tunnels, forwards, route, test, edit, delete) |
|
||||||
|
| m | Manage groups, tags, command templates, running tunnels, import/export, and vault |
|
||||||
| Ins | Select / deselect a server |
|
| Ins | Select / deselect a server |
|
||||||
| ? | Quick help (hotkeys) |
|
| ? | Quick help (hotkeys) |
|
||||||
| Ctrl+H | Full documentation |
|
| Ctrl+H | Full documentation |
|
||||||
|
|
@ -157,12 +158,25 @@ In add/edit forms:
|
||||||
|-----|--------|
|
|-----|--------|
|
||||||
| Tab / Down | Next field |
|
| Tab / Down | Next field |
|
||||||
| Shift+Tab / Up | Previous field |
|
| Shift+Tab / Up | Previous field |
|
||||||
| `/` on Auth Method or Group | Pick from list |
|
| `/` on Auth, Identity File, Route, Group, Startup Command, or Tags | Open the relevant picker/editor |
|
||||||
| Enter | Move to action / activate |
|
| Enter | Move to action / activate |
|
||||||
| Esc | Back |
|
| Esc | Back |
|
||||||
|
|
||||||
## Routes, Tunnels, and Port Forwards
|
## Routes, Tunnels, and Port Forwards
|
||||||
|
|
||||||
|
Routes are stored as ordered hops. If a hop matches an existing sshkeeper profile,
|
||||||
|
sshkeeper stores a stable reference to that profile ID, not the mutable alias. The
|
||||||
|
connection planner resolves the profile's real host/user/port/key and writes a
|
||||||
|
temporary OpenSSH config for the session, so a sshkeeper bastion does **not** need
|
||||||
|
a matching `Host` entry in `~/.ssh/config`.
|
||||||
|
|
||||||
|
Use `profile:<alias>` to require a profile reference and `raw:<target>` to require
|
||||||
|
a literal OpenSSH jump target. An unprefixed exact known alias is treated as a
|
||||||
|
profile; any other value remains a raw target.
|
||||||
|
|
||||||
|
In the TUI, `/` on Route opens the ordered route editor: `Enter` adds a profile,
|
||||||
|
`x`/Delete removes a hop, and `[`/`]` moves it.
|
||||||
|
|
||||||
### Jump host (single bastion)
|
### Jump host (single bastion)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -248,11 +262,11 @@ key-passphrase authentication so the PTY prompt handler can provide the secret.
|
||||||
| Action | Command | TUI | Description |
|
| Action | Command | TUI | Description |
|
||||||
|--------|---------|-----|-------------|
|
|--------|---------|-----|-------------|
|
||||||
| Connect | `sshkeeper connect <alias>` | `Enter` | Standard SSH session, no port forwards |
|
| Connect | `sshkeeper connect <alias>` | `Enter` | Standard SSH session, no port forwards |
|
||||||
| Connect with tunnels | `sshkeeper tunnel <alias>` | Action menu → Connect with tunnels | SSH session with all enabled forwards active |
|
| Connect with tunnels | `sshkeeper tunnel <alias>` | Server Actions → Connect with tunnels | SSH session with all enabled forwards active |
|
||||||
| Start tunnels only | `sshkeeper tunnel <alias> --forward-only` | Action menu → Start tunnels only | Foreground tunnel, no shell |
|
| Start tunnels only | `sshkeeper tunnel <alias> --forward-only` | Server Actions → Start tunnels only | Foreground tunnel, no shell |
|
||||||
| Start tunnels in background | `sshkeeper tunnel <alias> --background` | Action menu → Start tunnels in background | Detached tunnel process with PID tracking |
|
| Start tunnels in background | `sshkeeper tunnel <alias> --background` | Server Actions → Start tunnels in background | Detached tunnel process with PID tracking |
|
||||||
| Manage port forwards | `sshkeeper forward` | Action menu → Manage port forwards | Add/edit/delete forward rules |
|
| Port forwards | `sshkeeper forward` | Server Actions → Port forwards (or `Ctrl+W`) | Add/edit/enable/delete forward rules |
|
||||||
| Manage tunnels | `sshkeeper tunnel list/stop/stop-all` | Action menu → Manage tunnels | View running tunnels and stop them |
|
| Running tunnels | `sshkeeper tunnel list/stop/stop-all` | `m` → Running tunnels | View tracked/running tunnels and stop them |
|
||||||
|
|
||||||
## Vault
|
## Vault
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,8 @@ Auth: agent Group: - Status: ?
|
||||||
| `Enter` | Подключиться к серверу |
|
| `Enter` | Подключиться к серверу |
|
||||||
| `Ctrl+A` | Добавить сервер |
|
| `Ctrl+A` | Добавить сервер |
|
||||||
| `Ctrl+E` | Редактировать сервер |
|
| `Ctrl+E` | Редактировать сервер |
|
||||||
| `Ctrl+X` | Меню действий |
|
| `Ctrl+X` | Действия выбранного сервера |
|
||||||
|
| `m` | Глобальное меню Manage |
|
||||||
| `Ctrl+F` | Поиск |
|
| `Ctrl+F` | Поиск |
|
||||||
| `Ins` | Выбрать/снять выбор |
|
| `Ins` | Выбрать/снять выбор |
|
||||||
| `?` | Краткая справка по клавишам |
|
| `?` | Краткая справка по клавишам |
|
||||||
|
|
@ -201,7 +202,8 @@ sshkeeper — Quick Help
|
||||||
Ctrl+A Add server
|
Ctrl+A Add server
|
||||||
Ctrl+E Edit server
|
Ctrl+E Edit server
|
||||||
Ctrl+F Search
|
Ctrl+F Search
|
||||||
Ctrl+X Action menu
|
Ctrl+X Server actions
|
||||||
|
m Manage
|
||||||
Ins Select / deselect
|
Ins Select / deselect
|
||||||
|
|
||||||
Port forwards
|
Port forwards
|
||||||
|
|
@ -252,7 +254,8 @@ sshkeeper — Full Help
|
||||||
Ctrl+A Add server
|
Ctrl+A Add server
|
||||||
Ctrl+E Edit server
|
Ctrl+E Edit server
|
||||||
Ctrl+F Search
|
Ctrl+F Search
|
||||||
Ctrl+X Action menu
|
Ctrl+X Server actions
|
||||||
|
m Manage
|
||||||
Ins Select / deselect
|
Ins Select / deselect
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
@ -287,7 +290,7 @@ Add Server
|
||||||
User: root
|
User: root
|
||||||
Auth Method: key
|
Auth Method: key
|
||||||
Identity File: ~/.ssh/id_ed25519
|
Identity File: ~/.ssh/id_ed25519
|
||||||
Route hops: bastion
|
Route: profile:bastion
|
||||||
Group: KP
|
Group: KP
|
||||||
Notes: Main mail server
|
Notes: Main mail server
|
||||||
Startup Command: tmux attach -t ops
|
Startup Command: tmux attach -t ops
|
||||||
|
|
@ -311,8 +314,12 @@ Add Server
|
||||||
|---------|----------|
|
|---------|----------|
|
||||||
| `Tab` или `↓` | Следующее поле |
|
| `Tab` или `↓` | Следующее поле |
|
||||||
| `Shift+Tab` или `↑` | Предыдущее поле |
|
| `Shift+Tab` или `↑` | Предыдущее поле |
|
||||||
| `/` на Auth Method | Выбрать из списка (password/key/key_passphrase/agent) |
|
| `/` на Auth Method | Выбрать password/key/key_passphrase/agent |
|
||||||
| `/` на Group | Выбрать из существующих групп |
|
| `/` на Identity File | Выбрать приватный ключ из `~/.ssh` |
|
||||||
|
| `/` на Route | Открыть редактор цепочки бастионов |
|
||||||
|
| `/` на Group | Выбрать существующую группу |
|
||||||
|
| `/` на Startup Command | Скопировать команду из глобального шаблона |
|
||||||
|
| `/` на Tags | Multi-select существующих тегов; новые можно ввести вручную |
|
||||||
| `Enter` на Test | Проверить подключение |
|
| `Enter` на Test | Проверить подключение |
|
||||||
| `Enter` на Save | Сохранить |
|
| `Enter` на Save | Сохранить |
|
||||||
| `Esc` | Назад; при изменённых данных сначала запросить подтверждение сброса |
|
| `Esc` | Назад; при изменённых данных сначала запросить подтверждение сброса |
|
||||||
|
|
@ -378,9 +385,16 @@ ROUTE: ⇒ bastion → dmz-gw → … → root@secure.internal:22
|
||||||
### Настройка маршрута
|
### Настройка маршрута
|
||||||
|
|
||||||
**Через TUI:**
|
**Через TUI:**
|
||||||
1. Добавьте/редактируйте сервер или выберите `Ctrl+X` → "Manage route"
|
1. Добавьте/редактируйте сервер или выберите `Ctrl+X` → **Route**.
|
||||||
2. В поле "Route hops" введите бастионы через запятую: `bastion,dmz-gw`
|
2. Нажмите `/` на поле Route — откроется список существующих профилей.
|
||||||
3. Или введите адрес напрямую: `user@bastion.example.com:2222`
|
3. `Enter` добавляет выбранный профиль в ordered chain, `x`/Delete удаляет hop, `[`/`]` меняет порядок.
|
||||||
|
4. Для произвольной OpenSSH-цели оставьте escape hatch в поле: `raw:user@bastion.example.com:2222`.
|
||||||
|
|
||||||
|
Ссылка на профиль хранится по стабильному ID. Переименование alias бастиона не
|
||||||
|
ломает зависимые маршруты, а удалить используемый бастион sshkeeper не даст,
|
||||||
|
пока он присутствует в route других серверов. Во время подключения profile-hop
|
||||||
|
разрешается из БД sshkeeper; отдельная запись с тем же alias в `~/.ssh/config`
|
||||||
|
не требуется.
|
||||||
|
|
||||||
**Через CLI:**
|
**Через CLI:**
|
||||||
|
|
||||||
|
|
@ -413,7 +427,7 @@ sshkeeper route clear web
|
||||||
### Управление forwards через TUI
|
### Управление forwards через TUI
|
||||||
|
|
||||||
1. Выберите сервер на главном экране
|
1. Выберите сервер на главном экране
|
||||||
2. Нажмите `Ctrl+X` → "Manage port forwards"
|
2. Нажмите `Ctrl+X` → **Port forwards**
|
||||||
3. Откроется список forwards:
|
3. Откроется список forwards:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -426,7 +440,7 @@ Selected
|
||||||
Port 127.0.0.1:15432 on this machine will be forwarded through web to 127.0.0.1:5432.
|
Port 127.0.0.1:15432 on this machine will be forwarded through web to 127.0.0.1:5432.
|
||||||
ssh -L 127.0.0.1:15432:127.0.0.1:5432
|
ssh -L 127.0.0.1:15432:127.0.0.1:5432
|
||||||
|
|
||||||
Ctrl+A: add | Ctrl+E/Enter: edit | Ctrl+D: delete | Esc: back
|
Ctrl+A: add | Ctrl+E/Enter: edit | Space: enable/disable | Ctrl+D: delete | Esc: back
|
||||||
```
|
```
|
||||||
|
|
||||||
Строки и пояснение выбранного forward сокращаются по экранным ячейкам, а не
|
Строки и пояснение выбранного forward сокращаются по экранным ячейкам, а не
|
||||||
|
|
@ -438,6 +452,7 @@ Selected
|
||||||
|---------|----------|
|
|---------|----------|
|
||||||
| `Ctrl+A` | Добавить forward |
|
| `Ctrl+A` | Добавить forward |
|
||||||
| `Enter` или `Ctrl+E` | Редактировать выбранный |
|
| `Enter` или `Ctrl+E` | Редактировать выбранный |
|
||||||
|
| `Space` | Включить/выключить правило |
|
||||||
| `Ctrl+D` | Удалить (с подтверждением) |
|
| `Ctrl+D` | Удалить (с подтверждением) |
|
||||||
| `Esc` | Назад |
|
| `Esc` | Назад |
|
||||||
|
|
||||||
|
|
@ -514,7 +529,7 @@ forward и сейчас поддерживает только `key` или `agen
|
||||||
### Управление туннелями
|
### Управление туннелями
|
||||||
|
|
||||||
**Через TUI:**
|
**Через TUI:**
|
||||||
1. Нажмите `Ctrl+X` → "Manage tunnels"
|
1. Нажмите `m` → **Running tunnels**
|
||||||
2. Список запущенных туннелей:
|
2. Список запущенных туннелей:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -730,7 +745,7 @@ sshkeeper connect secure
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# В TUI: выбрать несколько серверов (Ins), затем:
|
# В TUI: выбрать несколько серверов (Ins), затем:
|
||||||
# Ctrl+X → Run template → выбрать шаблон
|
# Ctrl+R → выбрать шаблон
|
||||||
# Команда выполнится на всех выбранных серверах
|
# Команда выполнится на всех выбранных серверах
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -746,13 +761,14 @@ sshkeeper connect secure
|
||||||
| `Ctrl+A` | Добавить сервер |
|
| `Ctrl+A` | Добавить сервер |
|
||||||
| `Ctrl+E` | Редактировать сервер |
|
| `Ctrl+E` | Редактировать сервер |
|
||||||
| `Ctrl+F` | Поиск |
|
| `Ctrl+F` | Поиск |
|
||||||
| `Ctrl+X` | Меню действий |
|
| `Ctrl+X` | Действия выбранного сервера |
|
||||||
|
| `m` | Глобальное меню Manage |
|
||||||
| `Ins` | Выбрать/снять выбор |
|
| `Ins` | Выбрать/снять выбор |
|
||||||
| `?` | Краткая справка по клавишам |
|
| `?` | Краткая справка по клавишам |
|
||||||
| `Ctrl+H` | Полная справка по приложению |
|
| `Ctrl+H` | Полная справка по приложению |
|
||||||
| `Ctrl+Q` | Выход |
|
| `Ctrl+Q` | Выход |
|
||||||
|
|
||||||
### Меню действий (Ctrl+X)
|
### Действия сервера (Ctrl+X)
|
||||||
|
|
||||||
| Действие | Описание |
|
| Действие | Описание |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
|
|
@ -760,13 +776,21 @@ sshkeeper connect secure
|
||||||
| Connect with tunnels | SSH + все активные forwards |
|
| Connect with tunnels | SSH + все активные forwards |
|
||||||
| Start tunnels only | Туннель без shell |
|
| Start tunnels only | Туннель без shell |
|
||||||
| Start tunnels in background | Фоновый туннель |
|
| Start tunnels in background | Фоновый туннель |
|
||||||
| Manage port forwards | Управление forwards |
|
| Port forwards | Управление forwards выбранного сервера |
|
||||||
| Manage tunnels | Список туннелей |
|
| Route | Ordered chain бастионов выбранного сервера |
|
||||||
| Manage route | Настройка маршрута |
|
|
||||||
| Test connection | Проверка подключения |
|
| Test connection | Проверка подключения |
|
||||||
| Edit | Редактирование сервера |
|
| Edit | Редактирование сервера |
|
||||||
| Delete | Удаление (с подтверждением) |
|
| Delete | Удаление (с подтверждением) |
|
||||||
| Import | Импорт из `~/.ssh/config` и обновление списка |
|
|
||||||
|
### Manage (`m`)
|
||||||
|
|
||||||
|
| Действие | Описание |
|
||||||
|
|----------|----------|
|
||||||
|
| Groups | Создание, переименование и удаление групп с количеством серверов |
|
||||||
|
| Tags | Управление тегами |
|
||||||
|
| Command templates | Глобальные шаблоны команд |
|
||||||
|
| Running tunnels | Список и остановка фоновых туннелей |
|
||||||
|
| Import SSH config | Импорт из `~/.ssh/config` |
|
||||||
| Export | Выход в терминал и печать экспорта |
|
| Export | Выход в терминал и печать экспорта |
|
||||||
| Vault: lock | Заблокировать vault в текущем процессе |
|
| Vault: lock | Заблокировать vault в текущем процессе |
|
||||||
| Vault: change password | Выход в терминал и смена master password |
|
| Vault: change password | Выход в терминал и смена master password |
|
||||||
|
|
@ -777,7 +801,7 @@ sshkeeper connect secure
|
||||||
|---------|----------|
|
|---------|----------|
|
||||||
| `Tab` / `↓` | Следующее поле |
|
| `Tab` / `↓` | Следующее поле |
|
||||||
| `Shift+Tab` / `↑` | Предыдущее поле |
|
| `Shift+Tab` / `↑` | Предыдущее поле |
|
||||||
| `/` | Выбрать из списка (Auth Method, Group) |
|
| `/` | Открыть picker/editor для Auth, key, Route, Group, Startup Command или Tags |
|
||||||
| `Enter` | Действие / переход |
|
| `Enter` | Действие / переход |
|
||||||
| `Esc` | Назад / отмена |
|
| `Esc` | Назад / отмена |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,195 @@
|
||||||
|
# sshkeeper v0.4.0 — Model & Workflow Cleanup
|
||||||
|
|
||||||
|
v0.4.0 is a structural release. The main goal is to make sshkeeper's data model
|
||||||
|
match what the user sees: server profiles are real reusable objects, routes
|
||||||
|
reference those objects instead of mutable text, and the TUI offers pickers for
|
||||||
|
things that already exist instead of asking you to retype them.
|
||||||
|
|
||||||
|
Existing databases and vaults are migrated automatically. No manual conversion
|
||||||
|
is required.
|
||||||
|
|
||||||
|
## Routes are now real relationships
|
||||||
|
|
||||||
|
The old implementation stored both `ProxyJump` text and a second route
|
||||||
|
representation. Different commands wrote different fields, and runtime SSH used
|
||||||
|
one in preference to the other. That made it possible for `edit --proxy-jump` to
|
||||||
|
say "Saved" while the old structured route was still used.
|
||||||
|
|
||||||
|
v0.4.0 makes `Route` canonical and stores profile hops in a normalized
|
||||||
|
`server_route_hops` table with foreign keys to stable server IDs.
|
||||||
|
|
||||||
|
- Renaming a bastion no longer breaks dependent routes.
|
||||||
|
- Deleting a profile that is still used as a route hop is rejected and names
|
||||||
|
the dependent profiles.
|
||||||
|
- Self references, duplicate hops and route cycles are rejected.
|
||||||
|
- `proxy_jump` and legacy `route_hops` remain compatibility projections for old
|
||||||
|
databases/tools, not competing sources of truth.
|
||||||
|
- Existing `group_name` strings are likewise migrated to first-class `groups`
|
||||||
|
with stable IDs.
|
||||||
|
|
||||||
|
### Profile hops no longer depend on `~/.ssh/config`
|
||||||
|
|
||||||
|
A route hop that references a sshkeeper profile now resolves that profile's real
|
||||||
|
host, user, port and identity file from SQLite. sshkeeper generates a temporary
|
||||||
|
OpenSSH config for the connection and passes it with `ssh -F`.
|
||||||
|
|
||||||
|
This fixes the old accidental requirement that a sshkeeper alias such as
|
||||||
|
`bastion-prod` also had to exist as a matching `Host` in the user's OpenSSH
|
||||||
|
config.
|
||||||
|
|
||||||
|
CLI route syntax is explicit when needed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# exact known aliases are profile references
|
||||||
|
sshkeeper route set prod --jumps bastion,dmz-gw
|
||||||
|
|
||||||
|
# force the interpretation
|
||||||
|
sshkeeper route set prod --jumps profile:bastion,raw:ops@external-gw:2222
|
||||||
|
```
|
||||||
|
|
||||||
|
An unprefixed value matching an existing sshkeeper alias becomes a profile hop;
|
||||||
|
an unknown value remains a raw OpenSSH target.
|
||||||
|
|
||||||
|
Password or key-passphrase authentication on an *intermediate* profile hop is
|
||||||
|
rejected with a clear error for now. The current PTY secret flow can safely feed
|
||||||
|
the target profile, but it cannot reliably route different vault secrets to
|
||||||
|
multiple OpenSSH prompts in a jump chain. Key/agent bastions are supported.
|
||||||
|
|
||||||
|
## Route editor in the TUI
|
||||||
|
|
||||||
|
`Ctrl+X` → **Route**, or `/` while the Route field is focused, opens an ordered
|
||||||
|
route editor.
|
||||||
|
|
||||||
|
- `Enter` adds an existing server profile as a hop.
|
||||||
|
- `x` / Delete removes a hop.
|
||||||
|
- `[` / `]` moves a hop up/down in the chain.
|
||||||
|
- `/` filters the available profiles.
|
||||||
|
- `raw:<target>` remains available in the editable field for arbitrary OpenSSH
|
||||||
|
targets.
|
||||||
|
|
||||||
|
The server form no longer claims that a picker exists while still requiring a
|
||||||
|
comma-separated string.
|
||||||
|
|
||||||
|
## Server Actions vs Manage
|
||||||
|
|
||||||
|
`Ctrl+X` is now strictly about the selected server:
|
||||||
|
|
||||||
|
- Connect
|
||||||
|
- Connect with tunnels
|
||||||
|
- Start tunnels only / in background
|
||||||
|
- Port forwards
|
||||||
|
- Route
|
||||||
|
- Test connection
|
||||||
|
- Edit
|
||||||
|
- Delete
|
||||||
|
|
||||||
|
Press **`m`** for global management:
|
||||||
|
|
||||||
|
- Groups
|
||||||
|
- Tags
|
||||||
|
- Command templates
|
||||||
|
- Running tunnels
|
||||||
|
- Import SSH config
|
||||||
|
- Export
|
||||||
|
- Vault lock / password change
|
||||||
|
|
||||||
|
Groups now have their own manager with server counts, create/rename/delete
|
||||||
|
operations, and safe delete consequences.
|
||||||
|
|
||||||
|
## Context-aware server form
|
||||||
|
|
||||||
|
The form now exposes only authentication fields that matter:
|
||||||
|
|
||||||
|
| Auth | Fields |
|
||||||
|
|------|--------|
|
||||||
|
| password | Password |
|
||||||
|
| key | Identity File |
|
||||||
|
| key_passphrase | Identity File + Key passphrase |
|
||||||
|
| agent | no credential fields |
|
||||||
|
|
||||||
|
`/` opens context-specific pickers:
|
||||||
|
|
||||||
|
- Auth method → auth list
|
||||||
|
- Identity File → detected private keys in `~/.ssh`
|
||||||
|
- Route → profile/chain editor
|
||||||
|
- Group → existing groups
|
||||||
|
- Startup Command → global command templates (the command is copied, not linked)
|
||||||
|
- Tags → multi-select existing tags; new tags can still be typed manually
|
||||||
|
|
||||||
|
## CLI consistency fixes
|
||||||
|
|
||||||
|
All writers now go through the same route semantics.
|
||||||
|
|
||||||
|
- `add`, `edit`, `route set`, TUI save and SSH config import all create the same
|
||||||
|
canonical route model.
|
||||||
|
- SSH config import is two-pass: profiles are created first, then `ProxyJump`
|
||||||
|
aliases are resolved against the complete imported/existing profile set.
|
||||||
|
- `edit` uses Cobra's `Changed()` state, so `--group ''`, `--notes ''`,
|
||||||
|
`--startup-command ''`, `--identity-file ''`, `--proxy-jump ''` and
|
||||||
|
`--tags ''` can actually clear values.
|
||||||
|
- An empty server `User` no longer produces the invalid target `@host`; OpenSSH
|
||||||
|
is allowed to choose its configured/current user.
|
||||||
|
- Shared server/auth/route validation replaced duplicated partial checks.
|
||||||
|
|
||||||
|
## Vault identity follows the server, not its alias
|
||||||
|
|
||||||
|
New and migrated server secrets are stored under stable server IDs. Renaming a
|
||||||
|
profile no longer requires a risky copy/delete of secrets keyed by alias.
|
||||||
|
|
||||||
|
Legacy `server:<alias>:<type>` records remain readable and are lazily migrated
|
||||||
|
when used. `vault list` understands both legacy and stable-ID records and
|
||||||
|
resolves stable IDs back to current aliases when the database is available.
|
||||||
|
|
||||||
|
TUI server save now commits the database change before rewriting vault state;
|
||||||
|
if the vault step fails, the profile/tags are rolled back instead of leaving the
|
||||||
|
database and vault disagreeing.
|
||||||
|
|
||||||
|
## Port forward fixes
|
||||||
|
|
||||||
|
Two concrete TUI bugs are fixed:
|
||||||
|
|
||||||
|
- Editing a disabled forward no longer silently re-enables it.
|
||||||
|
- Remote-forward preview now uses the same semantic builder as validation/save,
|
||||||
|
so listen/target endpoints cannot be shown reversed.
|
||||||
|
|
||||||
|
The editor has an explicit Enabled toggle and the forward list supports `Space`
|
||||||
|
to enable/disable a rule quickly.
|
||||||
|
|
||||||
|
## Tunnel fixes
|
||||||
|
|
||||||
|
Profile routes work consistently for foreground and background tunnels.
|
||||||
|
Background tunnels keep their generated temporary SSH config for the lifetime of
|
||||||
|
the process and remove it on stop/stop-all.
|
||||||
|
|
||||||
|
Tunnel Manager now reports `running` separately from `tracked`; stale tracked
|
||||||
|
state is no longer counted as a running process.
|
||||||
|
|
||||||
|
## Cleanup
|
||||||
|
|
||||||
|
- Removed the stale per-server `CommandTemplate.ServerID` field; command
|
||||||
|
templates are global.
|
||||||
|
- Removed an unused legacy `model.Secret` type; the encrypted vault has its own
|
||||||
|
actual storage model.
|
||||||
|
- Added regression coverage for stable route references, deletion protection,
|
||||||
|
cycle detection, stable-ID vault metadata, contextual auth fields, Manage,
|
||||||
|
route/identity/tag/startup pickers, and forward semantics.
|
||||||
|
|
||||||
|
## Upgrade notes
|
||||||
|
|
||||||
|
On first start, v0.4.0 automatically creates `groups` and
|
||||||
|
`server_route_hops`, links existing group names, and converts existing route
|
||||||
|
text/JSON. The old columns are retained for compatibility.
|
||||||
|
|
||||||
|
As always, keep a copy of `~/.local/share/sshkeeper/` before a major upgrade if
|
||||||
|
the data matters to you.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```bash
|
||||||
|
tar -xzf sshkeeper_v0.4.0_linux_amd64.tar.gz
|
||||||
|
sudo install -m 0755 sshkeeper_v0.4.0_linux_amd64/sshkeeper /usr/local/bin/sshkeeper
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify downloads against `checksums.txt`. Linux and macOS are the primary
|
||||||
|
release targets. Windows remains experimental and requires OpenSSH Client
|
||||||
|
(`ssh.exe`) in `PATH`.
|
||||||
Loading…
Reference in New Issue