hostfn 0.1.1 → 0.1.2

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 (179) hide show
  1. package/dist/__tests__/core/backup.test.d.ts +2 -0
  2. package/dist/__tests__/core/backup.test.d.ts.map +1 -0
  3. package/dist/__tests__/core/backup.test.js +108 -0
  4. package/dist/__tests__/core/backup.test.js.map +1 -0
  5. package/dist/__tests__/core/health.test.d.ts +2 -0
  6. package/dist/__tests__/core/health.test.d.ts.map +1 -0
  7. package/dist/__tests__/core/health.test.js +97 -0
  8. package/dist/__tests__/core/health.test.js.map +1 -0
  9. package/dist/__tests__/core/lock.test.d.ts +2 -0
  10. package/dist/__tests__/core/lock.test.d.ts.map +1 -0
  11. package/dist/__tests__/core/lock.test.js +136 -0
  12. package/dist/__tests__/core/lock.test.js.map +1 -0
  13. package/dist/__tests__/core/nginx-multi-domain.test.d.ts +2 -0
  14. package/dist/__tests__/core/nginx-multi-domain.test.d.ts.map +1 -0
  15. package/dist/__tests__/core/nginx-multi-domain.test.js +158 -0
  16. package/dist/__tests__/core/nginx-multi-domain.test.js.map +1 -0
  17. package/dist/__tests__/runtimes/pm2.test.d.ts +2 -0
  18. package/dist/__tests__/runtimes/pm2.test.d.ts.map +1 -0
  19. package/dist/__tests__/runtimes/pm2.test.js +111 -0
  20. package/dist/__tests__/runtimes/pm2.test.js.map +1 -0
  21. package/dist/__tests__/utils/validation.test.d.ts +2 -0
  22. package/dist/__tests__/utils/validation.test.d.ts.map +1 -0
  23. package/dist/__tests__/utils/validation.test.js +136 -0
  24. package/dist/__tests__/utils/validation.test.js.map +1 -0
  25. package/dist/commands/deploy.d.ts +11 -0
  26. package/dist/commands/deploy.d.ts.map +1 -0
  27. package/dist/commands/deploy.js +636 -0
  28. package/dist/commands/deploy.js.map +1 -0
  29. package/dist/commands/env.d.ts +21 -0
  30. package/dist/commands/env.d.ts.map +1 -0
  31. package/dist/commands/env.js +317 -0
  32. package/dist/commands/env.js.map +1 -0
  33. package/dist/commands/expose.d.ts +6 -0
  34. package/dist/commands/expose.d.ts.map +1 -0
  35. package/dist/commands/expose.js +379 -0
  36. package/dist/commands/expose.js.map +1 -0
  37. package/dist/commands/init.d.ts +2 -0
  38. package/dist/commands/init.d.ts.map +1 -0
  39. package/dist/commands/init.js +175 -0
  40. package/dist/commands/init.js.map +1 -0
  41. package/dist/commands/logs.d.ts +10 -0
  42. package/dist/commands/logs.d.ts.map +1 -0
  43. package/dist/commands/logs.js +75 -0
  44. package/dist/commands/logs.js.map +1 -0
  45. package/dist/commands/rollback.d.ts +6 -0
  46. package/dist/commands/rollback.d.ts.map +1 -0
  47. package/dist/commands/rollback.js +113 -0
  48. package/dist/commands/rollback.js.map +1 -0
  49. package/dist/commands/server/info.d.ts +2 -0
  50. package/dist/commands/server/info.d.ts.map +1 -0
  51. package/dist/commands/server/info.js +104 -0
  52. package/dist/commands/server/info.js.map +1 -0
  53. package/dist/commands/server/setup.d.ts +11 -0
  54. package/dist/commands/server/setup.d.ts.map +1 -0
  55. package/dist/commands/server/setup.js +161 -0
  56. package/dist/commands/server/setup.js.map +1 -0
  57. package/dist/commands/status.d.ts +6 -0
  58. package/dist/commands/status.d.ts.map +1 -0
  59. package/dist/commands/status.js +120 -0
  60. package/dist/commands/status.js.map +1 -0
  61. package/dist/config/loader.d.ts +21 -0
  62. package/dist/config/loader.d.ts.map +1 -0
  63. package/dist/config/loader.js +54 -0
  64. package/dist/config/loader.js.map +1 -0
  65. package/dist/config/schema.d.ts +323 -0
  66. package/dist/config/schema.d.ts.map +1 -0
  67. package/dist/config/schema.js +108 -0
  68. package/dist/config/schema.js.map +1 -0
  69. package/dist/core/backup.d.ts +34 -0
  70. package/dist/core/backup.d.ts.map +1 -0
  71. package/dist/core/backup.js +95 -0
  72. package/dist/core/backup.js.map +1 -0
  73. package/dist/core/health.d.ts +31 -0
  74. package/dist/core/health.d.ts.map +1 -0
  75. package/dist/core/health.js +78 -0
  76. package/dist/core/health.js.map +1 -0
  77. package/dist/core/local.d.ts +19 -0
  78. package/dist/core/local.d.ts.map +1 -0
  79. package/dist/core/local.js +50 -0
  80. package/dist/core/local.js.map +1 -0
  81. package/dist/core/lock.d.ts +28 -0
  82. package/dist/core/lock.d.ts.map +1 -0
  83. package/dist/core/lock.js +89 -0
  84. package/dist/core/lock.js.map +1 -0
  85. package/dist/core/nginx.d.ts +43 -0
  86. package/dist/core/nginx.d.ts.map +1 -0
  87. package/dist/core/nginx.js +131 -0
  88. package/dist/core/nginx.js.map +1 -0
  89. package/dist/core/ssh.d.ts +79 -0
  90. package/dist/core/ssh.d.ts.map +1 -0
  91. package/dist/core/ssh.js +264 -0
  92. package/dist/core/ssh.js.map +1 -0
  93. package/dist/core/sync.d.ts +25 -0
  94. package/dist/core/sync.d.ts.map +1 -0
  95. package/dist/core/sync.js +117 -0
  96. package/dist/core/sync.js.map +1 -0
  97. package/dist/core/workspace.d.ts +13 -0
  98. package/dist/core/workspace.d.ts.map +1 -0
  99. package/dist/core/workspace.js +141 -0
  100. package/dist/core/workspace.js.map +1 -0
  101. package/dist/index.d.ts +3 -0
  102. package/dist/index.d.ts.map +1 -0
  103. package/dist/index.js +232 -0
  104. package/dist/index.js.map +1 -0
  105. package/dist/runtimes/base.d.ts +115 -0
  106. package/dist/runtimes/base.d.ts.map +1 -0
  107. package/dist/runtimes/base.js +16 -0
  108. package/dist/runtimes/base.js.map +1 -0
  109. package/dist/runtimes/nodejs/detector.d.ts +47 -0
  110. package/dist/runtimes/nodejs/detector.d.ts.map +1 -0
  111. package/dist/runtimes/nodejs/detector.js +143 -0
  112. package/dist/runtimes/nodejs/detector.js.map +1 -0
  113. package/dist/runtimes/nodejs/index.d.ts +14 -0
  114. package/dist/runtimes/nodejs/index.d.ts.map +1 -0
  115. package/dist/runtimes/nodejs/index.js +213 -0
  116. package/dist/runtimes/nodejs/index.js.map +1 -0
  117. package/dist/runtimes/nodejs/pm2.d.ts +17 -0
  118. package/dist/runtimes/nodejs/pm2.d.ts.map +1 -0
  119. package/dist/runtimes/nodejs/pm2.js +60 -0
  120. package/dist/runtimes/nodejs/pm2.js.map +1 -0
  121. package/dist/runtimes/registry.d.ts +34 -0
  122. package/dist/runtimes/registry.d.ts.map +1 -0
  123. package/dist/runtimes/registry.js +58 -0
  124. package/dist/runtimes/registry.js.map +1 -0
  125. package/dist/utils/logger.d.ts +47 -0
  126. package/dist/utils/logger.d.ts.map +1 -0
  127. package/dist/utils/logger.js +76 -0
  128. package/dist/utils/logger.js.map +1 -0
  129. package/dist/utils/validation.d.ts +32 -0
  130. package/dist/utils/validation.d.ts.map +1 -0
  131. package/dist/utils/validation.js +125 -0
  132. package/dist/utils/validation.js.map +1 -0
  133. package/package.json +33 -16
  134. package/LICENSE +0 -21
  135. package/README.md +0 -1136
  136. package/_conduct/specs/1.v0.spec.md +0 -1041
  137. package/examples/express-api/package.json +0 -22
  138. package/examples/express-api/src/index.ts +0 -16
  139. package/examples/express-api/tsconfig.json +0 -11
  140. package/examples/github-actions-deploy.yml +0 -40
  141. package/examples/monorepo-config.json +0 -76
  142. package/examples/monorepo-multi-server-config.json +0 -74
  143. package/packages/cli/package.json +0 -40
  144. package/turbo.json +0 -24
  145. /package/{packages/cli/src → src}/__tests__/core/backup.test.ts +0 -0
  146. /package/{packages/cli/src → src}/__tests__/core/health.test.ts +0 -0
  147. /package/{packages/cli/src → src}/__tests__/core/lock.test.ts +0 -0
  148. /package/{packages/cli/src → src}/__tests__/core/nginx-multi-domain.test.ts +0 -0
  149. /package/{packages/cli/src → src}/__tests__/runtimes/pm2.test.ts +0 -0
  150. /package/{packages/cli/src → src}/__tests__/utils/validation.test.ts +0 -0
  151. /package/{packages/cli/src → src}/commands/deploy.ts +0 -0
  152. /package/{packages/cli/src → src}/commands/env.ts +0 -0
  153. /package/{packages/cli/src → src}/commands/expose.ts +0 -0
  154. /package/{packages/cli/src → src}/commands/init.ts +0 -0
  155. /package/{packages/cli/src → src}/commands/logs.ts +0 -0
  156. /package/{packages/cli/src → src}/commands/rollback.ts +0 -0
  157. /package/{packages/cli/src → src}/commands/server/info.ts +0 -0
  158. /package/{packages/cli/src → src}/commands/server/setup.ts +0 -0
  159. /package/{packages/cli/src → src}/commands/status.ts +0 -0
  160. /package/{packages/cli/src → src}/config/loader.ts +0 -0
  161. /package/{packages/cli/src → src}/config/schema.ts +0 -0
  162. /package/{packages/cli/src → src}/core/backup.ts +0 -0
  163. /package/{packages/cli/src → src}/core/health.ts +0 -0
  164. /package/{packages/cli/src → src}/core/local.ts +0 -0
  165. /package/{packages/cli/src → src}/core/lock.ts +0 -0
  166. /package/{packages/cli/src → src}/core/nginx.ts +0 -0
  167. /package/{packages/cli/src → src}/core/ssh.ts +0 -0
  168. /package/{packages/cli/src → src}/core/sync.ts +0 -0
  169. /package/{packages/cli/src → src}/core/workspace.ts +0 -0
  170. /package/{packages/cli/src → src}/index.ts +0 -0
  171. /package/{packages/cli/src → src}/runtimes/base.ts +0 -0
  172. /package/{packages/cli/src → src}/runtimes/nodejs/detector.ts +0 -0
  173. /package/{packages/cli/src → src}/runtimes/nodejs/index.ts +0 -0
  174. /package/{packages/cli/src → src}/runtimes/nodejs/pm2.ts +0 -0
  175. /package/{packages/cli/src → src}/runtimes/registry.ts +0 -0
  176. /package/{packages/cli/src → src}/utils/logger.ts +0 -0
  177. /package/{packages/cli/src → src}/utils/validation.ts +0 -0
  178. /package/{packages/cli/tsconfig.json → tsconfig.json} +0 -0
  179. /package/{packages/cli/vitest.config.ts → vitest.config.ts} +0 -0
package/README.md DELETED
@@ -1,1136 +0,0 @@
1
- # hostfn
2
-
3
- **Universal application deployment CLI** - Deploy Node.js applications to any VPS.
4
-
5
- > Zero-downtime deployments • Health checks • Auto-rollback • PM2 integration • Nginx setup and SSL support
6
-
7
- ---
8
-
9
- ## Quick Start
10
-
11
- ```bash
12
- # Initialize configuration
13
- cd your-project
14
- hostfn init
15
-
16
- # Setup server (Requires ssh keys pre-configured)
17
- hostfn server setup username@your-server.com
18
-
19
- # Deploy to production
20
- hostfn deploy production
21
-
22
- # Expose via Nginx, provision SSL certificate(s)
23
- hostfn expose production
24
-
25
- # Monitor your app
26
- hostfn status production
27
- hostfn logs production
28
- ```
29
-
30
- ---
31
-
32
- ## Table of Contents
33
-
34
- - [Installation](#installation)
35
- - [Getting Started](#getting-started)
36
- - [Configuration](#configuration)
37
- - [Single Application](#single-application)
38
- - [Monorepo / Multi-Service](#monorepo--multi-service)
39
- - [Commands Reference](#commands-reference)
40
- - [Deployment Strategies](#deployment-strategies)
41
- - [Advanced Topics](#advanced-topics)
42
- - [Examples](#examples)
43
- - [Architecture](#architecture)
44
- - [Development](#development)
45
-
46
- ---
47
- ## Installation
48
-
49
- ### via npm
50
-
51
- ```bash
52
- npm install -g hostfn
53
- ```
54
-
55
- ### via source
56
-
57
- ```bash
58
- # Clone repository
59
- cd hostfn/
60
- # Install dependencies
61
- npm install
62
- # Build the project
63
- npm run build
64
- cd packages/cli
65
- npm link
66
- ```
67
-
68
- ### Using the CLI
69
-
70
- ```bash
71
- # After linking
72
- hostfn --version
73
- hostfn --help
74
- ```
75
-
76
- ---
77
-
78
- ## Getting Started
79
-
80
- ### 1. Initialize Your Project
81
-
82
- ```bash
83
- cd your-project
84
- hostfn init
85
- ```
86
-
87
- This creates `hostfn.config.json` with smart defaults detected from your project.
88
-
89
- ### 2. Setup Your Server
90
-
91
- For the next steps to work, the ssh keys should configured on the machine where hostfn CLI is being used.
92
-
93
- ```bash
94
- eval "$(ssh-agent -s)"
95
- ssh-add ~/.ssh/your-private-key
96
- ```
97
-
98
- If ssh-agent or default ssh config is not available, you can set the SSH key and passphrase manually:
99
- ```bash
100
- export HOSTFN_SSH_PASSPHRASE="your-passphrase"
101
- export HOSTFN_SSH_KEY=$(cat ~/.ssh/your-private-key.pem | base64)
102
- hostfn <command> <environment>
103
- ```
104
-
105
- ```bash
106
- hostfn server setup ubuntu@your-server.com
107
- ```
108
-
109
- This installs:
110
- - Node.js (via nvm)
111
- - PM2 (process manager)
112
- - Required system dependencies
113
-
114
- ### 3. Setup environment variables and deploy
115
-
116
- ```bash
117
- hostfn env push production .env.production
118
- ```
119
- This uploads your local `.env.production` file to the server.
120
- To update an individual env value, use `hostfn env set <environment> <key> <value>` instead.
121
-
122
-
123
- ```bash
124
- hostfn deploy <environment>
125
- ```
126
-
127
- Deploy command will run the application with:
128
- - PM2 managing the process
129
- - Automatic restarts on crashes
130
- - Health checks ensuring readiness
131
- - Backup created for rollback
132
-
133
-
134
- ### 4. Expose the application
135
-
136
- ```bash
137
- hostfn expose <environment>
138
- ```
139
-
140
- This will expose the application via Nginx, provision SSL certificate(s) and create a DNS record.
141
-
142
- ### 5. Monitor the application
143
-
144
- ```bash
145
- hostfn status <environment>
146
- hostfn logs <environment>
147
- ```
148
-
149
- ---
150
-
151
- ## Configuration
152
-
153
- ### Single Application
154
-
155
- Create `hostfn.config.json` in your project root:
156
-
157
- ```json
158
- {
159
- "name": "my-app",
160
- "runtime": "nodejs",
161
- "version": "18",
162
- "environments": {
163
- "production": {
164
- "server": "ubuntu@prod.example.com",
165
- "port": 3000,
166
- "instances": "max",
167
- "domain": "api.example.com",
168
- "sslEmail": "admin@example.com"
169
- },
170
- "staging": {
171
- "server": "ubuntu@staging.example.com",
172
- "port": 3000,
173
- "instances": 2,
174
- "sslEmail": "admin@example.com",
175
- "domain": ["domain1.example.com", "domain2.example.com"]
176
- }
177
- },
178
- "build": {
179
- "command": "npm run build",
180
- "directory": "dist",
181
- "nodeModules": "production"
182
- },
183
- "start": {
184
- "command": "npm start",
185
- "entry": "dist/index.js"
186
- },
187
- "health": {
188
- "path": "/health",
189
- "timeout": 60,
190
- "retries": 10,
191
- "interval": 3
192
- },
193
- "env": {
194
- "required": ["NODE_ENV", "DATABASE_URL"],
195
- "optional": ["REDIS_URL", "LOG_LEVEL"]
196
- },
197
- "sync": {
198
- "exclude": [
199
- "node_modules",
200
- ".git",
201
- "dist",
202
- ".env",
203
- "*.log"
204
- ]
205
- },
206
- "backup": {
207
- "keep": 5
208
- }
209
- }
210
- ```
211
-
212
- ### Monorepo / Multi-Service
213
-
214
- Perfect for microservices architectures where each service lives in its own directory.
215
-
216
- #### Strategy 1: All Services on Same Server
217
-
218
- ```json
219
- {
220
- "name": "my-monorepo",
221
- "runtime": "nodejs",
222
- "version": "18",
223
- "environments": {
224
- "production": {
225
- "server": "ubuntu@shared-server.com",
226
- "port": 3000,
227
- "instances": "max"
228
- }
229
- },
230
- "build": {
231
- "command": "npm run build",
232
- "directory": "dist"
233
- },
234
- "start": {
235
- "command": "npm start"
236
- },
237
- "services": {
238
- "account": {
239
- "port": 3001,
240
- "path": "services/account",
241
- "domain": "account.example.com",
242
- "instances": "max"
243
- },
244
- "auth": {
245
- "port": 3002,
246
- "path": "services/auth",
247
- "domain": "auth.example.com",
248
- "instances": 4
249
- },
250
- "notification": {
251
- "port": 3003,
252
- "path": "services/notification"
253
- }
254
- }
255
- }
256
- ```
257
-
258
- **Result**: All 3 services deploy to `ubuntu@shared-server.com`:
259
- - `my-monorepo-account-production` on port 3001
260
- - `my-monorepo-auth-production` on port 3002
261
- - `my-monorepo-notification-production` on port 3003
262
-
263
- #### Strategy 2: Services on Different Servers
264
-
265
- ```json
266
- {
267
- "name": "my-monorepo",
268
- "runtime": "nodejs",
269
- "version": "18",
270
- "environments": {
271
- "production": {
272
- "server": "ubuntu@default-server.com",
273
- "port": 3000,
274
- "instances": "max"
275
- }
276
- },
277
- "build": {
278
- "command": "npm run build",
279
- "directory": "dist"
280
- },
281
- "start": {
282
- "command": "npm start"
283
- },
284
- "services": {
285
- "account": {
286
- "port": 3001,
287
- "path": "services/account",
288
- "server": "ubuntu@account-dedicated.com",
289
- "instances": "max"
290
- },
291
- "auth": {
292
- "port": 3002,
293
- "path": "services/auth",
294
- "server": "ubuntu@auth-dedicated.com",
295
- "instances": 4
296
- },
297
- "notification": {
298
- "port": 3003,
299
- "path": "services/notification"
300
- }
301
- }
302
- }
303
- ```
304
-
305
- **Result**:
306
- - `account` → `ubuntu@account-dedicated.com`
307
- - `auth` → `ubuntu@auth-dedicated.com`
308
- - `notification` → `ubuntu@default-server.com` (fallback)
309
-
310
- **Perfect for:**
311
- - Isolating critical services (auth, payments)
312
- - Dedicated resources for high-traffic services
313
- - Geographic distribution
314
- - Security/compliance requirements
315
-
316
- ### Configuration Schema
317
-
318
- #### Root Fields
319
-
320
- | Field | Type | Required | Description |
321
- |-------|------|----------|-------------|
322
- | `name` | `string` | ✅ | Application name |
323
- | `runtime` | `'nodejs' \| 'python' \| 'go' \| 'ruby' \| 'rust' \| 'docker'` | ✅ | Runtime (only nodejs supported currently) |
324
- | `version` | `string` | ✅ | Runtime version |
325
- | `environments` | `object` | ✅ | Environment configurations |
326
- | `build` | `object` | ❌ | Build configuration |
327
- | `start` | `object` | ✅ | Start configuration |
328
- | `health` | `object` | ❌ | Health check configuration |
329
- | `env` | `object` | ❌ | Environment variable requirements |
330
- | `sync` | `object` | ❌ | File sync configuration |
331
- | `backup` | `object` | ❌ | Backup retention configuration |
332
- | `services` | `object` | ❌ | Multi-service configuration (monorepo) |
333
-
334
- #### Environment Configuration
335
-
336
- ```typescript
337
- {
338
- server: string; // SSH connection (user@host)
339
- port: number; // Service port
340
- instances: number | 'max'; // PM2 instances (default: 1)
341
- domain?: string; // Domain name
342
- sslEmail?: string; // Email for SSL certificate
343
- }
344
- ```
345
-
346
- #### Service Configuration (Monorepo)
347
-
348
- ```typescript
349
- {
350
- port: number; // Service port (required)
351
- path: string; // Path in monorepo (required)
352
- domain?: string; // Custom domain
353
- server?: string; // Override environment server
354
- instances?: number | 'max'; // Override PM2 instances
355
- }
356
- ```
357
-
358
- ---
359
-
360
- ## Commands Reference
361
-
362
- ### Initialize
363
-
364
- ```bash
365
- hostfn init
366
- ```
367
-
368
- Interactive setup that:
369
- - Detects your project runtime
370
- - Prompts for configuration
371
- - Creates `hostfn.config.json`
372
-
373
- ### Server Management
374
-
375
- ```bash
376
- # Setup a new server
377
- hostfn server setup ubuntu@your-server.com [options]
378
- --env <environment> Environment name (default: production)
379
- --node-version <version> Node.js version (default: 18)
380
- --port <port> Service port (default: 3000)
381
- --redis Install Redis
382
- --password <password> SSH password (if not using key auth)
383
-
384
- # View server information
385
- hostfn server info ubuntu@your-server.com
386
- ```
387
-
388
- ### Deployment
389
-
390
- ```bash
391
- # Deploy to an environment
392
- hostfn deploy [environment] [options]
393
- [environment] Environment to deploy to (default: production)
394
- --host <host> Override server host
395
- --ci CI/CD mode (non-interactive)
396
- --dry-run Show what would be deployed
397
- --service <name> Deploy specific service (monorepo)
398
- --all Deploy all services (monorepo)
399
-
400
- # Examples
401
- hostfn deploy production
402
- hostfn deploy staging --dry-run
403
- hostfn deploy prod --ci
404
- hostfn deploy production --service account
405
- hostfn deploy production --all
406
- hostfn deploy production --local --ci # Self-hosted runner
407
- ```
408
-
409
- ### Monitoring
410
-
411
- ```bash
412
- # View application status
413
- hostfn status [environment] [options]
414
- [environment] Environment (default: production)
415
- --service <name> Show specific service status (monorepo)
416
-
417
- # View logs
418
- hostfn logs [environment] [options]
419
- [environment] Environment (default: production)
420
- --lines <n> Number of lines (default: 100)
421
- --errors Show only errors
422
- --output <file> Save logs to file
423
- --service <name> View specific service logs (monorepo)
424
-
425
- # Examples
426
- hostfn status production
427
- hostfn status prod --service account
428
- hostfn logs production --lines 500
429
- hostfn logs prod --service auth --errors
430
- hostfn logs production --output debug.log
431
- ```
432
-
433
- ### Rollback
434
-
435
- ```bash
436
- # Rollback to previous deployment
437
- hostfn rollback [environment] [options]
438
- [environment] Environment (default: production)
439
- --to <timestamp> Rollback to specific backup
440
-
441
- # Examples
442
- hostfn rollback production # Interactive selection
443
- hostfn rollback prod --to 20240115-120000
444
- ```
445
-
446
- ### Environment Variables
447
-
448
- ```bash
449
- # List environment variables (masked)
450
- hostfn env list <environment>
451
-
452
- # Set a variable
453
- hostfn env set <environment> <key> <value>
454
-
455
- # Upload .env file
456
- hostfn env push <environment> <file>
457
-
458
- # Download .env file
459
- hostfn env pull <environment> <file>
460
-
461
- # Validate required variables
462
- hostfn env validate <environment>
463
-
464
- # Examples
465
- hostfn env list production
466
- hostfn env set prod DATABASE_URL "postgresql://..."
467
- hostfn env push production .env.production
468
- hostfn env pull production .env.backup
469
- hostfn env validate production
470
- ```
471
-
472
- ---
473
-
474
- ## CI/CD Integration
475
-
476
- ### GitHub Actions
477
-
478
- #### Remote Deployment (Standard CI/CD)
479
-
480
- For deploying from GitHub Actions to a remote server:
481
-
482
- ```yaml
483
- name: Deploy
484
-
485
- on:
486
- push:
487
- branches: [main]
488
-
489
- jobs:
490
- deploy:
491
- runs-on: ubuntu-latest
492
-
493
- steps:
494
- - uses: actions/checkout@v4
495
-
496
- - name: Setup Node.js
497
- uses: actions/setup-node@v4
498
- with:
499
- node-version: '20'
500
-
501
- - name: Install hostfn
502
- run: npm install -g hostfn
503
-
504
- - name: Deploy
505
- env:
506
- HOSTFN_SSH_KEY: ${{ secrets.HOSTFN_SSH_KEY }}
507
- HOSTFN_SSH_PASSPHRASE: ${{ secrets.HOSTFN_SSH_PASSPHRASE }}
508
- run: hostfn deploy production --ci
509
- ```
510
-
511
- **Setup GitHub Secrets:**
512
-
513
- 1. Generate base64-encoded SSH key:
514
- ```bash
515
- cat ~/.ssh/your_key | base64
516
- ```
517
-
518
- 2. Add to GitHub repository secrets:
519
- - `HOSTFN_SSH_KEY`: Base64-encoded private key
520
- - `HOSTFN_SSH_PASSPHRASE`: SSH key passphrase (if any)
521
-
522
- #### Self-Hosted Runner (Local Deployment)
523
-
524
- For deploying on a self-hosted GitHub Actions runner running on your deployment server:
525
-
526
- ```yaml
527
- name: Deploy
528
-
529
- on:
530
- push:
531
- branches: [main]
532
-
533
- jobs:
534
- deploy:
535
- runs-on: self-hosted
536
-
537
- steps:
538
- - uses: actions/checkout@v4
539
-
540
- - name: Deploy locally
541
- run: hostfn deploy production --local --ci
542
- ```
543
-
544
- **Why `--local` mode?**
545
- - No SSH needed (already on the server)
546
- - Faster deployment (no network transfer)
547
- - Uses local file operations instead of rsync
548
- - Perfect for self-hosted runners
549
-
550
- ### Environment Variables
551
-
552
- **For CI/CD:**
553
- - `HOSTFN_SSH_KEY`: Base64-encoded SSH private key
554
- - `HOSTFN_SSH_PASSPHRASE`: SSH key passphrase (optional)
555
- - `HOSTFN_HOST`: Override server host
556
-
557
- **In GitHub Actions, these are set automatically from secrets:**
558
- ```yaml
559
- env:
560
- HOSTFN_SSH_KEY: ${{ secrets.HOSTFN_SSH_KEY }}
561
- HOSTFN_SSH_PASSPHRASE: ${{ secrets.HOSTFN_SSH_PASSPHRASE }}
562
- ```
563
-
564
- **For local testing or other CI platforms:**
565
- ```bash
566
- # Encode SSH key for GitHub secrets
567
- cat ~/.ssh/id_rsa | base64
568
-
569
- # Then add to GitHub secrets via repository settings
570
- ```
571
-
572
- ### Other CI/CD Platforms
573
-
574
- **GitLab CI:**
575
- ```yaml
576
- deploy:
577
- stage: deploy
578
- script:
579
- - npm install -g hostfn
580
- - hostfn deploy production --ci
581
- variables:
582
- HOSTFN_SSH_KEY: $CI_SSH_KEY
583
- HOSTFN_SSH_PASSPHRASE: $CI_SSH_PASSPHRASE
584
- only:
585
- - main
586
- ```
587
-
588
- **CircleCI:**
589
- ```yaml
590
- deploy:
591
- docker:
592
- - image: node:20
593
- steps:
594
- - checkout
595
- - run: npm install -g hostfn
596
- - run: hostfn deploy production --ci
597
- environment:
598
- HOSTFN_SSH_KEY: $HOSTFN_SSH_KEY
599
- HOSTFN_SSH_PASSPHRASE: $HOSTFN_SSH_PASSPHRASE
600
- ```
601
-
602
- ---
603
-
604
- ## Deployment Strategies
605
-
606
- ### Single Application
607
-
608
- Perfect for:
609
- - Simple APIs or web apps
610
- - Monolithic applications
611
- - Single-service projects
612
-
613
- ```json
614
- {
615
- "name": "my-api",
616
- "runtime": "nodejs",
617
- "version": "18",
618
- "environments": {
619
- "production": {
620
- "server": "ubuntu@prod.com",
621
- "port": 3000,
622
- "instances": "max"
623
- }
624
- }
625
- }
626
- ```
627
-
628
- ### Monorepo: All Services on Same Server
629
-
630
- Perfect for:
631
- - Development/staging environments
632
- - Small to medium applications
633
- - Cost-effective deployments
634
- - Services that don't need isolation
635
-
636
- ```json
637
- {
638
- "environments": {
639
- "production": {
640
- "server": "ubuntu@shared.com"
641
- }
642
- },
643
- "services": {
644
- "api": { "port": 3001, "path": "services/api" },
645
- "worker": { "port": 3002, "path": "services/worker" },
646
- "admin": { "port": 3003, "path": "services/admin" }
647
- }
648
- }
649
- ```
650
-
651
- **Deployment:**
652
- ```bash
653
- hostfn deploy production # Deploys all 3 services
654
- hostfn deploy production --service api # Deploys just api
655
- ```
656
-
657
- ### Monorepo: Services on Different Servers
658
-
659
- Perfect for:
660
- - Production environments
661
- - High-traffic services needing dedicated resources
662
- - Critical service isolation (auth, payments)
663
- - Geographic distribution
664
- - Security/compliance requirements
665
-
666
- ```json
667
- {
668
- "environments": {
669
- "production": {
670
- "server": "ubuntu@default.com"
671
- }
672
- },
673
- "services": {
674
- "api": {
675
- "port": 3001,
676
- "path": "services/api",
677
- "instances": "max"
678
- },
679
- "auth": {
680
- "port": 3002,
681
- "path": "services/auth",
682
- "server": "ubuntu@auth-dedicated.com",
683
- "instances": 4
684
- },
685
- "payment": {
686
- "port": 3003,
687
- "path": "services/payment",
688
- "server": "ubuntu@pci-compliant.com",
689
- "instances": 2
690
- }
691
- }
692
- }
693
- ```
694
-
695
- **Result:**
696
- - `api` → `ubuntu@default.com` (shared server)
697
- - `auth` → `ubuntu@auth-dedicated.com` (dedicated)
698
- - `payment` → `ubuntu@pci-compliant.com` (isolated for compliance)
699
-
700
- ### Hybrid Approach
701
-
702
- Mix shared and dedicated servers based on needs:
703
-
704
- ```json
705
- {
706
- "services": {
707
- "public-api": {
708
- "port": 3001,
709
- "path": "services/api",
710
- "server": "ubuntu@public-edge.com",
711
- "instances": "max"
712
- },
713
- "internal-api": {
714
- "port": 3002,
715
- "path": "services/internal"
716
- },
717
- "worker": {
718
- "port": 3003,
719
- "path": "services/worker",
720
- "instances": 2
721
- }
722
- }
723
- }
724
- ```
725
-
726
- ---
727
-
728
- ## Advanced Topics
729
-
730
- ### Deployment Flow
731
-
732
- 1. **Pre-flight Checks**
733
- - Verify rsync availability
734
- - Connect to server via SSH
735
- - Check/create remote directory
736
- - Acquire deployment lock
737
-
738
- 2. **File Sync**
739
- - Sync files with rsync (respects `.exclude` patterns)
740
- - Fast incremental transfers
741
-
742
- 3. **Remote Build**
743
- - Install dependencies (`npm ci --production`)
744
- - Run build command if specified
745
- - Build output in configured directory
746
-
747
- 4. **Backup**
748
- - Create timestamped backup of current deployment
749
- - Keep N most recent backups (configurable)
750
-
751
- 5. **PM2 Deployment**
752
- - Generate PM2 ecosystem config
753
- - Start new process or reload existing (zero-downtime)
754
- - Save PM2 configuration
755
-
756
- 6. **Health Check**
757
- - Poll health endpoint with retries
758
- - Configurable timeout and interval
759
- - Fail deployment if unhealthy
760
-
761
- 7. **Auto-Rollback** (on failure)
762
- - Restore previous deployment from backup
763
- - Reload PM2 with old version
764
- - Report rollback status
765
-
766
- ### Directory Structure on Server
767
-
768
- Single application:
769
- ```
770
- /var/www/
771
- └── my-app-production/
772
- ├── .env
773
- ├── package.json
774
- ├── node_modules/
775
- ├── dist/
776
- └── ecosystem.config.cjs
777
- ```
778
-
779
- Monorepo (multi-service):
780
- ```
781
- /var/www/
782
- ├── my-monorepo-account-production/
783
- │ ├── .env
784
- │ ├── package.json
785
- │ ├── node_modules/
786
- │ └── dist/
787
- ├── my-monorepo-auth-production/
788
- │ ├── .env
789
- │ ├── package.json
790
- │ ├── node_modules/
791
- │ └── dist/
792
- └── my-monorepo-notification-production/
793
- ├── .env
794
- ├── package.json
795
- ├── node_modules/
796
- └── dist/
797
- ```
798
-
799
- ### Service Naming Convention
800
-
801
- - **Single app**: `{name}-{environment}`
802
- - Example: `my-app-production`
803
-
804
- - **Monorepo**: `{name}-{serviceName}-{environment}`
805
- - Example: `21n-account-production`
806
-
807
- ### Health Check Implementation
808
-
809
- Your application should expose a health endpoint:
810
-
811
- ```javascript
812
- // Express example
813
- app.get('/health', (req, res) => {
814
- res.json({ status: 'ok' });
815
- });
816
-
817
- // Fastify example
818
- fastify.get('/health', async (request, reply) => {
819
- return { status: 'ok' };
820
- });
821
- ```
822
-
823
- Configure in `hostfn.config.json`:
824
- ```json
825
- {
826
- "health": {
827
- "path": "/health",
828
- "timeout": 60,
829
- "retries": 10,
830
- "interval": 3
831
- }
832
- }
833
- ```
834
-
835
- ### Environment Variables
836
-
837
- hostfn automatically loads environment variables from a `.env` file on your server. The PM2 process manager is configured to read from `.env` in the deployment directory.
838
-
839
- #### Option 1: Push .env file (Recommended)
840
- ```bash
841
- hostfn env push production .env.production
842
- ```
843
-
844
- This uploads your local `.env` file to the server. After deployment, PM2 will automatically load these variables.
845
-
846
- #### Option 2: Set individual variables
847
- ```bash
848
- hostfn env set production DATABASE_URL "postgresql://..."
849
- hostfn env set production REDIS_URL "redis://..."
850
- ```
851
-
852
- Note: After setting variables, redeploy to reload the PM2 process with updated env vars.
853
-
854
- #### Option 3: Validate requirements
855
- ```json
856
- {
857
- "env": {
858
- "required": ["DATABASE_URL", "API_KEY"],
859
- "optional": ["REDIS_URL", "LOG_LEVEL"]
860
- }
861
- }
862
- ```
863
-
864
- ```bash
865
- hostfn env validate production
866
- ```
867
-
868
- ### CI/CD Integration
869
-
870
- ```yaml
871
- # GitHub Actions example
872
- name: Deploy
873
- on:
874
- push:
875
- branches: [main]
876
-
877
- jobs:
878
- deploy:
879
- runs-on: ubuntu-latest
880
- steps:
881
- - uses: actions/checkout@v3
882
-
883
- - name: Setup Node.js
884
- uses: actions/setup-node@v3
885
- with:
886
- node-version: '18'
887
-
888
- - name: Install hostfn
889
- run: npm install -g hostfn
890
-
891
- - name: Setup SSH Key
892
- run: |
893
- mkdir -p ~/.ssh
894
- echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
895
- chmod 600 ~/.ssh/id_rsa
896
-
897
- - name: Deploy to Production
898
- run: hostfn deploy production --ci
899
- env:
900
- HOSTFN_HOST: ${{ secrets.PRODUCTION_HOST }}
901
- ```
902
-
903
- For monorepo, deploy only changed services:
904
- ```yaml
905
- - name: Deploy Changed Services
906
- run: |
907
- if [[ $(git diff --name-only HEAD~1 | grep '^services/account/') ]]; then
908
- hostfn deploy production --ci --service account
909
- fi
910
- if [[ $(git diff --name-only HEAD~1 | grep '^services/auth/') ]]; then
911
- hostfn deploy production --ci --service auth
912
- fi
913
- ```
914
-
915
- ---
916
-
917
- ## 📚 Examples
918
-
919
- ### Example 1: Simple Express API
920
-
921
- ```json
922
- {
923
- "name": "express-api",
924
- "runtime": "nodejs",
925
- "version": "18",
926
- "environments": {
927
- "production": {
928
- "server": "ubuntu@api.example.com",
929
- "port": 3000,
930
- "instances": "max"
931
- }
932
- },
933
- "build": {
934
- "command": "npm run build",
935
- "directory": "dist"
936
- },
937
- "start": {
938
- "command": "npm start",
939
- "entry": "dist/server.js"
940
- }
941
- }
942
- ```
943
-
944
- ### Example 2: Microservices Monorepo
945
-
946
- ```json
947
- {
948
- "name": "21n",
949
- "runtime": "nodejs",
950
- "version": "18",
951
- "environments": {
952
- "production": {
953
- "server": "ubuntu@shared.21n.com",
954
- "port": 3000,
955
- "instances": "max"
956
- }
957
- },
958
- "build": {
959
- "command": "npm run build",
960
- "directory": "dist"
961
- },
962
- "start": {
963
- "command": "npm start"
964
- },
965
- "services": {
966
- "account": {
967
- "port": 3001,
968
- "path": "services/account",
969
- "domain": "account.21n.com",
970
- "instances": "max"
971
- },
972
- "auth": {
973
- "port": 3002,
974
- "path": "services/auth",
975
- "domain": "auth.21n.com",
976
- "server": "ubuntu@auth.21n.com",
977
- "instances": 4
978
- },
979
- "notification": {
980
- "port": 3003,
981
- "path": "services/notification",
982
- "domain": "notification.21n.com",
983
- "instances": 2
984
- },
985
- "analytics": {
986
- "port": 3004,
987
- "path": "services/analytics",
988
- "instances": 1
989
- }
990
- },
991
- "health": {
992
- "path": "/health",
993
- "timeout": 60,
994
- "retries": 10,
995
- "interval": 3
996
- }
997
- }
998
- ```
999
-
1000
- See `examples/` directory for more complete examples.
1001
-
1002
- ---
1003
-
1004
- ## Architecture
1005
-
1006
- ```
1007
- hostfn/
1008
- ├── packages/
1009
- │ └── cli/ # Main CLI package
1010
- │ ├── src/
1011
- │ │ ├── commands/ # Command implementations
1012
- │ │ │ ├── deploy.ts # Deployment engine
1013
- │ │ │ ├── status.ts # Status monitoring
1014
- │ │ │ ├── logs.ts # Log streaming
1015
- │ │ │ ├── rollback.ts # Rollback system
1016
- │ │ │ ├── env.ts # Environment variables
1017
- │ │ │ ├── init.ts # Project initialization
1018
- │ │ │ └── server/ # Server management
1019
- │ │ ├── config/ # Config schema & loader
1020
- │ │ │ ├── schema.ts # Zod schema
1021
- │ │ │ └── loader.ts # Config loading
1022
- │ │ ├── runtimes/ # Runtime adapters
1023
- │ │ │ ├── base.ts # Base adapter interface
1024
- │ │ │ ├── registry.ts # Runtime registry
1025
- │ │ │ └── nodejs/ # Node.js adapter (PM2)
1026
- │ │ ├── core/ # Core business logic
1027
- │ │ │ ├── ssh.ts # SSH connection manager
1028
- │ │ │ ├── sync.ts # File sync (rsync)
1029
- │ │ │ ├── health.ts # Health checking
1030
- │ │ │ ├── backup.ts # Backup management
1031
- │ │ │ └── lock.ts # Deployment locking
1032
- │ │ └── utils/ # Utilities
1033
- │ │ ├── logger.ts # Pretty logging
1034
- │ │ └── validation.ts
1035
- │ └── package.json
1036
- ├── examples/ # Example configurations
1037
- │ ├── monorepo-config.json
1038
- │ └── monorepo-multi-server-config.json
1039
- ├── _conduct/
1040
- │ ├── specs/ # Project specifications
1041
- │ └── .meta/ # Additional documentation
1042
- │ ├── MONOREPO_GUIDE.md
1043
- │ ├── QUICK_START_MONOREPO.md
1044
- │ ├── CHANGELOG_MONOREPO.md
1045
- │ └── MULTI_SERVER_SUMMARY.md
1046
- └── README.md
1047
- ```
1048
-
1049
- ### Design Principles
1050
-
1051
- 1. **Pluggable Runtime System**
1052
- - Base adapter interface
1053
- - Runtime-specific implementations
1054
- - Easy to add new languages
1055
-
1056
- 2. **Type Safety**
1057
- - Zod for runtime validation
1058
- - TypeScript for compile-time safety
1059
- - Schema-driven configuration
1060
-
1061
- 3. **Production Ready**
1062
- - Health checks
1063
- - Auto-rollback on failure
1064
- - Zero-downtime deployments
1065
- - Deployment locking
1066
-
1067
- 4. **Developer Experience**
1068
- - Interactive CLI
1069
- - Smart defaults
1070
- - Clear error messages
1071
- - Dry-run mode
1072
-
1073
- ---
1074
-
1075
- ## Development
1076
-
1077
- ```bash
1078
- # Clone and setup
1079
- git clone <repo>
1080
- cd hostfn
1081
- npm install
1082
-
1083
- # Build
1084
- npm run build
1085
-
1086
- # Watch mode (development)
1087
- npm run dev
1088
-
1089
- # Lint
1090
- npm run lint
1091
-
1092
- # Test
1093
- npm run test
1094
-
1095
- # Link for local testing
1096
- cd packages/cli
1097
- npm link
1098
-
1099
- # Use globally
1100
- hostfn --help
1101
- ```
1102
-
1103
- ### Project Structure
1104
-
1105
- - **Monorepo**: Managed with Turborepo
1106
- - **TypeScript**: Strict mode enabled
1107
- - **Package Manager**: npm
1108
- - **Node Version**: >=18.0.0
1109
-
1110
- ---
1111
-
1112
- ## Contributing
1113
-
1114
- 1. Fork the repository
1115
- 2. Create a feature branch
1116
- 3. Make your changes
1117
- 4. Run tests and linting
1118
- 5. Submit a pull request
1119
-
1120
- ---
1121
- ### Roadmap
1122
- - Additional runtime adapters (Python, Go, Ruby, Rust)
1123
- - Parallel service deployments
1124
- - Service dependency graphs
1125
- - Web dashboard
1126
- - Metrics collection
1127
- - CI/CD templates
1128
- ---
1129
-
1130
- ## License
1131
-
1132
- MIT
1133
-
1134
-
1135
-
1136
-