Deploy a Laravel App
A walkthrough for getting a Laravel application running on AidiPanel, from a fresh site to a live app with SSL. This assumes your app already exists in a Git repository — either your own project or something you're deploying from a template.
Before you start:
- AidiPanel is installed and you can log into the panel
- Your Laravel app is in a Git repository you can clone from the server (public repo, or SSH/token access set up for a private one)
- A domain pointed at your server
1. Create the site
sudo aidipanel site:add --domain myapp.com --user myapp --type laravelUsing --type laravel (rather than plain php) matters here: it tells AidiPanel to point the Nginx vhost's document root at public/ instead of the site root, which is exactly where Laravel expects incoming requests to land.
This creates the dedicated Linux user myapp, an isolated PHP-FPM pool running as that user, and the web root at /home/myapp/htdocs/myapp.com.
2. Clone and install
sudo -u myapp -H bash -lc '
cd /home/myapp/htdocs/myapp.com
git clone https://github.com/your/repo.git .
composer install --no-dev --optimize-autoloader
'The trailing . on git clone clones directly into the current (already-created) directory instead of making a new subfolder. --no-dev skips dev-only dependencies (test frameworks, debug tools) you don't want on production; --optimize-autoloader speeds up class loading for a real deployment.
No Composer on the server yet?
AidiPanel's default install doesn't assume every site needs Composer. If composer isn't found, install it directly: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer.
3. Configure the environment
sudo -u myapp -H bash -lc '
cd /home/myapp/htdocs/myapp.com
cp .env.example .env
php artisan key:generate
'Now edit .env and fill in your database credentials (create the database first if you haven't — see Site Management → Installing WordPress, step 3 for the equivalent db:add pattern, it's identical for Laravel):
sudo aidipanel db:add --name myapp_db --user myapp_db_userThis prints a generated password once — save it, then put it straight into .env:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=myapp_db
DB_USERNAME=myapp_db_user
DB_PASSWORD=<the generated password>4. Run migrations
sudo -u myapp -H bash -lc 'cd /home/myapp/htdocs/myapp.com && php artisan migrate --force'Add --seed if your app ships seeders you want run on first deploy. If this fails with a connection error, double-check the four DB values above — same troubleshooting path as WordPress: Permissions & Database.
5. Fix ownership and storage permissions
sudo chown -R myapp:myapp /home/myapp/htdocs/myapp.com
sudo -u myapp chmod -R u+rwX /home/myapp/htdocs/myapp.com/storage
sudo -u myapp chmod -R u+rwX /home/myapp/htdocs/myapp.com/bootstrap/cacheLaravel writes logs, compiled views, and cache files into storage/ and bootstrap/cache/ constantly — if PHP (running as myapp) can't write there, you'll get a 500 with a permissions error in storage/logs/laravel.log the moment the app tries to do anything.
Don't chmod 777
775 is enough since PHP-FPM already runs as the owning user (myapp) — there's no other process on the box that needs write access to these folders. 777 opens them to every user on the system for no benefit.
6. Set production mode
In .env:
APP_ENV=production
APP_DEBUG=falseNever leave APP_DEBUG=true in production
With debug mode on, an unhandled exception dumps a full stack trace — including your .env values — straight to the browser. Turn it off before you point real traffic at the site.
Then cache the config and routes for a speed boost:
sudo -u myapp -H bash -lc '
cd /home/myapp/htdocs/myapp.com
php artisan config:cache
php artisan route:cache
php artisan view:cache
'Remember to clear these after every deploy
If you update .env or your routes later and the app doesn't seem to notice, you likely have a stale cache from this step. Re-run php artisan config:clear && php artisan route:clear (or re-run the :cache versions after your change) — this is one of the most common "why isn't my change showing up" moments in Laravel specifically.
7. Install SSL
dig +short myapp.com # confirm DNS has propagated first
sudo aidipanel ssl:install --domain myapp.com --email admin@myapp.com8. The scheduler (if your app uses one)
If your app has scheduled tasks, Laravel needs one cron entry. Add it through AidiPanel so it is validated and installed in the site's own crontab:
printf '%s\n' 'cd /home/myapp/htdocs/myapp.com && php artisan schedule:run >> /dev/null 2>&1' |
sudo aidipanel cron:add --domain myapp.com --schedule '* * * * *'Running it as myapp (rather than root) keeps it consistent with the same isolation model as everything else — the scheduler can only touch what that site's user can touch.
Done
Your Laravel app is live, migrated, and served over HTTPS with an isolated PHP-FPM pool. A few things worth knowing as you keep working on it:
- Redeploying:
git pull,composer install --no-dev, re-run any new migrations, thenphp artisan config:cache route:cache view:cacheagain. Consider scripting this as a smalldeploy.shin the repo. - Switching PHP version: see PHP Management if your app needs a specific version.
- FastCGI Cache: Laravel apps are usually far more dynamic/session-heavy than a WordPress blog, so full-page caching is rarely a fit — the FastCGI Cache exclusion rules already skip logged-in and cookie-bearing requests, but you may want to leave page cache off entirely for an authenticated app and rely on Laravel's own caching (
config:cache, query caching, Redis) instead.