Web server with Apache/MariaDB/PHP on Ubuntu

In this article we will setup a web server with Apache/MariaDB/PHP on Ubuntu 20.04. Most of the packages we will install will be from the default repositories.

1st thing we will do is, update our system and enable firewall with few specific ports we need.

Note: Words highlighted in bold within code snippets are pointers or need to be changed.

apt update
apt upgrade

ufw allow 22
ufw allow 80
ufw allow 443

ufw enable

Let’s install all the base packages of Apache, MariaDB and PHP. Modify to remove or add any package of your choice.

apt install vim apache2 mariadb-server libapache2-mod-php php php-gmp php-bcmath php-gd php-json php-mysql php-curl php-mbstring php-intl php-imagick php-xml php-zip bzip2 zip unzip php-imagick imagemagick php-fpm php-fileinfo php-apcu

Enable Apache modules:

a2enmod ssl rewrite headers proxy proxy_http deflate cache proxy_wstunnel http2 proxy_fcgi env expires

Enable and start Apache:

systemctl enable apache2
systemctl start apache2

At this point if you want to enable and use http2 for you applications, click on the button below to setup php-fpm. The article is generic but at that time was written for Nextcloud setup.

There are some basic changes you can make to php.ini. If you use http2, php.ini location is /etc/php/7.4/fpm/php.ini, otherwise it is /etc/php/7.4/apache2/php.ini.

vim /etc/php/7.4/apache2/php.ini
output_buffering = off (line 215)
max_execution_time = 120 (line 388)
memory_limit = 512M (line 409)
post_max_size = 100M (line 694)
upload_max_filesize = 100M (line 846)
date.timezone = Europe/Berlin (line 962)

These are the changes I would make initially. You can go through php.ini and make changes according to your needs.

Database server setup

We are done with the basic setup of PHP. Now let’s setup our database server. The 1st thing we would do is secure our database server with the likes of setting up root password, removing test database and user, remove remote access etc.

/usr/bin/mysql_secure_installation

Login to database server with:

mysql -u root -p

Create a database and assign a user to it:

create database DATABASE CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

grant all on DATABASE.* to 'DBUSER'@'localhost' identified by 'PASSWORD';

flush privileges;

If you want to use a database management tool, I would recommend Adminer. It’s simple, light and only one file.

cd /var/www/html
wget https://github.com/vrana/adminer/releases/download/v4.8.1/adminer-4.8.1-en.php

Creating a virtual host

I personally create virtual hosts with Apache, that way you have more control over the sites the server serve in the long run. Location for Apache virtual hosts is /etc/apache2/sites-available.

Enable virtual host

a2ensite DOMAIN.com

Disable virtual host

a2dissite DOMAIN.com

Don’t forget to restart Apache afterwards.

A simple block for port 80 would look like this.

<VirtualHost *:80>
	ServerName DOMAIN.com
	ServerAlias www.DOMAIN.com
	DocumentRoot /var/www/html/DOMAIN.com	

	<Directory "/var/www/html/DOMAIN.com">
		AllowOverride All
		Options -Indexes +FollowSymLinks
	</Directory>

	ErrorLog /var/log/apache2/DOMAIN-error.log
	CustomLog /var/log/apache2/DOMAIN-requests.log combined
</VirtualHost>

A block with 443, and redirection from port 80(http).

Note: do not use the 443 block if you haven’t have any SSL certificate yet.

<VirtualHost *:80>
	ServerName DOMAIN.com
	ServerAlias www.DOMAIN.com
	DocumentRoot /var/www/html/DOMAIN.com
	RewriteEngine On
	RewriteCond %{HTTPS} off
	RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

	<Directory "/var/www/html/DOMAIN.com">
		AllowOverride All
		Options -Indexes +FollowSymLinks
	</Directory>

	ErrorLog /var/log/apache2/DOMAIN-error.log
	CustomLog /var/log/apache2/DOMAIN-requests.log combined
</VirtualHost>

<VirtualHost *:443>
	ServerName DOMAIN.com
	ServerAlias www.DOMAIN.com
	DocumentRoot /var/www/html/DOMAIN.com

	SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4
	SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
	SSLHonorCipherOrder On
	Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
	Header always set X-Frame-Options DENY
	Header always set X-Content-Type-Options nosniff

	<Directory "/var/www/html/DOMAIN.com">
		AllowOverride All
		Options -Indexes +FollowSymLinks
	</Directory>

	ErrorLog /var/log/apache2/DOMAIN-error.log
	CustomLog /var/log/apache2/DOMAIN-requests.log combined

	SSLEngine on
	SSLCertificateKeyFile /etc/letsencrypt/live/DOMAIN.com/privkey.pem
	SSLCertificateFile /etc/letsencrypt/live/DOMAIN.com/fullchain.pem
</VirtualHost>

You can always check your SSL setup and ciphers with sites like ssllabs.com.

Certbot installation and getting a certificate

Click the following button to install certbot and get a certificate. Use the web root method to renew the certificates without a worry of expiration.