Laravel deploys on Hangar straight from the repository. The automatic builder recognises the framework, and the database, cache and queue run next to the app as services of the same project.
Before you start
- A Laravel app in a Git repository, with
composer.lockcommitted. - Your
APP_KEY. Generate one withphp artisan key:generate --show. - A Hangar account.
1. Create the database
In a new project, add a MySQL, MariaDB or PostgreSQL service and pick a region. Copy its internal connection URL.
2. Create the Laravel service
Add a service from your repository in the same region, and leave the builder on Automatic. It installs the PHP version your composer.json asks for, runs Composer, and builds your assets with Vite if the project has a package.json.
3. Set the variables
APP_ENV=production
APP_DEBUG=false
APP_KEY=<your key>
APP_URL=https://app.example.com
DB_CONNECTION=mysql
DB_URL=<the internal connection URL>
LOG_CHANNEL=stderr
Use DB_CONNECTION=pgsql for PostgreSQL. LOG_CHANNEL=stderr sends Laravel's log to the service's runtime logs, where you can search it.
4. Trust the proxy
Hangar terminates TLS in front of your app. Without this, Laravel generates http:// links:
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->trustProxies(at: '*');
})
5. Deploy
Start the deploy. Railpack, the automatic builder, serves the app with FrankenPHP and runs database migrations and seeding when a Laravel app starts, so the schema is migrated on every release. Set RAILPACK_SKIP_MIGRATIONS=true to turn that off and run them yourself; its PHP documentation has the details.
6. Add a domain
In Settings → Networking, add the hostname you set in APP_URL and turn HTTPS on. For the container port, use the port the server reports in the first lines of the runtime log.
Queue workers
Add a second service from the same repository with the same variables and this start command:
php artisan queue:work --tries=3
For a Redis queue, add a Redis database and set QUEUE_CONNECTION=redis and REDIS_URL.
Scheduler
Run the scheduler as a third service with:
php artisan schedule:work
Sessions, cache and uploads
A container's filesystem is replaced on every deploy, and a service can run more than one replica. Keep state out of the container:
SESSION_DRIVERandCACHE_STOREset toredisordatabase.- Uploads on an S3-compatible disk, or on a volume attached to the service.
Troubleshooting
- Assets or links load over
http://: the proxy is not trusted, orAPP_URLis nothttps://. No application encryption key has been specified:APP_KEYis missing.SQLSTATEconnection errors: the app and the database are in different regions, orDB_CONNECTIONdoes not match the database engine.