How to Install WordPress with LEMP on Ubuntu 20.04

Introduction

WordPress is the most popular content management systems (CMS) on the internet currently, allows users to set up flexible blogs and websites using a MySQL backend with PHP processing. WordPress has seen an incredible adoption rate among new and experienced engineers alike, and is a great choice for getting a website up and running efficiently. After an initial setup, almost all administration for WordPress websites can be done through its graphical interface— these features and more make WordPress a great choice for websites built to scale.

In this tutorial, you’ll focus on getting an instance of WordPress set up on a LEMP stack (Linux, Nginx, MySQL, and PHP) for an Ubuntu 20.04 server.

Prerequisites

In order to complete this tutorial, you’ll need access to an Ubuntu 20.04 server. To successfully install WordPress with LEMP on your server, you’ll also need to perform the following tasks before starting this tutorial:

  • Create a sudo user on your server: The steps in this tutorial are using a non-root user with sudo privileges. You can create a user with sudo privileges by following our Ubuntu 20.04 initial server setup tutorial.
  • Install a LEMP stack: WordPress will need a web server, a database, and PHP in order to correctly function. Setting up a LEMP stack (Linux, Nginx, MySQL, and PHP) fulfills all of these requirements. Follow this tutorial to install and configure this software.
  • Secure your site with SSL: WordPress serves dynamic content and handles user authentication and authorization. TLS/SSL is the technology that allows you to encrypt the traffic from your site so that your connection is secure. The way you set up SSL will depend on whether you have a domain name for your site.

When you are finished with setup, log in to your server as the sudo user to continue.

Step 1 — Creating a MySQL Database and User for WordPress

WordPress uses MySQL to manage and store site and user information. Although you already have MySQL installed, let’s create a database and a user for WordPress to use.

To get started, log in to the MySQL root (administrative) account. If MySQL is configured to use the auth_socket authentication plugin (which is default), you can log in to the MySQL administrative account using sudo:

 $ sudo mysql

If you have changed the authentication method to use a password for the MySQL root account, use the following command instead:

 $ mysql -u root -p

You will be prompted for the password you set for the MySQL root account.

Once logged in, create a separate database that WordPress can control. You can call this whatever you would like, but we will be using wordpress in this guide to keep it simple. You can create a database for WordPress by entering:

Mysql> CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Note: Every MySQL statement must end in a semi-colon (;). If you’ve encountered an error, check to make sure the semicolon is present.

Next, let’s create a separate MySQL user account that we will use exclusively to operate on our new database. Creating single-purpose databases and accounts is a good idea from a management and security standpoint. We’ll use the name wordpressuser in this guide — feel free to change this if you’d like.

In the following command, you are going to create an account, set a password, and grant access to the database you created. Remember to choose a strong password here:

CREATE USER 'wordpressuser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL ON wordpress.* TO 'wordpressuser'@'localhost';

You now have a database and user account, each made specifically for WordPress.

With the database tasks complete, let’s exit out of MySQL by typing:

EXIT

The MySQL session will exit, returning you to the regular Linux shell.

Step 2 — Installing Additional PHP Extensions

When setting up the LEMP stack, it required a very minimal set of extensions to get PHP to communicate with MySQL. WordPress and many of its plugins leverage additional PHP extensions, and you’ll use a few more in this tutorial.

Let’s download and install some of the most popular PHP extensions for use with WordPress by typing:

 $ sudo apt update
 $ sudo apt install php-curl php-gd php-intl php-mbstring php-soap php-xml php-xmlrpc php-zip

Note: Each WordPress plugin has its own set of requirements. Some may require additional PHP extension packages to be installed. Check your plugin documentation to discover its PHP requirements. If they are available, they can be installed with apt as demonstrated above.

When you are finished installing the extensions, restart the PHP-FPM process so that the running PHP processor can leverage the newly installed features:

 $ sudo systemctl restart php7.4-fpm

You now have all of the PHP extensions needed, installed on the server.

Step 3 — Configuring Nginx
Next, let’s make a few adjustments to our Nginx server block files. Based on the prerequisite tutorials, you should have a configuration file for your site in the /etc/nginx/sites-available/ directory configured to respond to your server’s domain name or IP address and protected by a TLS/SSL certificate. We’ll use /etc/apache2/sites-available/wordpress as an example here, but you should substitute the path to your configuration file where appropriate.

Additionally, we will use /var/www/wordpress as the root directory of our WordPress install in this guide. Again, you should use the web root specified in your own configuration.

Note: It’s possible you are using the /etc/nginx/sites-available/default default configuration (with /var/www/html as your web root). This is fine to use if you’re only going to host one website on this server. If not, it’s best to split the necessary configuration into logical chunks, one file per site.

Open your site’s server block file with sudo privileges to begin:

 $ sudo nano /etc/nginx/sites-available/wordpress

Within the main server block, let’s add a few location blocks.

Start by creating exact-matching location blocks for requests to /favicon.ico and /robots.txt, both of which you do not want to log requests for.

Use a regular expression location to match any requests for static files. We will again turn off the logging for these requests and will mark them as highly cacheable, since these are typically expensive resources to serve. You can adjust this static files list to contain any other file extensions your site may use:

/etc/nginx/sites-available/wordpress
server {
    . . .

    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt { log_not_found off; access_log off; allow all; }
    location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
        expires max;
        log_not_found off;
    }
    . . .
}

Inside of the existing location / block, let’s adjust the try_files list. Comment out the default setting by prepending the line with a pound sign (#) and then add the highlighted line. This way, instead of returning a 404 error as the default option, control is passed to the index.php file with the request arguments.

This should look something like this:

/etc/nginx/sites-available/wordpress
server {
. . .
location / {
#try_files $uri $uri/ =404;
try_files $uri $uri/ /index.php$is_args$args;
}
. . .
}

When you are finished, save and close the file.

Now, let’s check our configuration for syntax errors by typing:

 $ sudo nginx -t

If no errors were reported, reload Nginx by typing:

$ sudo systemctl reload nginx

Next, let’s download and set up WordPress.

Step 4 — Downloading WordPress
Now that your server software is configured, let’s download and set up WordPress. For security reasons, it is always recommended to get the latest version of WordPress directly from the project’s website.

Change into a writable directory and then download the compressed release by typing:

 $ cd /tmp

This changes your directory to the temporary folder. Then, enter the following command to download the latest version of WordPress in a compressed file:

curl -LO https://wordpress.org/latest.tar.gz

Note: The -LO flag is used to get directly to the source of the compressed file. -L ensures that fetching the file is successful in the case of redirects, and -O writes the output of our remote file with a local file that has the same name. To learn more about curl commands, visit How to Download Files with cURL
Extract the compressed file to create the WordPress directory structure:

tar xzvf latest.tar.gz

You will be moving these files into our document root momentarily, but before you do, let’s copy over the sample configuration file to the filename that WordPress actually reads:

cp /tmp/wordpress/wp-config-sample.php /tmp/wordpress/wp-config.php

Now, let’s copy the entire contents of the directory into our document root. We’re using the -a flag to make sure our permissions are maintained, and a dot at the end of our source directory to indicate that everything within the directory should be copied (including hidden files):

sudo cp -a /tmp/wordpress/. /var/www/wordpress

Now that our files are in place, you’ll assign ownership to the www-data user and group. This is the user and group that Nginx runs as, and Nginx will need to be able to read and write WordPress files in order to serve the website and perform automatic updates:

sudo chown -R www-data:www-data /var/www/wordpress

Files are now in the server’s document root and have the correct ownership, but you still need to complete some additional configuration.

Step 5 — Setting up the WordPress Configuration File
Next, let’s make some changes to the main WordPress configuration file.

When you open the file, you’ll start by adjusting some secret keys to provide some security for our installation. WordPress provides a secure generator for these values so that you don’t have to come up with values on your own. These are only used internally, so it won’t hurt usability to have complex, secure values here.

To grab secure values from the WordPress secret key generator, type:

curl -s https://api.wordpress.org/secret-key/1.1/salt/

You will get back unique values that look something like this:
Warning: It is important that you request unique values each time. Do NOT copy the values shown below!

Output
define(‘AUTH_KEY’, ‘1jl/vqfs define(‘SECURE_AUTH_KEY’, ‘E2N-h2]Dcvp+aS/p7X DO NOT COPY THESE VALUES {Ka(f;rv?Pxf})CgLi-3’);
define(‘LOGGED_IN_KEY’, ‘W(50,{W^,OPB%PB define(‘NONCE_KEY’, ‘ll,4UC)7ua+8<!4VM+ DO NOT COPY THESE VALUES #`DXF+[$atzM7 o^-C7g’);
define(‘AUTH_SALT’, ‘koMrurzOA+|L_lG}kf DO NOT COPY THESE VALUES 07VC*Lj*lD&?3w!BT#-‘);
define(‘SECURE_AUTH_SALT’, ‘p32*p,]z%LZ+pAu:VY DO NOT COPY THESE VALUES C-?y+K0DK_+F|0h{!_xY’);
define(‘LOGGED_IN_SALT’, ‘i^/G2W7!-1H2OQ+t$3 DO NOT COPY THESE VALUES t6**bRVFSD[Hi])-qS`|’);
define(‘NONCE_SALT’, ‘Q6]U:K?j4L%Z]}h^q7 DO NOT COPY THESE VALUES 1% ^qUswWgn+6&xqHN&%’);

These are configuration lines that you can paste directly in your configuration file to set secure keys. Copy the output you received now.

Now, open the WordPress configuration file:

 $ sudo nano /var/www/wordpress/wp-config.php

Find the section that contains the dummy values for those settings. It will look something like this:
/var/www/wordpress/wp-config.php
. . .

define(‘AUTH_KEY’, ‘put your unique phrase here’);
define(‘SECURE_AUTH_KEY’, ‘put your unique phrase here’);
define(‘LOGGED_IN_KEY’, ‘put your unique phrase here’);
define(‘NONCE_KEY’, ‘put your unique phrase here’);
define(‘AUTH_SALT’, ‘put your unique phrase here’);
define(‘SECURE_AUTH_SALT’, ‘put your unique phrase here’);
define(‘LOGGED_IN_SALT’, ‘put your unique phrase here’);
define(‘NONCE_SALT’, ‘put your unique phrase here’);
Delete those lines and paste in the values you copied from the command line:

/var/www/wordpress/wp-config.php
. . .

define(‘AUTH_KEY’, ‘VALUES COPIED FROM THE COMMAND LINE’);
define(‘SECURE_AUTH_KEY’, ‘VALUES COPIED FROM THE COMMAND LINE’);
define(‘LOGGED_IN_KEY’, ‘VALUES COPIED FROM THE COMMAND LINE’);
define(‘NONCE_KEY’, ‘VALUES COPIED FROM THE COMMAND LINE’);
define(‘AUTH_SALT’, ‘VALUES COPIED FROM THE COMMAND LINE’);
define(‘SECURE_AUTH_SALT’, ‘VALUES COPIED FROM THE COMMAND LINE’);
define(‘LOGGED_IN_SALT’, ‘VALUES COPIED FROM THE COMMAND LINE’);
define(‘NONCE_SALT’, ‘VALUES COPIED FROM THE COMMAND LINE’);
Next, let’s modify some of the database connection settings at the beginning of the file. You’ll have to adjust the database name, the database user, and the associated password that was configured within MySQL.

The other change you should make is to set the method that WordPress uses to write to the filesystem. Since you’ve given the web server permission to write where it needs to, you can explicitly set the filesystem method to “direct”. Failure to set this with our current settings would result in WordPress prompting for FTP credentials when we perform some actions. Add this setting below the database connection settings, or anywhere else in the file:

/var/www/wordpress/wp-config.php
. . .

define( ‘DB_NAME’, ‘wordpress’ );

/** MySQL database username */
define( ‘DB_USER’, ‘wordpressuser’ );

/** MySQL database password */
define( ‘DB_PASSWORD’, ‘password’ );

. . .

define( ‘FS_METHOD’, ‘direct’ );
Save and close the file when you’re done.

Step 6 — Completing the Installation Through the Web Interface
Now that the server configuration is complete, you can finish up the installation through WordPress’ web interface.

In your web browser, navigate to your server’s domain name or public IP address:

http://server_domain_or_IP/wordpress
Select the language you would like to use:

WordPress language selection

Next, you will come to the main setup page.

Select a name for your WordPress site and choose a username (it is recommended not to choose something like “admin” for security purposes). A strong password is generated automatically. Save this password or select an alternative strong password.

Enter your email address and select whether you want to discourage search engines from indexing your site:

WordPress setup installation

When you click ahead, you will be taken to a page that prompts you to log in:

WordPress login prompt

Once you log in, you will be taken to the WordPress administration dashboard:

WordPress login prompt

Conclusion
WordPress should be installed and ready to use! Some common next steps are to choose the permalinks setting for your posts (can be found in Settings > Permalinks) or to select a new theme (in Appearance > Themes). If this is your first time using WordPress, explore the interface a bit to get acquainted with your new CMS.

How To Serve Flask Applications with uWSGI and Nginx on Ubuntu 20.04

How To Serve Flask Applications with uWSGI and Nginx on Ubuntu 20.04

Introduction

In this guide, you will build a Python application using the Flask microframework on Ubuntu 20.04. The bulk of this article will be about how to set up the uWSGI application server and how to launch the application and configure Nginx to act as a front-end reverse proxy.

Before starting this guide, you should have:

  • A server with Ubuntu 20.04 installed and a non-root user with sudo privileges. Follow our initial server setup guide for guidance.
  • Nginx installed, following Steps 1 through 3 of How To Install Nginx on Ubuntu 20.04.
  • A domain name configured to point to your server. You can purchase one on Namecheap or get one for free on Freenom. You can learn how to point domains to DigitalOcean by following the relevant documentation on domains and DNS. This tutorial assumes you’ve created the following DNS records:
    • An A record with your_domain pointing to your server’s public IP address.
    • An A record with www.your_domain pointing to your server’s public IP address.

Additionally, it may be helpful to have some familiarity with uWSGI, the application server you’ll set up in this guide, and the WSGI specification. This discussion of definitions and concepts goes over both in detail.

Step 1 — Installing the Components from the Ubuntu Repositories

Your first step will be to install all of the pieces that you need from the Ubuntu repositories. The packages you need to install include pip, the Python package manager, to manage your Python components. You’ll also get the Python development files necessary to build uWSGI.

First, update the local package index:

 $ sudo apt update

Then install the packages that will allow you to build your Python environment. These will include python3-pip, along with a few more packages and development tools necessary for a robust programming environment:

 $ sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools

With these packages in place, you’re ready to move on to creating a virtual environment for your project.

Step 2 — Creating a Python Virtual Environment

A Python virtual environment is a self-contained project directory that contains specific versions of Python and the Python modules required for the given project. This is useful for isolating one application from others on the same system by managing each one’s dependencies separately. In this step, you’ll set up a Python virtual environment from which you’ll run your Flask application.

Start by installing the python3-venv package, which will install the venv module:

 $ sudo apt install python3-venv

Next, make a parent directory for your Flask project:

  • mkdir ~/myproject

Move into the directory after you create it:

  • cd ~/myproject

Create a virtual environment to store your Flask project’s Python requirements by typing:

  • python3.8 -m venv myprojectenv

This will install a local copy of Python and pip into a directory called myprojectenv within your project directory.

Before installing applications within the virtual environment, you need to activate it. Do so by typing:

  • source myprojectenv/bin/activate

Your prompt will change to indicate that you are now operating within the virtual environment. It will look something like this: (myprojectenv)user@host:~/myproject$.

Now that you are in your virtual environment, you can install Flask and uWSGI and then get started on designing your application.

First, install wheel with the local instance of pip to ensure that your packages will install even if they are missing wheel archives:

  • pip install wheel

Note: Regardless of which version of Python you are using, when the virtual environment is activated, you should use the pip command (not pip3).

Next, install Flask and uWSGI:

  • pip install uwsgi flask

Creating a Sample App

Now that you have Flask available, you can create a sample application. Flask is a microframework. It does not include many of the tools that more full-featured frameworks might, and exists mainly as a module that you can import into your projects to assist you in initializing a web application.

While your application might be more complex, in this example you’ll create your Flask app in a single file, called myproject.py:

  • nano ~/myproject/myproject.py

The application code will live in this file. It will import Flask and instantiate a Flask object. You can use this to define the functions that you want to be run when a specific route is requested:

~/myproject/myproject.py
from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

Essentially, this defines what content to present to whoever accesses the root domain. Save and close the file when you’re finished. If you used nano to edit the file, as in the previous example, do so by pressing CTRL + XY, and then ENTER.

If you followed the initial server setup guide, you should have a UFW firewall enabled. To test the application, you need to allow access to port 5000:

sudo ufw allow 5000

Now, you can test your Flask app by typing:

  • python myproject.py

You will see output like the following, including a helpful warning reminding you not to use this server setup in production:

Output
* Serving Flask app "myproject" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

Visit your server’s IP address followed by :5000 in your web browser:

http://your_server_ip:5000

You will see something like this:

Flask sample app

When you are finished, hit CTRL + C in your terminal window to stop the Flask development server.

Creating the WSGI Entry Point

Next, create a file that will serve as the entry point for your application. This will tell your uWSGI server how to interact with it.

Call the file wsgi.py:

  • nano ~/myproject/wsgi.py

In this file, import the Flask instance from your application and then run it:

~/myproject/wsgi.py
from myproject import app

if __name__ == "__main__":
    app.run()

Save and close the file when you are finished.

Step 4 — Configuring uWSGI

Your application is now written with an entry point established. You can move on to configuring uWSGI.

Testing Whether uWSGI Can Serve the Application

As a first step, test to make sure that uWSGI can correctly serve your application by passing it the name of your entry point. This is constructed by the name of the module (minus the .pyextension) plus the name of the callable within the application. In the context of this tutorial, the name of the entry point is wsgi:app.

Also, specify the socket so that it will be started on a publicly available interface, as well as the protocol, so that it will use HTTP instead of the uwsgi binary protocol. Use the same port number, 5000, that you opened earlier:

  • uwsgi –socket 0.0.0.0:5000 –protocol=http -w wsgi:app

Visit your server’s IP address with :5000 appended to the end in your web browser again:

http://your_server_ip:5000

You will see your application’s output again:

Flask sample app

When you have confirmed that it’s functioning properly, press CTRL + C in your terminal window.

You’re now done with your virtual environment, so you can deactivate it:

  • deactivate

Any Python commands will now use the system’s Python environment again.

Creating a uWSGI Configuration File

You have tested that uWSGI is able to serve your application, but ultimately you will want something more robust for long-term usage. You can create a uWSGI configuration file with the relevant options for this.

Place that file in your project directory and call it myproject.ini:

  • nano ~/myproject/myproject.ini

Inside, start the file off with the [uwsgi] header so that uWSGI knows to apply the settings. Below that, specify module itself — by referring to the wsgi.py file minus the extension — and the callable within the file, app:

~/myproject/myproject.ini
[uwsgi]
module = wsgi:app

Next, tell uWSGI to start up in master mode and spawn five worker processes to serve actual requests:

~/myproject/myproject.ini
[uwsgi]
module = wsgi:app

master = true
processes = 5

When you were testing, you exposed uWSGI on a network port. However, you’re going to be using Nginx to handle actual client connections, which will then pass requests to uWSGI. Since these components are operating on the same computer, a Unix socket is preferable because it is faster and more secure. Call the socket myproject.sock and place it in this directory.

Next, change the permissions on the socket. You’ll be giving the Nginx group ownership of the uWSGI process later on, so you need to make sure the group owner of the socket can read information from it and write to it. Also, add the vacuum option and set it to true; this will clean up the socket when the process stops:

~/myproject/myproject.ini
[uwsgi]
module = wsgi:app

master = true
processes = 5

socket = myproject.sock
chmod-socket = 660
vacuum = true

The last thing to do is set the die-on-term option. This can help ensure that the init system and uWSGI have the same assumptions about what each process signal means. Setting this aligns the two system components, implementing the expected behavior:

~/myproject/myproject.ini
[uwsgi]
module = wsgi:app

master = true
processes = 5

socket = myproject.sock
chmod-socket = 660
vacuum = true

die-on-term = true

You may have noticed that these lines do not specify a protocol like you did from the command line. That is because by default, uWSGI speaks using the uwsgi protocol, a fast binary protocol designed to communicate with other servers. Nginx can speak this protocol natively, so it’s better to use this than to force communication by HTTP.

When you are finished, save and close the file.

With that, uWSGI is configured on your system. In order to give you more flexibility in how you manage your Flask application, you can now configure it to run as a systemd service.

Step 5 — Creating a systemd Unit File

Systemd is a suite of tools that provides a fast and flexible init model for managing system services. Creating a systemd unit file will allow Ubuntu’s init system to automatically start uWSGI and serve the Flask application whenever the server boots.

Create a unit file ending in .service within the /etc/systemd/system directory to begin:

  • sudo nano /etc/systemd/system/myproject.service

Inside, start with the [Unit] section, which is used to specify metadata and dependencies. Then put a description of the service here and tell the init system to only start this after the networking target has been reached:

/etc/systemd/system/myproject.service
[Unit]
Description=uWSGI instance to serve myproject
After=network.target

Next, open up the [Service] section. This will specify the user and group that you want the process to run under. Give your regular user account ownership of the process since it owns all of the relevant files. Then give group ownership to the www-data group so that Nginx can communicate easily with the uWSGI processes. Remember to replace the username here with your username:

/etc/systemd/system/myproject.service
[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data

Next, map out the working directory and set the PATH environmental variable so that the init system knows that the executables for the process are located within your virtual environment. Also, specify the command to start the service. Systemd requires that you give the full path to the uWSGI executable, which is installed within your virtual environment. Here, we pass the name of the .ini configuration file you created in your project directory.

Remember to replace the username and project paths with your own information:

/etc/systemd/system/myproject.service
[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

Finally, add an [Install] section. This will tell systemd what to link this service to if you enable it to start at boot. In this case, set the service to start when the regular multi-user system is up and running:

/etc/systemd/system/myproject.service
[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
ExecStart=/home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

[Install]
WantedBy=multi-user.target

With that, your systemd service file is complete. Save and close it now.

You can now start the uWSGI service you created:

  • sudo systemctl start myproject

Then enable it so that it starts at boot:

  • sudo systemctl enable myproject

Check the status:

  • sudo systemctl status myproject

You will see output like this:

Output
● myproject.service - uWSGI instance to serve myproject
     Loaded: loaded (/etc/systemd/system/myproject.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2020-05-20 13:21:39 UTC; 8h ago
   Main PID: 22146 (uwsgi)
      Tasks: 6 (limit: 2345)
     Memory: 25.5M
     CGroup: /system.slice/myproject.service
             ├─22146 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
             ├─22161 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
             ├─22162 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
             ├─22163 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
             ├─22164 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
             └─22165 /home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini

If you see any errors, be sure to resolve them before continuing with the tutorial. Otherwise, you can move on to configuring your Nginx installation to pass requests to the myproject.socksocket.

Step 6 — Configuring Nginx to Proxy Requests

Your uWSGI application server is now up and running, waiting for requests on the socket file in the project directory. In this step, you’ll configure Nginx to pass web requests to that socket using the uwsgi protocol.

Begin by creating a new server block configuration file in Nginx’s sites-available directory. To keep in line with the rest of the guide, the following example refers to this as myproject:

 $ sudo nano /etc/nginx/sites-available/myproject

 

Open up a server block and tell Nginx to listen on the default port 80. Additionally, tell it to use this block for requests for your server’s domain name:

/etc/nginx/sites-available/myproject

 

server {
    listen 80;
    server_name your_domain www.your_domain;
}

Next, add a location block that matches every request. Within this block, include the uwsgi_paramsfile that specifies some general uWSGI parameters that need to be set. Then pass the requests to the socket you defined using the uwsgi_pass directive:

/etc/nginx/sites-available/myproject
server {
    listen 80;
    server_name your_domain www.your_domain;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/home/sammy/myproject/myproject.sock;
    }
}

Save and close the file when you’re finished.

To enable the Nginx server block configuration you’ve just created, link the file to the sites-enabled directory:

  • sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

With the file in that directory, you can test for syntax errors by typing:

  • sudo nginx -t

If this returns without indicating any issues, restart the Nginx process to read the new configuration:

  • sudo systemctl restart nginx

Finally, adjust the firewall once again. You no longer need access through port 5000, so you can remove that rule. Then, you can allow access to the Nginx server:

  • sudo ufw delete allow 5000
  • sudo ufw allow ‘Nginx Full’

You will now be able to navigate to your server’s domain name in your web browser:

http://your_domain

You will see your application output:

Flask sample app

If you encounter any errors, trying checking the following:

  • sudo less /var/log/nginx/error.log: checks the Nginx error logs.
  • sudo less /var/log/nginx/access.log: checks the Nginx access logs.
  • sudo journalctl -u nginx: checks the Nginx process logs.
  • sudo journalctl -u myproject: checks your Flask app’s uWSGI logs.

To ensure that traffic to your server remains secure, obtain an SSL certificate for your domain. There are multiple ways to do this, including getting a free certificate from Let’s Encrypt, generating a self-signed certificate, or buying one from a commercial provider. For the sake of expediency, this tutorial explains how to obtain a free certificate from Let’s Encrypt.

First, install Certbot and its Nginx plugin with apt:

  • sudo apt install certbot python3-certbot-nginx

Certbot provides a variety of ways to obtain SSL certificates through plugins. The Nginx plugin will take care of reconfiguring Nginx and reloading the config whenever necessary. To use this plugin, type the following:

  • sudo certbot –nginx -d your_domain -d www.your_domain

This runs certbot with the --nginx plugin, using -d to specify the names you’d like the certificate to be valid for.

If this is your first time running certbot on this server, you will be prompted to enter an email address and agree to the terms of service. After doing so, certbot will communicate with the Let’s Encrypt server, then run a challenge to verify that you control the domain you’re requesting a certificate for.

If that’s successful, certbot will ask how you’d like to configure your HTTPS settings:

Output
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):

Select your choice then hit ENTER. The configuration will be updated, and Nginx will reload to pick up the new settings. certbot will wrap up with a message telling you the process was successful and where your certificates are stored:

Output
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/your_domain/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/your_domain/privkey.pem
   Your cert will expire on 2020-08-18. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

If you followed the Nginx installation instructions in the prerequisites, you will no longer need the redundant HTTP profile allowance:

  • sudo ufw delete allow ‘Nginx HTTP’

To verify the configuration, navigate once again to your domain, using https://:

https://your_domain

You will see your application output once again, along with your browser’s security indicator, which should indicate that the site is secured.

Conclusion

In this guide, you created and secured a basic Flask application within a Python virtual environment. Then you created a WSGI entry point so that any WSGI-capable application server can interface with it, and then configured the uWSGI app server to provide this function. Afterwards, you created a systemd service file to automatically launch the application server on boot. You also created an Nginx server block that passes web client traffic to the application server, thereby relaying external requests, and secured traffic to your server with Let’s Encrypt.

Flask is a simple yet flexible framework meant to provide your applications with functionality without being too restrictive about structure or design. You can use the general stack described in this guide to serve the flask applications that you design.

How To Install and Configure Zabbix to Securely Monitor Remote Servers on Ubuntu 20.04

The author selected the Computer History Museum to receive a donation as part of the Write for DOnations program.

Introduction

Zabbix is open-source monitoring software for networks and applications. It offers real-time monitoring of thousands of metrics collected from servers, virtual machines, network devices, and web applications. These metrics can help you determine the current health of your IT infrastructure and detect problems with hardware or software components before customers complain. Useful information is stored in a database so you can analyze data over time and improve the quality of provided services or plan upgrades of your equipment.

Zabbix uses several options for collecting metrics, including agentless monitoring of user services and client-server architecture. To collect server metrics, it uses a small agent on the monitored client to gather data and send it to the Zabbix server. Zabbix supports encrypted communication between the server and connected clients, so your data is protected while it travels over insecure networks.

The Zabbix server stores its data in a relational database powered by MySQL or PostgreSQL. You can also store historical data in NoSQL databases like Elasticsearch and TimescaleDB. Zabbix provides a web interface so you can view data and configure system settings.

In this tutorial, you will configure Zabbix on two Ubuntu 20.04 machines. One will be configured as the Zabbix server, and the other as a client that you’ll monitor. The Zabbix server will use a MySQL database to record monitoring data and use Nginx to serve the web interface.

Prerequisites

To follow this tutorial, you will need:

  • Two Ubuntu 20.04 servers set up by following the Initial Server Setup Guide for Ubuntu 20.04, including a non-root user with sudo privileges and a firewall configured with ufw. On one server, you will install Zabbix; this tutorial will refer to this as the Zabbix server. It will monitor your second server; this second server will be referred to as the second Ubuntu server.
  • The server that will run the Zabbix server needs Nginx, MySQL, and PHP installed. Follow Steps 1–3 of our Ubuntu 20.04 LEMP Stack guide to configure those on your Zabbix server.
  • A registered domain name. This tutorial will use your_domain throughout. You can purchase a domain name from Namecheap, get one for free with Freenom, or use the domain registrar of your choice.
  • Both of the following DNS records set up for your Zabbix server. If you are using DigitalOcean, please see our DNS documentation for details on how to add them.
    • An A record with your_domain pointing to your Zabbix server’s public IP address.
    • An A record with www.your_domain pointing to your Zabbix server’s public IP address.

Additionally, because the Zabbix Server is used to access valuable information about your infrastructure that you would not want unauthorized users to access, it’s important that you keep your server secure by installing a TLS/SSL certificate. This is optional but strongly encouraged. If you would like to secure your server, follow the Let’s Encrypt on Ubuntu 20.04 guide after Step 3 of this tutorial.

Step 1 — Installing the Zabbix Server

First, you need to install Zabbix on the server where you installed MySQL, Nginx, and PHP. Log in to this machine as your non-root user:

  • ssh sammy@zabbix_server_ip_address

Zabbix is available in Ubuntu’s package manager, but it’s outdated, so use the official Zabbix repository to install the latest stable version. Download and install the repository configuration package:

  • wget https://repo.zabbix.com/zabbix/5.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.0-1+focal_all.deb
  • sudo dpkg -i zabbix-release_5.0-1+focal_all.deb

You will see the following output:

Output
Selecting previously unselected package zabbix-release.
(Reading database ... 64058 files and directories currently installed.)
Preparing to unpack zabbix-release_5.0-1+focal_all.deb ...
Unpacking zabbix-release (1:5.0-1+focal) ...
Setting up zabbix-release (1:5.0-1+focal) ...

Update the package index so the new repository is included:

  • sudo apt update

Then install the Zabbix server and web frontend with MySQL database support:

  • sudo apt install zabbix-server-mysql zabbix-frontend-php

Also, install the Zabbix agent, which will let you collect data about the Zabbix server status itself.

  • sudo apt install zabbix-agent

Before you can use Zabbix, you have to set up a database to hold the data that the Zabbix server will collect from its agents. You can do this in the next step.

Step 2 — Configuring the MySQL Database for Zabbix

You need to create a new MySQL database and populate it with some basic information in order to make it suitable for Zabbix. You’ll also create a specific user for this database so Zabbix isn’t logging in to MySQL with the root account.

Log in to MySQL as the root user:

  • sudo mysql

Create the Zabbix database with UTF-8 character support:

  • create database zabbix character set utf8 collate utf8_bin;

Then create a user that the Zabbix server will use, give it access to the new database, and set the password for the user:

  • create user zabbix@localhost identified by ‘your_zabbix_mysql_password‘;
  • grant all privileges on zabbix.* to zabbix@localhost;

That takes care of the user and the database. Exit out of the database console.

  • quit;

Next you have to import the initial schema and data. The Zabbix installation provided you with a file that sets this up.

Run the following command to set up the schema and import the data into the zabbix database. Use zcat since the data in the file is compressed:

  • zcat /usr/share/doc/zabbix-server-mysql*/create.sql.gz | mysql -uzabbix -p zabbix

Enter the password for the zabbix MySQL user that you configured when prompted.

This command may take a minute or two to execute. If you see the error ERROR 1045 (28000): Access denied for userzabbix@'localhost' (using password: YES) then make sure you used the right password for the zabbix user.

In order for the Zabbix server to use this database, you need to set the database password in the Zabbix server configuration file. Open the configuration file in your preferred text editor. This tutorial will use nano:

  • sudo nano /etc/zabbix/zabbix_server.conf

Look for the following section of the file:

/etc/zabbix/zabbix_server.conf
...
### Option: DBPassword                           
#       Database password. Ignored for SQLite.   
#       Comment this line if no password is used.
#                                                
# Mandatory: no                                  
# Default:                                       
# DBPassword=
...

These comments in the file explain how to connect to the database. You need to set the DBPassword value in the file to the password for your database user. Add this line after those comments to configure the database:

/etc/zabbix/zabbix_server.conf
...
DBPassword=your_zabbix_mysql_password
...

Save and close zabbix_server.conf by pressing CTRL+X, followed by Y and then ENTER if you’re using nano.

You’ve now configured the Zabbix server to connect to the database. Next, you will configure the Nginx web server to serve the Zabbix frontend.

Step 3 — Configuring Nginx for Zabbix

To configure Nginx automatically, install the automatic configuration package:

  • sudo apt install zabbix-nginx-conf

As a result, you will get the configuration file /etc/zabbix/nginx.conf, as well as a link to it in the Nginx configuration directory /etc/nginx/conf.d/zabbix.conf.

Next, you need to make changes to this file. Open the configuration file:

  • sudo nano /etc/zabbix/nginx.conf

The file contains an automatically generated Nginx server block configuration. It contains two lines that determine the server name and what port it is listening on:

/etc/zabbix/nginx.conf
server {
#        listen          80;
#        server_name     example.com;
...

Uncomment the two lines, and replace example.com with your domain name. Your settings will look like this:

/etc/zabbix/nginx.conf
server {
        listen          80;
        server_name     your_domain;
...

Save and close the file. Next, test to make sure that there are no syntax errors in any of your Nginx files and reload the configuration:

  • sudo nginx -t
  • sudo nginx -s reload

Now that Nginx is set up to serve the Zabbix frontend, you will make some modifications to your PHP setup in order for the Zabbix web interface to work properly.

Note: As mentioned in the Prerequisites section, it is recommended that you enable SSL/TLS on your server. If you would like to do this, follow our Ubuntu 20.04 Let’s Encrypt tutorial before you move on to Step 4 to obtain a free SSL certificate for Nginx. This process will automatically detect your Zabbix server block and configure it for HTTPS. After obtaining your SSL/TLS certificates, you can come back and complete this tutorial.

Step 4 — Configuring PHP for Zabbix

The Zabbix web interface is written in PHP and requires some special PHP server settings. The Zabbix installation process created a PHP-FPM configuration file that contains these settings. It is located in the directory /etc/zabbix and is loaded automatically by PHP-FPM. You need to make a small change to this file, so open it up with the following:

  • sudo nano /etc/zabbix/php-fpm.conf

The file contains PHP settings that meet the necessary requirements for the Zabbix web interface. However, the timezone setting is commented out by default. To make sure that Zabbix uses the correct time, you need to set the appropriate timezone:

/etc/zabbix/php-fpm.conf
...
php_value[max_execution_time] = 300
php_value[memory_limit] = 128M
php_value[post_max_size] = 16M
php_value[upload_max_filesize] = 2M
php_value[max_input_time] = 300
php_value[max_input_vars] = 10000
; php_value[date.timezone] = Europe/Riga

Uncomment the timezone line highlighted in the preceding code block and change it to your timezone. You can use this list of supported time zones to find the right one for you. Then save and close the file.

Now restart PHP-FPM to apply these new settings:

  • sudo systemctl restart php7.4-fpm.service

You can now start the Zabbix server:

  • sudo systemctl start zabbix-server

Then check whether the Zabbix server is running properly:

  • sudo systemctl status zabbix-server

You will see the following status:

Output
● zabbix-server.service - Zabbix Server
     Loaded: loaded (/lib/systemd/system/zabbix-server.service; disabled; vendor preset: enabled)
     Active: active (running) since Fri 2020-06-12 05:59:32 UTC; 36s ago
    Process: 27026 ExecStart=/usr/sbin/zabbix_server -c $CONFFILE (code=exited, status=0/SUCCESS)
  ...

Finally, enable the server to start at boot time:

  • sudo systemctl enable zabbix-server

The server is set up and connected to the database. Next, set up the web frontend.

Step 5 — Configuring Settings for the Zabbix Web Interface

The web interface lets you see reports and add hosts that you want to monitor, but it needs some initial setup before you can use it. Launch your browser and go to the address http://zabbix_server_name or https://zabbix_server_name if you set up Let’s Encrypt. On the first screen, you will see a welcome message. Click Next step to continue.

On the next screen, you will see the table that lists all of the prerequisites to run Zabbix.

Prerequisites

All of the values in this table must be OK, so verify that they are. Be sure to scroll down and look at all of the prerequisites. Once you’ve verified that everything is ready to go, click Next step to proceed.

The next screen asks for database connection information.

DB Connection

You told the Zabbix server about your database, but the Zabbix web interface also needs access to the database to manage hosts and read data. Therefore enter the MySQL credentials you configured in Step 2. Click Next step to proceed.

On the next screen, you can leave the options at their default values.

Zabbix Server Details

The Name is optional; it is used in the web interface to distinguish one server from another in case you have several monitoring servers. Click Next step to proceed.

The next screen will show the pre-installation summary so you can confirm everything is correct.

Summary

Click Next step to proceed to the final screen.

The web interface setup is now complete. This process creates the configuration file /usr/share/zabbix/conf/zabbix.conf.php, which you could back up and use in the future. Click Finish to proceed to the login screen. The default user is Admin and the password is zabbix.

Before you log in, set up the Zabbix agent on your second Ubuntu server.

Step 6 — Installing and Configuring the Zabbix Agent

Now you need to configure the agent software that will send monitoring data to the Zabbix server.

Log in to the second Ubuntu server:

  • ssh sammy@second_ubuntu_server_ip_address

Just like on the Zabbix server, run the following commands to install the repository configuration package:

  • wget https://repo.zabbix.com/zabbix/5.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.0-1+focal_all.deb
  • sudo dpkg -i zabbix-release_5.0-1+focal_all.deb

Next, update the package index:

  • sudo apt update

Then install the Zabbix agent:

  • sudo apt install zabbix-agent

While Zabbix supports certificate-based encryption, setting up a certificate authority is beyond the scope of this tutorial. But you can use pre-shared keys (PSK) to secure the connection between the server and agent.

First, generate a PSK:

  • sudo sh -c “openssl rand -hex 32 > /etc/zabbix/zabbix_agentd.psk”

Show the key by using cat so you can copy it somewhere:

  • cat /etc/zabbix/zabbix_agentd.psk

The key will look something like this:

Output
75ad6cb5e17d244ac8c00c96a1b074d0550b8e7b15d0ab3cde60cd79af280fca

Save this for later; you will need it to configure the host.

Now edit the Zabbix agent settings to set up its secure connection to the Zabbix server. Open the agent configuration file in your text editor:

  • sudo nano /etc/zabbix/zabbix_agentd.conf

Each setting within this file is documented via informative comments throughout the file, but you only need to edit some of them.

First you have to edit the IP address of the Zabbix server. Find the following section:

/etc/zabbix/zabbix_agentd.conf
...
### Option: Server
#       List of comma delimited IP addresses, optionally in CIDR notation, or DNS names of Zabbix servers and Zabbix proxies.
#       Incoming connections will be accepted only from the hosts listed here.
#       If IPv6 support is enabled then '127.0.0.1', '::127.0.0.1', '::ffff:127.0.0.1' are treated equally
#       and '::/0' will allow any IPv4 or IPv6 address.
#       '0.0.0.0/0' can be used to allow any IPv4 address.
#       Example: Server=127.0.0.1,192.168.1.0/24,::1,2001:db8::/32,zabbix.example.com
#
# Mandatory: yes, if StartAgents is not explicitly set to 0
# Default:
# Server=

Server=127.0.0.1
...

Change the default value to the IP of your Zabbix server:

/etc/zabbix/zabbix_agentd.conf
...
Server=zabbix_server_ip_address
...

By default, Zabbix server connects to the agent. But for some checks (for example, monitoring the logs), a reverse connection is required. For correct operation, you need to specify the Zabbix server address and a unique host name.

Find the section that configures the active checks and change the default values:

/etc/zabbix/zabbix_agentd.conf
...
##### Active checks related

### Option: ServerActive
#       List of comma delimited IP:port (or DNS name:port) pairs of Zabbix servers and Zabbix proxies for active checks.
#       If port is not specified, default port is used.
#       IPv6 addresses must be enclosed in square brackets if port for that host is specified.
#       If port is not specified, square brackets for IPv6 addresses are optional.
#       If this parameter is not specified, active checks are disabled.
#       Example: ServerActive=127.0.0.1:20051,zabbix.domain,[::1]:30051,::1,[12fc::1]
#
# Mandatory: no
# Default:
# ServerActive=

ServerActive=zabbix_server_ip_address

### Option: Hostname
#       Unique, case sensitive hostname.
#       Required for active checks and must match hostname as configured on the server.
#       Value is acquired from HostnameItem if undefined.
#
# Mandatory: no
# Default:
# Hostname=

Hostname=Second Ubuntu Server
...

Next, find the section that configures the secure connection to the Zabbix server and enable pre-shared key support. Find the TLSConnect section, which looks like this:

/etc/zabbix/zabbix_agentd.conf
...
### Option: TLSConnect
#       How the agent should connect to server or proxy. Used for active checks.
#       Only one value can be specified:
#               unencrypted - connect without encryption
#               psk         - connect using TLS and a pre-shared key
#               cert        - connect using TLS and a certificate
#
# Mandatory: yes, if TLS certificate or PSK parameters are defined (even for 'unencrypted' connection)
# Default:
# TLSConnect=unencrypted
...

Then add this line to configure pre-shared key support:

/etc/zabbix/zabbix_agentd.conf
...
TLSConnect=psk
...

Next, locate the TLSAccept section, which looks like this:

/etc/zabbix/zabbix_agentd.conf
...
### Option: TLSAccept
#       What incoming connections to accept.
#       Multiple values can be specified, separated by comma:
#               unencrypted - accept connections without encryption
#               psk         - accept connections secured with TLS and a pre-shared key
#               cert        - accept connections secured with TLS and a certificate
#
# Mandatory: yes, if TLS certificate or PSK parameters are defined (even for 'unencrypted' connection)
# Default:
# TLSAccept=unencrypted
...

Configure incoming connections to support pre-shared keys by adding this line:

/etc/zabbix/zabbix_agentd.conf
...
TLSAccept=psk
...

Next, find the TLSPSKIdentity section, which looks like this:

/etc/zabbix/zabbix_agentd.conf
...
### Option: TLSPSKIdentity
#       Unique, case sensitive string used to identify the pre-shared key.
#
# Mandatory: no
# Default:
# TLSPSKIdentity=
...

Choose a unique name to identify your pre-shared key by adding this line:

/etc/zabbix/zabbix_agentd.conf
...
TLSPSKIdentity=PSK 001
...

You’ll use this as the PSK ID when you add your host through the Zabbix web interface.

Then set the option that points to your previously created pre-shared key. Locate the TLSPSKFileoption:

/etc/zabbix/zabbix_agentd.conf
...
### Option: TLSPSKFile
#       Full pathname of a file containing the pre-shared key.
#
# Mandatory: no
# Default:
# TLSPSKFile=
...

Add this line to point the Zabbix agent to your PSK file you created:

/etc/zabbix/zabbix_agentd.conf
...
TLSPSKFile=/etc/zabbix/zabbix_agentd.psk
...

Save and close the file. Now you can restart the Zabbix agent and set it to start at boot time:

  • sudo systemctl restart zabbix-agent
  • sudo systemctl enable zabbix-agent

For good measure, check that the Zabbix agent is running properly:

  • sudo systemctl status zabbix-agent

You will see the following status, indicating the agent is running:

Output
● zabbix-agent.service - Zabbix Agent
   Loaded: loaded (/lib/systemd/system/zabbix-agent.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2020-06-12 08:19:54 UTC; 25s ago
  ...

The agent will listen on port 10050 for connections from the server. Configure UFW to allow connections to this port:

  • sudo ufw allow 10050/tcp

You can learn more about UFW in How To Set Up a Firewall with UFW on Ubuntu 20.04.

Your agent is now ready to send data to the Zabbix server. But in order to use it, you have to link to it from the server’s web console. In the next step, you will complete the configuration.

Step 7 — Adding the New Host to the Zabbix Server

Installing an agent on a server you want to monitor is only half of the process. Each host you want to monitor needs to be registered on the Zabbix server, which you can do through the web interface.

Log in to the Zabbix Server web interface by navigating to the address http://zabbix_server_name or https://zabbix_server_name:

The Zabbix login screen

When you have logged in, click on Configuration and then Hosts in the left navigation bar. Then click the Create host button in the top right corner of the screen. This will open the host configuration page.

Creating a host

Adjust the Host name and IP address to reflect the host name and IP address of your second Ubuntu server, then add the host to a group. You can select an existing group, for example Linux servers, or create your own group. The host can be in multiple groups. To do this, enter the name of an existing or new group in the Groups field and select the desired value from the proposed list.

Before adding the group, click the Templates tab.

Adding a template to the host

Type Template OS Linux by Zabbix agent in the Search field and then select it from the list to add this template to the host.

Next, navigate to the Encryption tab. Select PSK for both Connections to host and Connections from host. Then set PSK identity to PSK 001, which is the value of the TLSPSKIdentity setting of the Zabbix agent you configured previously. Then set PSK value to the key you generated for the Zabbix agent. It’s the one stored in the file /etc/zabbix/zabbix_agentd.psk on the agent machine.

Setting up the encryption

Finally, click the Add button at the bottom of the form to create the host.

You will see your new host in the list. Wait for a minute and reload the page to see green labels indicating that everything is working fine and the connection is encrypted.

Zabbix shows your new host

If you have additional servers you need to monitor, log in to each host, install the Zabbix agent, generate a PSK, configure the agent, and add the host to the web interface following the same steps you followed to add your first host.

The Zabbix server is now monitoring your second Ubuntu server. Now, set up email notifications to be notified about problems.

Step 8 — Configuring Email Notifications

Zabbix automatically supports many types of notifications: email, OTRSSlackTelegram, SMS, etc. You can see the full list of integrations at the Zabbix website.

As an example, this tutorial will configure notifications for the Email media type.

Click on Administration, and then Media types in the left navigation bar. You will see the list of all media types. There are two preconfigured options for emails: for the plain text notification and for the HTML notifications. In this tutorial you will use plain text notification. Click on Email.

Adjust the SMTP options according to the settings provided by your email service. This tutorial uses Gmail’s SMTP capabilities to set up email notifications; if you would like more information about setting this up, see How To Use Google’s SMTP Server.


Note: If you use 2-Step Verification with Gmail, you need to generate an App Password for Zabbix. You’ll only have to enter an App password once during setup. You will find instructions on how to generate this password in the Google Help Center.

If you are using Gmail, type in smtp.gmail.com for the SMTP server field, 465 for the SMTP server port field, gmail.com for SMTP helo, and your email for SMTP email. Then choose SSL/TLS for Connection security and Username and password for Authentication. Enter your Gmail address as the Username, and the App Password you generated from your Google account as the Password.

Setting up email media type

On the Message templates tab you can see the list of predefined messages for various types of notifications. Finally, click the Update button at the bottom of the form to update the email parameters.

Now you can test sending notifications. To do this, click the Test underlined link in the corresponding line.

You will see a pop-up window. Enter your email address in the Send to field and click the Testbutton. You will see a message about the successful sending and you will receive a test message.

Testing email

Close the pop-up by clicking the Cancel button.

Now, create a new user. Click on Administration, and then Users in the left navigation bar. You will see the list of users. Then click the Create user button in the top right corner of the screen. This will open the user configuration page:

Creating a user

Enter the new username in the Alias field and set up a new password. Next, add the user to the administrator’s group. Type Zabbix administrators in the Groups field and select it from the proposed list.

Once you’ve added the group, click the Media tab and click on the Add underlined link (not the Add button below it). You will see a pop-up window.

Adding an email

Select the Email option from the Type drop down. Enter your email address in the Send to field. You can leave the rest of the options at the default values. Click the Add button at the bottom to submit.

Now navigate to the Permissions tab. Select Zabbix Super Admin from the User type drop-down menu.

Finally, click the Add button at the bottom of the form to create the user.

Note: Using the default password is not safe. In order to change the password of the built-in user Admin click on the alias in the list of users. Then click Change password, enter a new password, and confirm the changes by clicking Update button.

Now you need to enable notifications. Click on the Configuration tab and then Actions in the left navigation bar. You will see a pre-configured action, which is responsible for sending notifications to all Zabbix administrators. You can review and change the settings by clicking on its name. For the purposes of this tutorial, use the default parameters. To enable the action, click on the red Disabled link in the Status column.

Now you are ready to receive alerts. In the next step, you will generate one to test your notification setup.

Step 9 — Generating a Test Alert

In this step, you will generate a test alert to ensure everything is connected. By default, Zabbix keeps track of the amount of free disk space on your server. It automatically detects all disk mounts and adds the corresponding checks. This discovery is executed every hour, so you need to wait a while for the notification to be triggered.

Create a temporary file that’s large enough to trigger Zabbix’s file system usage alert. To do this, log in to your second Ubuntu server if you’re not already connected:

  • ssh sammy@second_ubuntu_server_ip_address

Next, determine how much free space you have on the server. You can use the df command to find out:

  • df -h

The command df will report the disk space usage of your file system, and the -h will make the output human-readable. You’ll see output like the following:

Output
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        78G  1.4G   77G    2% /

In this case, the free space is 77G. Your free space may differ.

Use the fallocate command, which allows you to pre-allocate or de-allocate space to a file, to create a file that takes up more than 80% of the available disk space. This will be enough to trigger the alert:

  • fallocate -l 70G /tmp/temp.img

After around an hour, Zabbix will trigger an alert about the amount of free disk space and will run the action you configured, sending the notification message. You can check your inbox for the message from the Zabbix server. You will see a message like:

Problem started at 09:49:08 on 2020.06.12
Problem name: /: Disk space is low (used > 80%)
Host: Second Ubuntu Server
Severity: Warning
Operational data: Space used: 71.34 GB of 77.36 GB (92.23 %)
Original problem ID: 106

You can also navigate to the Monitoring tab and then Dashboard to see the notification and its details.

Main dashboard

Now that you know the alerts are working, delete the temporary file you created so you can reclaim your disk space:

  • rm -f /tmp/temp.img

After a minute Zabbix will send the recovery message and the alert will disappear from the main dashboard.

Conclusion

In this tutorial, you learned how to set up a simple and secure monitoring solution that will help you monitor the state of your servers. It can now warn you of problems, and you have the opportunity to analyze the processes occurring in your IT infrastructure.

To learn more about setting up monitoring infrastructure, check out our Monitoring topic page.

How To Install Let’s Encrypt SSL With Nginx on CentOS 7

Let’s Encrypt SSL With Nginx on CentOS 7

LetsEncrypt is a free open certificate authority (CA) that provides free certificates for websites and other services. The service, which is backed by the Electronic Frontier Foundation, Mozilla, Cisco Systems, and Akamai. Unfortunately, LetsEncrypt.org certificates currently have a 3 month lifetime. This means you’ll need to renew your certificate quarterly for now.

Prerequisites

This article assumes you have at least basic knowledge of linux, know how to use the shell, and most importantly, you host your site on your own VPS. The installation is quite simple and assumes you are running in the root account, if not you may need to add ‘sudo’ to the commands to get root privileges. I will show you through the step by step installation Let’s Encrypt SSL with Nginx on a CentOS 7 server.
Install Let’s Encrypt SSL With Nginx on CentOS 7

Step 1. First let’s start by ensuring your system is up-to-date.

yum clean all
yum -y update
Step 2. Installing Let’s Encrypt SSL on CentOS 7.

In CentOS 7, you can find Certbot on the EPEL repository; if you enable it, just install what you need:
yum install epel-release
yum install certbot

You will also need to have nginx installed and running. Of course, if you are adding certificates onto a previously configured web host this would already be installed:

yum install nginx
systemctl start nginx

The first step to install let’s encrypt ssl on CentOS Linux is to add a simple configuration inside your nginx virtual host configuration. Add this line to your vhost configuration:

location ~ /.well-known {
allow all;
}

Save and exit to apply changes:

nginx -t
systemctl restart nginx

Obtaining a certificate with Certbot:

Run the command as you see below, replace “wpcademy.com” with your real domain name and /var/www/wpcademy.com with your real webroot path:

certbot certonly -a webroot --webroot-path=/var/www/wpcademy.com -d wpcademy.com -d www.wpcademy.com

Result:

[[email protected]:~]certbot certonly -a webroot --webroot-path=/var/www/wpcademy.com -d wpcademy.com -d www.wpcademy.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for wpcademy.com
Using the webroot path /var/www/html for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (2048 bits): /etc/letsencrypt/keys/0001_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0001_csr-certbot.pem
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/idroot.us/fullchain.pem. Your cert
will expire on 2017-07-16. To obtain a new or tweaked version of
this certificate in the future, simply run certbot again. To
non-interactively renew *all* of your certificates, run "certbot
renew"
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
[[email protected]:~]

Step 3. Configure Let’s Encrypt TLS/SSL on Nginx Web Server.

First, edit the Virtual Host file you specified during configuration through Certbot and add this three directives:

listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/idroot.us/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/idroot.us/privkey.pem;

The full nginx vhost configuration may look like this:

server {
listen 80;
server_name wpcademy.com www.wpcademy.com;
rewrite ^(.*) https://wpcademy.com$1 permanent;
}

server {
access_log off;
log_not_found off;
error_log logs/idroot.us-error_log warn;

server_name wpcademy.com;
root /var/www/wpcademy.com;
index index.php index.html index.htm;

listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/wpcademy.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/wpcademy.com/privkey.pem;

## Stuff required by certbot
location ~ /.well-known {
allow all;
}

## SSL
ssl_session_cache shared:SSL:20m;
ssl_session_timeout 10m;

ssl_prefer_server_ciphers On;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;

ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 10s;

access_log /var/www/wpcademy.com/logs/access.log;
error_log /var/www/wpcademy.com/logs/error.log;

# php-script handler
location ~ \.php$ {
fastcgi_index index.php;
fastcgi_pass 127.0.0.1:9000; fastcgi_read_timeout 150;
root /var/www/wpcademy.com/public_html;
fastcgi_param SCRIPT_FILENAME /var/www/idroot.us$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}

Step 5. Set Up Let’s Encrypt SSL Auto Renewal.

We will add a cronjob to run the renewal command every week, run this command:

export VISUAL=nano; crontab -e

Paste the following lines:

01 1 * * 0 /usr/bin/certbot renew >> /var/log/ssl-renew.log
06 1 * * 0 /usr/bin/systemctl nginx reload

Save and Exit from the crontab table.

This will create a new cronjob that will be executed every Sunday at 01 AM, and then it will reload Nginx web server to apply the changes. The output will be logged into /var/log/ssl-renew.log file for further analysis if needed.

Congratulation’s! You have successfully installed Let’s Encrypt. Thanks for using this tutorial for installing Let’s Encrypt SSL on CentOS 7 system. For additional help or useful information, we recommend you to check the official Let’s Encrypt web site.

How To Install Redmine on CentOS 7

Redmine on CentOS 7

Redmine is a project management web app that allows users to manage projects flexibly while offering robust monitoring tools and a broad library of plug-ins. This free and open source solution offers a substitute for paid job management tools and contains support for wikis, forums, calendars, and information visualization programs.

Table of Contents

Step 1. First let’s start by ensuring your system is up-to-date.

Step 2. Installing all dependencies.

Step 3. Installing Ruby and RVM.

Step 4. Installing MySQL server.

Step 5. Installing Passenger and Nginx.

Step 6. Installing Redmine.

Step 7. Accessing Redmine.

Prerequisites

This article assumes you have at least basic knowledge of Linux, know how to use the shell, and most importantly, you host your site on your own VPS. The installation is quite simple and assumes you are running in the root account, if not you may need to add ‘sudo’ to the commands to get root privileges. I will show you through the step by step installation the Redmine project management web app on a CentOS 7 server.
Install Redmine on CentOS 7

Step 1. First let’s start by ensuring your system is up-to-date.

yum clean all
yum -y install epel-release
yum -y update

Step 2. Installing all dependencies.

Install all dependencies that are required by Redmine:

yum install zlib-devel curl-devel openssl-devel httpd-devel apr-devel apr-util-devel mysql-devel ftp wget ImageMagick-devel gcc-c++ patch readline readline-devel zlib libyaml-devel libffi-devel make bzip2 autoconf automake libtool bison iconv-devel subversion

Step 3. Installing Ruby and RVM.

Redmin requires Ruby. So, first you’ll want to install Ruby Version Manager which allows managing of multiple ruby environments:

gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
curl -L https://get.rvm.io | bash -s stable --ruby=2.2.5

Now we have to add it the .bashrc file so it can be automatically reload and to add it to the .bashrc file run this:

echo '[[ -s "/usr/local/rvm/scripts/rvm" ]] && source "/usr/local/rvm/scripts/rvm"' >> ~/.bashrc

Reload the .bashrc file using this command:

source ~/.bashrc

Now run following command as shown below to check Ruby and RVM version:

ruby -v
rvm -v

Step 4. Installing MySQL server.

MySQL needs to be configured so that Redmine can store data, so we will install MySQL server:

rpm -Uvh https://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm
yum repolist
yum install mysql-server

Now start the mysqld service using systemctl command as shown below:

systemctl start mysqld

By default, MySQL is not hardened. You can secure MySQL using the mysql_secure_installation script. You should read and below each steps carefully which will set root password, remove anonymous users, disallow remote root login, and remove the test database and access to secure MySQL.

mysql_secure_installation

Configure it like this:

- Set root password? [Y/n] y
- Remove anonymous users? [Y/n] y
- Disallow root login remotely? [Y/n] y
- Remove test database and access to it? [Y/n] y
- Reload privilege tables now? [Y/n] y

Next we will need to log in to the MySQL console and create a database for the Redmine. Run the following command:

mysql -u root -p

This will prompt you for a password, so enter your MySQL root password and hit Enter. Once you are logged in to your database server you need to create a database for Redmine installation:

CREATE DATABASE redmin
GRANT ALL PRIVILEGES ON redmine.* TO 'redmine'@'localhost' IDENTIFIED BY 'PASSWORD';
FLUSH PRIVILEGES;
\q

Step 5. Installing Passenger and Nginx.

Passenger is an application server that runs your web application then communicates with the web server. We will install it and integrate it with Nginx:

gem install passenger --no-ri --no-rdoc
passenger-install-nginx-module

You will be asked for some information, and then it will install Nginx. The default installation directory is /opt/nginx. Of course, you can change it. In it, edit conf/nginx.conf.

On line 23, paste the following content:

include vhost/*.conf;

Save and close the file. Next, create a vhost directory for Virtual Host configuration files:

mkdir -p /opt/nginx/conf/vhost

ost

In this directory, create a redmine.conf file. The paste the following into that file:

server {
 listen 80;
 server_name yourdomain.com;

root /var/www/html/redmine/public;
 passenger_enabled on;
 client_max_body_size 10m; # Max attachemnt size

# redirect server error pages to the static page /50x.html
 #
 error_page 500 502 503 504 /50x.html;
 location = /50x.html {
 root html;
 }
 }

Restart the web server for the changes to take effect:

systemctl restart nginx
systemctl enable nginx

Step 6. Installing Redmine.

First, download the latest version of Redmine, at the moment of writing this article it is version 3.4:

cd /var/www/
svn co http://svn.redmine.org/redmine/branches/3.4-stable redmine

Next, change the current working directory and the example configuration files:

cd redmine
cp config/configuration.yml.example config/configuration.yml
cp config/database.yml.example config/database.yml

Make the following changes to the database.yml file:

nano config/database.yml

Add following content:

production:
 adapter: mysql2
 database: redmine
 host: localhost
 username: redmine
 password: PASSWORD
 encoding: utf8

Run following commands to change the owner to user and group nobody:

mkdir -p tmp tmp/pdf public/plugin_assetssud
chown -R nobody:nobody files log tmp public/plugin_assetssudo
chmod -R 775 files log tmp public/plugin_assets

Install the bundler and gem dependencies for redmine:

gem install bundlerbundle install --without development test

Generate the secret token using the following command:

bundle exec rake generate_secret_token
RAILS_ENV=production bundle exec rake db:migrate
RAILS_ENV=production bundle exec rake redmine:load_default_data

Finally, Restart the web server for the changes to take effect:

systemctl restart nginx

Step 7. Accessing Redmine.

Redmine will be available on HTTP port 80 by default. Open your favorite browser and navigate to http://mydomain.com and complete the required the steps to finish the installation using the default credentials (admin/admin). If you are using a firewall, please open port 80 to enable access to the control panel.

Congratulation’s! You have successfully installed Redmine. Thanks for using this tutorial for installing Redmine project management web app on CentOS 7 systems. For additional help or useful information, we recommend you to check the official Redmine web site.

How To Install Redmine 4.0.3 on Ubuntu 18.04 LTS

Install Redmine on Ubuntu 18

Redmine is a project management web app that allows users to manage projects flexibly while offering robust monitoring tools and a broad library of plug-ins. This free and open source solution offers a substitute for paid job management tools and contains support for wikis, forums, calendars, and information visualization programs.

This article assumes you have at least basic knowledge of Linux, know how to use the shell, and most importantly, you host your site on your own VPS. The installation is quite simple and assumes you are running in the root account, if not you may need to add ‘sudo’ to the commands to get root privileges. I will show you through the step by step installation Wine on an Ubuntu 18.04 (Bionic Beaver) server.

Install Redmine on Ubuntu 18.04 LTS

Step 1. First, make sure that all your system packages are up-to-date

sudo apt update
sudo apt upgrade
sudo apt install build-essential libmysqlclient-dev imagemagick libmagickwand-dev
[php]

Step 2. Installing MySQL server.

[php]
MySQL needs to be configured so that Redmine can store data, so we will install MySQL server:
apt-get install mysql-server mysql-client

By default, MySQL is not hardened. You can secure MySQL using the mysql_secure_installation script. You should read and below each steps carefully which will set root password, remove anonymous users, disallow remote root login, and remove the test database and access to secure MySQL.

mysql_secure_installation

Configure it like this:

- Set root password? [Y/n] y
- Remove anonymous users? [Y/n] y
- Disallow root login remotely? [Y/n] y
- Remove test database and access to it? [Y/n] y
- Reload privilege tables now? [Y/n] y

Next we will need to log in to the MySQL console and create a database for the Redmine. Run the following command:

mysql -u root -p

This will prompt you for a password, so enter your MySQL root password and hit Enter. Once you are logged in to your database server you need to create a database for Redmine installation:

CREATE DATABASE redmin
GRANT ALL PRIVILEGES ON redmine.* TO 'redmine'@'localhost' IDENTIFIED BY 'PASSWORD';
FLUSH PRIVILEGES;
\q

Step 3. Installing Ruby.

Install Ruby using following command:

sudo apt install ruby-full

Step 4. Installing Passenger and Nginx.

Passenger is a fast and lightweight web application server for Ruby, Node.js and Python that can be integrated with Apache and Nginx. We will install Passenger as an Nginx module:

sudo apt install dirmngr gnupg apt-transport-https ca-certificates

Next, import the repository GPG key and enable the Phusionpassenger repository:

sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 561F9B9CAC40B2F7
sudo add-apt-repository 'deb https://oss-binaries.phusionpassenger.com/apt/passenger bionic main'

Once the repository is enabled, update the packages list and install the Passenger Nginx module with:

sudo apt update
sudo apt install libnginx-mod-http-passenger

Step 5. Installing Redmine on Ubuntu 18.04.

First, download the latest version of Redmine, at the moment of writing this article it is version 4:

sudo curl -L http://www.redmine.org/releases/redmine-4.0.1.tar.gz -o /tmp/redmine.tar.gz
sudo tar zxf /tmp/redmine.tar.gz
sudo mv /tmp/redmine-4.0.1 /opt/redmine

Make the following changes to the database.yml file:

sudo cp /opt/redmine/config/database.yml.example /opt/redmine/config/database.yml
sudo nano /opt/redmine/config/database.yml

Add following content:

production:
  adapter: mysql2
  database: redmine
  host: localhost
  username: redmine
  password: "change-with-strong-password"
  encoding: utf8

Install the Ruby dependencies and migrate the database:

cd /opt/redmine/
sudo gem install bundler --no-rdoc --no-ri
sudo bundle install --without development test postgresql sqlite

Generate the secret token using the following command:

cd /opt/redmine/
sudo bundle exec rake generate_secret_token
sudo RAILS_ENV=production bundle exec rake db:migrate

Then, Set the correct permissions by issuing following chown command:

sudo chown -R www-data: /opt/redmine/

Open your text editor and create the following Nginx vhost file:

sudo nano /etc/nginx/sites-available/example.com
# Redirect HTTP -> HTTPS
server {
    listen 80;
    server_name www.example.com example.com;

    include snippets/letsencrypt.conf;
    return 301 https://example.com$request_uri;
}

# Redirect WWW -> NON WWW
server {
    listen 443 ssl http2;
    server_name www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    include snippets/ssl.conf;

    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    root /opt/redmine/public;

    # SSL parameters
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    # log files
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;

    passenger_enabled on;
    passenger_min_instances 1;
    client_max_body_size 10m;
}

Enable the server block by creating a symbolic link to the sites-enabled directory:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

Restart the web server for the changes to take effect:

sudo systemctl restart nginx

Step 6. Accessing Redmine.

Redmine will be available on HTTPInstall Redmine on Ubuntu 18 port 80 by default. Open your favorite browser and navigate to http://mydomain.com and complete the required the steps to finish the installation using the default credentials (admin/admin). If you are using a firewall, please open port 80 to enable access to the control panel.

Congratulation’s! You have successfully installed Redmine. Thanks for using this tutorial for installing Redmine project management web app on Ubuntu 18.04 LTS (Bionic Beaver) system. For additional help or useful information, we recommend you to check the official Redmine web site.

How To Install Joomla 3.9.5 With Nginx on Ubuntu 18.04 LTS

Install Joomla With Nginx on Ubuntu 18

Joomla is a free and open source popular content management that uses a PHP and a backend database, such as MySQL. It offers a wide variety of features that make it an incredibly flexible content management system right out of the box. Furthermore, there are hundreds of free extensions written for that allows users to extend its functionality and customize it to their own objectives. A major advantage of using a content management system (CMS) is that it requires almost no technical skill or knowledge to manage. if you are planning to publish content on your website frequently, then maybe using WordPress will be a better option for you.

This article assumes you have at least basic knowledge of Linux, know how to use the shell, and most importantly, you host your site on your own VPS. The installation is quite simple and assumes you are running in the root account, if not you may need to add ‘sudo’ to the commands to get root privileges. I will show you through the step by step installation Joomla with Nginx on an Ubuntu 18.04 (Bionic Beaver) server.

Install Joomla With Nginx on Ubuntu 18.04

Step 1. First make sure that all your system packages are up-to-date

sudo apt-get update
sudo apt-get upgrade

Step 2. Install LEMP (Linux, Apache, MariaDB, PHP) server.

A Ubuntu 18.04 LAMP server is required. If you do not have LAMP installed, you can follow our guide here. Also install all required PHP modules:

apt-get install php7.1-cli php7.1-gd php7.1-opcache php7.1-mysql php7.1-json php7.1-mcrypt php7.1-xml php7.1-curl

Step 3. Installing Joomla with Nginx on Ubuntu 18.04.

First thing to do is to go to Joomla’s download page and download the latest stable version of Joomla, At the moment of writing this article it is version 3.8.5:

wget https://downloads.joomla.org/us/cms/joomla3/3-8-12/Joomla_3-8-12-Stable-Full_Package.zip
mkdir /var/www/html/joomla
unzip Joomla*.zip -d /var/www/html/joomla

We will need to change some folders permissions:

chown -R www-data.www-data /var/www/html
chmod -R 755 /var/www/html

Step 4. Configuring MariaDB for Joomla.

By default, MariaDB is not hardened. You can secure MariaDB using the mysql_secure_installation script. You should read and below each steps carefully which will set root password, remove anonymous users, disallow remote root login, and remove the test database and access to secure MariaDB.

mysql_secure_installation

Configure it like this:

- Set root password? [Y/n] y
- Remove anonymous users? [Y/n] y
- Disallow root login remotely? [Y/n] y
- Remove test database and access to it? [Y/n] y
- Reload privilege tables now? [Y/n] y

Next we will need to log in to the MariaDB console and create a database for the Joomla. Run the following command:

mysql -u root -p

This will prompt you for a password, so enter your MariaDB root password and hit Enter. Once you are logged in to your database server you need to create a database for Joomla installation:

CREATE DATABASE joomladb;
CREATE USER joomlauser@localhost;
SET PASSWORD FOR 'joomlauser'@'localhost' = PASSWORD("your-password");
GRANT ALL PRIVILEGES ON joomladb.* TO 'joomlauser'@'localhost' IDENTIFIED BY 'your-password' WITH GRANT OPTION;
FLUSH PRIVILEGES;
quit

Step 5. Configuring Nginx web server for Joomla.

Finally, configure Nginx site configuration file for Joomla. Run the commands below to create a new configuration file called joomla:

nano /etc/nginx/sites-available/joomla

Add the following lines:

server {
    listen 80;
    listen [::]:80;
    root /var/www/html/joomla;
    index  index.php index.html index.htm;
    server_name  example.com www.example.com;

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

    location ~ \.php$ {
         include snippets/fastcgi-php.conf;
         fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
         include fastcgi_params;
    }

After configuring the VirtualHost above, enable it by running the commands below:

ln -s /etc/nginx/sites-available/joomla /etc/nginx/sites-enabled/

Now, we can restart Apache web server so that the changes take place:

nginx -t
systemctl restart nginx
systemctl restart php7.1-fpm

Step 6. Accessing Joomla.

Joomla will be available on HTTP port 80 by default. Open your favorite browser and navigate to http://yourdomain.com/ or http://server-ip and complete the required the steps to finish the installation. If you are using a firewall, please open port 80 to enable access to the control panel.

joomla-web-interface

[youtube https://www.youtube.com/watch?v=prBpxVspDHs]

Congratulation’s! You have successfully installed Joomla. Thanks for using this tutorial for installing Joomla CMS (content management system) with Nginx on Ubuntu 18.04 LTS systems. For additional help or useful information, we recommend you to check the official Joomla web site.