Hosting Laravel 5.6 on Digital Ocean

Digital Ocean is a cloud hosting provider that offers flexible virtual infrastructure with advanced orchestration tools. Digital Ocean virtual machines (‘droplets’) are dirt cheap and that makes them a terrific resource for hosting small-to-sized apps with ample scope to scale upward. I recently migrated a Laravel SAAS app from AWS to DO. Here’s the process I followed:

1 – Generate ssh keys

Depending on prior knowledge, this step may be redundant. Using key-based ssh authentication adds an additional layer of defence in protecting your environment from attack and is thoroughly recommended. We’re going to create two ssh keys: one for the ‘root’ user (required for initially commissioning a new DO droplet) and the second for a regular user account that is used everything else.



$ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key 
(/Users/ben/.ssh/id_rsa):

Then just follow the prompts. The contents of the .pub file are used to commission the server in step 2. You’ll want to also create a second key pair for the non-root user as recycling ssh keys is not a good idea.

See Atlassian’s guide to generating keys on other platforms

2 – Commission a DigitalOcean Droplet

Jump into the Digital Ocean and create a new Doplet.

  • Operating System: I’m using Ubuntu 18.04
  • Instance type: 1GB / 1vCPU Instance
  • Back ups: Enabling backups is a good idea. They’re charged at 20% of the droplet instance price and will save you in a bind but you should ensure your app’s architecture is resilient to worker nodes failing. Admittedly this is an issue more closely related load-balanced cloud environments and fortunately Laravel’s design philosophy promotes this approach.
  • The decision to add a storage block depends on the storage requirements of your application. In cloud environments you’ll want to avoid reading/writing to local filesystems. These resources (that can be managed independent of your instance) are designed to be more fault tolerant than using the local disk. Personally, I’d recommend sticking with S3 storage and DO’s S3 Spaces are perfect for this. From the Laravel perspective, they’re basically 100% comparable with an equivalent AWS S3 configuration and there’s a tonne of material available on how to set them up.

  • Region: Choose a region that suits your needs. I’m based in Australia so typically go with SGP1 – customise as appropriate to your needs.
  • Add your SSH keys: Add the ssh key created in step 1. The key you upload will be use to provision the root user in your new environment.
  • # Instances: Unless you’re feeling ambitious, it’s best to leave the number of instances at 1.
  • Choose a hostname: anything you like but I recommend keeping it practical.
  • Click create and wait for the instance to start.

    You’ll be able to see the IP address of your instance once it’s up and running. To login use ssh (change IP address and -i ssh key path as appropriate):

    
     $ssh root@111.222.333.444 -i ./.ssh/digitalocean
    Enter passphrase for key './.ssh/digitalocean': 
    Welcome to Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-36-generic x86_64)
    
    …
    
    Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
    applicable law.
    
    root@demo:~#
    

    Game on!

    3 – Create a user account

    Logging into your server with the root account for routine tasks is not a good idea. DO droplets are only ever commissioned with a root account so this means one of your first steps should be to create a non-root account to access the server and grant sudo access for any tasks that might require root privileges.

    
    root@demo:~# adduser ben
    Adding user `ben' ...
    Adding new group `ben' (1001) ...
    Adding new user `ben' (1001) with group `ben' ...
    Creating home directory `/home/ben' ...
    Copying files from `/etc/skel' ...
    Enter new UNIX password: 
    Retype new UNIX password: 
    passwd: password updated successfully
    Changing the user information for ben
    Enter the new value, or press ENTER for the default
    	Full Name []: 
    	Room Number []: 
    	Work Phone []: 
    	Home Phone []: 
    	Other []: 
    Is the information correct? [Y/n] Y
    

    Give the new user account access to Sudo:

    
    root@demo:~#  usermod -aG sudo ben
    

    Finally, add the second ssh key for your new user account that we created in step 1 to /home/ben/.ssh/authorized_keys (change ‘ben’ as necessary). If you have problems with this step, be sure to triple-check you have correct permissions set on ./.ssh and the key files. You’ll want chmod 700 and make sure you chown user:user ./.ssh/ -R if needed.

    3a – disable remote access by the root user account

    This step is optional but also simple and a sensible action toward keeping your new server secure. It’s a very good idea to test that your new user account can access the server before doing this (especially that the 2nd ssh key has been correctly set). You might inadvertently block yourself from connecting, so be careful. Log in with you new user account:

    
    $sudo  vi /etc/ssh/sshd_config
    

    Find the setting for ‘PermitRootLogin’ and change the value from ‘yes’ to ‘no’,
    Save the file ([esc] :wq)
    Finally restart the ssh service:

    
    service ssh restart 
    

    4 – Install Dependencies

    Okay, time to start installing stuff! For brevity’s sake I’m only listing install commands here. If you’re aiming to install PHP 7.2 (required for Laravel 5.6) you need to add to apt sources:

    
    $sudo add-apt-repository ppa:ondrej/php
    $sudo apt-get update
    

    With that done, let’s go:

    
    $sudo apt-get update
    $sudo apt-get install language-pack-en
    $sudo apt-get install nginx
    $sudo apt-get install mysql-server
    $sudo ufw allow 'Nginx HTTP'
    $sudo apt-get install php7.2-mbstring php7.2-curl php7.2-zip php7.2-gd php7.2-mysql php7.2-xml composer unzip
    

    I strongly recommend running mysql_secure_installation following the mysql installation – this guided script will help with tying down some common mysql attack vectors that are left open in a default installation. I should also point out that running your database and web server on the same sever is not encouraged practice – it works for the purpose of demo but for production environments you will ultimately want to run the database on a separate instance with secure connections via a Private Network between your nodes.

    There maybe a few other packages or libraries to install depending on the requirements of your Laravel app so be sure to check your documentation for anything additional. Composer will also do a reliable job of alerting you to missing dependencies in the next step.

    Finally, don’t forget to create a database and user credentials for your app. A guide to this process can be found here: (https://www.digitalocean.com/community/tutorials/how-to-deploy-a-laravel-application-with-nginx-on-ubuntu-16-04#step-2-—-configuring-mysql ) – make a note of the database name, user and password so that you can add them to your .env at end of step 5.

    5 – install your app

    This part should be familiar:

    
    $sudo mkdir /var/www/my_laravel_app
    $sudo git clone https://you@github.com/some/repsitory/ /var/www/my_laravel_app
    $sudo chown ben:ben /var/www/my_laravel_app
    $cd var/www/my_laravel_app
    $composer update
    $php artisan key:generate
    $sudo chgrp -R www-data storage bootstrap/cache
    $sudo chmod -R ug+rwx storage bootstrap/cache
    

    At this point you application and all dependencies should be installed. Don’t forget make any changes to the .env file necessary for your Laravel app. At minimum you’ll want to set the url for your application and set your database credentials created in the previous step.


    6 – configure Nginx


    
    $sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com
    $sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
    $sudo rm /etc/nginx/sites-available/default
    $sudo vi /etc/nginx/sites-available/example.com
    

    Your final Nginx config should look the following (the file paths, server name/ip will obviously be different):

    
    server {
        listen 80;
        listen [::]:80;
    
        . . .
    
        root /var/www/html/my_laravel_app/public;
        index index.php index.html index.htm index.nginx-debian.html;
    
        server_name example.com www.example.com;
    
        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }
    
    }
    

    8 – Restart your web server


    
    $sudo systemctl reload nginx
    

    There’s a lot more to cover in deploying a full-scale production environment, such as enabling HTTPS/SSL, adding S3 storage, load balancing and using a more resilient approach to hosting the database (ie, a separate instances). Possible topics for next time!


    References:-


    https://dev.to/alchermd/laravel-56-on-digital-ocean-2i33

    https://www.digitalocean.com/community/tutorials/how-to-install-linux-nginx-mysql-php-lemp-stack-in-ubuntu-16-04

    https://www.digitalocean.com/community/tutorials/how-to-deploy-a-laravel-application-with-nginx-on-ubuntu-16-04

Leave a Reply

Your email address will not be published. Required fields are marked *