Skip to content

Instantly share code, notes, and snippets.

@vacmar01
Created June 14, 2023 18:42
Show Gist options
  • Save vacmar01/a0ed343d464d4099fbd99917f567ae42 to your computer and use it in GitHub Desktop.
Save vacmar01/a0ed343d464d4099fbd99917f567ae42 to your computer and use it in GitHub Desktop.
Install LEMP Stack on DigitalOcean Droplet.

How to Install Nginx, MySQL and PHP on an Ubuntu Droplet from DigitalOcean

This is meant to be as a reminder to myself and as a quick and dirty reference to others (heavily inspired by: https://www.techalyst.com/posts/laravel-hosting-with-digital-ocean-droplet-step-by-step-tutorial). It assumes you want to install a Laravel app afterwards, but it should be easily adaptable to other PHP apps.

I know that there are probably much more things you could config in your nginx (and maybe you should), but this works for now for me. I might update this with new things I learn.

1. Create DigitalOcean droplet

Choose the region that is nearest to you. If you plan to use MySQL get the Droplet with at least 1 GB of RAM. I run into an OOM error on the Droplet with 512 mb RAM. The 1GB RAM droplet costs 6€/month. choose root admin password as authentication method (it's easier) As an image choose the latest version of Ubuntu. You can also use their marketplace one-click install of the LEMP Stack (Linux, Nginx, MySQL and PHP), but I haven't tried it yet.

2. Log into your droplet by copying the public ip and opening your terminal:

ssh root@<public-ip>

If asked for a password, provide the root password you created while creating the Droplet.

3. create a new (non-root) user for security purposes (so you can't mess up your server that easily). after that grant your new user sudo rights so you can write inside the /etc folder and so on.

adduser <username>
usermod -aG sudo <username>

you will be asked some details about the user. Just hit enter. Choose a password for your new user.

4. enable the firewall (ufw)

ufw enable
ufw allow OpenSSH
sudo ufw allow http
sudo ufw allow https

5. log out as root (ctrl+d or exit) and log in as your newly created non-root user.

6. update your local package index (it is a good habit to do this before installing anything new)

sudo apt-get update

7. Install the nginx package. This is your webserver that handles the incoming http requests and routes them accordingly to the entrypoint of your web app.

sudo apt-get install nginx

Now you can enter the public ip adress into your browser and should see the welcome page of nginx. Yay.

8. Install MySQL. If you don't need MySQL, because you don't need a database or you want to use something like SQLite as your database you can skip this step (sqlite is super easy: sudo apt-get sqlite3 php-sqlite3 and then you just create your db with touch database.sqlite and you are good to go).

sudo apt-get install mysql-server

enter a root password for mysql.

Now we need to secure the mysql installation, because the default mysql config is too unsafe. Luckily this is super easy:

sudo mysql_secure_installation

Basically you want to say yes to everything it suggests, the password validation is optional imo.

9. Install PHP (and the necessary extensions). PHP should be already installed on a Ubuntu Droplet, but we need some extensions for our webapp. The most important one is php-fpm which is basically a layer between nginx (our webserver) and our web app (Laravel e.g.).

sudo apt-get install php-fpm php-mysql php-mbstring

Configure PHP by opening the php.ini file in a text editor that is installed with Ubuntu (nano or vim probably). Remember to use your version number (just hit tab at /etc/php/ to see whats available).

sudo vim /etc/php/<version-number>/fpm/php.ini

you can also type:

sudo sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' /etc/php/<version-number>/fpm/php.ini

search for cgi.fix_pathinfo=, e.g. by typing /cgi.fix_pathinfo= in vim and hitting enter. uncomment the line by deleting the ; and change the 1 into a 0.

after that you have to restart php<version-number>-fpm like this:

sudo systemctl restart php<version-number>-fpm

10. Configure nginx to serve your webapp correctly.

Open /etc/nginx/sites-available/default in your favorite text editor (I love vim).

Change it so the file looks like this (make sure to enter your php-fpm version and your domain and webapp name):

server {
    listen 80 default_server;
    listen [::]:80 default_server;

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

    server_name yourdomain.com www.yourdomain.com;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php<version-number>-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }
}

The root line says where to look for the entry point of your web app (the public folder in Laravel. We added index.php to the index line, since we are working with a php-Webapp here and public/index.php is our entrypoint. If it does not find an index.php file it will look for the other files from left to right.

The server_name specifies what the user can enter into their webbrowser to access your webapp. You need to make an DNS A record that points your top level domain to the public IP of your server. The easiest way is if you let DigitalOcean manage the nameservers of your Domain (https://docs.digitalocean.com/tutorials/dns-registrars/). How to add an A record in DigitalOcean is explained here: https://docs.digitalocean.com/products/networking/dns/how-to/manage-records/.

The other configurations make sure that the query_strings are correctly passed to your webapp and that it uses php-fpm (fastCGI) for serving all .php files. You don't really need to understand it deeply to get your first webapp running.

check that the config has no errors with sudo nginx -t and restart the nginx service: sudo systemctl reload nginx.

That's it. This is how you install the LEMP stack on an Ubuntu Server.

Here is a full bash script to automate all steps after you logged-in as non-root user:

#!/bin/bash

# Set error handling
set -e

# Extract PHP version
php_version=$(php -r "echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;")

# Ask user for custom inputs
read -p "Enter your web app name: " app_name
read -p "Enter your domain (without www): " domain

# Update your system
sudo apt update -y

# Install Nginx
sudo apt install -y nginx

# Install MySQL
sudo apt install -y mysql-server
sudo mysql_secure_installation

# Install PHP and related modules
sudo apt install -y php${php_version}-fpm php-mysql php-mbstring

# Configure PHP to use PHP-FPM and disable cgi.fix_pathinfo
sudo sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' /etc/php/${php_version}/fpm/php.ini

# Restart PHP-FPM service to apply changes
sudo systemctl restart php${php_version}-fpm

# Configure Nginx to use PHP FPM
sudo bash -c "cat > /etc/nginx/sites-available/default" << EOF
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/${app_name}/public;
    index index.php index.html index.htm index.nginx-debian.html;

    server_name ${domain} www.${domain};

    location / {
        try_files \$uri \$uri/ /index.php?\$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php${php_version}-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }
}
EOF

# Check Nginx configuration for syntax errors
sudo nginx -t

# If there's no error, reload Nginx to apply the changes
sudo systemctl reload nginx

echo "LEMP stack installation completed."

Now you can go on and install Laravel. This will be another post.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment