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**
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)
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
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
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)
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
Access the default Apache landing page to confirm that the software is running properly through your IP address. We should see something like this:
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>
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>
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>
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
🚀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
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)
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)
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
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
- 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
- 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):
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
- 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
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.
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:
- MySQL on Ubuntu
- Apache on Ubuntu
- Apache Software Foundation
- Lamp on Ubuntu 22-04
- Secure Apache with Let's Encrypt
- Let's Encrypt
The process for setup LAMP in an EC2 is quite similar, which I will write about soon.
Top comments (1)
LAMP Server Setup on Vultr VPS
Setting up a LAMP stack (Linux, Apache, MySQL, PHP) on Vultr VPS is efficient and secure. Here’s a simple guide to get you started:
Start by deploying your VPS through Vultr's Cloud Compute, offering high performance with NVMe SSDs.
sudo apt update
sudo apt install apache2
Configure your firewall to allow HTTP/HTTPS traffic.
sudo apt install mysql-server
For larger projects, consider Vultr Managed Databases to simplify scaling and backups.
sudo apt install php libapache2-mod-php php-mysql
Use Let’s Encrypt to secure your website:
sudo apt install certbot python3-certbot-apache
sudo certbot --apache
Why Vultr for LAMP Servers?
Start building scalable web applications with Vultr today.
*Follow the More Guide That Help me to Deploy:
*
Guide to the installation of MySQL on Ubuntu 24.04