Deploy a Laravel app

Deploy a Laravel app on Hangar from Git with a managed MySQL or PostgreSQL database, queue workers, the scheduler and HTTPS on your domain.

Updated

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.lock committed.
  • Your APP_KEY. Generate one with php 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_DRIVER and CACHE_STORE set to redis or database.
  • 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, or APP_URL is not https://.
  • No application encryption key has been specified: APP_KEY is missing.
  • SQLSTATE connection errors: the app and the database are in different regions, or DB_CONNECTION does not match the database engine.

Frequently asked questions

Does Hangar support Laravel without a Dockerfile?
Yes. The automatic builder detects Laravel from composer.json, installs PHP and Composer dependencies, builds front-end assets when the project has them and serves the public directory.
How do I run Laravel queue workers on Hangar?
Add a second service from the same repository and set its start command to php artisan queue:work. It shares the database and Redis of the web service through environment variables.
Which database should I use for Laravel on Hangar?
MySQL, MariaDB and PostgreSQL are all available as managed databases. Pick the one your app already uses and point DB_URL at its internal connection URL.

Deploy your app on Hangar

Connect a repository and it is live in minutes.

Start deploying