Setup a VM for Laravel 8 with Ubuntu 20.04, PHP8, Nginx and MySql
By: Roberto Butti
Tags: PHP, Ubuntu, Nginx, Laravel, Droplet

My goal is to setup a GNU/Linux VM with Ubuntu 20.04 LTS, PHP8, Nginx and MySql to serve a Laravel 8 Application. For the Web Server I’m going to use Nginx so I will need php-fpm.

There are some ways to achieve that, you could consider to use:

a software that helps you to maintain servers like Forge (https://forge.laravel.com/);

a Serverless approach, using Vapor (https://vapor.laravel.com/);

an App Platform like DigitalOcean App Platform (https://www.digitalocean.com/products/app-platform/)

a Linux Virtual Machine provided by DigitalOcean Droplets.

For my side projects usually I use DigitalOcean Droplets because:

it is a “manual” approach, but one of my goals, when I work on side project, is to learn and understand the processes/tools/configurations “under the hood”;

the costs are predictable;

I like to get my hands dirty on my side project.

For my work projects, I usually choose “managed” solutions.

A thought about automation. I’m a fan of “automate everything”. But before to automate a process, or a setup, or a workflow, I think we need to figure out what’s going on under the hood.

Setup Droplet

As I mentioned before, I’m going to use a Droplet by DigitalOcean. A droplet is essentially a VM with an Operating System where you can add your software stack, with tools and applications provided by the operating system. In our case I will select Ubuntu 20.04, so I will add software with Apt. When you create a Droplet you can select some parameters, like operating system, VM size (cpu/memory), datacenter location…

Creating a droplet, you need to select some options

The cheapest configuration (but with less performance):

Choose image: Distributions Ubuntu 20.04 LTS

Choose a plan: shared CPU Basic — 5 $ / month (1 GB , 1 CPU, 25 GB SSD Disk, 1000 GB transfer)

Choose a datacenter region : Frankfurt 1 (the closest to Italy), if you want to perform a speed test you could use this tool: http://speedtest-fra1.digitalocean.com/

Authentication, you can choose SSH Keys if you are able to upload your public key, otherwise you could use the classic way login / password for root user.

The authentication method. My suggestion is to use SSH keys instead of a very long complex password.

Once you create the Droplet you can see your new IPv4 address.

This is very important to access to your new virtual machine.

Your first access

If you selected SSH key Auth method instead of login/password, when you created your droplet, I suggest you to create an SSH alias in your machine in order to have a shortcut for defining the “ssh” user name, the IP address and the key to use to access to your VM.

In this case in your ~/.ssh/config, add these lines:

host <alias_name>

HostName <ip_address>

User <user_name>

IdentityFile <key_file>

Where:

<alias_name> is the name used when you will launch ssh;

<ip_address> the IP address provided by the Droplet;

<user_name> the user, for the initial configuration it is ok using root. During the setup process we will create a “no root” user;

<key_file> the ssh key file, in my case is ~/.ssh/id_rsa_sideproject_dev;

To access to your Droplet you can use ssh:

ssh <alias_name>

With the first access, you will be prompted a question about the creation of ECDSA key fingerprint. Select “yes” to accept it.

If you selected login/password method instead of SSH keys, you could use ssh root@<ip_address> to access to your VM.

Upgrade your system packages

First of all, I suggest you to upgrade your packages with Apt command (we are using Ubuntu so we have Apt). With the first access you are using “root” user, so for now you don’t need to use sudo .

apt-get update

apt-get upgrade

Now, we can start with the installation of all packages needed:

Nginx

PHP 8 (fpm) (and the modules needed by Laravel 8)

MySql 8

You are installing some services, so my suggestion is to configure also the firewall.

Install Nginx

apt-get install nginx

Optional: if you want to host multiple domains (or sub domains) I suggest to create one directory for each sub domain you want to serve with Nginx. Anyway, the default directory is : /var/www/html/. So, after installing Nginx you try to go tu url http://<ip_address>, you will see the default html file served by nginx from /var/www/html directory.

The welcome page of a new fresh installation of Nginx

We are going to install Laravel so we need to set public/ as document root.

mkdir -p /var/www/mydomain/htdocs/public

In this case:

/var/www/mydomain/htdocs will be the directory where your Laravel application will be copied;

/var/www/mydomain/htdocs/public will be the document root.

Install PHP 8

We just installed Ubuntu 20.04 that ships PHP 7.4. Before to install PHP we need to add a repository in order to have the opportunity to install PHP 8. So we’ll install PHP from the ondrej/php PPA repository. To enable the repo and update packages:

apt install software-properties-common

add-apt-repository ppa:ondrej/php

apt update

apt upgrade

Now you can install PHP 8:

apt install php8.0-fpm

To test if you have PHP 8:

php -v

Your new PHP 8

To check if the PHP-fpm is up and running:

systemctl status php8.0-fpm

Now we can install all PHP dependencies for your Laravel 8 application:

apt-get install php8.0-mysql php8.0-mbstring php8.0-xml php8.0-bcmath

Configure Nginx and PHP 8 fpm

Now you are using root user, and it could be fine for initial setup. I suggest to create an unprivileged user in order to login to the system and access to the directory where is deployed your Laravel application.

adduser deploy

usermod -aG www-data deploy

chown -R deploy:www-data /var/www/mydomain/

Now let’s focus on the Nginx configuration, we can start from the default configuration for Nginx and then we will customize it:

cp /etc/nginx/sites-available/default /etc/nginx/sites-available/mydomain

Edit your new file following this example:

Then, you need to create a symbolic link in order to activate the new configuration (take a look sites-available VS. sites-enabled):

ln -s /etc/nginx/sites-available/mydomain /etc/nginx/sites-enabled/

If you want to check the syntax of your configuration:

nginx -t

To restart Nginx and load your new configuration:

service nginx restart

Install Database

We are going to install MySql server 8:

apt install mysql-server

mysql_secure_installation

during the execution of this script, it will ask you to type the root database password. When the execution is completed, try to access to your database server:

mysql -u root -p

and type the new password to access to the database administration console. In the database administration console:

create the database db_laravel8;

create the user to access the database (userdb) with the password somepassword

grant the right privileges to the new user;

CREATE DATABASE db_laravel8;

CREATE USER 'userdb'@'localhost' IDENTIFIED BY 'somepassword';

GRANT ALL PRIVILEGES ON * . * TO 'userdb'@'localhost';

FLUSH PRIVILEGES;

Setup Firewall

Open only HTTP and SSH ports:

ufw allow 'Nginx HTTP'

ufw allow 'OpenSSH'

Activate the firewall:

ufw enable

And finally check the status:

ufw status

The output should be something like this:

Status: active

To Action From

— — — — — —

Nginx HTTP ALLOW Anywhere

OpenSSH ALLOW Anywhere

Nginx HTTP (v6) ALLOW Anywhere (v6)

OpenSSH (v6) ALLOW Anywhere (v6)

Setup HTTPS

For side project usually I use https://letsencrypt.org/ to obtain the certificate to enable HTTPS protocol.

As root , to install the tool to install certificate, run:

apt-get install certbot python3-certbot-nginx

If you need to install a certificate for hostname host.mydomain.com:

certbot --nginx -d host.mydomain.com

This command will update also the Nginx configuration file (enabling directive listen on port 443 and load certificate just created).

You need also to open your firewall for HTTPS ports:

ufw allow 'Nginx HTTPS'

Wrap up

If you followed these steps we:

created a VM on DigitalOcean with Ubuntu 20.04 LTS

installed Nginx to serve files via HTTP;

installed PHP8 and the modules needed by Laravel 8

installed MySql 8 server;

configured Nginx in order to serve PHP files and a specific directory where we can copy Laravel files;

configured an unprivileged user to access to the VM;

configured a database user and create a new database to use it with Laravel Application (remember to update your .env file with DB_NAME, DB_USER, DB_PASSWORD);

setup HTTPS in order to serve Laravel application.

Now you can deploy your application in /var/www/mydomain/htdocs.

Feel free to drop comments and feedback, I could improve this tutorial (or my english ;) )