DEV Community

Cover image for Setting a LAMP server on Digital Ocean + SSL
Sarah Siqueira
Sarah Siqueira

Posted on • Edited on

Setting a LAMP server on Digital Ocean + SSL

Disclaimer: Although I had done this procedure several times through the years before, I have never documented it until now. I am writing this article with no pretension to make this an innovative tutorial, everything that will be said below, all commands and instructions are already available online in lots of other articles, and documentation, etc. The host providers themself use to make available these instructions very clear. My main goal in writing this is to register for my own future reference, as we often forgot commands and end up spending lots of time "googling" to remember.

With some hope, this can somehow help someone else too!

Steps to deploy Lamp in a VPS on Droplet on Digital Ocean

Initial Setup

We must have a Digital Ocean account. If you still don't sign up through this link and get $200, 60-day credit.

After login in your account, create a project and then create a Droplet.

Create Droplet and set SSH Keys

Create a Droplet

To create your Droplet you can choose among lots of configurations, prices, sizes, memory, processors, etc. Select the most suitable one for your project. How to make this decision is completely out of the scope of this article, because well, it depends.

Create SSH keys

Login to the console

Create a new user

adduser username

Create password
_
password_

It's necessary to grant privileges to the new user:

usermod -aG sudo username

Now, when logged in as a regular user, we can type sudo before commands to run them with superuser privileges.

Setting firewall

ufw app list

The expected output:

Available applications:
 ** OpenSSH**
Enter fullscreen mode Exit fullscreen mode

ufw allow OpenSSH

Enable firewall

ufw enable

ufw status

The expected output:

Output
Status: active

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

Enabling External Access

With SSH keys

rsync --archive --chown=username:username ~/.ssh /home/username

To access:

ssh -i keypub username@ip

The keypub is the file with the SSH keys.

Apache

Image description

Installing Apache

sudo apt update

sudo apt install apache2

Adjusting firewall

sudo ufw app list

The expected output:

Available applications:
  Apache
  Apache Full
  Apache Secure
  OpenSSH
Enter fullscreen mode Exit fullscreen mode

As indicated by the output, there are three profiles available for Apache:

  • Apache: This profile opens only port 80;

  • Apache Full: This profile opens both port 80 and port 443 (TLS/SSL encrypted traffic);

  • Apache Secure: This profile opens only port 443 (TLS/SSL encrypted traffic);

sudo ufw allow 'Apache'

sudo ufw status

The expected output:

Output
Status: active

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

Checking the Web Server

sudo systemctl status apache2

The expected output:

apache2.service - The Apache HTTP Server
     Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2020-04-23 22:36:30 UTC; 20h ago
       Docs: https://httpd.apache.org/docs/2.4/
   Main PID: 29435 (apache2)
      Tasks: 55 (limit: 1137)
     Memory: 8.0M
     CGroup: /system.slice/apache2.service
             ├─29435 /usr/sbin/apache2 -k start
             ├─29437 /usr/sbin/apache2 -k start
             └─29438 /usr/sbin/apache2 -k start
Enter fullscreen mode Exit fullscreen mode

Access the default Apache landing page to confirm that the software is running properly through your IP address. We should see something like this:

Image description

If you do not know your server’s IP address, try typing this at your server’s command prompt:

hostname -I

You will get back a few addresses separated by spaces.

Handling Apache Basic Commands

Some basic management commands to handle Apache using systemctl are necessary.

To stop your web server:

sudo systemctl stop apache2

To start the web server when it is stopped:

sudo systemctl start apache2

To stop and then start the service again:

sudo systemctl restart apache2

Reload without dropping connections:

sudo systemctl reload apache2

By default, Apache is configured to start automatically when the server boots. If this is not what you want, disable this behavior by typing:

sudo systemctl disable apache2

To re-enable the service to start up at boot:

sudo systemctl enable apache2

Virtual Hosts

While working with an Apache web server, we can use virtual hosts (see server blocks in Nginx) to encapsulate configuration details and host more than one domain from a single server.

Apache on Ubuntu has one server block enabled by default that is configured to serve documents from the /var/www/html directory. We will create a directory structure within /var/www for a domain-name site, leaving /var/www/html in place as the default directory to be served if a client request doesn’t match any other sites.

Make sure to replace the domain-name this with your own domain name.

Creating dir:

sudo mkdir /var/www/domain-name.com

Assign user to dir:

sudo chown -R $USER:$USER /var/www/domain-name

Set permissions:

sudo chmod -R 755 /var/www/domain-name

Create index (optional):

sudo nano /var/www/domain-name/index.html

The index.html content:

<html>
    <head>
        <title>Welcome to domain-name!</title>
    </head>
    <body>
        <h1>The domain-name virtual host is working!</h1>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Create the virtual host

For Apache to serve this content, it’s necessary to create a virtual host file with the correct directives. Instead of modifying the default configuration file located at /etc/apache2/sites-available/000-default.conf directly, let’s make a new one at /etc/apache2/sites-available/your_domain.conf:

sudo nano /etc/apache2/sites-available/domain-name.conf

The file content:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName domain-name.com
    ServerAlias www.domain-name.com
    DocumentRoot /var/www/domain-name
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Enter fullscreen mode Exit fullscreen mode

sudo a2ensite domain-name.conf

sudo a2dissite 000-default.conf

sudo apache2ctl configtest

sudo systemctl restart apache2

Apache Files and Directories Overview

It's interesting to be familiarized with a few important Apache directories and files.

Content

  • /var/www/html: The actual web content, can be changed by altering Apache configuration files.

Server Configuration

  • /etc/apache2: The Apache configuration directory;
  • /etc/apache2/apache2.conf: The main Apache configuration file. This can be modified to make changes to the Apache global configuration. This file is responsible for loading many of the other files in the configuration directory.

  • /etc/apache2/ports.conf: This file specifies the ports that Apache will listen on.

  • /etc/apache2/sites-available/: The directory where per-site virtual hosts can be stored. Apache will not use the configuration files found in this directory unless they are linked to the sites-enabled directory. Typically, all server block configuration is done in this directory and then enabled by linking to the other directory with the a2ensite command.

  • /etc/apache2/sites-enabled/: The directory where enabled per-site virtual hosts are stored. Typically, these are created by linking to configuration files found in the sites-available directory with the a2ensite.

  • /etc/apache2/conf-available/, /etc/apache2/conf-enabled/: These directories have the same relationship as the sites-available and sites-enabled directories but are used to store configuration fragments that do not belong in a virtual host. Files in the conf-available directory can be enabled with the a2enconf command and disabled with the a2disconf command.

  • /etc/apache2/mods-available/, /etc/apache2/mods-enabled/: These directories contain the available and enabled modules, respectively. Files ending in .load contain fragments to load specific modules, while files ending in .conf contain the configuration for those modules. Modules can be enabled and disabled using the a2enmod and a2dismod commands.

Server Logs

  • /var/log/apache2/access.log: By default, every request to your web server is recorded in this log file unless Apache is configured to do otherwise.

  • /var/log/apache2/error.log: By default, all errors are recorded in this file. The LogLevel directive in the Apache configuration specifies how much detail the error logs will contain.

MySQL

Now we have a web server up and running, we need to install the database system. MySQL is a popular option used within PHP environments.
Use apt to acquire and install this software:

sudo apt install mysql-server

Access the mysql:

sudo mysql

This will connect to the MySQL server as the administrative database user root, which is inferred by the use of sudo when running this command.

Expected output:

Output
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 8.0.28-0ubuntu4 (Ubuntu)

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
Enter fullscreen mode Exit fullscreen mode

Exit mysql:

mysql> exit

PHP

With Apache installed to serve our content and MySQL installed to store and manage our data, we need PHP that will process code to display dynamic content to the final user.

In addition to the php package, we will need php-mysql, a PHP module that allows PHP to communicate with MySQL-based databases. We will also need libapache2-mod-php to enable Apache to handle PHP files. Core PHP packages will automatically be installed as dependencies.

sudo apt install php libapache2-mod-php php-mysql

Check version:

php -v

Expected similar output:

Output
PHP 8.1.2 (cli) (built: Mar  4 2022 18:13:46) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.2, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.2, Copyright (c), by Zend Technologies
Enter fullscreen mode Exit fullscreen mode

🚀Yay! Our LAMP server is fully installed and cofigured. To add more domains, performe the virtual hosts stpes over and over again (of course we have to think about traffic, hardware capacity, but it is completeley out of the scope of this article). For our purposes we can stop here and everything is working already. For safety, I will add SSL for securing our Apache in the next step and although is higly recommendable, it's optional.

🔐 SSL

That's a plus section. For securing Secure Apache on Ubuntu we will be using Let's Encrypt, a Certificate Authority (CA) that facilitates obtaining and installing free TLS/SSL certificates.

Installing Certbot

To obtain an SSL certificate with Let’s Encrypt, we need to install the Certbot software on our server and a plugin that integrates Certbot with Apache:

sudo apt install certbot python3-certbot-apache

Checking your Apache Virtual Host Configuration

To automatically obtain and configure SSL for your web server, Certbot needs to find the correct virtual host within your Apache configuration files, which we already did previously.

Checking just in case:

sudo apache2ctl configtest

The expected output should be:

Output
Syntax OK
Enter fullscreen mode Exit fullscreen mode

Allowing HTTPS Through the Firewall

Previously we enabled the UFW firewall, so we'll need to adjust the settings to allow HTTPS traffic.

Verifying what kind of traffic is currently allowed on your server:

sudo ufw status

Our output should look something like this, meaning that only HTTP traffic on port 80 is currently allowed:

Output
Status: active

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

To let in HTTPS traffic, we have to allow the “Apache Full” profile and delete the redundant “Apache” profile:

sudo ufw allow 'Apache Full'

sudo ufw delete allow 'Apache'

Our status will now look like this:

sudo ufw status

Expected output:

Output
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                  
Apache Full                ALLOW       Anywhere                  
OpenSSH (v6)               ALLOW       Anywhere (v6)             
Apache Full (v6)           ALLOW       Anywhere (v6)  
Enter fullscreen mode Exit fullscreen mode

Obtaining an SSL Certificate

Certbot provides a variety of ways to obtain SSL certificates through plugins, let's use Apache:

sudo certbot --apache

A series of questions will be prompted to configure our SSL certificate.

  • Valid e-mail address which will be used for renewal notifications and security notices:
Output
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): you@your_domain
Enter fullscreen mode Exit fullscreen mode

Hit ENTER to proceed to the next step.

  • Confirm if you agree to Let’s Encrypt terms of service:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A
Enter fullscreen mode Exit fullscreen mode
  • We’ll be asked if you would like to share your email with the Electronic Frontier Foundation to receive news and other information:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N
Enter fullscreen mode Exit fullscreen mode
  • Inform Certbot of which domains we’d like to activate HTTPS for. The listed domain names are automatically obtained from your Apache virtual host configuration:
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: your_domain
2: www.your_domain
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 
Enter fullscreen mode Exit fullscreen mode

We’ll see output like this:

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for domain-name
http-01 challenge for www.domain-name
Enabled Apache rewrite module
Waiting for verification...
Cleaning up challenges
Created an SSL vhost at /etc/apache2/sites-available/domain-name-ssl.conf
Enabled Apache socache_shmcb module
Enabled Apache ssl module
Deploying Certificate to VirtualHost /etc/apache2/sites-available/domain-name-le-ssl.conf
Enabling available site: /etc/apache2/sites-available/domain-name-le-ssl.conf
Deploying Certificate to VirtualHost /etc/apache2/sites-available/domain-name-le-ssl.conf

Enter fullscreen mode Exit fullscreen mode
  • Next, select whether or not you want HTTP traffic redirected to HTTPS:
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Enter fullscreen mode Exit fullscreen mode

After this, Certbot’s configuration is finished, and we will be presented with the final remarks about your new certificate.

Verifying Certbot Auto-Renewal

Let’s Encrypt’s certificates are only valid for ninety days to ensure that misused certificates or stolen keys will expire sooner rather than later.

We do not need to worry about this renewal process since the certbot package we installed previously takes care of this. It has a script that runs twice a day and will automatically renew any certificate that’s within thirty days of expiration.

To check the status of this service:

sudo systemctl status certbot.timer

The expected output should be similar to this:

Output
● certbot.timer - Run certbot twice daily
     Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled)
     Active: active (waiting) since Tue 2020-04-28 17:57:48 UTC; 17h ago
    Trigger: Wed 2020-04-29 23:50:31 UTC; 12h left
   Triggers: ● certbot.service

Apr 28 17:57:48 fine-turtle systemd[1]: Started Run certbot twice daily.
Enter fullscreen mode Exit fullscreen mode

To test the renewal process manually:

sudo certbot renew --dry-run

If you see no errors, you’re all set. When necessary, Certbot will renew your certificates and reload Apache to pick up the changes. If the automated renewal process ever fails, Let’s Encrypt will send a message to the email you specified, warning you when your certificate is about to expire.

For further questions about using Certbot, please refer to their documentation.

Some References:

The process for setup LAMP in an EC2 is quite similar, which I will write about soon.

Top comments (0)