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
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
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
We should get a listing of the application profile
//Output
Available applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
Now we can enable HTTP by typing
$ ufw allow 'Nginx HTTP'
Lets verify the change by typing
$ ufw status
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)
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
//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
Now if we go to our server_ip_or_domain
from our browser we will the following 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
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
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
To test whether mysql
is running run the following command
$ systemctl status mysql
// 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
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
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
Finally, we can restart Nginx to allow PHP to run
$ systemctl restart nginx
And confirm the PHP version by
$ php --version
// 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
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
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
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
//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
To test our installation, we can run
$ composer
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]
...
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
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 replacepassword
with the user's password.
$ mysql> GRANT ALL PRIVILEGES ON *.* TO 'username'@'localhost' IDENTIFIED BY 'password';
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
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;
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
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
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
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
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
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
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
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;
}
}
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/
To test whether the nginx config is correct we can run the following command.
$ nginx -t
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
Now we have to restart Nginx service.
$ systemctl restart nginx
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)
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
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?
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)
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
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?
that's correct, and fixed running this
sudo chown -R :www-data /var/www/yourlaravelapp
Hi, When implementing authentication and logging in to the session, it shows error 404. Can you help me?