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.
Files changed (65) hide show
  1. package/.editorconfig +17 -0
  2. package/.prettierignore +6 -0
  3. package/.prettierrc +7 -0
  4. package/.vscode/settings.json +19 -0
  5. package/LICENSE +21 -0
  6. package/README.md +217 -0
  7. package/dist/commands/deploy.js +318 -0
  8. package/dist/commands/deploy.js.map +1 -0
  9. package/dist/commands/init.js +188 -0
  10. package/dist/commands/init.js.map +1 -0
  11. package/dist/commands/setup.js +90 -0
  12. package/dist/commands/setup.js.map +1 -0
  13. package/dist/index.js +19 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/utils/certbot.js +64 -0
  16. package/dist/utils/certbot.js.map +1 -0
  17. package/dist/utils/config-loader.js +95 -0
  18. package/dist/utils/config-loader.js.map +1 -0
  19. package/dist/utils/deployment.js +76 -0
  20. package/dist/utils/deployment.js.map +1 -0
  21. package/dist/utils/docker.js +393 -0
  22. package/dist/utils/docker.js.map +1 -0
  23. package/dist/utils/nginx.js +303 -0
  24. package/dist/utils/nginx.js.map +1 -0
  25. package/docs/README.md +95 -0
  26. package/docs/TRANSLATIONS.md +211 -0
  27. package/docs/en/README.md +76 -0
  28. package/docs/en/api-reference.md +545 -0
  29. package/docs/en/architecture.md +369 -0
  30. package/docs/en/commands.md +273 -0
  31. package/docs/en/configuration.md +347 -0
  32. package/docs/en/developer-guide.md +588 -0
  33. package/docs/en/docker-ports-config.md +333 -0
  34. package/docs/en/examples.md +537 -0
  35. package/docs/en/getting-started.md +202 -0
  36. package/docs/en/port-binding.md +268 -0
  37. package/docs/en/troubleshooting.md +441 -0
  38. package/docs/th/README.md +64 -0
  39. package/docs/th/commands.md +202 -0
  40. package/docs/th/configuration.md +325 -0
  41. package/docs/th/getting-started.md +203 -0
  42. package/example/README.md +85 -0
  43. package/example/docker-compose.yml +76 -0
  44. package/example/docker-ports-example.yml +81 -0
  45. package/example/muacle.yml +47 -0
  46. package/example/port-binding-example.yml +45 -0
  47. package/example/suthep.yml +46 -0
  48. package/example/suthep=1.yml +46 -0
  49. package/package.json +45 -0
  50. package/src/commands/deploy.ts +405 -0
  51. package/src/commands/init.ts +214 -0
  52. package/src/commands/setup.ts +112 -0
  53. package/src/index.ts +42 -0
  54. package/src/types/config.ts +52 -0
  55. package/src/utils/certbot.ts +144 -0
  56. package/src/utils/config-loader.ts +121 -0
  57. package/src/utils/deployment.ts +157 -0
  58. package/src/utils/docker.ts +755 -0
  59. package/src/utils/nginx.ts +326 -0
  60. package/suthep-0.1.1.tgz +0 -0
  61. package/suthep.example.yml +98 -0
  62. package/test +0 -0
  63. package/todo.md +6 -0
  64. package/tsconfig.json +26 -0
  65. package/vite.config.ts +46 -0
@@ -0,0 +1,268 @@
1
+ # Port Binding Guide
2
+
3
+ This guide explains how port binding works in Suthep when deploying Docker containers.
4
+
5
+ ## How Port Binding Works
6
+
7
+ When you deploy a service with Docker, Suthep automatically binds ports between the host machine and the container using Docker's port mapping feature.
8
+
9
+ ### Port Mapping Format
10
+
11
+ The port binding follows this format:
12
+ ```
13
+ hostPort:containerPort
14
+ ```
15
+
16
+ Where:
17
+ - **hostPort** (`service.port`): The port on your host machine (accessible at `localhost:hostPort`)
18
+ - **containerPort** (`service.docker.port`): The port inside the Docker container (what your application listens on)
19
+
20
+ ### Configuration
21
+
22
+ In your `suthep.yml` file:
23
+
24
+ ```yaml
25
+ services:
26
+ - name: api
27
+ port: 3001 # Host port (exposed on host machine)
28
+ docker:
29
+ image: myapp/api:latest
30
+ container: api-container
31
+ port: 3001 # Container port (inside the container)
32
+ ```
33
+
34
+ This configuration creates a Docker port mapping: `3001:3001`
35
+
36
+ ### How It Works
37
+
38
+ 1. **Docker Command Generated**:
39
+ ```bash
40
+ docker run -d -p 3001:3001 --name api-container myapp/api:latest
41
+ ```
42
+
43
+ 2. **Port Mapping**:
44
+ - Traffic to `localhost:3001` on the host → forwarded to port `3001` inside the container
45
+ - Your application inside the container listens on port `3001`
46
+ - Nginx connects to `localhost:3001` to reach your service
47
+
48
+ 3. **Nginx Configuration**:
49
+ ```nginx
50
+ upstream api {
51
+ server localhost:3001; # Connects to host port
52
+ }
53
+ ```
54
+
55
+ ## Common Scenarios
56
+
57
+ ### Same Port on Host and Container
58
+
59
+ When your app listens on the same port inside and outside the container:
60
+
61
+ ```yaml
62
+ - name: api
63
+ port: 3000 # Host: 3000
64
+ docker:
65
+ port: 3000 # Container: 3000
66
+ ```
67
+
68
+ **Result**: `docker run -p 3000:3000 ...`
69
+
70
+ ### Different Ports (Host Port ≠ Container Port)
71
+
72
+ When you want to expose a different host port than the container port:
73
+
74
+ **Example: Bind host port 3002 to container port 3000**
75
+
76
+ ```yaml
77
+ - name: api
78
+ port: 3002 # Host: 3002 (external, accessible at localhost:3002)
79
+ docker:
80
+ port: 3000 # Container: 3000 (internal, app listens on 3000 inside)
81
+ ```
82
+
83
+ **Result**: `docker run -p 3002:3000 ...`
84
+ - External access: `localhost:3002` → forwards to container port `3000`
85
+ - Container internal: your app listens on port `3000`
86
+ - Nginx connects to: `localhost:3002`
87
+
88
+ **Another Example: Host 8080 → Container 80**
89
+
90
+ ```yaml
91
+ - name: web
92
+ port: 8080 # Host: 8080 (external)
93
+ docker:
94
+ port: 80 # Container: 80 (internal, Nginx listens on 80)
95
+ ```
96
+
97
+ **Result**: `docker run -p 8080:80 ...`
98
+ - External access: `localhost:8080` → forwards to container port `80`
99
+ - Container internal: Nginx listens on port `80`
100
+
101
+ ### Multiple Services on Same Domain
102
+
103
+ When multiple services share a domain but use different ports:
104
+
105
+ ```yaml
106
+ services:
107
+ - name: api
108
+ port: 3001 # Host port 3001
109
+ path: /api
110
+ domains:
111
+ - example.com
112
+ docker:
113
+ port: 3001 # Container port 3001
114
+
115
+ - name: ui
116
+ port: 3000 # Host port 3000
117
+ path: /
118
+ domains:
119
+ - example.com
120
+ docker:
121
+ port: 3000 # Container port 3000
122
+ ```
123
+
124
+ **Result**:
125
+ - API: `localhost:3001` → container port `3001`
126
+ - UI: `localhost:3000` → container port `3000`
127
+ - Nginx routes:
128
+ - `example.com/api/*` → `localhost:3001`
129
+ - `example.com/*` → `localhost:3000`
130
+
131
+ ## Port Conflict Detection
132
+
133
+ Suthep automatically detects and prevents port conflicts:
134
+
135
+ ### Configuration Validation
136
+
137
+ Before deployment, Suthep checks:
138
+ - ✅ No two services use the same host port
139
+ - ✅ No two Docker containers have the same name
140
+
141
+ **Error Example**:
142
+ ```
143
+ Port conflict: Service "api" uses port 3000 which is already used by: webapp.
144
+ Each service must use a unique port.
145
+ ```
146
+
147
+ ### Runtime Port Check
148
+
149
+ When creating containers, Suthep:
150
+ 1. Checks if the port is already bound by another container
151
+ 2. Catches Docker port binding errors
152
+ 3. Provides clear error messages
153
+
154
+ **Error Example**:
155
+ ```
156
+ Port 3000 is already in use by another container.
157
+ Please use a different port for service "api".
158
+ ```
159
+
160
+ ## Advanced Port Binding
161
+
162
+ ### Binding to Specific Interface
163
+
164
+ Currently, Suthep binds to all interfaces (`0.0.0.0`). To bind to a specific interface, you would need to modify the Docker command manually or use Docker Compose.
165
+
166
+ ### Port Range Binding
167
+
168
+ For binding port ranges, you would need to use Docker Compose or modify the container creation manually.
169
+
170
+ ### UDP Ports
171
+
172
+ Currently, Suthep only supports TCP ports. For UDP, you would need to manually configure Docker.
173
+
174
+ ## Troubleshooting
175
+
176
+ ### Port Already in Use
177
+
178
+ **Problem**: `Port X is already in use`
179
+
180
+ **Solutions**:
181
+ 1. Check what's using the port:
182
+ ```bash
183
+ sudo lsof -i :3000
184
+ # or
185
+ sudo netstat -tulpn | grep 3000
186
+ ```
187
+
188
+ 2. Stop the conflicting service or container
189
+ 3. Use a different port in your configuration
190
+
191
+ ### Container Port Mismatch
192
+
193
+ **Problem**: Container can't be reached
194
+
195
+ **Check**:
196
+ 1. Verify your app listens on the correct port inside the container
197
+ 2. Ensure `docker.port` matches your app's listening port
198
+ 3. Check container logs:
199
+ ```bash
200
+ docker logs container-name
201
+ ```
202
+
203
+ ### Port Not Accessible
204
+
205
+ **Problem**: Can't access service on host port
206
+
207
+ **Check**:
208
+ 1. Verify container is running:
209
+ ```bash
210
+ docker ps
211
+ ```
212
+
213
+ 2. Check port mapping:
214
+ ```bash
215
+ docker port container-name
216
+ ```
217
+
218
+ 3. Test connection:
219
+ ```bash
220
+ curl http://localhost:PORT
221
+ ```
222
+
223
+ ## Best Practices
224
+
225
+ 1. **Use Unique Host Ports**: Each service should use a unique host port
226
+ 2. **Match Container Ports**: Set `docker.port` to match what your app listens on inside the container
227
+ 3. **Document Port Usage**: Keep track of which ports are used by which services
228
+ 4. **Use High Ports for Development**: Use ports above 8000 for development to avoid conflicts
229
+ 5. **Check Before Deploying**: Verify ports aren't in use before deployment
230
+
231
+ ## Examples
232
+
233
+ ### Simple Node.js API
234
+
235
+ ```yaml
236
+ - name: api
237
+ port: 3000
238
+ docker:
239
+ image: node:18
240
+ container: api-container
241
+ port: 3000 # App listens on 3000 inside container
242
+ ```
243
+
244
+ ### Nginx Web Server
245
+
246
+ ```yaml
247
+ - name: web
248
+ port: 8080
249
+ docker:
250
+ image: nginx:alpine
251
+ container: web-container
252
+ port: 80 # Nginx listens on 80 inside container
253
+ ```
254
+
255
+ **Result**: Host port `8080` → Container port `80`
256
+
257
+ ### PostgreSQL Database
258
+
259
+ ```yaml
260
+ - name: db
261
+ port: 5432
262
+ docker:
263
+ image: postgres:15
264
+ container: postgres-container
265
+ port: 5432
266
+ ```
267
+
268
+ **Result**: Host port `5432` → Container port `5432`
@@ -0,0 +1,441 @@
1
+ # Troubleshooting
2
+
3
+ This guide helps you resolve common issues when using Suthep.
4
+
5
+ ## Common Issues
6
+
7
+ ### Permission Denied Errors
8
+
9
+ **Problem**: Getting "Permission denied" or "EACCES" errors.
10
+
11
+ **Solutions**:
12
+ 1. Ensure you have `sudo` access:
13
+ ```bash
14
+ sudo -v
15
+ ```
16
+
17
+ 2. For Nginx operations, Suthep requires sudo. Make sure you're running commands that need it with appropriate permissions.
18
+
19
+ 3. Check file permissions:
20
+ ```bash
21
+ ls -la /etc/nginx/sites-available
22
+ ```
23
+
24
+ ### Nginx Not Found
25
+
26
+ **Problem**: `nginx: command not found`
27
+
28
+ **Solutions**:
29
+ 1. Run the setup command:
30
+ ```bash
31
+ suthep setup --nginx-only
32
+ ```
33
+
34
+ 2. If setup fails, install manually:
35
+ ```bash
36
+ # Ubuntu/Debian
37
+ sudo apt-get update
38
+ sudo apt-get install nginx
39
+
40
+ # RHEL/CentOS
41
+ sudo yum install nginx
42
+
43
+ # macOS
44
+ brew install nginx
45
+ ```
46
+
47
+ 3. Verify installation:
48
+ ```bash
49
+ nginx -v
50
+ ```
51
+
52
+ ### Certbot Not Found
53
+
54
+ **Problem**: `certbot: command not found`
55
+
56
+ **Solutions**:
57
+ 1. Run the setup command:
58
+ ```bash
59
+ suthep setup --certbot-only
60
+ ```
61
+
62
+ 2. If setup fails, install manually:
63
+ ```bash
64
+ # Ubuntu/Debian
65
+ sudo apt-get update
66
+ sudo apt-get install certbot python3-certbot-nginx
67
+
68
+ # RHEL/CentOS
69
+ sudo yum install certbot python3-certbot-nginx
70
+
71
+ # macOS
72
+ brew install certbot
73
+ ```
74
+
75
+ 3. Verify installation:
76
+ ```bash
77
+ certbot --version
78
+ ```
79
+
80
+ ### SSL Certificate Request Failed
81
+
82
+ **Problem**: Certificate request fails with errors like "Failed to obtain SSL certificate"
83
+
84
+ **Common Causes**:
85
+ 1. **Domain not pointing to server**: DNS not configured correctly
86
+ 2. **Port 80 blocked**: Firewall blocking HTTP traffic
87
+ 3. **Rate limits**: Too many certificate requests (use staging mode)
88
+ 4. **Domain already has certificate**: Certificate already exists
89
+
90
+ **Solutions**:
91
+ 1. **Check DNS**:
92
+ ```bash
93
+ dig example.com
94
+ # Should return your server's IP
95
+ ```
96
+
97
+ 2. **Check firewall**:
98
+ ```bash
99
+ sudo ufw status
100
+ # Ensure ports 80 and 443 are open
101
+ sudo ufw allow 80
102
+ sudo ufw allow 443
103
+ ```
104
+
105
+ 3. **Use staging mode** for testing:
106
+ ```yaml
107
+ certbot:
108
+ staging: true
109
+ ```
110
+
111
+ 4. **Check existing certificates**:
112
+ ```bash
113
+ sudo certbot certificates
114
+ ```
115
+
116
+ 5. **Revoke and retry** (if needed):
117
+ ```bash
118
+ sudo certbot revoke -d example.com
119
+ ```
120
+
121
+ ### Nginx Configuration Test Fails
122
+
123
+ **Problem**: `nginx -t` fails with syntax errors
124
+
125
+ **Solutions**:
126
+ 1. Check the generated Nginx config:
127
+ ```bash
128
+ sudo cat /etc/nginx/sites-available/service-name.conf
129
+ ```
130
+
131
+ 2. Test Nginx configuration manually:
132
+ ```bash
133
+ sudo nginx -t
134
+ ```
135
+
136
+ 3. Check Nginx error logs:
137
+ ```bash
138
+ sudo tail -f /var/log/nginx/error.log
139
+ ```
140
+
141
+ 4. Common issues:
142
+ - Missing SSL certificates (if HTTPS enabled)
143
+ - Invalid domain names
144
+ - Port conflicts
145
+
146
+ ### Service Health Check Fails
147
+
148
+ **Problem**: Health check times out or fails
149
+
150
+ **Solutions**:
151
+ 1. **Verify service is running**:
152
+ ```bash
153
+ curl http://localhost:PORT/health
154
+ ```
155
+
156
+ 2. **Check service logs**:
157
+ ```bash
158
+ # For Docker containers
159
+ docker logs container-name
160
+
161
+ # For Node.js services
162
+ # Check your application logs
163
+ ```
164
+
165
+ 3. **Verify health check path**:
166
+ - Ensure the path in configuration matches your service endpoint
167
+ - Test the endpoint manually
168
+
169
+ 4. **Increase timeout**:
170
+ ```yaml
171
+ deployment:
172
+ healthCheckTimeout: 60000 # Increase to 60 seconds
173
+ ```
174
+
175
+ 5. **Check service is listening on correct port**:
176
+ ```bash
177
+ netstat -tuln | grep PORT
178
+ # or
179
+ ss -tuln | grep PORT
180
+ ```
181
+
182
+ ### Docker Container Issues
183
+
184
+ **Problem**: Docker container fails to start or connect
185
+
186
+ **Solutions**:
187
+ 1. **Check Docker is running**:
188
+ ```bash
189
+ docker ps
190
+ ```
191
+
192
+ 2. **Check container exists**:
193
+ ```bash
194
+ docker ps -a | grep container-name
195
+ ```
196
+
197
+ 3. **Check container logs**:
198
+ ```bash
199
+ docker logs container-name
200
+ ```
201
+
202
+ 4. **Verify port mapping**:
203
+ - Ensure host port doesn't conflict with other services
204
+ - Check if port is already in use:
205
+ ```bash
206
+ lsof -i :PORT
207
+ ```
208
+
209
+ 5. **Check Docker image exists**:
210
+ ```bash
211
+ docker images | grep image-name
212
+ ```
213
+
214
+ 6. **Pull image manually** (if needed):
215
+ ```bash
216
+ docker pull image-name:tag
217
+ ```
218
+
219
+ ### Domain Not Resolving
220
+
221
+ **Problem**: Can't access service via domain name
222
+
223
+ **Solutions**:
224
+ 1. **Check DNS configuration**:
225
+ ```bash
226
+ dig example.com
227
+ nslookup example.com
228
+ ```
229
+
230
+ 2. **Verify DNS points to server**:
231
+ - Check your DNS provider settings
232
+ - Ensure A record points to your server's IP
233
+
234
+ 3. **Test locally** (add to /etc/hosts for testing):
235
+ ```bash
236
+ sudo echo "127.0.0.1 example.com" >> /etc/hosts
237
+ ```
238
+
239
+ 4. **Check Nginx is serving the domain**:
240
+ ```bash
241
+ curl -H "Host: example.com" http://localhost
242
+ ```
243
+
244
+ ### Port Already in Use
245
+
246
+ **Problem**: Port conflict errors
247
+
248
+ **Solutions**:
249
+ 1. **Find what's using the port**:
250
+ ```bash
251
+ sudo lsof -i :PORT
252
+ # or
253
+ sudo netstat -tulpn | grep PORT
254
+ ```
255
+
256
+ 2. **Stop conflicting service** or change port in configuration
257
+
258
+ 3. **For Docker containers**, check if port mapping conflicts:
259
+ ```bash
260
+ docker ps | grep PORT
261
+ ```
262
+
263
+ ### Nginx Site Not Enabled
264
+
265
+ **Problem**: Service not accessible even though deployment succeeded
266
+
267
+ **Solutions**:
268
+ 1. **Check if site is enabled**:
269
+ ```bash
270
+ ls -la /etc/nginx/sites-enabled/ | grep service-name
271
+ ```
272
+
273
+ 2. **Manually enable site**:
274
+ ```bash
275
+ sudo ln -s /etc/nginx/sites-available/service-name.conf /etc/nginx/sites-enabled/
276
+ ```
277
+
278
+ 3. **Reload Nginx**:
279
+ ```bash
280
+ sudo nginx -t
281
+ sudo systemctl reload nginx
282
+ ```
283
+
284
+ ### Configuration File Not Found
285
+
286
+ **Problem**: `Configuration file not found: suthep.yml`
287
+
288
+ **Solutions**:
289
+ 1. **Check current directory**:
290
+ ```bash
291
+ pwd
292
+ ls -la suthep.yml
293
+ ```
294
+
295
+ 2. **Specify custom path**:
296
+ ```bash
297
+ suthep deploy -f /path/to/config.yml
298
+ ```
299
+
300
+ 3. **Create configuration**:
301
+ ```bash
302
+ suthep init
303
+ ```
304
+
305
+ ### Service Deployment Fails Midway
306
+
307
+ **Problem**: Deployment fails for one service, affecting others
308
+
309
+ **Solutions**:
310
+ 1. **Check error message** - it will indicate which service failed
311
+
312
+ 2. **Fix the issue** for the failing service
313
+
314
+ 3. **Redeploy**:
315
+ ```bash
316
+ suthep deploy
317
+ ```
318
+
319
+ 4. **Note**: Suthep uses fail-fast, so if one service fails, deployment stops. Previous services remain deployed.
320
+
321
+ ### SSL Certificate Expired
322
+
323
+ **Problem**: SSL certificate has expired
324
+
325
+ **Solutions**:
326
+ 1. **Check certificate expiration**:
327
+ ```bash
328
+ sudo certbot certificates
329
+ ```
330
+
331
+ 2. **Renew certificates**:
332
+ ```bash
333
+ sudo certbot renew
334
+ ```
335
+
336
+ 3. **Set up auto-renewal** (recommended):
337
+ ```bash
338
+ # Add to crontab
339
+ sudo crontab -e
340
+ # Add: 0 0 * * * certbot renew --quiet
341
+ ```
342
+
343
+ ### Multiple Services on Same Port
344
+
345
+ **Problem**: Two services configured with the same port
346
+
347
+ **Solutions**:
348
+ 1. **Use different ports** for each service:
349
+ ```yaml
350
+ services:
351
+ - name: api
352
+ port: 3000
353
+ - name: webapp
354
+ port: 3001 # Different port
355
+ ```
356
+
357
+ 2. **Use Docker port mapping** to map different host ports to same container port
358
+
359
+ ## Debugging Tips
360
+
361
+ ### Enable Verbose Logging
362
+
363
+ Check Nginx and application logs:
364
+
365
+ ```bash
366
+ # Nginx access logs
367
+ sudo tail -f /var/log/nginx/service-name_access.log
368
+
369
+ # Nginx error logs
370
+ sudo tail -f /var/log/nginx/service-name_error.log
371
+
372
+ # Nginx general error log
373
+ sudo tail -f /var/log/nginx/error.log
374
+ ```
375
+
376
+ ### Test Nginx Configuration
377
+
378
+ ```bash
379
+ # Test configuration syntax
380
+ sudo nginx -t
381
+
382
+ # Test specific config file
383
+ sudo nginx -t -c /etc/nginx/sites-available/service-name.conf
384
+ ```
385
+
386
+ ### Verify Service Endpoints
387
+
388
+ ```bash
389
+ # Test health endpoint
390
+ curl http://localhost:PORT/health
391
+
392
+ # Test main endpoint
393
+ curl http://localhost:PORT/
394
+
395
+ # Test via domain (if DNS configured)
396
+ curl http://example.com
397
+ ```
398
+
399
+ ### Check Docker Status
400
+
401
+ ```bash
402
+ # List all containers
403
+ docker ps -a
404
+
405
+ # Check container status
406
+ docker inspect container-name
407
+
408
+ # View container logs
409
+ docker logs -f container-name
410
+ ```
411
+
412
+ ### Verify SSL Certificates
413
+
414
+ ```bash
415
+ # List all certificates
416
+ sudo certbot certificates
417
+
418
+ # Check certificate details
419
+ sudo openssl x509 -in /etc/letsencrypt/live/domain.com/cert.pem -text -noout
420
+ ```
421
+
422
+ ## Getting Help
423
+
424
+ If you're still experiencing issues:
425
+
426
+ 1. **Check logs**: Review Nginx, Docker, and application logs
427
+ 2. **Verify configuration**: Ensure `suthep.yml` is valid YAML
428
+ 3. **Test components individually**: Test Nginx, Certbot, and Docker separately
429
+ 4. **Review documentation**: Check [Configuration Reference](./configuration.md) and [Examples](./examples.md)
430
+ 5. **Check system requirements**: Ensure all prerequisites are installed
431
+
432
+ ## Prevention
433
+
434
+ To avoid common issues:
435
+
436
+ 1. **Use staging certificates** during development
437
+ 2. **Test health endpoints** before deployment
438
+ 3. **Verify DNS** before requesting certificates
439
+ 4. **Check port availability** before deployment
440
+ 5. **Backup configurations** before making changes
441
+ 6. **Monitor logs** during and after deployment