telegram-ssh-bot 2.0.0 → 2.2.0
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.
- package/LICENSE +21 -0
- package/README.md +103 -22
- package/deploy/.env.example +86 -0
- package/dist/config/index.d.ts +68 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +315 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +6 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +50 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/Bot.d.ts +91 -0
- package/dist/core/Bot.d.ts.map +1 -0
- package/dist/core/Bot.js +263 -0
- package/dist/core/Bot.js.map +1 -0
- package/dist/core/ConnectionPool.d.ts +125 -0
- package/dist/core/ConnectionPool.d.ts.map +1 -0
- package/dist/core/ConnectionPool.js +397 -0
- package/dist/core/ConnectionPool.js.map +1 -0
- package/dist/core/SSHClient.d.ts +112 -0
- package/dist/core/SSHClient.d.ts.map +1 -0
- package/dist/core/SSHClient.js +367 -0
- package/dist/core/SSHClient.js.map +1 -0
- package/dist/core/ServerManager.d.ts +80 -0
- package/dist/core/ServerManager.d.ts.map +1 -0
- package/dist/core/ServerManager.js +207 -0
- package/dist/core/ServerManager.js.map +1 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +8 -0
- package/dist/core/index.js.map +1 -0
- package/dist/errors/AuthError.d.ts +30 -0
- package/dist/errors/AuthError.d.ts.map +1 -0
- package/dist/errors/AuthError.js +35 -0
- package/dist/errors/AuthError.js.map +1 -0
- package/dist/errors/BaseError.d.ts +17 -0
- package/dist/errors/BaseError.d.ts.map +1 -0
- package/dist/errors/BaseError.js +34 -0
- package/dist/errors/BaseError.js.map +1 -0
- package/dist/errors/ConfigurationError.d.ts +24 -0
- package/dist/errors/ConfigurationError.d.ts.map +1 -0
- package/dist/errors/ConfigurationError.js +24 -0
- package/dist/errors/ConfigurationError.js.map +1 -0
- package/dist/errors/PoolError.d.ts +21 -0
- package/dist/errors/PoolError.d.ts.map +1 -0
- package/dist/errors/PoolError.js +30 -0
- package/dist/errors/PoolError.js.map +1 -0
- package/dist/errors/SSHError.d.ts +24 -0
- package/dist/errors/SSHError.d.ts.map +1 -0
- package/dist/errors/SSHError.js +38 -0
- package/dist/errors/SSHError.js.map +1 -0
- package/dist/errors/StorageError.d.ts +24 -0
- package/dist/errors/StorageError.d.ts.map +1 -0
- package/dist/errors/StorageError.js +35 -0
- package/dist/errors/StorageError.js.map +1 -0
- package/dist/errors/ValidationError.d.ts +29 -0
- package/dist/errors/ValidationError.d.ts.map +1 -0
- package/dist/errors/ValidationError.js +35 -0
- package/dist/errors/ValidationError.js.map +1 -0
- package/dist/errors/index.d.ts +11 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +18 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/handlers/BaseHandler.d.ts +50 -0
- package/dist/handlers/BaseHandler.d.ts.map +1 -0
- package/dist/handlers/BaseHandler.js +87 -0
- package/dist/handlers/BaseHandler.js.map +1 -0
- package/dist/handlers/CommandHandler.d.ts +23 -0
- package/dist/handlers/CommandHandler.d.ts.map +1 -0
- package/dist/handlers/CommandHandler.js +99 -0
- package/dist/handlers/CommandHandler.js.map +1 -0
- package/dist/handlers/HealthHandler.d.ts +25 -0
- package/dist/handlers/HealthHandler.d.ts.map +1 -0
- package/dist/handlers/HealthHandler.js +51 -0
- package/dist/handlers/HealthHandler.js.map +1 -0
- package/dist/handlers/HelpHandler.d.ts +32 -0
- package/dist/handlers/HelpHandler.d.ts.map +1 -0
- package/dist/handlers/HelpHandler.js +76 -0
- package/dist/handlers/HelpHandler.js.map +1 -0
- package/dist/handlers/ServerHandler.d.ts +72 -0
- package/dist/handlers/ServerHandler.d.ts.map +1 -0
- package/dist/handlers/ServerHandler.js +272 -0
- package/dist/handlers/ServerHandler.js.map +1 -0
- package/dist/handlers/index.d.ts +9 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +9 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +348 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/AuthMiddleware.d.ts +28 -0
- package/dist/middleware/AuthMiddleware.d.ts.map +1 -0
- package/dist/middleware/AuthMiddleware.js +49 -0
- package/dist/middleware/AuthMiddleware.js.map +1 -0
- package/dist/middleware/RateLimitMiddleware.d.ts +23 -0
- package/dist/middleware/RateLimitMiddleware.d.ts.map +1 -0
- package/dist/middleware/RateLimitMiddleware.js +34 -0
- package/dist/middleware/RateLimitMiddleware.js.map +1 -0
- package/dist/middleware/index.d.ts +6 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +6 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/services/BackupService.d.ts +119 -0
- package/dist/services/BackupService.d.ts.map +1 -0
- package/dist/services/BackupService.js +313 -0
- package/dist/services/BackupService.js.map +1 -0
- package/dist/services/CryptoService.d.ts +37 -0
- package/dist/services/CryptoService.d.ts.map +1 -0
- package/dist/services/CryptoService.js +108 -0
- package/dist/services/CryptoService.js.map +1 -0
- package/dist/services/HealthService.d.ts +126 -0
- package/dist/services/HealthService.d.ts.map +1 -0
- package/dist/services/HealthService.js +213 -0
- package/dist/services/HealthService.js.map +1 -0
- package/dist/services/LoggingService.d.ts +115 -0
- package/dist/services/LoggingService.d.ts.map +1 -0
- package/dist/services/LoggingService.js +334 -0
- package/dist/services/LoggingService.js.map +1 -0
- package/dist/services/MonitoringService.d.ts +119 -0
- package/dist/services/MonitoringService.d.ts.map +1 -0
- package/dist/services/MonitoringService.js +267 -0
- package/dist/services/MonitoringService.js.map +1 -0
- package/dist/services/NotificationService.d.ts +132 -0
- package/dist/services/NotificationService.d.ts.map +1 -0
- package/dist/services/NotificationService.js +297 -0
- package/dist/services/NotificationService.js.map +1 -0
- package/dist/services/RateLimiter.d.ts +51 -0
- package/dist/services/RateLimiter.d.ts.map +1 -0
- package/dist/services/RateLimiter.js +141 -0
- package/dist/services/RateLimiter.js.map +1 -0
- package/dist/services/ValidationService.d.ts +49 -0
- package/dist/services/ValidationService.d.ts.map +1 -0
- package/dist/services/ValidationService.js +158 -0
- package/dist/services/ValidationService.js.map +1 -0
- package/dist/services/index.d.ts +12 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +12 -0
- package/dist/services/index.js.map +1 -0
- package/dist/types/Bot.d.ts +63 -0
- package/dist/types/Bot.d.ts.map +1 -0
- package/dist/types/Bot.js +5 -0
- package/dist/types/Bot.js.map +1 -0
- package/dist/types/Config.d.ts +57 -0
- package/dist/types/Config.d.ts.map +1 -0
- package/dist/types/Config.js +5 -0
- package/dist/types/Config.js.map +1 -0
- package/dist/types/Errors.d.ts +37 -0
- package/dist/types/Errors.d.ts.map +1 -0
- package/dist/types/Errors.js +34 -0
- package/dist/types/Errors.js.map +1 -0
- package/dist/types/SSH.d.ts +56 -0
- package/dist/types/SSH.d.ts.map +1 -0
- package/dist/types/SSH.js +6 -0
- package/dist/types/SSH.js.map +1 -0
- package/dist/types/Server.d.ts +39 -0
- package/dist/types/Server.d.ts.map +1 -0
- package/dist/types/Server.js +5 -0
- package/dist/types/Server.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/commandUtils.d.ts +25 -0
- package/dist/utils/commandUtils.d.ts.map +1 -0
- package/dist/utils/commandUtils.js +94 -0
- package/dist/utils/commandUtils.js.map +1 -0
- package/dist/utils/fileUtils.d.ts +40 -0
- package/dist/utils/fileUtils.d.ts.map +1 -0
- package/dist/utils/fileUtils.js +114 -0
- package/dist/utils/fileUtils.js.map +1 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/pathUtils.d.ts +40 -0
- package/dist/utils/pathUtils.d.ts.map +1 -0
- package/dist/utils/pathUtils.js +140 -0
- package/dist/utils/pathUtils.js.map +1 -0
- package/package.json +31 -5
- package/scripts/build.sh +20 -0
- package/scripts/postinstall.js +87 -0
- package/scripts/release.sh +22 -0
- package/scripts/setup-env.js +237 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 farhanzzg
|
|
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.
|
package/README.md
CHANGED
|
@@ -26,29 +26,47 @@ A secure, production-ready Telegram bot for remote SSH server management.
|
|
|
26
26
|
|
|
27
27
|
### Prerequisites
|
|
28
28
|
|
|
29
|
-
- Node.js 18+ (for development)
|
|
30
|
-
- Linux (for production deployment)
|
|
29
|
+
- Node.js 18+ (for npm/pnpm installation or development)
|
|
30
|
+
- Linux (for production deployment with systemd)
|
|
31
31
|
|
|
32
32
|
### Installation
|
|
33
33
|
|
|
34
|
-
####
|
|
34
|
+
#### Option 1: npm/pnpm Global (Recommended)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Install globally with npm
|
|
38
|
+
npm install -g telegram-ssh-bot
|
|
39
|
+
|
|
40
|
+
# Or with pnpm
|
|
41
|
+
pnpm add -g telegram-ssh-bot
|
|
42
|
+
|
|
43
|
+
# The .env file is auto-generated at ~/.config/telegram-ssh-bot/.env
|
|
44
|
+
# Edit with your credentials
|
|
45
|
+
nano ~/.config/telegram-ssh-bot/.env
|
|
46
|
+
|
|
47
|
+
# Start the bot
|
|
48
|
+
telegram-ssh-bot
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### Option 2: Binary Installation
|
|
35
52
|
|
|
36
53
|
```bash
|
|
37
54
|
# Download and install
|
|
38
55
|
./deploy/install.sh
|
|
39
56
|
|
|
40
|
-
#
|
|
57
|
+
# The .env file is auto-generated at ~/.config/telegram-ssh-bot/.env
|
|
58
|
+
# Edit with your credentials
|
|
41
59
|
nano ~/.config/telegram-ssh-bot/.env
|
|
42
60
|
|
|
43
|
-
# Start
|
|
61
|
+
# Start with systemd
|
|
44
62
|
./deploy/manage.sh start
|
|
45
63
|
```
|
|
46
64
|
|
|
47
|
-
#### From Source
|
|
65
|
+
#### Option 3: From Source
|
|
48
66
|
|
|
49
67
|
```bash
|
|
50
68
|
# Clone and build
|
|
51
|
-
git clone https://github.com/
|
|
69
|
+
git clone https://github.com/farhanzzg/telegram-ssh.git
|
|
52
70
|
cd telegram-ssh-bot
|
|
53
71
|
npm install
|
|
54
72
|
npm run build:binary
|
|
@@ -59,40 +77,103 @@ npm run build:binary
|
|
|
59
77
|
|
|
60
78
|
## Configuration
|
|
61
79
|
|
|
62
|
-
|
|
80
|
+
The configuration file is automatically generated at `~/.config/telegram-ssh-bot/.env` during installation. The encryption key is also auto-generated for you.
|
|
63
81
|
|
|
64
82
|
```bash
|
|
65
83
|
# Required
|
|
66
84
|
BOT_TOKEN=your_telegram_bot_token
|
|
67
85
|
BOT_CHAT_ID=your_chat_id
|
|
68
86
|
BOT_OWNER_IDS=123456789,987654321
|
|
69
|
-
ENCRYPTION_KEY=
|
|
87
|
+
ENCRYPTION_KEY=auto_generated_64_char_hex_key
|
|
70
88
|
|
|
71
|
-
#
|
|
72
|
-
|
|
89
|
+
# SSH Configuration
|
|
90
|
+
SSH_DEFAULT_PORT=22
|
|
91
|
+
SSH_CONNECTION_TIMEOUT=30000
|
|
73
92
|
SSH_COMMAND_TIMEOUT=30000
|
|
93
|
+
SSH_DEFAULT_PRIVATE_KEY_PATH=
|
|
94
|
+
|
|
95
|
+
# Rate Limiting
|
|
96
|
+
RATE_LIMIT_WINDOW_MS=60000
|
|
97
|
+
RATE_LIMIT_MAX_REQUESTS=100
|
|
98
|
+
|
|
99
|
+
# Backup
|
|
100
|
+
BACKUP_ENABLED=true
|
|
101
|
+
BACKUP_INTERVAL_MS=3600000
|
|
102
|
+
BACKUP_MAX_COUNT=10
|
|
103
|
+
|
|
104
|
+
# Monitoring
|
|
105
|
+
MONITORING_ENABLED=true
|
|
106
|
+
MONITORING_INTERVAL_MS=300000
|
|
107
|
+
|
|
108
|
+
# Logging (Optional)
|
|
109
|
+
LOG_LEVEL=info
|
|
74
110
|
```
|
|
75
111
|
|
|
76
112
|
### Configuration Options
|
|
77
113
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `BACKUP_INTERVAL` | No | Backup interval in ms (default: `3600000`) |
|
|
87
|
-
| `MAX_CONNECTIONS` | No | Max SSH connections in pool (default: `10`) |
|
|
114
|
+
#### Required Variables
|
|
115
|
+
|
|
116
|
+
| Variable | Description |
|
|
117
|
+
| ---------------- | --------------------------------------------------------------- |
|
|
118
|
+
| `BOT_TOKEN` | Telegram bot token from [@BotFather](https://t.me/botfather) |
|
|
119
|
+
| `BOT_CHAT_ID` | Primary chat ID for notifications |
|
|
120
|
+
| `BOT_OWNER_IDS` | Comma-separated list of authorized user IDs |
|
|
121
|
+
| `ENCRYPTION_KEY` | 64-character hex key for credential encryption (auto-generated) |
|
|
88
122
|
|
|
89
|
-
|
|
123
|
+
#### SSH Configuration
|
|
124
|
+
|
|
125
|
+
| Variable | Default | Description |
|
|
126
|
+
| ------------------------------ | --------------- | -------------------------------- |
|
|
127
|
+
| `SSH_DEFAULT_PORT` | `22` | Default SSH port for new servers |
|
|
128
|
+
| `SSH_CONNECTION_TIMEOUT` | `30000` | Connection timeout in ms |
|
|
129
|
+
| `SSH_COMMAND_TIMEOUT` | `30000` | Command execution timeout in ms |
|
|
130
|
+
| `SSH_DEFAULT_PRIVATE_KEY_PATH` | `~/.ssh/id_rsa` | Default private key path |
|
|
131
|
+
|
|
132
|
+
#### Rate Limiting
|
|
133
|
+
|
|
134
|
+
| Variable | Default | Description |
|
|
135
|
+
| ------------------------- | ------- | ---------------------------------- |
|
|
136
|
+
| `RATE_LIMIT_WINDOW_MS` | `60000` | Rate limit window in ms (1 minute) |
|
|
137
|
+
| `RATE_LIMIT_MAX_REQUESTS` | `100` | Max requests per window |
|
|
138
|
+
|
|
139
|
+
#### Backup Configuration
|
|
140
|
+
|
|
141
|
+
| Variable | Default | Description |
|
|
142
|
+
| -------------------- | --------- | ------------------------------ |
|
|
143
|
+
| `BACKUP_ENABLED` | `true` | Enable automatic backups |
|
|
144
|
+
| `BACKUP_INTERVAL_MS` | `3600000` | Backup interval in ms (1 hour) |
|
|
145
|
+
| `BACKUP_MAX_COUNT` | `10` | Maximum backup files to keep |
|
|
146
|
+
|
|
147
|
+
#### Monitoring Configuration
|
|
148
|
+
|
|
149
|
+
| Variable | Default | Description |
|
|
150
|
+
| ------------------------ | -------- | ----------------------------------- |
|
|
151
|
+
| `MONITORING_ENABLED` | `true` | Enable health monitoring |
|
|
152
|
+
| `MONITORING_INTERVAL_MS` | `300000` | Health check interval in ms (5 min) |
|
|
153
|
+
|
|
154
|
+
#### Optional Variables
|
|
155
|
+
|
|
156
|
+
| Variable | Default | Description |
|
|
157
|
+
| ------------- | ------- | ----------------------------------------------------- |
|
|
158
|
+
| `LOG_LEVEL` | `info` | Logging level: `error`, `warn`, `info`, `debug` |
|
|
159
|
+
| `BOT_API_URL` | - | Custom Telegram Bot API URL (for proxies/middlewares) |
|
|
160
|
+
|
|
161
|
+
### Auto-Generated Configuration
|
|
162
|
+
|
|
163
|
+
During installation, the following are automatically generated:
|
|
164
|
+
|
|
165
|
+
- **Configuration file**: `~/.config/telegram-ssh-bot/.env`
|
|
166
|
+
- **Encryption key**: Secure 64-character hex key (32 bytes)
|
|
167
|
+
|
|
168
|
+
If you need to regenerate the encryption key:
|
|
90
169
|
|
|
91
170
|
```bash
|
|
92
171
|
# Generate a secure 64-character hex key
|
|
93
172
|
openssl rand -hex 32
|
|
94
173
|
```
|
|
95
174
|
|
|
175
|
+
> **Note**: Changing the encryption key will make previously encrypted credentials unreadable. You'll need to re-add your servers after changing the key.
|
|
176
|
+
|
|
96
177
|
## Usage
|
|
97
178
|
|
|
98
179
|
### Bot Commands
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# Telegram SSH Bot Configuration
|
|
3
|
+
# =============================================================================
|
|
4
|
+
# Copy this file to ~/.config/telegram-ssh-bot/.env and fill in your values
|
|
5
|
+
# =============================================================================
|
|
6
|
+
|
|
7
|
+
# -----------------------------------------------------------------------------
|
|
8
|
+
# Telegram Bot Configuration
|
|
9
|
+
# -----------------------------------------------------------------------------
|
|
10
|
+
# Your Telegram bot token obtained from @BotFather
|
|
11
|
+
BOT_TOKEN=your_telegram_bot_token_here
|
|
12
|
+
|
|
13
|
+
# The default chat ID for notifications (your personal chat or a group)
|
|
14
|
+
# Use @userinfobot to get your chat ID
|
|
15
|
+
BOT_CHAT_ID=your_chat_id_here
|
|
16
|
+
|
|
17
|
+
# Comma-separated list of Telegram user IDs who can control the bot
|
|
18
|
+
# These users will have full access to all bot commands
|
|
19
|
+
BOT_OWNER_IDS=123456789,987654321
|
|
20
|
+
|
|
21
|
+
# -----------------------------------------------------------------------------
|
|
22
|
+
# Security
|
|
23
|
+
# -----------------------------------------------------------------------------
|
|
24
|
+
# Encryption key for sensitive data (64 hex characters = 32 bytes)
|
|
25
|
+
# A secure key will be auto-generated during installation
|
|
26
|
+
# You can generate a new one with: openssl rand -hex 32
|
|
27
|
+
ENCRYPTION_KEY=
|
|
28
|
+
|
|
29
|
+
# -----------------------------------------------------------------------------
|
|
30
|
+
# SSH Configuration
|
|
31
|
+
# -----------------------------------------------------------------------------
|
|
32
|
+
# Default SSH port for new server connections
|
|
33
|
+
SSH_DEFAULT_PORT=22
|
|
34
|
+
|
|
35
|
+
# Timeout for establishing SSH connections (in milliseconds)
|
|
36
|
+
SSH_CONNECTION_TIMEOUT=30000
|
|
37
|
+
|
|
38
|
+
# Timeout for executing SSH commands (in milliseconds)
|
|
39
|
+
SSH_COMMAND_TIMEOUT=30000
|
|
40
|
+
|
|
41
|
+
# Default path to SSH private key (leave empty to use ~/.ssh/id_rsa)
|
|
42
|
+
# Example: /home/user/.ssh/custom_key
|
|
43
|
+
SSH_DEFAULT_PRIVATE_KEY_PATH=
|
|
44
|
+
|
|
45
|
+
# -----------------------------------------------------------------------------
|
|
46
|
+
# Rate Limiting
|
|
47
|
+
# -----------------------------------------------------------------------------
|
|
48
|
+
# Time window for rate limiting (in milliseconds)
|
|
49
|
+
# Default: 60000 (1 minute)
|
|
50
|
+
RATE_LIMIT_WINDOW_MS=60000
|
|
51
|
+
|
|
52
|
+
# Maximum number of requests allowed within the rate limit window
|
|
53
|
+
RATE_LIMIT_MAX_REQUESTS=100
|
|
54
|
+
|
|
55
|
+
# -----------------------------------------------------------------------------
|
|
56
|
+
# Backup Configuration
|
|
57
|
+
# -----------------------------------------------------------------------------
|
|
58
|
+
# Enable automatic backup of server configurations
|
|
59
|
+
BACKUP_ENABLED=true
|
|
60
|
+
|
|
61
|
+
# Interval between automatic backups (in milliseconds)
|
|
62
|
+
# Default: 3600000 (1 hour)
|
|
63
|
+
BACKUP_INTERVAL_MS=3600000
|
|
64
|
+
|
|
65
|
+
# Maximum number of backup files to keep
|
|
66
|
+
# Older backups will be automatically deleted
|
|
67
|
+
BACKUP_MAX_COUNT=10
|
|
68
|
+
|
|
69
|
+
# -----------------------------------------------------------------------------
|
|
70
|
+
# Monitoring Configuration
|
|
71
|
+
# -----------------------------------------------------------------------------
|
|
72
|
+
# Enable automatic server health monitoring
|
|
73
|
+
MONITORING_ENABLED=true
|
|
74
|
+
|
|
75
|
+
# Interval between health checks (in milliseconds)
|
|
76
|
+
# Default: 300000 (5 minutes)
|
|
77
|
+
MONITORING_INTERVAL_MS=300000
|
|
78
|
+
|
|
79
|
+
# -----------------------------------------------------------------------------
|
|
80
|
+
# Logging Configuration (Optional)
|
|
81
|
+
# -----------------------------------------------------------------------------
|
|
82
|
+
# Log level: debug, info, warn, error
|
|
83
|
+
# LOG_LEVEL=info
|
|
84
|
+
|
|
85
|
+
# Log file name (stored in config directory)
|
|
86
|
+
# LOG_FILE=telegram-ssh-bot.log
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader module with hot reload support
|
|
3
|
+
*/
|
|
4
|
+
import "dotenv/config";
|
|
5
|
+
import { EventEmitter } from "events";
|
|
6
|
+
import type { AppConfig } from "../types/index.js";
|
|
7
|
+
/**
|
|
8
|
+
* Configuration reload event
|
|
9
|
+
*/
|
|
10
|
+
export interface ConfigReloadEvent {
|
|
11
|
+
oldConfig: AppConfig;
|
|
12
|
+
newConfig: AppConfig;
|
|
13
|
+
changedKeys: string[];
|
|
14
|
+
timestamp: Date;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Configuration reloader for hot reload support
|
|
18
|
+
*/
|
|
19
|
+
export declare class ConfigReloader extends EventEmitter {
|
|
20
|
+
private currentConfig;
|
|
21
|
+
private readonly envPath;
|
|
22
|
+
private watcher;
|
|
23
|
+
private reloadDebounce;
|
|
24
|
+
private reloadPromise;
|
|
25
|
+
constructor(initialConfig: AppConfig, envPath?: string);
|
|
26
|
+
/**
|
|
27
|
+
* Start watching for configuration changes
|
|
28
|
+
*/
|
|
29
|
+
startWatching(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Stop watching for configuration changes
|
|
32
|
+
*/
|
|
33
|
+
stopWatching(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get current configuration
|
|
36
|
+
*/
|
|
37
|
+
getConfig(): AppConfig;
|
|
38
|
+
/**
|
|
39
|
+
* Schedule a configuration reload (debounced)
|
|
40
|
+
*/
|
|
41
|
+
private scheduleReload;
|
|
42
|
+
/**
|
|
43
|
+
* Reload configuration from environment
|
|
44
|
+
* Uses promise-based locking to prevent race conditions
|
|
45
|
+
*/
|
|
46
|
+
reload(): Promise<boolean>;
|
|
47
|
+
/**
|
|
48
|
+
* Internal reload implementation
|
|
49
|
+
*/
|
|
50
|
+
private doReload;
|
|
51
|
+
/**
|
|
52
|
+
* Load .env file manually
|
|
53
|
+
*/
|
|
54
|
+
private loadEnvFile;
|
|
55
|
+
/**
|
|
56
|
+
* Find changed keys between two configurations
|
|
57
|
+
*/
|
|
58
|
+
private findChangedKeys;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Load and validate configuration from environment
|
|
62
|
+
*/
|
|
63
|
+
export declare function loadConfig(): Promise<AppConfig>;
|
|
64
|
+
/**
|
|
65
|
+
* Validate that owner IDs are configured
|
|
66
|
+
*/
|
|
67
|
+
export declare function validateOwnerIds(config: AppConfig): void;
|
|
68
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAItC,OAAO,KAAK,EACV,SAAS,EAIV,MAAM,mBAAmB,CAAC;AAI3B;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,OAAO,CAAyC;IACxD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,aAAa,CAAiC;gBAE1C,aAAa,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM;IAMtD;;OAEG;IACH,aAAa,IAAI,IAAI;IAqBrB;;OAEG;IACH,YAAY,IAAI,IAAI;IAWpB;;OAEG;IACH,SAAS,IAAI,SAAS;IAItB;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;;OAGG;IACG,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAgBhC;;OAEG;YACW,QAAQ;IAqCtB;;OAEG;YACW,WAAW;IAqBzB;;OAEG;IACH,OAAO,CAAC,eAAe;CAiCxB;AA8ED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC,CAsFrD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAMxD"}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader module with hot reload support
|
|
3
|
+
*/
|
|
4
|
+
import "dotenv/config";
|
|
5
|
+
import { EventEmitter } from "events";
|
|
6
|
+
import { existsSync, watch } from "fs";
|
|
7
|
+
import * as path from "path";
|
|
8
|
+
import { InvalidConfigError, MissingConfigError } from "../errors/index.js";
|
|
9
|
+
import { expandTilde } from "../utils/pathUtils.js";
|
|
10
|
+
import { configSchema } from "./schema.js";
|
|
11
|
+
/**
|
|
12
|
+
* Configuration reloader for hot reload support
|
|
13
|
+
*/
|
|
14
|
+
export class ConfigReloader extends EventEmitter {
|
|
15
|
+
currentConfig;
|
|
16
|
+
envPath;
|
|
17
|
+
watcher = null;
|
|
18
|
+
reloadDebounce = null;
|
|
19
|
+
reloadPromise = null;
|
|
20
|
+
constructor(initialConfig, envPath) {
|
|
21
|
+
super();
|
|
22
|
+
this.currentConfig = initialConfig;
|
|
23
|
+
this.envPath = envPath ?? path.resolve(process.cwd(), ".env");
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Start watching for configuration changes
|
|
27
|
+
*/
|
|
28
|
+
startWatching() {
|
|
29
|
+
if (this.watcher) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Check if .env file exists
|
|
33
|
+
if (!existsSync(this.envPath)) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
this.watcher = watch(this.envPath, (eventType) => {
|
|
37
|
+
if (eventType === "change") {
|
|
38
|
+
this.scheduleReload();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
this.watcher.on("error", (error) => {
|
|
42
|
+
this.emit("error", error);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Stop watching for configuration changes
|
|
47
|
+
*/
|
|
48
|
+
stopWatching() {
|
|
49
|
+
if (this.watcher) {
|
|
50
|
+
this.watcher.close();
|
|
51
|
+
this.watcher = null;
|
|
52
|
+
}
|
|
53
|
+
if (this.reloadDebounce) {
|
|
54
|
+
clearTimeout(this.reloadDebounce);
|
|
55
|
+
this.reloadDebounce = null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get current configuration
|
|
60
|
+
*/
|
|
61
|
+
getConfig() {
|
|
62
|
+
return this.currentConfig;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Schedule a configuration reload (debounced)
|
|
66
|
+
*/
|
|
67
|
+
scheduleReload() {
|
|
68
|
+
if (this.reloadDebounce) {
|
|
69
|
+
clearTimeout(this.reloadDebounce);
|
|
70
|
+
}
|
|
71
|
+
this.reloadDebounce = setTimeout(() => {
|
|
72
|
+
this.reload();
|
|
73
|
+
}, 1000); // 1 second debounce
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Reload configuration from environment
|
|
77
|
+
* Uses promise-based locking to prevent race conditions
|
|
78
|
+
*/
|
|
79
|
+
async reload() {
|
|
80
|
+
// If already reloading, return the existing promise
|
|
81
|
+
if (this.reloadPromise) {
|
|
82
|
+
return this.reloadPromise;
|
|
83
|
+
}
|
|
84
|
+
// Create a new reload operation
|
|
85
|
+
this.reloadPromise = this.doReload();
|
|
86
|
+
try {
|
|
87
|
+
return await this.reloadPromise;
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
this.reloadPromise = null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Internal reload implementation
|
|
95
|
+
*/
|
|
96
|
+
async doReload() {
|
|
97
|
+
try {
|
|
98
|
+
// Re-read .env file
|
|
99
|
+
const result = await this.loadEnvFile();
|
|
100
|
+
if (!result.success) {
|
|
101
|
+
this.emit("error", new Error(`Failed to reload .env: ${result.error}`));
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
// Load new configuration
|
|
105
|
+
const newConfig = await loadConfig();
|
|
106
|
+
const changedKeys = this.findChangedKeys(this.currentConfig, newConfig);
|
|
107
|
+
if (changedKeys.length === 0) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
const event = {
|
|
111
|
+
oldConfig: this.currentConfig,
|
|
112
|
+
newConfig,
|
|
113
|
+
changedKeys,
|
|
114
|
+
timestamp: new Date(),
|
|
115
|
+
};
|
|
116
|
+
this.currentConfig = newConfig;
|
|
117
|
+
this.emit("reload", event);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
this.emit("error", error instanceof Error ? error : new Error(String(error)));
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Load .env file manually
|
|
127
|
+
*/
|
|
128
|
+
async loadEnvFile() {
|
|
129
|
+
try {
|
|
130
|
+
if (!existsSync(this.envPath)) {
|
|
131
|
+
return { success: false, error: ".env file not found" };
|
|
132
|
+
}
|
|
133
|
+
// Re-import dotenv to reload
|
|
134
|
+
// Note: This is a simplified approach; in production you might want
|
|
135
|
+
// to manually parse the .env file and update process.env
|
|
136
|
+
const { config } = await import("dotenv");
|
|
137
|
+
config({ path: this.envPath, override: true });
|
|
138
|
+
return { success: true };
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
return {
|
|
142
|
+
success: false,
|
|
143
|
+
error: error instanceof Error ? error.message : String(error),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Find changed keys between two configurations
|
|
149
|
+
*/
|
|
150
|
+
findChangedKeys(old, new_) {
|
|
151
|
+
const changed = [];
|
|
152
|
+
// Compare telegram config
|
|
153
|
+
if (old.telegram.token !== new_.telegram.token)
|
|
154
|
+
changed.push("telegram.token");
|
|
155
|
+
if (old.telegram.chatId !== new_.telegram.chatId)
|
|
156
|
+
changed.push("telegram.chatId");
|
|
157
|
+
if (JSON.stringify(old.telegram.ownerIds) !==
|
|
158
|
+
JSON.stringify(new_.telegram.ownerIds)) {
|
|
159
|
+
changed.push("telegram.ownerIds");
|
|
160
|
+
}
|
|
161
|
+
// Compare security config
|
|
162
|
+
if (old.security.encryptionKey !== new_.security.encryptionKey) {
|
|
163
|
+
changed.push("security.encryptionKey");
|
|
164
|
+
}
|
|
165
|
+
if (old.security.rateLimit.enabled !== new_.security.rateLimit.enabled) {
|
|
166
|
+
changed.push("security.rateLimit.enabled");
|
|
167
|
+
}
|
|
168
|
+
if (old.security.rateLimit.maxRequests !== new_.security.rateLimit.maxRequests) {
|
|
169
|
+
changed.push("security.rateLimit.maxRequests");
|
|
170
|
+
}
|
|
171
|
+
// Compare logging config
|
|
172
|
+
if (old.logging.level !== new_.logging.level)
|
|
173
|
+
changed.push("logging.level");
|
|
174
|
+
return changed;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Required environment variable keys
|
|
179
|
+
*/
|
|
180
|
+
const REQUIRED_ENV_KEYS = ["BOT_TOKEN", "BOT_CHAT_ID", "ENCRYPTION_KEY"];
|
|
181
|
+
/**
|
|
182
|
+
* Collect all missing required environment variables
|
|
183
|
+
*/
|
|
184
|
+
function getMissingEnvKeys() {
|
|
185
|
+
const missing = [];
|
|
186
|
+
for (const key of REQUIRED_ENV_KEYS) {
|
|
187
|
+
if (!process.env[key]) {
|
|
188
|
+
missing.push(key);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return missing;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get required environment variable or throw error
|
|
195
|
+
*/
|
|
196
|
+
function getRequiredEnv(key) {
|
|
197
|
+
const value = process.env[key];
|
|
198
|
+
if (!value) {
|
|
199
|
+
throw new MissingConfigError(key);
|
|
200
|
+
}
|
|
201
|
+
return value;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Get optional environment variable with default
|
|
205
|
+
*/
|
|
206
|
+
function getOptionalEnv(key, defaultValue) {
|
|
207
|
+
return process.env[key] ?? defaultValue;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Parse comma-separated string to array
|
|
211
|
+
*/
|
|
212
|
+
function parseArray(value, defaultValue) {
|
|
213
|
+
if (!value) {
|
|
214
|
+
return defaultValue;
|
|
215
|
+
}
|
|
216
|
+
return value
|
|
217
|
+
.split(",")
|
|
218
|
+
.map((s) => s.trim())
|
|
219
|
+
.filter((s) => s.length > 0);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Parse boolean from string
|
|
223
|
+
*/
|
|
224
|
+
function parseBoolean(value, defaultValue) {
|
|
225
|
+
if (value === undefined) {
|
|
226
|
+
return defaultValue;
|
|
227
|
+
}
|
|
228
|
+
return value.toLowerCase() === "true" || value === "1";
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Parse number from string
|
|
232
|
+
*/
|
|
233
|
+
function parseNumber(value, defaultValue) {
|
|
234
|
+
if (value === undefined) {
|
|
235
|
+
return defaultValue;
|
|
236
|
+
}
|
|
237
|
+
const parsed = parseInt(value, 10);
|
|
238
|
+
return isNaN(parsed) ? defaultValue : parsed;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Load and validate configuration from environment
|
|
242
|
+
*/
|
|
243
|
+
export async function loadConfig() {
|
|
244
|
+
// Check for all missing required environment variables upfront
|
|
245
|
+
const missingKeys = getMissingEnvKeys();
|
|
246
|
+
if (missingKeys.length > 0) {
|
|
247
|
+
throw new InvalidConfigError(`Missing required environment variables: ${missingKeys.join(", ")}. ` +
|
|
248
|
+
`Please set these in your .env file or environment.`);
|
|
249
|
+
}
|
|
250
|
+
// Build config from environment variables
|
|
251
|
+
const envConfig = {
|
|
252
|
+
telegram: {
|
|
253
|
+
token: getRequiredEnv("BOT_TOKEN"),
|
|
254
|
+
chatId: getRequiredEnv("BOT_CHAT_ID"),
|
|
255
|
+
ownerIds: parseArray(process.env.BOT_OWNER_IDS, []),
|
|
256
|
+
polling: parseBoolean(process.env.BOT_POLLING, true),
|
|
257
|
+
},
|
|
258
|
+
security: {
|
|
259
|
+
encryptionKey: getRequiredEnv("ENCRYPTION_KEY"),
|
|
260
|
+
rateLimit: {
|
|
261
|
+
enabled: parseBoolean(process.env.RATE_LIMIT_ENABLED, true),
|
|
262
|
+
windowMs: parseNumber(process.env.RATE_LIMIT_WINDOW_MS, 60000),
|
|
263
|
+
maxRequests: parseNumber(process.env.RATE_LIMIT_MAX_REQUESTS, 30),
|
|
264
|
+
skipFailedRequests: parseBoolean(process.env.RATE_LIMIT_SKIP_FAILED, false),
|
|
265
|
+
},
|
|
266
|
+
allowedCommands: parseArray(process.env.ALLOWED_COMMANDS, []),
|
|
267
|
+
blockedCommands: parseArray(process.env.BLOCKED_COMMANDS, []),
|
|
268
|
+
},
|
|
269
|
+
ssh: {
|
|
270
|
+
defaultPrivateKeyPath: expandTilde(getOptionalEnv("SSH_DEFAULT_PRIVATE_KEY_PATH", "~/.ssh/id_rsa")),
|
|
271
|
+
defaultPort: parseNumber(process.env.SSH_DEFAULT_PORT, 22),
|
|
272
|
+
connectionTimeout: parseNumber(process.env.SSH_CONNECTION_TIMEOUT, 30000),
|
|
273
|
+
keepaliveInterval: parseNumber(process.env.SSH_KEEPALIVE_INTERVAL, 10000),
|
|
274
|
+
maxConnections: parseNumber(process.env.SSH_MAX_CONNECTIONS, 5),
|
|
275
|
+
commandTimeout: parseNumber(process.env.SSH_COMMAND_TIMEOUT, 60000),
|
|
276
|
+
},
|
|
277
|
+
logging: {
|
|
278
|
+
level: getOptionalEnv("LOG_LEVEL", "info"),
|
|
279
|
+
format: getOptionalEnv("LOG_FORMAT", "json"),
|
|
280
|
+
file: process.env.LOG_FILE,
|
|
281
|
+
},
|
|
282
|
+
storage: {
|
|
283
|
+
serversFile: getOptionalEnv("STORAGE_SERVERS_FILE", "./conf/servers.json"),
|
|
284
|
+
encryptionEnabled: parseBoolean(process.env.STORAGE_ENCRYPTION_ENABLED, true),
|
|
285
|
+
},
|
|
286
|
+
backup: {
|
|
287
|
+
enabled: parseBoolean(process.env.BACKUP_ENABLED, true),
|
|
288
|
+
intervalMs: parseNumber(process.env.BACKUP_INTERVAL_MS, 3600000),
|
|
289
|
+
maxCount: parseNumber(process.env.BACKUP_MAX_COUNT, 10),
|
|
290
|
+
},
|
|
291
|
+
monitoring: {
|
|
292
|
+
enabled: parseBoolean(process.env.MONITORING_ENABLED, true),
|
|
293
|
+
intervalMs: parseNumber(process.env.MONITORING_INTERVAL_MS, 300000),
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
// Validate configuration
|
|
297
|
+
const { error, value } = configSchema.validate(envConfig, {
|
|
298
|
+
abortEarly: false,
|
|
299
|
+
allowUnknown: false,
|
|
300
|
+
});
|
|
301
|
+
if (error) {
|
|
302
|
+
const messages = error.details.map((d) => d.message).join(", ");
|
|
303
|
+
throw new InvalidConfigError(`Configuration validation failed: ${messages}`);
|
|
304
|
+
}
|
|
305
|
+
return value;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Validate that owner IDs are configured
|
|
309
|
+
*/
|
|
310
|
+
export function validateOwnerIds(config) {
|
|
311
|
+
if (config.telegram.ownerIds.length === 0) {
|
|
312
|
+
throw new InvalidConfigError("At least one owner ID must be configured via BOT_OWNER_IDS");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"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"}
|