|
| 1 | +<!-- e1958379-99ce-42d2-8fe6-2c5007b3f52a cd8f1eb6-6ae5-4b21-9ca9-c208d4e80622 --> |
| 2 | +# Persistent SSH Keys with Simplified Authentication |
| 3 | + |
| 4 | +## Overview |
| 5 | + |
| 6 | +Simplify SSH authentication to only support password OR key (remove confusing 'both' option). Use persistent key files instead of temporary files. Add on-the-fly key generation with public key viewing/copying. |
| 7 | + |
| 8 | +## Implementation Steps |
| 9 | + |
| 10 | +### 1. Create SSH Keys Directory Structure |
| 11 | + |
| 12 | +- Add `data/ssh-keys/` directory for persistent SSH key files |
| 13 | +- Name format: `server_{id}_key` and `server_{id}_key.pub` |
| 14 | +- Set permissions: 0700 for directory, 0600 for key files |
| 15 | +- Add to `.gitignore` to prevent committing keys |
| 16 | + |
| 17 | +### 2. Update Database Schema (`src/server/database.js`) |
| 18 | + |
| 19 | +- Change auth_type CHECK constraint: only allow 'password' or 'key' (remove 'both') |
| 20 | +- Add `ssh_key_path` TEXT column for file path |
| 21 | +- Add `key_generated` INTEGER (0/1) to track generated vs user-provided keys |
| 22 | +- Migration: Convert existing 'both' auth_type to 'key' |
| 23 | +- Update `addServer()`: Write key to persistent file, store path |
| 24 | +- Update `updateServer()`: Handle key changes (write new, delete old) |
| 25 | +- Update `deleteServer()`: Clean up key files |
| 26 | + |
| 27 | +### 3. SSH Key Generation Feature (`src/server/ssh-service.js`) |
| 28 | + |
| 29 | +- Add `generateKeyPair(serverId)` method using `ssh-keygen` command |
| 30 | +- Command: `ssh-keygen -t ed25519 -f data/ssh-keys/server_{id}_key -N "" -C "pve-scripts-local"` |
| 31 | +- Return both private and public key content |
| 32 | +- Add `getPublicKey(keyPath)` to extract public key from private key |
| 33 | + |
| 34 | +### 4. Backend API Endpoints (New Files) |
| 35 | + |
| 36 | +- `POST /api/servers/generate-keypair` |
| 37 | +- Generate temporary key pair (not yet saved to server) |
| 38 | +- Return `{ privateKey, publicKey }` |
| 39 | +- `GET /api/servers/[id]/public-key` |
| 40 | +- Only if `key_generated === 1` |
| 41 | +- Return `{ publicKey, serverName, serverIp }` |
| 42 | + |
| 43 | +### 5. Frontend: ServerForm Component |
| 44 | + |
| 45 | +- **Remove 'both' from auth_type dropdown** - only show Password/SSH Key |
| 46 | +- Add "Generate Key Pair" button (visible when auth_type === 'key') |
| 47 | +- On generate: populate SSH key field, show modal with public key |
| 48 | +- Add PublicKeyModal component with copy-to-clipboard |
| 49 | +- Disable manual key entry when using generated key |
| 50 | + |
| 51 | +### 6. Frontend: ServerList Component |
| 52 | + |
| 53 | +- Add "View Public Key" button between Test Connection and Edit |
| 54 | +- Only show when `server.key_generated === true` |
| 55 | +- Click opens PublicKeyModal with copy button |
| 56 | +- Show instructions: "Add this to /root/.ssh/authorized_keys on your server" |
| 57 | + |
| 58 | +### 7. Update SSH Service (`src/server/ssh-service.js`) |
| 59 | + |
| 60 | +- **Remove all 'both' auth_type handling** |
| 61 | +- Remove temp file creation from `testWithSSHKey()` |
| 62 | +- Use persistent `ssh_key_path` from database |
| 63 | +- Simplify `testConnection()`: only handle 'password' or 'key' |
| 64 | + |
| 65 | +### 8. Update SSH Execution Service (`src/server/ssh-execution-service.js`) |
| 66 | + |
| 67 | +- **Remove `createTempKeyFile()` method** |
| 68 | +- **Remove all 'both' auth_type cases** |
| 69 | +- Update `buildSSHCommand()`: use `ssh_key_path`, only handle 'password'/'key' |
| 70 | +- Update `transferScriptsFolder()`: use `ssh_key_path` in rsync |
| 71 | +- Update `executeCommand()`: use `ssh_key_path` |
| 72 | +- Remove all temp file cleanup code |
| 73 | + |
| 74 | +### 9. Files to Create/Modify |
| 75 | + |
| 76 | +- `src/server/database.js` - Schema changes, persistence |
| 77 | +- `src/server/ssh-service.js` - Key generation, remove temp files, remove 'both' |
| 78 | +- `src/server/ssh-execution-service.js` - Use persistent keys, remove 'both' |
| 79 | +- `src/app/api/servers/generate-keypair/route.ts` - NEW |
| 80 | +- `src/app/api/servers/[id]/public-key/route.ts` - NEW |
| 81 | +- `src/app/_components/ServerForm.tsx` - Generate button, remove 'both' |
| 82 | +- `src/app/_components/ServerList.tsx` - View public key button |
| 83 | +- `src/app/_components/PublicKeyModal.tsx` - NEW component |
| 84 | +- `.gitignore` - Add `data/ssh-keys/` |
| 85 | + |
| 86 | +### 11. Migration & Initialization |
| 87 | + |
| 88 | +- On startup: create `data/ssh-keys/` if missing |
| 89 | +- Existing 'both' servers: convert to 'key' auth_type |
| 90 | +- Existing ssh_key content: migrate to persistent files on first use |
| 91 | +- Set `key_generated = 0` for migrated servers |
| 92 | + |
| 93 | +## Benefits |
| 94 | + |
| 95 | +- Simpler auth model (no confusing 'both' option) |
| 96 | +- Fixes "error in libcrypto" timing issues |
| 97 | +- User-friendly key generation |
| 98 | +- Easy public key access for setup |
| 99 | +- Less code complexity |
| 100 | + |
| 101 | +### To-dos |
| 102 | + |
| 103 | +- [ ] Create data/ssh-keys directory structure and update .gitignore |
| 104 | +- [ ] Add ssh_key_path column to database and implement migration |
| 105 | +- [ ] Modify addServer/updateServer/deleteServer to handle persistent key files |
| 106 | +- [ ] Remove temp key creation from ssh-service.js and use persistent paths |
| 107 | +- [ ] Remove createTempKeyFile and update all methods to use persistent keys |
| 108 | +- [ ] Test with existing servers that have SSH keys to ensure migration works |
| 109 | +- [ ] Modify the HelpModal to reflect the changes Made to the SSH auth |
| 110 | +- [ ] Create a fix branch |
0 commit comments