Skip to content
Pvtw

How I host and deploy my Laravel website

I will guide you through how I host my website and deploy the latest version.

Website

My website is build with Laravel. An amazing PHP framework for artisans.
I really like Laravel because it is very easy to get started.

Hosting

I host my website on a very cheap VPS (Virtual Private Server). Which has basically nothing inside of it.
And that is great, because I want that. Now you may ask, why an VPS and not dedicated hosting?
For me, I also like linux and running my website on an (almost) empty VPS where you have to do everything yourself, is just amazing.
Learning linux and server management during the progress.
If you want that too, I will hold your hand in setting it up.

PHP

First we are going to install PHP with the following commands.
Add the repository:

sudo add-apt-repository ppa:ondrej/php

Update the packages:

sudo apt update

Install the latest PHP version:

sudo apt install php8.3

You may need to install extra PHP extensions and I recommend using php-fpm to run your application on.

Using PHP, we can install composer, the package manager for PHP.

curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php

This will download the composer installer to a temporarly location.
After that, we will execute the file in the following command:

sudo php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer

This will install composer to a global location so you can use the composer command everywhere.

MySQL

MySQL is a popular database management system especially for PHP applications.
It can be installed with the following command:

sudo apt install mysql-server

Then run the installation script:

sudo mysql_secure_installation

You have to answer a few questions.
One important note: I recommend disabling root access (you can still be root with $ sudo mysql).

Nginx

Nginx is a fast web server and also easy to install.
With just one command:

sudo apt install nginx

To verify it is installed correctly, go to your browser and go to http://localhost.
You will see a default page.

Now the server is ready to host your Laravel application.

NodeJS

I recommend installing node with nvm, node version manager.
It can be installed with this command:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

You now have access to the nvm command where you can download and manage different node versions.
To install the latest version, run the following command:

nvm install --lts

You should now been able to use the node and npm command.

Deployment

You can deploy your application manually with git, by updating the repository after every change.
However, we can automate this proccess. Which is way cooler, isn't it?
We are going to use a free tool called deployer, which can be used to deploy a PHP application on an server.
It supports many frameworks and more importantly, Laravel.
To install deployer, go to your Laravel project and install deployer with composer.

composer require --dev deployer/deployer

Then initialize deployer to generate a configuration file in the root of your project.

./vendor/bin/dep init

I personally use a PHP file but you can also use a yaml file if you prefer.

My configuration file looks like this:

<?php

declare(strict_types=1);

namespace Deployer;

require 'recipe/laravel.php';

// Config

set('application', 'pvtw');
set('repository', 'https://github.com/pvtw/pvtw.dev.git');

// Hosts

host('pvtw.dev')
    ->set('remote_user', 'deployer')
    ->set('hostname', 'pvtw.dev')
    ->set('deploy_path', '/var/www/{{hostname}}');

task('npm:install', function (): void {
    cd('{{release_or_current_path}}');
    run('source $HOME/.nvm/nvm.sh && npm install');
});

task('npm:run:build', function (): void {
    cd('{{release_or_current_path}}');
    run('source $HOME/.nvm/nvm.sh && npm run build');
});

task('deploy', [
    'deploy:prepare',
    'deploy:vendors',
    'artisan:storage:link',
    'artisan:config:cache',
    'artisan:route:cache',
    'artisan:view:cache',
    'artisan:event:cache',
    'artisan:migrate',
    'npm:install',
    'npm:run:build',
    'deploy:publish',
]);

// Hooks

after('deploy:failed', 'deploy:unlock');

I've overriden 2 tasks. The npm install and npm run build task because I had a bug where npm could not be found unless I source nvm before every npm command. Maybe it works for you without it.
There are a few important things to setup in the configuration file.

  • First we are including the Laravel recipe, which is pre-installed. It adds the artisan tasks we reference later.
  • Set the application name and repository where your project lives. Of cource change it to your repository.
  • The host() function accepts a string, a name for the host. This can be anything but keep it simple. We will use it later.
  • Set the remote user. This is the unix user deployer will use to deploy. This user should not have sudo rights.
    If you don't have a user yet (without sudo rights), create one with:
    sudo adduser [user]
    
    Replace [user] with the name of the user.
  • Specify the hostname and deploy path. In my case it will deploy my project to /var/www/pvtw.dev on the server.
  • The deploy task is your main task which will contain all the tasks being run during the deploy.

The first deploy

Now it is finally time to deploy your project to the server.
With this command you can start it:

./vendor/bin/dep deploy

If you have SSH setup, make sure to add the public key to the authorized hosts.
During the first deploy it will do alot. Creating the .dep directory, releases directory where all the releases of your project are stored. A current directory which is a symbolic link to the latest release and a shared directory. There are files stored like the .env and storage directory.
Note that the .env file is not copied. You can do it yourself by copying the .env.example from the release directory to the shared directory.
Like this:

./releases/1/.env.example ./shared/.env

After that, you will need to create a nginx configuration file to make your website publicly available.
The Laravel documentation has an example.
Change the root to the current/public directory with a full path to that location.
For example in my case: /var/www/pvtw.dev/current/public. Basically the deploy path you've defined in the deployer config plus the /current/public path.

When you visit your domain, you should get the default Laravel page.
Congratz. You have made it.

Bonus: GitHub Action

You can even automate the deploy after every commit with a GitHub action.
It is very easy to setup.
Create a file from the root of your project to .github/workflows/deploy.yml with the following contents:

name: deploy

on:
  push:
    branches: [ "main" ]

concurrency: production_environment

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: "8.3"

      - name: Install dependencies
        run: composer install

      - name: Deploy
        uses: deployphp/action@v1
        with:
          private-key: ${{ secrets.PRIVATE_KEY }}
          dep: deploy

Next you need to set a secret for the private key. Go to your project on GitHub and go to the settings. Then click Secrets and variables and go to actions. Here create a repository secret. The name would be PRIVATE_KEY with contents of the private key. Deployer will use it to login to your server.
To test it out, commit your yml file and see the action happening at the Actions tab.

And that is it! You now have a website up and running. Make something awesome.