suthep 0.1.0-beta.1
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/.editorconfig +17 -0
- package/.prettierignore +6 -0
- package/.prettierrc +7 -0
- package/.vscode/settings.json +19 -0
- package/LICENSE +21 -0
- package/README.md +217 -0
- package/dist/commands/deploy.js +318 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/init.js +188 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/setup.js +90 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/certbot.js +64 -0
- package/dist/utils/certbot.js.map +1 -0
- package/dist/utils/config-loader.js +95 -0
- package/dist/utils/config-loader.js.map +1 -0
- package/dist/utils/deployment.js +76 -0
- package/dist/utils/deployment.js.map +1 -0
- package/dist/utils/docker.js +393 -0
- package/dist/utils/docker.js.map +1 -0
- package/dist/utils/nginx.js +303 -0
- package/dist/utils/nginx.js.map +1 -0
- package/docs/README.md +95 -0
- package/docs/TRANSLATIONS.md +211 -0
- package/docs/en/README.md +76 -0
- package/docs/en/api-reference.md +545 -0
- package/docs/en/architecture.md +369 -0
- package/docs/en/commands.md +273 -0
- package/docs/en/configuration.md +347 -0
- package/docs/en/developer-guide.md +588 -0
- package/docs/en/docker-ports-config.md +333 -0
- package/docs/en/examples.md +537 -0
- package/docs/en/getting-started.md +202 -0
- package/docs/en/port-binding.md +268 -0
- package/docs/en/troubleshooting.md +441 -0
- package/docs/th/README.md +64 -0
- package/docs/th/commands.md +202 -0
- package/docs/th/configuration.md +325 -0
- package/docs/th/getting-started.md +203 -0
- package/example/README.md +85 -0
- package/example/docker-compose.yml +76 -0
- package/example/docker-ports-example.yml +81 -0
- package/example/muacle.yml +47 -0
- package/example/port-binding-example.yml +45 -0
- package/example/suthep.yml +46 -0
- package/example/suthep=1.yml +46 -0
- package/package.json +45 -0
- package/src/commands/deploy.ts +405 -0
- package/src/commands/init.ts +214 -0
- package/src/commands/setup.ts +112 -0
- package/src/index.ts +42 -0
- package/src/types/config.ts +52 -0
- package/src/utils/certbot.ts +144 -0
- package/src/utils/config-loader.ts +121 -0
- package/src/utils/deployment.ts +157 -0
- package/src/utils/docker.ts +755 -0
- package/src/utils/nginx.ts +326 -0
- package/suthep-0.1.1.tgz +0 -0
- package/suthep.example.yml +98 -0
- package/test +0 -0
- package/todo.md +6 -0
- package/tsconfig.json +26 -0
- package/vite.config.ts +46 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Suthep Documentation
|
|
2
|
+
|
|
3
|
+
Welcome to the Suthep documentation! This guide will help you understand and use Suthep, a powerful CLI tool for deploying projects with automatic Nginx reverse proxy setup, HTTPS with Certbot, and zero-downtime deployments.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
### User Documentation
|
|
8
|
+
|
|
9
|
+
1. [Getting Started](./getting-started.md) - Installation and quick start guide
|
|
10
|
+
2. [Configuration Reference](./configuration.md) - Complete configuration file reference
|
|
11
|
+
3. [Commands Reference](./commands.md) - Detailed command documentation
|
|
12
|
+
4. [Port Binding Guide](./port-binding.md) - How Docker port binding works
|
|
13
|
+
5. [Docker Ports Configuration](./docker-ports-config.md) - How to configure ports in suthep.yml
|
|
14
|
+
6. [Examples](./examples.md) - Real-world deployment examples
|
|
15
|
+
7. [Troubleshooting](./troubleshooting.md) - Common issues and solutions
|
|
16
|
+
|
|
17
|
+
### Developer Documentation
|
|
18
|
+
|
|
19
|
+
8. [Developer Guide](./developer-guide.md) - **Complete guide for developers and contributors**
|
|
20
|
+
9. [Architecture](./architecture.md) - How Suthep works under the hood
|
|
21
|
+
10. [API Reference](./api-reference.md) - Internal utilities and functions
|
|
22
|
+
|
|
23
|
+
## What is Suthep?
|
|
24
|
+
|
|
25
|
+
Suthep is a deployment automation tool that simplifies the process of deploying web services with:
|
|
26
|
+
|
|
27
|
+
- ✅ **Automatic Nginx reverse proxy setup** - No manual Nginx configuration needed
|
|
28
|
+
- ✅ **Automatic HTTPS with Certbot** - Free SSL certificates from Let's Encrypt
|
|
29
|
+
- ✅ **Zero-downtime deployment** - Rolling and blue-green deployment strategies
|
|
30
|
+
- ✅ **Docker container support** - Deploy containerized applications easily
|
|
31
|
+
- ✅ **Multiple domain/subdomain support** - One service, multiple domains
|
|
32
|
+
- ✅ **Health check integration** - Ensure services are healthy before going live
|
|
33
|
+
- ✅ **YAML-based configuration** - Simple, declarative configuration
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Install dependencies
|
|
39
|
+
npm install
|
|
40
|
+
npm link
|
|
41
|
+
|
|
42
|
+
# Initialize configuration
|
|
43
|
+
suthep init
|
|
44
|
+
|
|
45
|
+
# Setup prerequisites
|
|
46
|
+
suthep setup
|
|
47
|
+
|
|
48
|
+
# Deploy your services
|
|
49
|
+
suthep deploy
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Requirements
|
|
53
|
+
|
|
54
|
+
- Node.js 16+
|
|
55
|
+
- Nginx (installed via `suthep setup`)
|
|
56
|
+
- Certbot (installed via `suthep setup`)
|
|
57
|
+
- Docker (optional, for Docker-based services)
|
|
58
|
+
- sudo access (for Nginx and Certbot operations)
|
|
59
|
+
|
|
60
|
+
## Cost Optimization
|
|
61
|
+
|
|
62
|
+
Suthep helps save costs on VMs by:
|
|
63
|
+
- Efficiently managing multiple services on a single server
|
|
64
|
+
- Automatic reverse proxy setup reduces manual configuration time
|
|
65
|
+
- Zero-downtime deployments reduce service interruptions
|
|
66
|
+
- Health checks ensure service reliability
|
|
67
|
+
|
|
68
|
+
## Other Languages / ภาษาอื่นๆ
|
|
69
|
+
|
|
70
|
+
- [English](./README.md) - English documentation (current)
|
|
71
|
+
- [ไทย](../th/README.md) - Thai documentation / เอกสารภาษาไทย
|
|
72
|
+
- [Back to Main Documentation](../README.md) - Return to language selection
|
|
73
|
+
|
|
74
|
+
## License
|
|
75
|
+
|
|
76
|
+
[MIT](../../LICENSE)
|
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
This document provides detailed reference for Suthep's internal APIs and utility functions.
|
|
4
|
+
|
|
5
|
+
## Configuration Loader
|
|
6
|
+
|
|
7
|
+
**File**: `src/utils/config-loader.ts`
|
|
8
|
+
|
|
9
|
+
### `loadConfig(filePath: string): Promise<DeployConfig>`
|
|
10
|
+
|
|
11
|
+
Loads and parses a YAML configuration file.
|
|
12
|
+
|
|
13
|
+
**Parameters**:
|
|
14
|
+
- `filePath`: Path to the configuration file
|
|
15
|
+
|
|
16
|
+
**Returns**: Promise resolving to `DeployConfig` object
|
|
17
|
+
|
|
18
|
+
**Throws**: Error if file doesn't exist or is invalid
|
|
19
|
+
|
|
20
|
+
**Example**:
|
|
21
|
+
```typescript
|
|
22
|
+
const config = await loadConfig('suthep.yml');
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### `saveConfig(filePath: string, config: DeployConfig): Promise<void>`
|
|
26
|
+
|
|
27
|
+
Saves a configuration object to a YAML file.
|
|
28
|
+
|
|
29
|
+
**Parameters**:
|
|
30
|
+
- `filePath`: Path where to save the configuration
|
|
31
|
+
- `config`: Configuration object to save
|
|
32
|
+
|
|
33
|
+
**Returns**: Promise that resolves when file is saved
|
|
34
|
+
|
|
35
|
+
**Example**:
|
|
36
|
+
```typescript
|
|
37
|
+
await saveConfig('suthep.yml', config);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Docker Utilities
|
|
41
|
+
|
|
42
|
+
**File**: `src/utils/docker.ts`
|
|
43
|
+
|
|
44
|
+
### `startDockerContainer(service: ServiceConfig): Promise<void>`
|
|
45
|
+
|
|
46
|
+
Starts or connects to a Docker container for a service.
|
|
47
|
+
|
|
48
|
+
**Parameters**:
|
|
49
|
+
- `service`: Service configuration with Docker settings
|
|
50
|
+
|
|
51
|
+
**Returns**: Promise that resolves when container is running
|
|
52
|
+
|
|
53
|
+
**Throws**: Error if container can't be started
|
|
54
|
+
|
|
55
|
+
**Behavior**:
|
|
56
|
+
- If container exists and is running: Does nothing
|
|
57
|
+
- If container exists but is stopped: Starts it
|
|
58
|
+
- If container doesn't exist and image provided: Creates and runs new container
|
|
59
|
+
- If container doesn't exist and no image: Throws error
|
|
60
|
+
|
|
61
|
+
**Example**:
|
|
62
|
+
```typescript
|
|
63
|
+
await startDockerContainer(service);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### `stopDockerContainer(containerName: string): Promise<void>`
|
|
67
|
+
|
|
68
|
+
Stops a running Docker container.
|
|
69
|
+
|
|
70
|
+
**Parameters**:
|
|
71
|
+
- `containerName`: Name of the container to stop
|
|
72
|
+
|
|
73
|
+
**Returns**: Promise that resolves when container is stopped
|
|
74
|
+
|
|
75
|
+
**Throws**: Error if container can't be stopped
|
|
76
|
+
|
|
77
|
+
**Example**:
|
|
78
|
+
```typescript
|
|
79
|
+
await stopDockerContainer('my-container');
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### `removeDockerContainer(containerName: string): Promise<void>`
|
|
83
|
+
|
|
84
|
+
Removes a Docker container (force stop and remove).
|
|
85
|
+
|
|
86
|
+
**Parameters**:
|
|
87
|
+
- `containerName`: Name of the container to remove
|
|
88
|
+
|
|
89
|
+
**Returns**: Promise that resolves when container is removed
|
|
90
|
+
|
|
91
|
+
**Throws**: Error if container can't be removed
|
|
92
|
+
|
|
93
|
+
**Example**:
|
|
94
|
+
```typescript
|
|
95
|
+
await removeDockerContainer('my-container');
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `isContainerRunning(containerName: string): Promise<boolean>`
|
|
99
|
+
|
|
100
|
+
Checks if a Docker container is currently running.
|
|
101
|
+
|
|
102
|
+
**Parameters**:
|
|
103
|
+
- `containerName`: Name of the container to check
|
|
104
|
+
|
|
105
|
+
**Returns**: Promise resolving to `true` if running, `false` otherwise
|
|
106
|
+
|
|
107
|
+
**Example**:
|
|
108
|
+
```typescript
|
|
109
|
+
const running = await isContainerRunning('my-container');
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### `getContainerLogs(containerName: string, lines?: number): Promise<string>`
|
|
113
|
+
|
|
114
|
+
Retrieves logs from a Docker container.
|
|
115
|
+
|
|
116
|
+
**Parameters**:
|
|
117
|
+
- `containerName`: Name of the container
|
|
118
|
+
- `lines`: Number of log lines to retrieve (default: 100)
|
|
119
|
+
|
|
120
|
+
**Returns**: Promise resolving to log output as string
|
|
121
|
+
|
|
122
|
+
**Throws**: Error if logs can't be retrieved
|
|
123
|
+
|
|
124
|
+
**Example**:
|
|
125
|
+
```typescript
|
|
126
|
+
const logs = await getContainerLogs('my-container', 50);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### `inspectContainer(containerName: string): Promise<any>`
|
|
130
|
+
|
|
131
|
+
Inspects a Docker container and returns its configuration.
|
|
132
|
+
|
|
133
|
+
**Parameters**:
|
|
134
|
+
- `containerName`: Name of the container to inspect
|
|
135
|
+
|
|
136
|
+
**Returns**: Promise resolving to container inspection object
|
|
137
|
+
|
|
138
|
+
**Throws**: Error if container can't be inspected
|
|
139
|
+
|
|
140
|
+
**Example**:
|
|
141
|
+
```typescript
|
|
142
|
+
const info = await inspectContainer('my-container');
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Nginx Utilities
|
|
146
|
+
|
|
147
|
+
**File**: `src/utils/nginx.ts`
|
|
148
|
+
|
|
149
|
+
### `generateNginxConfig(service: ServiceConfig, withHttps: boolean): string`
|
|
150
|
+
|
|
151
|
+
Generates Nginx server block configuration for a service.
|
|
152
|
+
|
|
153
|
+
**Parameters**:
|
|
154
|
+
- `service`: Service configuration
|
|
155
|
+
- `withHttps`: Whether to include HTTPS configuration
|
|
156
|
+
|
|
157
|
+
**Returns**: Nginx configuration as string
|
|
158
|
+
|
|
159
|
+
**Example**:
|
|
160
|
+
```typescript
|
|
161
|
+
const config = generateNginxConfig(service, true);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Generated Configuration Includes**:
|
|
165
|
+
- Upstream definition
|
|
166
|
+
- HTTP server (with HTTPS redirect if enabled)
|
|
167
|
+
- HTTPS server (if enabled)
|
|
168
|
+
- SSL configuration (if enabled)
|
|
169
|
+
- Proxy settings
|
|
170
|
+
- Health check endpoint (if configured)
|
|
171
|
+
- Logging configuration
|
|
172
|
+
|
|
173
|
+
### `enableSite(siteName: string, configPath: string): Promise<void>`
|
|
174
|
+
|
|
175
|
+
Enables an Nginx site by creating a symbolic link in `sites-enabled`.
|
|
176
|
+
|
|
177
|
+
**Parameters**:
|
|
178
|
+
- `siteName`: Name of the site (without .conf extension)
|
|
179
|
+
- `configPath`: Path to sites-available directory
|
|
180
|
+
|
|
181
|
+
**Returns**: Promise that resolves when site is enabled
|
|
182
|
+
|
|
183
|
+
**Example**:
|
|
184
|
+
```typescript
|
|
185
|
+
await enableSite('my-service', '/etc/nginx/sites-available');
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### `disableSite(siteName: string, configPath: string): Promise<void>`
|
|
189
|
+
|
|
190
|
+
Disables an Nginx site by removing the symbolic link.
|
|
191
|
+
|
|
192
|
+
**Parameters**:
|
|
193
|
+
- `siteName`: Name of the site
|
|
194
|
+
- `configPath`: Path to sites-available directory
|
|
195
|
+
|
|
196
|
+
**Returns**: Promise that resolves when site is disabled
|
|
197
|
+
|
|
198
|
+
**Example**:
|
|
199
|
+
```typescript
|
|
200
|
+
await disableSite('my-service', '/etc/nginx/sites-available');
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### `reloadNginx(reloadCommand: string): Promise<void>`
|
|
204
|
+
|
|
205
|
+
Tests and reloads Nginx configuration.
|
|
206
|
+
|
|
207
|
+
**Parameters**:
|
|
208
|
+
- `reloadCommand`: Command to execute for reloading
|
|
209
|
+
|
|
210
|
+
**Returns**: Promise that resolves when Nginx is reloaded
|
|
211
|
+
|
|
212
|
+
**Throws**: Error if Nginx configuration test fails or reload fails
|
|
213
|
+
|
|
214
|
+
**Example**:
|
|
215
|
+
```typescript
|
|
216
|
+
await reloadNginx('sudo nginx -t && sudo systemctl reload nginx');
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Certbot Utilities
|
|
220
|
+
|
|
221
|
+
**File**: `src/utils/certbot.ts`
|
|
222
|
+
|
|
223
|
+
### `requestCertificate(domain: string, email: string, staging?: boolean): Promise<void>`
|
|
224
|
+
|
|
225
|
+
Requests an SSL certificate from Let's Encrypt using Certbot.
|
|
226
|
+
|
|
227
|
+
**Parameters**:
|
|
228
|
+
- `domain`: Domain name for the certificate
|
|
229
|
+
- `email`: Email address for certificate notifications
|
|
230
|
+
- `staging`: Use staging environment (default: false)
|
|
231
|
+
|
|
232
|
+
**Returns**: Promise that resolves when certificate is obtained
|
|
233
|
+
|
|
234
|
+
**Throws**: Error if certificate request fails
|
|
235
|
+
|
|
236
|
+
**Example**:
|
|
237
|
+
```typescript
|
|
238
|
+
await requestCertificate('example.com', 'admin@example.com', false);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### `renewCertificates(): Promise<void>`
|
|
242
|
+
|
|
243
|
+
Renews all SSL certificates that are due for renewal.
|
|
244
|
+
|
|
245
|
+
**Returns**: Promise that resolves when renewal is complete
|
|
246
|
+
|
|
247
|
+
**Throws**: Error if renewal fails
|
|
248
|
+
|
|
249
|
+
**Example**:
|
|
250
|
+
```typescript
|
|
251
|
+
await renewCertificates();
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### `checkCertificateExpiration(domain: string): Promise<Date | null>`
|
|
255
|
+
|
|
256
|
+
Checks the expiration date of a certificate for a domain.
|
|
257
|
+
|
|
258
|
+
**Parameters**:
|
|
259
|
+
- `domain`: Domain name to check
|
|
260
|
+
|
|
261
|
+
**Returns**: Promise resolving to expiration date or `null` if not found
|
|
262
|
+
|
|
263
|
+
**Example**:
|
|
264
|
+
```typescript
|
|
265
|
+
const expiry = await checkCertificateExpiration('example.com');
|
|
266
|
+
if (expiry) {
|
|
267
|
+
console.log(`Certificate expires on: ${expiry}`);
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### `revokeCertificate(domain: string): Promise<void>`
|
|
272
|
+
|
|
273
|
+
Revokes an SSL certificate for a domain.
|
|
274
|
+
|
|
275
|
+
**Parameters**:
|
|
276
|
+
- `domain`: Domain name whose certificate to revoke
|
|
277
|
+
|
|
278
|
+
**Returns**: Promise that resolves when certificate is revoked
|
|
279
|
+
|
|
280
|
+
**Throws**: Error if revocation fails
|
|
281
|
+
|
|
282
|
+
**Example**:
|
|
283
|
+
```typescript
|
|
284
|
+
await revokeCertificate('example.com');
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Deployment Utilities
|
|
288
|
+
|
|
289
|
+
**File**: `src/utils/deployment.ts`
|
|
290
|
+
|
|
291
|
+
### `deployService(service: ServiceConfig, deploymentConfig: DeploymentConfig): Promise<void>`
|
|
292
|
+
|
|
293
|
+
Deploys a service using the configured deployment strategy.
|
|
294
|
+
|
|
295
|
+
**Parameters**:
|
|
296
|
+
- `service`: Service configuration
|
|
297
|
+
- `deploymentConfig`: Deployment strategy configuration
|
|
298
|
+
|
|
299
|
+
**Returns**: Promise that resolves when service is deployed
|
|
300
|
+
|
|
301
|
+
**Throws**: Error if deployment fails
|
|
302
|
+
|
|
303
|
+
**Example**:
|
|
304
|
+
```typescript
|
|
305
|
+
await deployService(service, deploymentConfig);
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### `performHealthCheck(url: string, timeout?: number): Promise<boolean>`
|
|
309
|
+
|
|
310
|
+
Performs a health check on a service endpoint.
|
|
311
|
+
|
|
312
|
+
**Parameters**:
|
|
313
|
+
- `url`: Health check endpoint URL
|
|
314
|
+
- `timeout`: Maximum time to wait in milliseconds (default: 30000)
|
|
315
|
+
|
|
316
|
+
**Returns**: Promise resolving to `true` if healthy, `false` if timeout
|
|
317
|
+
|
|
318
|
+
**Behavior**:
|
|
319
|
+
- Polls endpoint every 2 seconds
|
|
320
|
+
- Returns `true` on first successful (200 OK) response
|
|
321
|
+
- Returns `false` if timeout is exceeded
|
|
322
|
+
|
|
323
|
+
**Example**:
|
|
324
|
+
```typescript
|
|
325
|
+
const isHealthy = await performHealthCheck('http://localhost:3000/health', 30000);
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### `waitForService(service: ServiceConfig, timeout?: number): Promise<boolean>`
|
|
329
|
+
|
|
330
|
+
Waits for a service to become healthy.
|
|
331
|
+
|
|
332
|
+
**Parameters**:
|
|
333
|
+
- `service`: Service configuration
|
|
334
|
+
- `timeout`: Maximum time to wait in milliseconds (default: 60000)
|
|
335
|
+
|
|
336
|
+
**Returns**: Promise resolving to `true` if service becomes healthy
|
|
337
|
+
|
|
338
|
+
**Example**:
|
|
339
|
+
```typescript
|
|
340
|
+
const ready = await waitForService(service, 60000);
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### `gracefulShutdown(service: ServiceConfig, timeout?: number): Promise<void>`
|
|
344
|
+
|
|
345
|
+
Gracefully shuts down a service.
|
|
346
|
+
|
|
347
|
+
**Parameters**:
|
|
348
|
+
- `service`: Service configuration
|
|
349
|
+
- `timeout`: Maximum time to wait for shutdown (default: 30000)
|
|
350
|
+
|
|
351
|
+
**Returns**: Promise that resolves when shutdown is complete
|
|
352
|
+
|
|
353
|
+
**Note**: This is a placeholder implementation. Actual implementation depends on service management.
|
|
354
|
+
|
|
355
|
+
**Example**:
|
|
356
|
+
```typescript
|
|
357
|
+
await gracefulShutdown(service, 30000);
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Type Definitions
|
|
361
|
+
|
|
362
|
+
**File**: `src/types/config.ts`
|
|
363
|
+
|
|
364
|
+
### `DeployConfig`
|
|
365
|
+
|
|
366
|
+
Root configuration interface.
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
interface DeployConfig {
|
|
370
|
+
project: ProjectConfig;
|
|
371
|
+
services: ServiceConfig[];
|
|
372
|
+
nginx: NginxConfig;
|
|
373
|
+
certbot: CertbotConfig;
|
|
374
|
+
deployment: DeploymentConfig;
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
### `ProjectConfig`
|
|
379
|
+
|
|
380
|
+
Project metadata.
|
|
381
|
+
|
|
382
|
+
```typescript
|
|
383
|
+
interface ProjectConfig {
|
|
384
|
+
name: string;
|
|
385
|
+
version: string;
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### `ServiceConfig`
|
|
390
|
+
|
|
391
|
+
Service configuration.
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
interface ServiceConfig {
|
|
395
|
+
name: string;
|
|
396
|
+
port: number;
|
|
397
|
+
domains: string[];
|
|
398
|
+
docker?: DockerConfig;
|
|
399
|
+
healthCheck?: HealthCheckConfig;
|
|
400
|
+
environment?: Record<string, string>;
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### `DockerConfig`
|
|
405
|
+
|
|
406
|
+
Docker container configuration.
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
interface DockerConfig {
|
|
410
|
+
image?: string;
|
|
411
|
+
container: string;
|
|
412
|
+
port: number;
|
|
413
|
+
}
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### `HealthCheckConfig`
|
|
417
|
+
|
|
418
|
+
Health check configuration.
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
interface HealthCheckConfig {
|
|
422
|
+
path: string;
|
|
423
|
+
interval: number;
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### `NginxConfig`
|
|
428
|
+
|
|
429
|
+
Nginx configuration.
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
interface NginxConfig {
|
|
433
|
+
configPath: string;
|
|
434
|
+
reloadCommand: string;
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### `CertbotConfig`
|
|
439
|
+
|
|
440
|
+
Certbot/SSL configuration.
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
interface CertbotConfig {
|
|
444
|
+
email: string;
|
|
445
|
+
staging: boolean;
|
|
446
|
+
}
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### `DeploymentConfig`
|
|
450
|
+
|
|
451
|
+
Deployment strategy configuration.
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
interface DeploymentConfig {
|
|
455
|
+
strategy: 'rolling' | 'blue-green';
|
|
456
|
+
healthCheckTimeout: number;
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
## Command Handlers
|
|
461
|
+
|
|
462
|
+
### `initCommand(options: InitOptions): Promise<void>`
|
|
463
|
+
|
|
464
|
+
**File**: `src/commands/init.ts`
|
|
465
|
+
|
|
466
|
+
Interactive configuration file creation.
|
|
467
|
+
|
|
468
|
+
**Parameters**:
|
|
469
|
+
- `options.file`: Configuration file path (default: 'suthep.yml')
|
|
470
|
+
|
|
471
|
+
### `setupCommand(options: SetupOptions): Promise<void>`
|
|
472
|
+
|
|
473
|
+
**File**: `src/commands/setup.ts`
|
|
474
|
+
|
|
475
|
+
Install and configure prerequisites.
|
|
476
|
+
|
|
477
|
+
**Parameters**:
|
|
478
|
+
- `options.nginxOnly`: Only setup Nginx
|
|
479
|
+
- `options.certbotOnly`: Only setup Certbot
|
|
480
|
+
|
|
481
|
+
### `deployCommand(options: DeployOptions): Promise<void>`
|
|
482
|
+
|
|
483
|
+
**File**: `src/commands/deploy.ts`
|
|
484
|
+
|
|
485
|
+
Deploy services using configuration.
|
|
486
|
+
|
|
487
|
+
**Parameters**:
|
|
488
|
+
- `options.file`: Configuration file path (default: 'suthep.yml')
|
|
489
|
+
- `options.https`: Enable HTTPS (default: true)
|
|
490
|
+
- `options.nginx`: Configure Nginx (default: true)
|
|
491
|
+
|
|
492
|
+
## Error Handling
|
|
493
|
+
|
|
494
|
+
All functions throw errors with descriptive messages. Common error patterns:
|
|
495
|
+
|
|
496
|
+
- **File operations**: `Error: Configuration file not found: ...`
|
|
497
|
+
- **Docker operations**: `Error: Failed to start Docker container: ...`
|
|
498
|
+
- **Nginx operations**: `Error: Failed to reload Nginx: ...`
|
|
499
|
+
- **Certbot operations**: `Error: Failed to obtain SSL certificate for ...: ...`
|
|
500
|
+
- **Health checks**: `Error: Service ... failed health check ...`
|
|
501
|
+
|
|
502
|
+
## Usage Examples
|
|
503
|
+
|
|
504
|
+
### Custom Deployment Script
|
|
505
|
+
|
|
506
|
+
```typescript
|
|
507
|
+
import { loadConfig } from './utils/config-loader';
|
|
508
|
+
import { startDockerContainer } from './utils/docker';
|
|
509
|
+
import { generateNginxConfig, enableSite, reloadNginx } from './utils/nginx';
|
|
510
|
+
import { requestCertificate } from './utils/certbot';
|
|
511
|
+
import { performHealthCheck } from './utils/deployment';
|
|
512
|
+
|
|
513
|
+
async function customDeploy() {
|
|
514
|
+
const config = await loadConfig('suthep.yml');
|
|
515
|
+
|
|
516
|
+
for (const service of config.services) {
|
|
517
|
+
// Start Docker container
|
|
518
|
+
if (service.docker) {
|
|
519
|
+
await startDockerContainer(service);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Generate and enable Nginx config
|
|
523
|
+
const nginxConfig = generateNginxConfig(service, false);
|
|
524
|
+
// ... write config file ...
|
|
525
|
+
await enableSite(service.name, config.nginx.configPath);
|
|
526
|
+
|
|
527
|
+
// Request certificate
|
|
528
|
+
for (const domain of service.domains) {
|
|
529
|
+
await requestCertificate(domain, config.certbot.email, config.certbot.staging);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// Health check
|
|
533
|
+
if (service.healthCheck) {
|
|
534
|
+
const url = `http://localhost:${service.port}${service.healthCheck.path}`;
|
|
535
|
+
const healthy = await performHealthCheck(url, 30000);
|
|
536
|
+
if (!healthy) {
|
|
537
|
+
throw new Error(`Service ${service.name} is not healthy`);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Reload Nginx
|
|
542
|
+
await reloadNginx(config.nginx.reloadCommand);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
```
|