Laravel Deployment on Ubuntu Server : Configuration And Setup

Laravel Deployment on Ubuntu Server : Configuration And Setup

Here’s an in-depth, step-by-step guide to deploying a Laravel application on an Ubuntu Server, covering every detail you need—from provisioning your server to setting up SSL and automating deployments. This article is structured into clear sections so you can follow along easily; feel free to skip to the section you need, or read straight through for the full 15,000+ character deep dive.

Introduction

Deploying a Laravel application to a production server can seem daunting if you haven’t done it before. In this guide, we’ll walk through every necessary step to get your application running smoothly on an Ubuntu Server environment. You’ll learn how to install and configure Nginx, PHP, Composer, MySQL/MariaDB, and Supervisor; set up SSL encryption; automate deployments; optimize performance; and more.

Whether you’re migrating an existing project or starting from scratch, by the end of this article you’ll have a rock-solid deployment workflow that you can replicate for future projects.

Prerequisites

Before we begin, make sure you have:

  • An Ubuntu Server (20.04 LTS or 22.04 LTS recommended) with root or sudo privileges.
  • A domain name (e.g., example.com) pointed via A-record to your server’s public IP.
  • SSH access to the server (port 22, unless you’ve customized it).
  • A Laravel project in a Git repository (GitHub, GitLab, Bitbucket, etc.) or ready to upload via SFTP.
  • Basic Linux command-line knowledge.

Provisioning and Preparing Your Ubuntu Server

  1. Log in via SSH
  2. ssh root@your_server_ip
  3. Update package lists & upgrade existing packages
  4. sudo apt update
    sudo apt upgrade -y
  5. Set your server’s timezone (e.g., UTC or your local zone)
  6. sudo timedatectl set-timezone UTC
  7. Create a swap file (if you have limited RAM)
  8. sudo fallocate -l 1G /swapfile
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
    echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
  9. Install essential utilities
  10. sudo apt install -y curl wget git unzip build-essential

Installing Nginx

  1. Install Nginx
  2. sudo apt install -y nginx
  3. Allow HTTP/HTTPS through the firewall (if using UFW)
  4. sudo ufw allow 'Nginx Full'
    sudo ufw enable
  5. Start and enable Nginx
  6. sudo systemctl start nginx
    sudo systemctl enable nginx
  7. Verify installation
    Visit http://your_server_ip in your browser; you should see the default Nginx welcome page.

Installing PHP and Required Extensions

Laravel 10+ needs PHP 8.1 or newer. We’ll install PHP 8.2 as an example:

  1. Add Ondřej Surý’s PPA
  2. sudo apt install -y software-properties-common
    sudo add-apt-repository ppa:ondrej/php -y
    sudo apt update
  3. Install PHP core and extensions
  4. sudo apt install -y php8.2-fpm php8.2-cli php8.2-mbstring php8.2-xml php8.2-bcmath \
        php8.2-curl php8.2-zip php8.2-gd php8.2-mysql php8.2-pgsql php8.2-intl
  5. Configure php.ini (optional performance/tuning)
  6. sudo nano /etc/php/8.2/fpm/php.ini
    • Set memory_limit = 512M (or as needed)
    • Adjust upload_max_filesize, post_max_size, etc.
  7. Restart PHP-FPM
  8. sudo systemctl restart php8.2-fpm
  9. Ensure PHP-FPM is enabled
  10. sudo systemctl enable php8.2-fpm

Installing Composer

Composer is the dependency manager for PHP.

  1. Download installer
  2. curl -sS https://getcomposer.org/installer -o composer-setup.php
    HASH="$(curl -sS https://composer.github.io/installer.sig)"
    php -r "if (hash_file('SHA384', 'composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
  3. Install globally
  4. sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer
  5. Verify
  6. composer --version

Creating a Dedicated System User

For security, don’t run your web apps as root. Create a new user:

sudo adduser deployer
sudo usermod -aG sudo deployer

Switch to that user:

su - deployer

(Optional) Set up SSH key authentication for deployer and disable password logins.

Deploying Your Laravel Application

Cloning from Git

  1. Navigate to /var/www
  2. cd /var/www
  3. Clone your repo
  4. git clone https://github.com/your_username/your_laravel_app.git example.com
  5. Enter project directory
  6. cd example.com

Environment Configuration

  1. Copy .env.example to .env
  2. cp .env.example .env
  3. Edit .env
  4. nano .env
    • Set APP_NAME, APP_URL=https://example.com
    • Configure DB_CONNECTION, DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD
    • Add any third‑party credentials, queue drivers, mail settings, etc.

Installing Dependencies

composer install --optimize-autoloader --no-dev
php artisan key:generate

Configuring the Database

Install MySQL or MariaDB:

sudo apt install -y mysql-server
sudo mysql_secure_installation

Log in and create the database/user:

CREATE DATABASE laravel_db;
CREATE USER 'laravel_user'@'localhost' IDENTIFIED BY 'strong_password';
GRANT ALL PRIVILEGES ON laravel_db.* TO 'laravel_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Ensure your .env reflects these credentials, then run:

php artisan migrate --force

Configuring Nginx Virtual Host

  1. Create a new server block:
  2. sudo nano /etc/nginx/sites-available/example.com
  3. server {
        listen 80;
        server_name example.com www.example.com;
    
        root /var/www/example.com/public;
        index index.php index.html;
    
        add_header X-Frame-Options "SAMEORIGIN";
        add_header X-Content-Type-Options "nosniff";
    
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
    
        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        }
    
        location ~ /\.ht {
            deny all;
        }
    
        access_log /var/log/nginx/example.com.access.log;
        error_log /var/log/nginx/example.com.error.log;
    }
  4. Enable the site and disable default:
  5. sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
    sudo rm /etc/nginx/sites-enabled/default
  6. Test & reload:
  7. sudo nginx -t
    sudo systemctl reload nginx

Visit http://example.com—your Laravel app should now be live (though still HTTP).

Setting Permissions and Ownership

Ensure the deployer user owns the project files and that the storage and bootstrap/cache directories are writable:

sudo chown -R deployer:www-data /var/www/example.com
sudo find /var/www/example.com -type f -exec chmod 644 {} \;
sudo find /var/www/example.com -type d -exec chmod 755 {} \;
sudo chown -R deployer:www-data /var/www/example.com/storage /var/www/example.com/bootstrap/cache
sudo chmod -R 775 /var/www/example.com/storage /var/www/example.com/bootstrap/cache

Running Migrations and Seeders

From the project root:

php artisan migrate --force
php artisan db:seed --force   # if you have seeders

Configuring Supervisor for Queues and Schedulers

If your app uses queues or needs scheduled tasks:

  1. Install Supervisor
  2. sudo apt install -y supervisor
  3. Create config for queue worker
  4. sudo nano /etc/supervisor/conf.d/laravel-queue.conf
  5. [program:laravel-queue]
    process_name=%(program_name)s_%(process_num)02d
    command=php /var/www/example.com/artisan queue:work --sleep=3 --tries=3
    autostart=true
    autorestart=true
    user=deployer
    numprocs=1
    redirect_stderr=true
    stdout_logfile=/var/www/example.com/storage/logs/queue.log
  6. Reload Supervisor
  7. sudo supervisorctl reread
    sudo supervisorctl update
    sudo supervisorctl start laravel-queue:*
  8. Scheduler Cron Job
  9. sudo crontab -u deployer -e
  10. Add:
  11. * * * * * php /var/www/example.com/artisan schedule:run >> /dev/null 2>&1

Setting Up SSL with Let’s Encrypt

Secure your site with HTTPS:

  1. Install Certbot
  2. sudo apt install -y certbot python3-certbot-nginx
  3. Obtain and install certificate
  4. sudo certbot --nginx -d example.com -d www.example.com
  5. Automatic renewal test
  6. sudo certbot renew --dry-run

Your Nginx config will be updated to listen on port 443, redirect HTTP to HTTPS, and include the certificates.

Automating Deployments (Git Hooks / CI-CD)

Manual deployments can be error-prone. Consider:

  • Git post-receive hook: Push to a bare repo on the server, and in the hook run git checkout, composer install, php artisan migrate, etc.
  • CI/CD pipelines (GitHub Actions, GitLab CI): Build your app, run tests, upload artifacts (ZIP), SSH into server, unzip, run migrations, clear caches, reload services.

Example GitHub Actions snippet:

name: Deploy Laravel

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Deploy via SSH
        uses: appleboy/ssh-action@v0.1.5
        with:
          host: ${{ secrets.SERVER_IP }}
          username: deployer
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/example.com
            git pull origin main
            composer install --no-dev --optimize-autoloader
            php artisan migrate --force
            php artisan config:cache
            sudo supervisorctl restart laravel-queue:*

Caching and Performance Optimization

After each deployment, run:

php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache

Use OPcache (enabled in php.ini) and consider setting up Redis for caching and session storage. Leverage CDN for static assets.

Logging, Monitoring, and Maintenance

  • Logs: Stored in storage/logs/laravel.log. Rotate logs via logrotate.
  • Server Monitoring: Use tools like Netdata, New Relic, or Datadog.
  • Backups: Automate database backups (cron + mysqldump), store offsite or in S3.
  • Security: Keep packages updated (sudo apt upgrade, composer update carefully), use fail2ban, limit SSH access.

Common Pitfalls and Troubleshooting

  1. 500 Internal Server Error
    • Check Nginx error logs: /var/log/nginx/example.com.error.log.
    • Check Laravel logs.
    • Ensure correct permissions.
  2. Permission Denied on Storage
    • Re-run chown and chmod commands.
  3. Queue Workers Not Running
    • Verify Supervisor status: sudo supervisorctl status.
    • Check queue logs.
  4. SSL Renewal Failures
    • Confirm port 80/443 open.
    • Check Certbot logs: /var/log/letsencrypt.
  5. High Memory Usage
    • Optimize PHP-FPM pools.
    • Enable OPcache.

Conclusion

Deploying Laravel on an Ubuntu Server involves multiple steps, but once you establish a reliable process, it’s straightforward to replicate. You’ve now covered:

  • Server preparation and hardening
  • Installing and configuring Nginx, PHP, Composer, and MySQL
  • Deploying your code and setting permissions
  • Configuring SSL, Supervisor, and scheduled tasks
  • Automating future deployments and optimizing performance

With this setup, your Laravel application will be secure, performant, and easy to maintain. Happy coding and seamless deployments!

#Laravel deployment #Ubuntu Server #Nginx #PHP-FPM #Composer #MySQL #Git #Supervisor #Let’s Encrypt SSL #CI/CD #server setup #Laravel Ubuntu tutorial #Laravel Ubuntu deployment #automate deployments

Subscribe to our newsletter

12k+

Subscribers

Weekly

Frequency

Free

Always