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:
Replacesudo adduser [user]
[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.