DEV Community

Cover image for Deploy Laravel Application with Nginx on Ubuntu 18.04 on DigitalOcean
Shah Nawaz Shuvo
Shah Nawaz Shuvo

Posted on

Deploy Laravel Application with Nginx on Ubuntu 18.04 on DigitalOcean

This is a complete guide on deploying a Laravel application on a fresh Ubuntu 18.04 droplet on DigitalOcean. We can follow the same steps to deploy on any similar host (like Linode) with Ubuntu 18.04 OS. For this you will need a fresh droplet with Ubuntu 18.04 server set up and root access of that server. We also need a domain/subdomain pointed to that server’s IP address (You can do that by setting ‘A Value’ in your DNS manager). If we are all set up to this point then lets move ahead and set up our new Ubuntu server.

Installing Prerequisites

Now we are going to install the following:

  • Nginx
  • MySQL 5.7
  • PHP 7.2

First of all run the following command:

$ apt-get update
Enter fullscreen mode Exit fullscreen mode

1. Nginx

Nginx is one of the most popular web servers in the world and is responsible for hosting some of the largest and highest-traffic sites on the internet. It is more resource-friendly than Apache in most cases and can be used as a web server or reverse proxy.

1.1. Installing Nginx

$ apt-get install nginx
Enter fullscreen mode Exit fullscreen mode

1.2. Adjusting Firewall

Before testing Nginx, the firewall software needs to be adjusted to allow access to the service. Nginx registers itself as a service with ufw upon installation, making it straightforward to allow Nginx access.

List the application configurations that ufw knows how to work with by typing:

$ ufw app list
Enter fullscreen mode Exit fullscreen mode

We should get a listing of the application profile

//Output
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH
Enter fullscreen mode Exit fullscreen mode

Now we can enable HTTP by typing

$ ufw allow 'Nginx HTTP'
Enter fullscreen mode Exit fullscreen mode

Lets verify the change by typing

$ ufw status
Enter fullscreen mode Exit fullscreen mode

We should see HTTP traffic allowed in the displayed output:

//Output
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                  
Nginx HTTP                 ALLOW       Anywhere                  
OpenSSH (v6)               ALLOW       Anywhere (v6)             
Nginx HTTP (v6)            ALLOW       Anywhere (v6)
Enter fullscreen mode Exit fullscreen mode

1.3. Checking the Web Server

At the end of the installation process, Ubuntu 18.04 starts Nginx. The web server should already be up and running. We can check by the following command

$ systemctl status nginx
Enter fullscreen mode Exit fullscreen mode
//Output
● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2019-06-09 00:00:00 ; 3h 33min ago
     Docs: man:nginx(8)
  Process: 2062 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
  Process: 1803 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 2064 (nginx)
    Tasks: 5 (limit: 4915)
   CGroup: /system.slice/nginx.service
           ├─2064 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           ├─2066 nginx: worker process
           ├─2068 nginx: worker process
           ├─2071 nginx: worker process
           └─2072 nginx: worker process
Enter fullscreen mode Exit fullscreen mode

Now if we go to our server_ip_or_domain from our browser we will the following page

nginx page

2. MySQL 5.7

On Ubuntu 18.04, only the latest version of MySQL is included in the APT package repository by default. At the time of writing, that's MySQL 5.7. To install run the following command:

$ apt-get install mysql-server
Enter fullscreen mode Exit fullscreen mode

This will install MySQL, but will not prompt you to set a password or make any other configuration changes. Because this leaves our installation of MySQL insecure, we will run the next command.

$ mysql_secure_installation
Enter fullscreen mode Exit fullscreen mode

This will take us through a series of prompts where we can make some changes to our MySQL installation’s security options like set a password for the root user etc. We must set a password for the root user. To log in to the root user with the newly set password we can run the following command

$ mysql -u root -p
Enter fullscreen mode Exit fullscreen mode

To test whether mysql is running run the following command

$ systemctl status mysql
Enter fullscreen mode Exit fullscreen mode
// Output
● mysql.service - MySQL Community Server
   Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2019-06-09 00:00:00; 3h 53min ago
  Process: 1948 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid (code=exited, status=0/SUCCESS)
  Process: 1792 ExecStartPre=/usr/share/mysql/mysql-systemd-start pre (code=exited, status=0/SUCCESS)
 Main PID: 1950 (mysqld)
    Tasks: 28 (limit: 4915)
   CGroup: /system.slice/mysql.service
           └─1950 /usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid
Enter fullscreen mode Exit fullscreen mode

3. PHP 7.2

PHP 7.2 is included in the default Ubuntu repository for 18.04. We can list each of the available PHP 7.2 packages with the following command

$ apt-cache pkgnames | grep php7.2
Enter fullscreen mode Exit fullscreen mode

Next, we can install the packages that our application requires

$ apt-get install php curl git unzip
$ apt-get install php-pear php-fpm php-dev php-zip php-curl php-xmlrpc php-gd php-mysql php-mbstring php-xml libapache2-mod-php
Enter fullscreen mode Exit fullscreen mode

Finally, we can restart Nginx to allow PHP to run

$ systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

And confirm the PHP version by

$ php --version
Enter fullscreen mode Exit fullscreen mode
// Output
PHP 7.2.16-1+ubuntu18.04.1+deb.sury.org+1 (cli) (built: Mar  7 2019 20:23:29) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.16-1+ubuntu18.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies
Enter fullscreen mode Exit fullscreen mode

The main config file of PHP 7.2 will be saved as /etc/php/7.2/fpm/php.ini. We can use the any text editor to modify relevant settings in that file

$ nano /etc/php/7.2/fpm/php.ini
Enter fullscreen mode Exit fullscreen mode

Now we need another tool before we can get into setting up Laravel. This tool is composer. Composer is a popular dependency management tool for PHP, created mainly to facilitate installation and updates for project dependencies. To install composer we have to run the following commands

$ cd ~
$ curl -sS https://getcomposer.org/installer -o composer-setup.php
Enter fullscreen mode Exit fullscreen mode

To install composer globally, use the following command which will download and install Composer as a system-wide command named composer, under /usr/local/bin

$ php composer-setup.php --install-dir=/usr/local/bin --filename=composer
Enter fullscreen mode Exit fullscreen mode
//Output
All settings correct for using Composer
Downloading...

Composer (version 1.6.5) successfully installed to: /usr/local/bin/composer
Use it: php /usr/local/bin/composer
Enter fullscreen mode Exit fullscreen mode

To test our installation, we can run

$ composer
Enter fullscreen mode Exit fullscreen mode

And we will get the following output with all composer's arguments

Output
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.6.5 2018-05-04 11:44:59

Usage:
  command [options] [arguments]
...
Enter fullscreen mode Exit fullscreen mode

Project Setup

As we are done installing all the dependencies. Now its time for us to set up the main project. Here I am going to use git to pull my Laravel project from a remote repository and maintain version control of the application.

Database Setup

But first we have to create a new database for the application. To create MySQL database and users, we have to follow these steps.

  • At the command line, we have to log in to MySQL as the root user.
$ mysql -u root -p
Enter fullscreen mode Exit fullscreen mode

Insert root password to enter into mysql shell.

  • To create a database user, we have to type the following command. Replace username with the user you want to create, and replace password with the user's password.
$ mysql> GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password';
Enter fullscreen mode Exit fullscreen mode

Then type \q to exit the mysql program.

  • To log in to MySQL as the user we just created, type the following command. Replace username with the name of the user you created in previous step.
$ mysql -u username -p
Enter fullscreen mode Exit fullscreen mode

Insert user password to enter into mysql shell.

  • To create a database, we have to type the following command. Replace dbname with the name of the database that you want to create.
$ mysql> CREATE DATABASE dbname;
Enter fullscreen mode Exit fullscreen mode

Application Setup

We are going to host our application in /var/www/html directory of our server. You can use any other directory if you want. We will be using git to upload the project files and maintain version control. I suppose we know the basics of Git. Lets dive in.

  • Create an empty Git repository in /var/www/html directory.
$ cd /var/www/html
$ git init
Enter fullscreen mode Exit fullscreen mode

Say our remote repository is on Github and we have the link https://github.com/username/project-name.git and this repo has a production branch. Now lets add this remote repo to our newly created empty repo and pull the project files from the remote.

$ git remote add origin https://github.com/username/project-name.git
$ git pull origin production
Enter fullscreen mode Exit fullscreen mode

We may have to enter our github username and password here. Then We have to wait until the full branch is uploaded to the server. Now we will configure the Laravel application on our server. Make sure we are in our project directory (Here it is /var/www/html).

$ cp .env.example .env
$ nano .env
Enter fullscreen mode Exit fullscreen mode

This will open the .env file in the nano editor so that we can make the necessary changes.

// .env file
APP_NAME=application_name
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=application_url

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=dbname
DB_USERNAME=username
DB_PASSWORD=password

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
Enter fullscreen mode Exit fullscreen mode

After editing we will save the file by Ctrl+o and exit it by Ctrl+x.
Now lets install all dependencies via composer.

$ composer update
Enter fullscreen mode Exit fullscreen mode

After all the dependencies are installed successfully run the following commands.

$ composer dump-autoload
$ php artisan config:clear
$ php artisan key:generate
$ php artisan migrate
$ php artisan db:seed
Enter fullscreen mode Exit fullscreen mode

Our laravel application is almost set up now. The only thing remaining to do now is to make an Nginx config file. We can use the /etc/nginx/sites-available/default.conf file or we can make a new config file. Either way it will work. Here we are going to use the default file.

$ nano /etc/nginx/sites-available/default.conf
Enter fullscreen mode Exit fullscreen mode

Clear everything from the file and add the following snippet.

// /etc/nginx/sites-available/default.conf file
server {
    listen 80;
    listen [::]:80;

    root /var/www/html/public;
    index index.php index.html index.htm index.nginx-debian.html;

    server_name <our.application.name>;

    location / {
    try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
      try_files $uri /index.php =404;
      fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
      fastcgi_index index.php;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }
}
Enter fullscreen mode Exit fullscreen mode

Save and close the file. Now we have to make a symbolic link of this file to the /etc/nginx/sites-enabled/ directory. To accomplish that run the following command.

$ ln -S /etc/nginx/sites-available/default.conf /etc/nginx/sites-enabled/
Enter fullscreen mode Exit fullscreen mode

To test whether the nginx config is correct we can run the following command.

$ nginx -t
Enter fullscreen mode Exit fullscreen mode

If the config file is correct then it will output the following.

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Enter fullscreen mode Exit fullscreen mode

Now we have to restart Nginx service.

$ systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

At this point our Laravel application is deployed successfully on our Ubuntu 18.04 server. Now to test we browse the server's IP or domain from the browser and will see our application live.

In this post I tried to give you guys a full guide to how you can deploy your Laravel application with Nginx on Ubuntu 18.04 on DigitalOcean or Linode or any other similar hosting platform. Hope this will help you all in some way. Peace.

Top comments (8)

Collapse
 
maurisource profile image
Manesh

I've followed this tutorial, and there's an issue with Location definition in default.conf. You don't need to define twice try_files, neither the fast_cgi index.php lines. Nginx throws an error.

After being able to get Nginx service running, you'll face this error in your Laravel app:

failed to open stream: Permission denied in /var/www/eshop/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php:107

To fix this, you need to provide proper permissions to your root folder

run this: sudo chown -R :www-data /var/www/mylaravelapp

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
shuv1824 profile image
Shah Nawaz Shuvo

I am really sorry that I am responding this late. I have been really busy with work and hardly got time for blog. I think you solved the problem by now. Will you share with us how you did it? Or can I help you with anything now?

Collapse
 
kp profile image
KP

Not a problem at all! I solved the issue (had to delete the comment because I realized I published my config and it wasn't secure)

Collapse
 
technov profile image
TechNov

hi, for this $ ln -S /etc/nginx/sites-available/default.conf /etc/nginx/sites-enabled/
i got "ln: /etc/nginx/sites-enabled/: hard link not allowed for directory"
and when i try my (ex mydomain.com) a got the index.nginx-debian.html result like the index page

Collapse
 
wmfairuz profile image
Fairuz Wan Ismail

Since the folder is owned by the user and Nginx is running with the user www-data, I would assume in your case, Laravel will not able to create file in the storage folder?

Collapse
 
maurisource profile image
Manesh

that's correct, and fixed running this

sudo chown -R :www-data /var/www/yourlaravelapp

Collapse
 
andrescardozoac profile image
Luis Andres Cardozo

Hi, When implementing authentication and logging in to the session, it shows error 404. Can you help me?