@kirschbaum-development/sst-laravel 0.2.14 → 0.2.16
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/docs/api.md +597 -0
- package/laravel-sst.ts +1 -1
- package/package.json +6 -2
- package/src/remote-env-file.ts +24 -5
package/docs/api.md
ADDED
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
# Laravel Component API Reference
|
|
2
|
+
|
|
3
|
+
## RemoteEnvVault
|
|
4
|
+
|
|
5
|
+
The `RemoteEnvVault` component manages environment variables for your Laravel application using AWS Secrets Manager. This provides a secure way to store and manage sensitive configuration values.
|
|
6
|
+
|
|
7
|
+
### Large Environment Files
|
|
8
|
+
|
|
9
|
+
Environment files that exceed AWS Secrets Manager's 64KB limit are automatically split into multiple chunks. This is handled transparently by the CLI commands - you don't need to do anything special.
|
|
10
|
+
|
|
11
|
+
When pushing a large `.env` file:
|
|
12
|
+
- The file is automatically split into multiple secrets (e.g., `/{app}/{stage}/env/1`, `/{app}/{stage}/env/2`, etc.)
|
|
13
|
+
- A metadata secret at `/{app}/{stage}/env` tracks the chunk count
|
|
14
|
+
- When pulling or deploying, all chunks are automatically merged back together
|
|
15
|
+
|
|
16
|
+
### Constructor
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
new RemoteEnvVault(name: string, args?: RemoteEnvVaultArgs, opts?: ComponentResourceOptions)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### RemoteEnvVaultArgs
|
|
23
|
+
|
|
24
|
+
#### `path`
|
|
25
|
+
- **Type:** `Input<string>`
|
|
26
|
+
- **Default:** `/{app-name}/{stage}/env`
|
|
27
|
+
- **Description:** The path in AWS Secrets Manager where environment variables will be stored.
|
|
28
|
+
|
|
29
|
+
**Example:**
|
|
30
|
+
```typescript
|
|
31
|
+
const env = new RemoteEnvVault("Env", {
|
|
32
|
+
path: "/my-app/production/env"
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Properties
|
|
37
|
+
|
|
38
|
+
#### `path`
|
|
39
|
+
- **Type:** `Output<string>`
|
|
40
|
+
- **Description:** The path in AWS Secrets Manager where environment variables are stored.
|
|
41
|
+
|
|
42
|
+
### CLI Commands
|
|
43
|
+
|
|
44
|
+
The following CLI commands are available for managing environment variables:
|
|
45
|
+
|
|
46
|
+
#### `env:push`
|
|
47
|
+
|
|
48
|
+
Push environment variables from a local `.env` file to AWS Secrets Manager.
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
sst-laravel env:push [options]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Options:**
|
|
55
|
+
- `-s, --stage <stage>` - SST stage name
|
|
56
|
+
- `-i, --input <file>` - Input file path (default: `.env`)
|
|
57
|
+
- `-f, --force` - Push without confirmation
|
|
58
|
+
|
|
59
|
+
**Example:**
|
|
60
|
+
```bash
|
|
61
|
+
# Push .env.production to the production stage
|
|
62
|
+
sst-laravel env:push --stage production --input .env.production
|
|
63
|
+
|
|
64
|
+
# Push .env to staging with confirmation
|
|
65
|
+
sst-laravel env:push --stage staging
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### `env:pull`
|
|
69
|
+
|
|
70
|
+
Pull environment variables from AWS Secrets Manager to a local `.env` file.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
sst-laravel env:pull [options]
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Options:**
|
|
77
|
+
- `-s, --stage <stage>` - SST stage name
|
|
78
|
+
- `-o, --output <file>` - Output file path (default: `.env.{stage}`)
|
|
79
|
+
- `-f, --force` - Overwrite existing file without confirmation
|
|
80
|
+
|
|
81
|
+
**Example:**
|
|
82
|
+
```bash
|
|
83
|
+
# Pull from production to .env.production
|
|
84
|
+
sst-laravel env:pull --stage production
|
|
85
|
+
|
|
86
|
+
# Pull from staging to a custom file
|
|
87
|
+
sst-laravel env:pull --stage staging --output .env.local
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Usage with LaravelService
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
const env = new RemoteEnvVault("Env");
|
|
94
|
+
|
|
95
|
+
new LaravelService("Laravel", {
|
|
96
|
+
vpc,
|
|
97
|
+
web: {
|
|
98
|
+
domain: "example.com"
|
|
99
|
+
},
|
|
100
|
+
config: {
|
|
101
|
+
environment: {
|
|
102
|
+
secrets: env
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
When using `RemoteEnvVault`, deploy your application using the `sst-laravel deploy` command, which will automatically fetch secrets from AWS Secrets Manager before building the Docker image:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
sst-laravel deploy --stage production
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## LaravelService
|
|
117
|
+
|
|
118
|
+
### Constructor
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
new LaravelService(name: string, args: LaravelArgs, opts?: ComponentResourceOptions)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Creates a new Laravel component for deploying Laravel applications to AWS Fargate.
|
|
125
|
+
|
|
126
|
+
## LaravelArgs
|
|
127
|
+
|
|
128
|
+
### `path`
|
|
129
|
+
- **Type:** `Input<string>`
|
|
130
|
+
- **Default:** `'.'`
|
|
131
|
+
- **Description:** Path to the Laravel application directory.
|
|
132
|
+
|
|
133
|
+
### `link`
|
|
134
|
+
- **Type:** `Array<Resource | { resource: Resource; environment?: EnvCallback }>`
|
|
135
|
+
- **Description:** Resources to link to the Laravel application. Supports SST resources like databases, Redis, email services, queues, and S3 buckets. When linked, environment variables are automatically configured.
|
|
136
|
+
|
|
137
|
+
Supported resources with automatic environment variable injection:
|
|
138
|
+
- `Postgres` - Sets `DB_CONNECTION`, `DB_HOST`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD`, `DB_PORT`
|
|
139
|
+
- `Mysql` - Sets `DB_CONNECTION`, `DB_HOST`, `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD`, `DB_PORT`
|
|
140
|
+
- `Aurora` - Sets database variables based on port (5432 for Postgres, 3306 for MySQL)
|
|
141
|
+
- `Redis` - Sets `REDIS_HOST`, `REDIS_PORT`, `REDIS_PASSWORD`
|
|
142
|
+
- `Email` - Sets `MAIL_MAILER` to 'ses'
|
|
143
|
+
- `Queue` - Sets `SQS_QUEUE`
|
|
144
|
+
- `Bucket` - Sets `FILESYSTEM_DISK` to 's3', `AWS_BUCKET`
|
|
145
|
+
|
|
146
|
+
You can provide a custom `environment` callback function to override or extend the default environment variables:
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
link: [
|
|
150
|
+
{
|
|
151
|
+
resource: myDatabase,
|
|
152
|
+
environment: (resource) => ({
|
|
153
|
+
CUSTOM_DB_VAR: resource.host
|
|
154
|
+
})
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `permissions`
|
|
160
|
+
- **Type:** `Array<{ actions: string[]; resources: string[] }>`
|
|
161
|
+
- **Description:** IAM permissions to grant to the Laravel application containers.
|
|
162
|
+
|
|
163
|
+
**Example:**
|
|
164
|
+
```typescript
|
|
165
|
+
permissions: [
|
|
166
|
+
{
|
|
167
|
+
actions: ["s3:GetObject", "s3:PutObject"],
|
|
168
|
+
resources: ["arn:aws:s3:::my-bucket/*"]
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### `vpc`
|
|
174
|
+
- **Type:** `ClusterArgs["vpc"]`
|
|
175
|
+
- **Description:** VPC configuration for the ECS cluster. Inherited from SST's Cluster component.
|
|
176
|
+
|
|
177
|
+
### `web`
|
|
178
|
+
- **Type:** `LaravelWebArgs`
|
|
179
|
+
- **Description:** Configuration for the web service that handles HTTP traffic.
|
|
180
|
+
|
|
181
|
+
#### `web.domain`
|
|
182
|
+
- **Type:** `Input<string | { name: Input<string>; cert?: Input<string>; dns?: Input<false | Dns> }>`
|
|
183
|
+
- **Description:** Custom domain for the web layer. If you don't provide a domain name, you will be able to use the load balancer domain for testing (http only).
|
|
184
|
+
|
|
185
|
+
**Example (simple string):**
|
|
186
|
+
```typescript
|
|
187
|
+
web: {
|
|
188
|
+
domain: "example.com"
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Example (with stage variable):**
|
|
193
|
+
```typescript
|
|
194
|
+
web: {
|
|
195
|
+
domain: {
|
|
196
|
+
name: `${$app.stage}.example.com`
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Example (with custom certificate):**
|
|
202
|
+
```typescript
|
|
203
|
+
web: {
|
|
204
|
+
domain: {
|
|
205
|
+
name: "example.com",
|
|
206
|
+
cert: "arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012"
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Example (with custom DNS provider):**
|
|
212
|
+
```typescript
|
|
213
|
+
web: {
|
|
214
|
+
domain: {
|
|
215
|
+
name: "example.com",
|
|
216
|
+
dns: sst.cloudflare.dns()
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### `web.architecture`
|
|
222
|
+
- **Type:** `ServiceArgs["architecture"]`
|
|
223
|
+
- **Description:** The CPU architecture for the web service.
|
|
224
|
+
|
|
225
|
+
#### `web.cpu`
|
|
226
|
+
- **Type:** `ServiceArgs["cpu"]`
|
|
227
|
+
- **Description:** CPU units for the web service.
|
|
228
|
+
|
|
229
|
+
#### `web.memory`
|
|
230
|
+
- **Type:** `ServiceArgs["memory"]`
|
|
231
|
+
- **Description:** Memory allocation for the web service.
|
|
232
|
+
|
|
233
|
+
#### `web.storage`
|
|
234
|
+
- **Type:** `ServiceArgs["storage"]`
|
|
235
|
+
- **Description:** Storage configuration for the web service.
|
|
236
|
+
|
|
237
|
+
#### `web.scaling`
|
|
238
|
+
- **Type:** `ServiceArgs["scaling"]`
|
|
239
|
+
- **Description:** Auto-scaling configuration for the web service.
|
|
240
|
+
|
|
241
|
+
**Example:**
|
|
242
|
+
```typescript
|
|
243
|
+
web: {
|
|
244
|
+
scaling: {
|
|
245
|
+
min: 2,
|
|
246
|
+
max: 10,
|
|
247
|
+
cpuUtilization: 70,
|
|
248
|
+
memoryUtilization: 80
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
#### `web.logging`
|
|
254
|
+
- **Type:** `ServiceArgs["logging"]`
|
|
255
|
+
- **Description:** Logging configuration for the web service.
|
|
256
|
+
|
|
257
|
+
#### `web.health`
|
|
258
|
+
- **Type:** `ServiceArgs["health"]`
|
|
259
|
+
- **Description:** Health check configuration for the web service.
|
|
260
|
+
|
|
261
|
+
#### `web.executionRole`
|
|
262
|
+
- **Type:** `ServiceArgs["executionRole"]`
|
|
263
|
+
- **Description:** Execution role for the web service.
|
|
264
|
+
|
|
265
|
+
#### `web.permissions`
|
|
266
|
+
- **Type:** `ServiceArgs["permissions"]`
|
|
267
|
+
- **Description:** IAM permissions specific to the web service.
|
|
268
|
+
|
|
269
|
+
### `workers`
|
|
270
|
+
- **Type:** `LaravelWorkerConfig[]`
|
|
271
|
+
- **Description:** Configuration for worker services (Horizon, scheduler, or custom tasks).
|
|
272
|
+
|
|
273
|
+
#### `workers[].name`
|
|
274
|
+
- **Type:** `Input<string>`
|
|
275
|
+
- **Description:** Name of the worker service. If not provided, defaults to `worker-{index}`.
|
|
276
|
+
|
|
277
|
+
#### `workers[].horizon`
|
|
278
|
+
- **Type:** `Input<boolean>`
|
|
279
|
+
- **Default:** `false`
|
|
280
|
+
- **Description:** Running horizon?
|
|
281
|
+
|
|
282
|
+
#### `workers[].scheduler`
|
|
283
|
+
- **Type:** `Input<boolean>`
|
|
284
|
+
- **Default:** `false`
|
|
285
|
+
- **Description:** Running scheduler?
|
|
286
|
+
|
|
287
|
+
#### `workers[].tasks`
|
|
288
|
+
- **Type:** `Input<{ [key: string]: Input<{ command: Input<string>; dependencies?: Input<string[]> }> }>`
|
|
289
|
+
- **Description:** Multiple tasks can be run in the worker.
|
|
290
|
+
|
|
291
|
+
**Example:**
|
|
292
|
+
```typescript
|
|
293
|
+
workers: [
|
|
294
|
+
{
|
|
295
|
+
name: "main-worker",
|
|
296
|
+
horizon: true,
|
|
297
|
+
scheduler: true,
|
|
298
|
+
scaling: {
|
|
299
|
+
min: 1,
|
|
300
|
+
max: 5
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
name: "custom-worker",
|
|
305
|
+
tasks: {
|
|
306
|
+
"my-task": {
|
|
307
|
+
command: "php artisan my:command",
|
|
308
|
+
dependencies: ["laravel-horizon"]
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
]
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
#### `workers[].architecture`
|
|
316
|
+
- **Type:** `ServiceArgs["architecture"]`
|
|
317
|
+
- **Description:** The CPU architecture for the worker service.
|
|
318
|
+
|
|
319
|
+
#### `workers[].cpu`
|
|
320
|
+
- **Type:** `ServiceArgs["cpu"]`
|
|
321
|
+
- **Description:** CPU units for the worker service.
|
|
322
|
+
|
|
323
|
+
#### `workers[].memory`
|
|
324
|
+
- **Type:** `ServiceArgs["memory"]`
|
|
325
|
+
- **Description:** Memory allocation for the worker service.
|
|
326
|
+
|
|
327
|
+
#### `workers[].storage`
|
|
328
|
+
- **Type:** `ServiceArgs["storage"]`
|
|
329
|
+
- **Description:** Storage configuration for the worker service.
|
|
330
|
+
|
|
331
|
+
#### `workers[].scaling`
|
|
332
|
+
- **Type:** `ServiceArgs["scaling"]`
|
|
333
|
+
- **Description:** Auto-scaling configuration for the worker service.
|
|
334
|
+
|
|
335
|
+
#### `workers[].logging`
|
|
336
|
+
- **Type:** `ServiceArgs["logging"]`
|
|
337
|
+
- **Description:** Logging configuration for the worker service.
|
|
338
|
+
|
|
339
|
+
#### `workers[].health`
|
|
340
|
+
- **Type:** `ServiceArgs["health"]`
|
|
341
|
+
- **Description:** Health check configuration for the worker service.
|
|
342
|
+
|
|
343
|
+
#### `workers[].executionRole`
|
|
344
|
+
- **Type:** `ServiceArgs["executionRole"]`
|
|
345
|
+
- **Description:** Execution role for the worker service.
|
|
346
|
+
|
|
347
|
+
#### `workers[].permissions`
|
|
348
|
+
- **Type:** `ServiceArgs["permissions"]`
|
|
349
|
+
- **Description:** IAM permissions specific to this worker.
|
|
350
|
+
|
|
351
|
+
### `config`
|
|
352
|
+
- **Type:** `object`
|
|
353
|
+
- **Description:** Config settings.
|
|
354
|
+
|
|
355
|
+
#### `config.php`
|
|
356
|
+
- **Type:** `Input<Number>`
|
|
357
|
+
- **Default:** `8.4`
|
|
358
|
+
- **Description:** PHP version. Available versions: 7.4, 8.0, 8.1, 8.2, 8.3, 8.4, 8.5
|
|
359
|
+
|
|
360
|
+
#### `config.opcache`
|
|
361
|
+
- **Type:** `Input<boolean>`
|
|
362
|
+
- **Default:** `true`
|
|
363
|
+
- **Description:** PHP Opcache should be enabled?
|
|
364
|
+
|
|
365
|
+
#### `config.environment`
|
|
366
|
+
- **Type:** `object`
|
|
367
|
+
- **Description:** Environment variable configuration.
|
|
368
|
+
|
|
369
|
+
##### `config.environment.file`
|
|
370
|
+
- **Type:** `Input<string>`
|
|
371
|
+
- **Description:** Use this option if you want to import an .env file during build. By default, SST Laravel won't use your .env file since that might be the wrong file when deploying from your local machine.
|
|
372
|
+
|
|
373
|
+
**Example:**
|
|
374
|
+
```typescript
|
|
375
|
+
config: {
|
|
376
|
+
environment: {
|
|
377
|
+
file: `.env.${$app.stage}`
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
##### `config.environment.autoInject`
|
|
383
|
+
- **Type:** `Input<boolean>`
|
|
384
|
+
- **Default:** `true`
|
|
385
|
+
- **Description:** Set this to false in case you don't want to auto inject environment variables from your linked resources.
|
|
386
|
+
|
|
387
|
+
##### `config.environment.vars`
|
|
388
|
+
- **Type:** `FunctionArgs["environment"]`
|
|
389
|
+
- **Description:** Custom environment variables that will be automatically injected into your application.
|
|
390
|
+
|
|
391
|
+
**Example:**
|
|
392
|
+
```typescript
|
|
393
|
+
config: {
|
|
394
|
+
environment: {
|
|
395
|
+
vars: {
|
|
396
|
+
SESSION_DRIVER: 'redis',
|
|
397
|
+
QUEUE_CONNECTION: 'redis',
|
|
398
|
+
LOG_CHANNEL: 'stderr'
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
##### `config.environment.secrets`
|
|
405
|
+
- **Type:** `RemoteEnvVault`
|
|
406
|
+
- **Description:** Use a `RemoteEnvVault` component to manage environment variables in AWS Secrets Manager. When provided, secrets will be fetched from AWS Secrets Manager at build time using the `sst-laravel deploy` command.
|
|
407
|
+
|
|
408
|
+
**Example:**
|
|
409
|
+
```typescript
|
|
410
|
+
const env = new RemoteEnvVault("Env");
|
|
411
|
+
|
|
412
|
+
new LaravelService("Laravel", {
|
|
413
|
+
config: {
|
|
414
|
+
environment: {
|
|
415
|
+
secrets: env
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
> **Note:** When using `secrets`, you should deploy using `sst-laravel deploy --stage <stage>` instead of `sst deploy` directly. This ensures secrets are fetched from AWS Secrets Manager before the Docker build.
|
|
422
|
+
|
|
423
|
+
#### `config.deployment`
|
|
424
|
+
- **Type:** `object`
|
|
425
|
+
- **Description:** Custom deployment configurations.
|
|
426
|
+
|
|
427
|
+
##### `config.deployment.script`
|
|
428
|
+
- **Type:** `Input<string>`
|
|
429
|
+
- **Description:** Path to a custom deployment script to run during container startup.
|
|
430
|
+
|
|
431
|
+
**Example:**
|
|
432
|
+
```typescript
|
|
433
|
+
config: {
|
|
434
|
+
deployment: {
|
|
435
|
+
script: "./deploy.sh"
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
## Properties
|
|
441
|
+
|
|
442
|
+
### `url`
|
|
443
|
+
- **Type:** `Output<string>`
|
|
444
|
+
- **Description:** The URL of the web service. If `web.domain` is set, returns the custom domain URL. Otherwise, returns the auto-generated load balancer URL.
|
|
445
|
+
|
|
446
|
+
**Example:**
|
|
447
|
+
```typescript
|
|
448
|
+
const app = new LaravelService("MyApp", { ... });
|
|
449
|
+
console.log(app.url); // https://example.com or https://xyz.elb.amazonaws.com
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
## Complete Example
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
const vpc = new sst.aws.Vpc("MyVpc");
|
|
456
|
+
const database = new sst.aws.Postgres("MyDatabase", { vpc });
|
|
457
|
+
const redis = new sst.aws.Redis("MyRedis", { vpc });
|
|
458
|
+
const bucket = new sst.aws.Bucket("MyBucket");
|
|
459
|
+
|
|
460
|
+
const app = new LaravelService("MyApp", {
|
|
461
|
+
path: "./",
|
|
462
|
+
vpc,
|
|
463
|
+
|
|
464
|
+
link: [database, redis, bucket],
|
|
465
|
+
|
|
466
|
+
permissions: [
|
|
467
|
+
{
|
|
468
|
+
actions: ["s3:*"],
|
|
469
|
+
resources: [bucket.arn, `${bucket.arn}/*`]
|
|
470
|
+
}
|
|
471
|
+
],
|
|
472
|
+
|
|
473
|
+
web: {
|
|
474
|
+
domain: "example.com",
|
|
475
|
+
scaling: {
|
|
476
|
+
min: 2,
|
|
477
|
+
max: 10
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
|
|
481
|
+
workers: [
|
|
482
|
+
{
|
|
483
|
+
name: "queue-worker",
|
|
484
|
+
horizon: true,
|
|
485
|
+
scheduler: true,
|
|
486
|
+
scaling: {
|
|
487
|
+
min: 1,
|
|
488
|
+
max: 5
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
],
|
|
492
|
+
|
|
493
|
+
config: {
|
|
494
|
+
php: 8.4,
|
|
495
|
+
opcache: true,
|
|
496
|
+
|
|
497
|
+
environment: {
|
|
498
|
+
file: `.env.${$app.stage}`,
|
|
499
|
+
autoInject: true,
|
|
500
|
+
vars: {
|
|
501
|
+
SESSION_DRIVER: 'redis',
|
|
502
|
+
QUEUE_CONNECTION: 'redis'
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
|
|
506
|
+
deployment: {
|
|
507
|
+
script: "./deploy.sh"
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
return {
|
|
513
|
+
url: app.url
|
|
514
|
+
};
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
## Example with RemoteEnvVault (Secrets Manager)
|
|
518
|
+
|
|
519
|
+
```typescript
|
|
520
|
+
const vpc = new sst.aws.Vpc("MyVpc");
|
|
521
|
+
const database = new sst.aws.Postgres("MyDatabase", { vpc });
|
|
522
|
+
const redis = new sst.aws.Redis("MyRedis", { vpc });
|
|
523
|
+
|
|
524
|
+
// Create environment secrets manager
|
|
525
|
+
const env = new RemoteEnvVault("Env");
|
|
526
|
+
|
|
527
|
+
const app = new LaravelService("MyApp", {
|
|
528
|
+
path: "./",
|
|
529
|
+
vpc,
|
|
530
|
+
|
|
531
|
+
link: [database, redis],
|
|
532
|
+
|
|
533
|
+
web: {
|
|
534
|
+
domain: "example.com",
|
|
535
|
+
scaling: {
|
|
536
|
+
min: 2,
|
|
537
|
+
max: 10
|
|
538
|
+
}
|
|
539
|
+
},
|
|
540
|
+
|
|
541
|
+
workers: [
|
|
542
|
+
{
|
|
543
|
+
name: "queue-worker",
|
|
544
|
+
horizon: true,
|
|
545
|
+
scheduler: true
|
|
546
|
+
}
|
|
547
|
+
],
|
|
548
|
+
|
|
549
|
+
config: {
|
|
550
|
+
php: 8.4,
|
|
551
|
+
|
|
552
|
+
environment: {
|
|
553
|
+
// Use secrets from AWS Secrets Manager
|
|
554
|
+
secrets: env,
|
|
555
|
+
// Auto-inject linked resource variables (database, redis)
|
|
556
|
+
autoInject: true,
|
|
557
|
+
// Additional runtime variables
|
|
558
|
+
vars: {
|
|
559
|
+
SESSION_DRIVER: 'redis',
|
|
560
|
+
QUEUE_CONNECTION: 'redis'
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
return {
|
|
567
|
+
url: app.url,
|
|
568
|
+
secretsPath: env.path
|
|
569
|
+
};
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
### Workflow with RemoteEnvVault
|
|
573
|
+
|
|
574
|
+
1. **Initial setup** - Push your `.env` file to AWS Secrets Manager:
|
|
575
|
+
```bash
|
|
576
|
+
sst-laravel env:push --stage production --input .env.production
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
2. **Deploy** - Use the sst-laravel CLI to deploy (automatically fetches secrets):
|
|
580
|
+
```bash
|
|
581
|
+
sst-laravel deploy --stage production
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
3. **Update secrets** - When you need to update environment variables:
|
|
585
|
+
```bash
|
|
586
|
+
# Pull current secrets (creates .env.production by default)
|
|
587
|
+
sst-laravel env:pull --stage production
|
|
588
|
+
|
|
589
|
+
# Edit the file
|
|
590
|
+
nano .env.production
|
|
591
|
+
|
|
592
|
+
# Push updated secrets
|
|
593
|
+
sst-laravel env:push --stage production --input .env.production
|
|
594
|
+
|
|
595
|
+
# Redeploy to apply changes
|
|
596
|
+
sst-laravel deploy --stage production
|
|
597
|
+
```
|
package/laravel-sst.ts
CHANGED
|
@@ -537,7 +537,7 @@ export class LaravelService extends Component {
|
|
|
537
537
|
return {
|
|
538
538
|
id: vpc.id,
|
|
539
539
|
securityGroups: vpc.securityGroups,
|
|
540
|
-
containerSubnets: vpc.
|
|
540
|
+
containerSubnets: vpc.privateSubnets,
|
|
541
541
|
loadBalancerSubnets: vpc.publicSubnets,
|
|
542
542
|
cloudmapNamespaceId: cloudmapNamespace.id,
|
|
543
543
|
cloudmapNamespaceName: cloudmapNamespace.name,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kirschbaum-development/sst-laravel",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "An unofficial extension of SST to deploy containerized Laravel applications to AWS Fargate.",
|
|
6
6
|
"main": "laravel-sst.ts",
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"templates",
|
|
20
20
|
"conf",
|
|
21
21
|
"images",
|
|
22
|
+
"docs",
|
|
23
|
+
"README.md",
|
|
22
24
|
"Dockerfile.web",
|
|
23
25
|
"Dockerfile.worker",
|
|
24
26
|
".dockerignore",
|
|
@@ -26,6 +28,7 @@
|
|
|
26
28
|
],
|
|
27
29
|
"scripts": {
|
|
28
30
|
"build": "tsc",
|
|
31
|
+
"test": "vitest run",
|
|
29
32
|
"release": "./scripts/publish.sh"
|
|
30
33
|
},
|
|
31
34
|
"repository": {
|
|
@@ -63,7 +66,8 @@
|
|
|
63
66
|
},
|
|
64
67
|
"devDependencies": {
|
|
65
68
|
"@types/node": "^20.0.0",
|
|
66
|
-
"typescript": "^5.0.0"
|
|
69
|
+
"typescript": "^5.0.0",
|
|
70
|
+
"vitest": "4.1.5"
|
|
67
71
|
},
|
|
68
72
|
"publishConfig": {
|
|
69
73
|
"access": "public",
|
package/src/remote-env-file.ts
CHANGED
|
@@ -213,19 +213,38 @@ function buildEnvFileContent(
|
|
|
213
213
|
].filter(Boolean).join('\n\n');
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
function toEnvFileContent(vars: Record<string, string>): string {
|
|
216
|
+
export function toEnvFileContent(vars: Record<string, string>): string {
|
|
217
217
|
const sortedKeys = Object.keys(vars).sort();
|
|
218
218
|
|
|
219
219
|
return sortedKeys
|
|
220
220
|
.map((key) => {
|
|
221
221
|
const value = vars[key];
|
|
222
|
+
const needsQuoting =
|
|
223
|
+
value.includes(' ') ||
|
|
224
|
+
value.includes('"') ||
|
|
225
|
+
value.includes("'") ||
|
|
226
|
+
value.includes('\n') ||
|
|
227
|
+
value.includes('$') ||
|
|
228
|
+
value.includes('\\') ||
|
|
229
|
+
value.includes('#');
|
|
230
|
+
|
|
231
|
+
if (!needsQuoting) {
|
|
232
|
+
return `${key}=${value}`;
|
|
233
|
+
}
|
|
222
234
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
235
|
+
// Single quotes are phpdotenv "raw literal" mode — no $ expansion, no escapes.
|
|
236
|
+
// Use them whenever possible so randomly-generated secrets round-trip safely.
|
|
237
|
+
if (!value.includes("'") && !value.includes('\n')) {
|
|
238
|
+
return `${key}='${value}'`;
|
|
226
239
|
}
|
|
227
240
|
|
|
228
|
-
|
|
241
|
+
// Fall back to double quotes when the value itself contains a single quote
|
|
242
|
+
// or newline. Escape \, $, and " so phpdotenv reads the literal value.
|
|
243
|
+
const escaped = value
|
|
244
|
+
.replace(/\\/g, '\\\\')
|
|
245
|
+
.replace(/\$/g, '\\$')
|
|
246
|
+
.replace(/"/g, '\\"');
|
|
247
|
+
return `${key}="${escaped}"`;
|
|
229
248
|
})
|
|
230
249
|
.join('\n');
|
|
231
250
|
}
|