@kirschbaum-development/sst-laravel 0.3.4 → 0.3.6
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/README.md +29 -0
- package/docs/api.md +25 -0
- package/laravel-sst.ts +61 -37
- package/package.json +1 -1
- package/src/load-balancer.ts +60 -0
- package/src/web-server.ts +26 -0
package/README.md
CHANGED
|
@@ -103,6 +103,35 @@ const app = new LaravelService('MyLaravelApp', {
|
|
|
103
103
|
|
|
104
104
|
All [`loadBalancer.health` options](https://sst.dev/docs/component/aws/service/#loadbalancer-health) are supported (`interval`, `timeout`, `healthyThreshold`, `unhealthyThreshold`, `successCodes`). If you set `web.loadBalancer` explicitly, `healthCheck` is ignored — configure `loadBalancer.health` directly there.
|
|
105
105
|
|
|
106
|
+
#### HTTP to HTTPS redirect
|
|
107
|
+
|
|
108
|
+
When you configure a `domain` (which provisions an SSL certificate and an HTTPS listener), HTTP (port 80) traffic is redirected to HTTPS (port 443) by default. To keep forwarding HTTP traffic straight to your application instead, set `httpsRedirect: false`:
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
const app = new LaravelService('MyLaravelApp', {
|
|
112
|
+
web: {
|
|
113
|
+
domain: { name: 'app.example.com' },
|
|
114
|
+
httpsRedirect: false,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
This has no effect when no `domain` is set, or when you provide an explicit `web.loadBalancer` (configure `loadBalancer.ports` yourself in that case).
|
|
120
|
+
|
|
121
|
+
#### Access logs
|
|
122
|
+
|
|
123
|
+
The web container runs nginx (`serversideup/php:*-fpm-nginx`), which logs every request — including the load balancer health-check pings — to stdout, where it ends up in CloudWatch. To silence those access logs, set `accessLogs: false`:
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
const app = new LaravelService('MyLaravelApp', {
|
|
127
|
+
web: {
|
|
128
|
+
accessLogs: false,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
This points the serversideup `NGINX_ACCESS_LOG` variable at `/dev/null`. Error logs and the Laravel application logs are unaffected. Only the web container runs nginx, so this has no effect on workers or the Reverb service.
|
|
134
|
+
|
|
106
135
|
### Reverb
|
|
107
136
|
|
|
108
137
|
You can deploy a dedicated Laravel Reverb service for WebSocket traffic. Reverb runs as a worker-style container using `php artisan reverb:start`, but SST Laravel also attaches a load balancer so you can give it its own public domain.
|
package/docs/api.md
CHANGED
|
@@ -279,6 +279,31 @@ web: {
|
|
|
279
279
|
}
|
|
280
280
|
```
|
|
281
281
|
|
|
282
|
+
#### `web.httpsRedirect`
|
|
283
|
+
- **Type:** `boolean`
|
|
284
|
+
- **Default:** `true`
|
|
285
|
+
- **Description:** When a `domain` is configured, redirect HTTP (port 80) traffic to the HTTPS (port 443) listener instead of forwarding it straight to the application. Set to `false` to keep forwarding HTTP traffic to the app. Has no effect when no `domain` is set (there is no HTTPS listener to redirect to) or when an explicit `loadBalancer` is provided.
|
|
286
|
+
|
|
287
|
+
**Example:**
|
|
288
|
+
```typescript
|
|
289
|
+
web: {
|
|
290
|
+
domain: { name: 'app.example.com' },
|
|
291
|
+
httpsRedirect: false,
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
#### `web.accessLogs`
|
|
296
|
+
- **Type:** `boolean`
|
|
297
|
+
- **Default:** `true`
|
|
298
|
+
- **Description:** Stream the nginx access logs from the web container to CloudWatch. The web container runs nginx (`serversideup/php:*-fpm-nginx`), which logs every request — including the load balancer health-check pings — to stdout. Set to `false` to silence those access logs (points the serversideup `NGINX_ACCESS_LOG` variable at `/dev/null`). Error logs and the Laravel application logs are unaffected. Only the web container runs nginx, so this has no effect on workers or the Reverb service.
|
|
299
|
+
|
|
300
|
+
**Example:**
|
|
301
|
+
```typescript
|
|
302
|
+
web: {
|
|
303
|
+
accessLogs: false,
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
282
307
|
#### `web.executionRole`
|
|
283
308
|
- **Type:** `ServiceArgs["executionRole"]`
|
|
284
309
|
- **Description:** Execution role for the web service.
|
package/laravel-sst.ts
CHANGED
|
@@ -27,18 +27,12 @@ import { getPackagePath } from './src/config';
|
|
|
27
27
|
import { RemoteEnvFile } from './src/remote-env-file';
|
|
28
28
|
import { buildReverbEnvironmentVariables } from './src/reverb';
|
|
29
29
|
import { getSecretsFingerprint } from './src/secrets-manager';
|
|
30
|
+
import { buildDefaultPublicPorts, Port } from './src/load-balancer';
|
|
31
|
+
import { buildWebServerEnvironment } from './src/web-server';
|
|
30
32
|
|
|
31
33
|
// Re-export RemoteEnvVault for external use
|
|
32
34
|
export { RemoteEnvVault, RemoteEnvVaultArgs };
|
|
33
35
|
|
|
34
|
-
// duplicate from cluster.ts
|
|
35
|
-
type Port = `${number}/${'http' | 'https' | 'tcp' | 'udp' | 'tcp_udp' | 'tls'}`;
|
|
36
|
-
|
|
37
|
-
type Ports = {
|
|
38
|
-
listen: Port;
|
|
39
|
-
forward: Port;
|
|
40
|
-
}[];
|
|
41
|
-
|
|
42
36
|
enum ImageType {
|
|
43
37
|
Web = 'web',
|
|
44
38
|
Worker = 'worker',
|
|
@@ -198,6 +192,50 @@ export interface LaravelWebArgs extends LaravelServiceArgs {
|
|
|
198
192
|
* ```
|
|
199
193
|
*/
|
|
200
194
|
healthCheck?: Input<LaravelHealthCheck>;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* When a `domain` is configured, redirect HTTP (port 80) traffic to the
|
|
198
|
+
* HTTPS (port 443) listener instead of forwarding it straight to the
|
|
199
|
+
* application. Set to `false` to keep forwarding HTTP traffic to the app.
|
|
200
|
+
*
|
|
201
|
+
* Has no effect when no `domain` is set (there is no HTTPS listener to
|
|
202
|
+
* redirect to) or when an explicit `loadBalancer` is provided (configure
|
|
203
|
+
* `loadBalancer.ports` yourself in that case).
|
|
204
|
+
*
|
|
205
|
+
* @default `true`
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```js
|
|
209
|
+
* web: {
|
|
210
|
+
* domain: 'example.com',
|
|
211
|
+
* httpsRedirect: false,
|
|
212
|
+
* }
|
|
213
|
+
* ```
|
|
214
|
+
*/
|
|
215
|
+
httpsRedirect?: boolean;
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Stream the nginx access logs from the web container to CloudWatch.
|
|
219
|
+
*
|
|
220
|
+
* The web container runs nginx (`serversideup/php:*-fpm-nginx`), which logs
|
|
221
|
+
* every request — including the load balancer health-check pings — to
|
|
222
|
+
* stdout. Set this to `false` to silence those access logs (it points the
|
|
223
|
+
* serversideup `NGINX_ACCESS_LOG` variable at `/dev/null`). Error logs and
|
|
224
|
+
* the Laravel application logs are unaffected.
|
|
225
|
+
*
|
|
226
|
+
* Only the web container runs nginx, so this has no effect on workers or
|
|
227
|
+
* the Reverb service.
|
|
228
|
+
*
|
|
229
|
+
* @default `true`
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```js
|
|
233
|
+
* web: {
|
|
234
|
+
* accessLogs: false,
|
|
235
|
+
* }
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
accessLogs?: boolean;
|
|
201
239
|
}
|
|
202
240
|
|
|
203
241
|
export interface LaravelReverbArgs extends LaravelServiceArgs {
|
|
@@ -452,7 +490,12 @@ export class LaravelService extends Component {
|
|
|
452
490
|
});
|
|
453
491
|
|
|
454
492
|
const addWebService = () => {
|
|
455
|
-
const envVariables =
|
|
493
|
+
const envVariables = {
|
|
494
|
+
...getEnvironmentVariables(),
|
|
495
|
+
...buildWebServerEnvironment({
|
|
496
|
+
accessLogs: args.web?.accessLogs,
|
|
497
|
+
}),
|
|
498
|
+
};
|
|
456
499
|
|
|
457
500
|
this.services['web'] = new sst.aws.Service(
|
|
458
501
|
`${name}-Web`,
|
|
@@ -473,9 +516,11 @@ export class LaravelService extends Component {
|
|
|
473
516
|
? args.web.loadBalancer
|
|
474
517
|
: {
|
|
475
518
|
domain: args.web?.domain,
|
|
476
|
-
ports:
|
|
477
|
-
args.web?.domain,
|
|
478
|
-
|
|
519
|
+
ports: buildDefaultPublicPorts({
|
|
520
|
+
hasDomain: Boolean(args.web?.domain),
|
|
521
|
+
httpsRedirect:
|
|
522
|
+
args.web?.httpsRedirect ?? true,
|
|
523
|
+
}),
|
|
479
524
|
...(args.web?.healthCheck
|
|
480
525
|
? {
|
|
481
526
|
health: {
|
|
@@ -645,10 +690,10 @@ export class LaravelService extends Component {
|
|
|
645
690
|
name: 'reverb',
|
|
646
691
|
loadBalancer: reverbConfig.loadBalancer ?? {
|
|
647
692
|
domain: reverbConfig.domain,
|
|
648
|
-
ports:
|
|
649
|
-
reverbConfig.domain,
|
|
650
|
-
reverbConfig.port,
|
|
651
|
-
),
|
|
693
|
+
ports: buildDefaultPublicPorts({
|
|
694
|
+
hasDomain: Boolean(reverbConfig.domain),
|
|
695
|
+
forwardPort: reverbConfig.port,
|
|
696
|
+
}),
|
|
652
697
|
health: {
|
|
653
698
|
[reverbPort]: {
|
|
654
699
|
path: '/apps',
|
|
@@ -728,27 +773,6 @@ export class LaravelService extends Component {
|
|
|
728
773
|
};
|
|
729
774
|
}
|
|
730
775
|
|
|
731
|
-
function getDefaultPublicPorts(
|
|
732
|
-
domain?: LaravelDomain,
|
|
733
|
-
forwardPortNumber = 8080,
|
|
734
|
-
): Ports {
|
|
735
|
-
let ports;
|
|
736
|
-
const forwardPort: Port = `${forwardPortNumber}/http`;
|
|
737
|
-
const portHttp: Port = '80/http';
|
|
738
|
-
const portHttps: Port = '443/https';
|
|
739
|
-
|
|
740
|
-
if (domain) {
|
|
741
|
-
ports = [
|
|
742
|
-
{ listen: portHttp, forward: forwardPort },
|
|
743
|
-
{ listen: portHttps, forward: forwardPort },
|
|
744
|
-
];
|
|
745
|
-
} else {
|
|
746
|
-
ports = [{ listen: portHttp, forward: forwardPort }];
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
return ports;
|
|
750
|
-
}
|
|
751
|
-
|
|
752
776
|
// TODO: We have to test if it works when a custom image is provided in sst.config.js
|
|
753
777
|
function getImage(imgType: ImageType, extraArgs: object = {}) {
|
|
754
778
|
const img = getDefaultImage(imgType, extraArgs);
|
package/package.json
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export type Port = `${number}/${'http' | 'https' | 'tcp' | 'udp' | 'tcp_udp' | 'tls'}`;
|
|
2
|
+
|
|
3
|
+
export type Ports = {
|
|
4
|
+
listen: Port;
|
|
5
|
+
forward?: Port;
|
|
6
|
+
redirect?: Port;
|
|
7
|
+
}[];
|
|
8
|
+
|
|
9
|
+
export interface DefaultPublicPortsOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Whether a custom domain (and therefore an HTTPS listener) is configured.
|
|
12
|
+
*/
|
|
13
|
+
hasDomain: boolean;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Container port the load balancer forwards application traffic to.
|
|
17
|
+
*
|
|
18
|
+
* @default 8080
|
|
19
|
+
*/
|
|
20
|
+
forwardPort?: number;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* When a domain is configured, redirect the HTTP (port 80) listener to the
|
|
24
|
+
* HTTPS (port 443) listener instead of forwarding it to the application.
|
|
25
|
+
* Ignored when no domain is configured, since there is no HTTPS listener to
|
|
26
|
+
* redirect to.
|
|
27
|
+
*
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
30
|
+
httpsRedirect?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Builds the default load balancer port mapping for a public service.
|
|
35
|
+
*
|
|
36
|
+
* Without a domain, only an HTTP listener is created (forwarding to the app).
|
|
37
|
+
* With a domain, both HTTP and HTTPS listeners are created; the HTTP listener
|
|
38
|
+
* redirects to HTTPS by default, or forwards to the app when
|
|
39
|
+
* `httpsRedirect` is disabled.
|
|
40
|
+
*/
|
|
41
|
+
export function buildDefaultPublicPorts({
|
|
42
|
+
hasDomain,
|
|
43
|
+
forwardPort = 8080,
|
|
44
|
+
httpsRedirect = true,
|
|
45
|
+
}: DefaultPublicPortsOptions): Ports {
|
|
46
|
+
const forward: Port = `${forwardPort}/http`;
|
|
47
|
+
const portHttp: Port = '80/http';
|
|
48
|
+
const portHttps: Port = '443/https';
|
|
49
|
+
|
|
50
|
+
if (!hasDomain) {
|
|
51
|
+
return [{ listen: portHttp, forward }];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return [
|
|
55
|
+
httpsRedirect
|
|
56
|
+
? { listen: portHttp, redirect: portHttps }
|
|
57
|
+
: { listen: portHttp, forward },
|
|
58
|
+
{ listen: portHttps, forward },
|
|
59
|
+
];
|
|
60
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface WebServerEnvironmentOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Whether the nginx access logs should keep streaming to CloudWatch.
|
|
4
|
+
*
|
|
5
|
+
* @default true
|
|
6
|
+
*/
|
|
7
|
+
accessLogs?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Builds the web-server-specific container environment overrides derived from
|
|
12
|
+
* the web service options.
|
|
13
|
+
*
|
|
14
|
+
* Setting `accessLogs` to `false` points the serversideup `NGINX_ACCESS_LOG`
|
|
15
|
+
* variable at `/dev/null`, which silences the nginx access logs (including the
|
|
16
|
+
* load balancer health-check pings) while leaving the error logs untouched.
|
|
17
|
+
*/
|
|
18
|
+
export function buildWebServerEnvironment({
|
|
19
|
+
accessLogs,
|
|
20
|
+
}: WebServerEnvironmentOptions): Record<string, string> {
|
|
21
|
+
if (accessLogs === false) {
|
|
22
|
+
return { NGINX_ACCESS_LOG: '/dev/null' };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return {};
|
|
26
|
+
}
|