Usage
To start using, you only need to import the component in your sst.config.ts file:
import { LaravelService } from "@kirschbaum-development/sst-laravel";
And now you can start using the Laravel SST component. All the configuration options are Typescript files with documentation, so
To check the full list of options. check here.
Web (HTTP)
Below is an example of setting up your application to receive HTTP requests, on the laravel-sst-demo.example.com domain (with SSL), with auto-scaling with a max of 3 servers.
const app = new LaravelService('MyLaravelApp', {
web: {
cpu: 1024,
memory: 2048,
domain: {
dns: sst.cloudflare.dns(),
name: 'laravel-sst-demo.example.com',
},
scaling: {
min: 1,
max: 3,
}
},
});
Check all the web options here.
Load balancer health check
Laravel ships a built-in /up health endpoint. Point the load balancer at it via web.healthCheck — a shortcut over loadBalancer.health that targets the default forward port for you:
const app = new LaravelService('MyLaravelApp', {
web: {
domain: { name: 'app.example.com' },
healthCheck: { path: '/up' },
},
});
All loadBalancer.health options are supported (interval, timeout, healthyThreshold, unhealthyThreshold, successCodes). If you set web.loadBalancer explicitly, healthCheck is ignored — configure loadBalancer.health directly there.
HTTP to HTTPS redirect
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:
const app = new LaravelService('MyLaravelApp', {
web: {
domain: { name: 'app.example.com' },
httpsRedirect: false,
},
});
This has no effect when no domain is set, or when you provide an explicit web.loadBalancer (configure loadBalancer.ports yourself in that case).
Access logs
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:
const app = new LaravelService('MyLaravelApp', {
web: {
accessLogs: false,
},
});
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.
Reverb
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.
const app = new LaravelService('MyLaravelApp', {
web: {
domain: 'app.example.com',
},
reverb: {
domain: {
dns: sst.cloudflare.dns(),
name: 'ws.example.com',
},
},
});
return {
url: app.url,
reverbUrl: app.reverbUrl,
};
When reverb.domain is configured, SST Laravel automatically injects the Reverb server variables:
REVERB_SERVER_HOST=0.0.0.0
REVERB_SERVER_PORT=8080
REVERB_HOST=ws.example.com
REVERB_PORT=443
REVERB_SCHEME=https
If you enable horizontal scaling for Reverb, make sure your Laravel application is configured for Reverb scaling with Redis.
Check all the reverb options here.
Workers
Beyond HTTP requests, you can set up one or more workers for your Laravel application. Workers are meant to run background commands like Laravel Horizon, the Laravel Scheduler or any background command you may need to run.
SST Laravel will automatically deploy and configure worker containers running your configured commands. See some examples below.
Running the Laravel scheduler
const app = new LaravelService('MyLaravelApp', {
workers: [
{
name: 'scheduler',
scheduler: true,
},
],
});
Running the Laravel Horizon
const app = new LaravelService('MyLaravelApp', {
workers: [
{
name: 'horizon',
horizon: true,
},
],
});
Running custom commands
const app = new LaravelService('MyLaravelApp', {
workers: [
{
name: 'worker',
tasks: {
'scheduler': {
command: 'php artisan schedule:work',
},
'queue': {
command: 'php artisan queue:work',
},
'pulse': {
command: 'php artisan pulse:work',
},
},
},
],
});
Check all the workers options here.
Running background processes in the web container
For smaller applications, you can run Horizon, the scheduler, or any custom long-running command inside the web container instead of paying for a dedicated worker service. The web block accepts the same horizon, scheduler, and tasks options as workers[]:
const app = new LaravelService('MyLaravelApp', {
web: {
domain: 'app.example.com',
horizon: true,
scheduler: true,
tasks: {
pulse: {
command: 'php artisan pulse:work',
},
},
},
});
A few things to keep in mind:
- Background processes share the web container's CPU and memory with nginx and PHP-FPM. If they need dedicated resources, use a
workersentry instead. - Unlike workers — where a dead Horizon/scheduler process halts the container so ECS replaces it — background processes in the web container are restarted in place by s6, so a crash never interrupts HTTP traffic.
- If the web service scales beyond one container, every replica runs these processes. Horizon handles this fine (shared queue), but scheduled jobs should use
onOneServer()backed by a shared cache store to avoid running more than once.