Prepare a LEMP Ubuntu 18 server with Ansible Galaxy

In this blog post, I will explain the server settings by parameterization and automation using ** Ansible Galaxy **.

Alibi Cloud Tech Share Author, Ankit Mehta. Tech Share is an Alibaba Cloud incentive program that encourages sharing of technical knowledge and best practices within the cloud community.

If you are new to Ansible, read the previous blog post (https://www.alibabacloud.com/blog/getting-started-with-configuration-management-and-ansible_594653?spm=a2c65.11461447.0.0.bd4e709aj0TCSK) ​​to read how Ansible works and some basic settings.

Parameterization is one of the most important segments of automation. Parameterization allows you to reuse scripts and files without having to rewrite the complete solution again.

People often ask me, "I only have one VPS, is there any benefit to using Ansible?", But the answer is whether it's a single VPS or multiple VPS servers. Is yes. You can use Ansible scripts to manage all your servers. This not only keeps your settings, but also helps you apply changes to SSL to set up a new server, and also helps you set up and deploy a website on your new cloud hosting provider.

In this blog post, we implement the following solution in Ansible.

image.png

  1. The website domain uses Cloudflare's DNS service.
  2. The website is hosted on Alibaba Cloud Elastic Compute Service (ECS).
  3. The web server is set as follows. 1, custom SSH port 1992 2, PHP version 7.2    3、MySQL    4、Fail2Ban    5、Swap size 1 GB 6, NginX web server 7, SSH block for root 8, firewall allows only SSH, HTTP and HTTPS 9, SSL from CloudFlare

To achieve the above, the blog is divided into two segments.

  1. Prepare a LEMP server on Ubuntu 18.04 (Linux, Nginx, MySQL, PHP)
  2. Prepare a server for one domain with Cloudflare SSL

Part 1. Preparing a LEMP server on Ubuntu 18.04

Prerequisites

Make sure the server is ready and accessible from the Ansible host. To set up an Ansible host, see the Ansible Basics blog post.

NGINX installation

There are several Ansible Galaxy scripts available for installing NGINX. However, in my own experience, I think it's better to use APT to install Nginx. A complete list of Ansible Galaxy can be found at https://galaxy.ansible.com/.

The next block installs NGINX on the server and verifies that the service is enabled.

---
- hosts: all
  tasks:
    - name: ensure nginx is at the latest version
      apt: name=nginx state=latest
      become: yes

    - name: start nginx
      service:
          name: nginx
          state: started
      become: yes

Save the above block as install-nginx.yml and execute it with the following command.

ansible-playbook -i hosts.yml install-nginx.yml -b -v 

Install PHP

Different Ubuntu versions come with support for different PHP versions. PHP version 7.2

Ansible galaxy helps reduce the task of quickly installing the required dependencies. Ansible Galaxy refers to the Galaxy website where users can share roles and command line tools for installing, creating, and managing roles.

You need two ansible galaxy roles to install PHP. PHP version and PHP (installation order can be arbitrary).

To install the PHP version, enter the following command.

ansible-galaxy install geerlingguy.php-versions 

To install the PHP version, enter the following command:

ansible-galaxy install geerlingguy.php 

image.png

After installing the Ansible Galaxy role, prepare the yaml file for installation. The Ansible role requires a variable file. For demonstration purposes, store the variable file in the vars/main.yml file. This time, I added the PHP version, PHP settings (php.ini file settings), and the required PHP extension to the vars file.

The contents of the main.yml file are as follows.

#PHP version
php_version: '7.2'
php_enable_webserver: true
php_webserver_daemon: "nginx"
php_packages_state: "present"
php_install_recommends: true
php_executable: "php"
php_enable_php_fpm: true
php_fpm_listen: "127.0.0.1:9000"
php_fpm_listen_allowed_clients: "127.0.0.1"
php_fpm_pm_max_children: 50
php_fpm_pm_start_servers: 5
php_fpm_pm_min_spare_servers: 5
php_fpm_pm_max_spare_servers: 5
php_use_managed_ini: true
php_fpm_pool_user: "www-data" # default varies by OS
php_fpm_pool_group: "www-data" # default varies by OS
php_memory_limit: "256M"
php_max_execution_time: "60"
php_max_input_time: "60"
php_max_input_vars: "1000"
php_realpath_cache_size: "32K"
php_file_uploads: "On"
php_upload_max_filesize: "64M"
php_max_file_uploads: "20"
php_post_max_size: "32M"
php_date_timezone: "Asia/Bangkok"
php_allow_url_fopen: "On"
php_sendmail_path: "/usr/sbin/sendmail -t -i"
php_output_buffering: "4096"
php_short_open_tag: false
php_error_reporting: "E_ALL & ~E_DEPRECATED & ~E_STRICT"
php_display_errors: "Off"
php_display_startup_errors: "On"
php_expose_php: "Off"
php_session_cookie_lifetime: 0
php_session_gc_probability: 1
php_session_gc_divisor: 1000
php_session_gc_maxlifetime: 1440
php_session_save_handler: files
php_opcache_zend_extension: "opcache.so"
php_opcache_enable: "1"
php_opcache_enable_cli: "0"
php_opcache_memory_consumption: "96"
php_opcache_interned_strings_buffer: "16"
php_opcache_max_accelerated_files: "4096"
php_opcache_max_wasted_percentage: "5"
php_opcache_validate_timestamps: "1"
php_opcache_revalidate_path: "0"
php_opcache_revalidate_freq: "2"
php_opcache_max_file_size: "0"
php_memory_limit: "128M"
php_max_execution_time: "90"
php_upload_max_filesize: "256M"
php_packages:
  - php
  - php-cli
  - php-common
  - php-devel
  - php-gd
  - php-mbstring
  - php-pdo
  - php-pecl-apcu
  - php-xml
  - php-fpm

The code snippet below is a yaml file (php-install.yml) for installation.

- hosts: all
  vars_files:
    - vars/main.yml
  roles:
    - geerlingguy.php-versions
    - geerlingguy.php

To install php, you need to enter the following command.

ansible-playbook -i hosts.yml php-install.yml -b -v

MariaDB installation

Similarly, there are many packages available for installing MySQL / MariaDB. However, the best option is to use the direct installation package. MariaDB / MySQL requires Python-py MySQL on the server. The following installation blocks install the dependencies and MySQL.

---
  - hosts: all
    tasks:
      - name: "Install Python MySQL Dependency"
        apt:
          name: ['python-mysqldb',
            'python3-pip',
            'python3-dev',
            'libmysqlclient-dev',
            'mysql-server',
            'php7.2-mysql']

      - name: select default locale
        debconf:
          name: locales
          question: locales/default_environment_locale
          value: en_US.UTF-8
          vtype: select

      - name: set timezone to Asia/Bangkok
        timezone:
          name: Asia/Bangkok

      - name: "Install Python MySQL Module"
        pip:
          name: mysqlclient
          extra_args: -i https://pypi.python.org/pypi/
          executable: pip3

Save the above block as mysql-install.yml and run the following command to install it.

ansible-playbook -i hosts.yml mysql-install.yml -b -v

Swap settings

Linux uses swap space to increase the amount of virtual memory available on the host. You can use one or more dedicated swap partitions, or you can use swap files on a regular file system or logical volume. Ansible's galaxy role helps you easily configure swap space.

Install the swap ansible role with the following command:

ansible-galaxy install geerlingguy.swap

Set the expected swap space and pressure details in vars/main.yml.

swap_file_path: /swapfile
swap_file_size: '1024'
swap_swappiness: 60
swap_file_state: present
swap_file_create_command: "dd if=/dev/zero of={{ swap_file_path }} bs=1M count={{ swap_file_size }}”

Save the following block of code as swap-install.yml.

- hosts: all
  vars_files:
    - vars/main.yml
  roles:
    - geerlingguy.swap

To install swap, run the following command:

ansible-playbook -i hosts.yml swap-install.yml -b -v

If you need a larger swap file size, update the swap_file_size parameter. The current setting creates a 1GB swap file partition.

Security settings

Web server security is the most important part of any server (ECS) configuration. For better security, we recommend disabling root login, disabling password login, changing SSH port, and enabling fail2ban. (Note that there are many other features and services to improve the security of your Linux server)

To install the Linux security ansible role, run the following command.

ansible-galaxy install geerlingguy.security

Add the following variables to vars/main.yml.

# Security Settings
security_ssh_port: 65239
security_ssh_password_authentication: "no"
security_ssh_permit_root_login: "no"
security_ssh_usedns: "no"
security_autoupdate_enabled: true
security_fail2ban_enabled: true

Save the following block of code as install-security.yml.

- hosts: all
  vars_files:
    - vars/main.yml
  roles:
    - geerlingguy.security

To install the security run:

ansible-galaxy -i hosts.yml install-security.yml -b -v

In the above example, the SSH port is changed to 65239 after a successful test run.

Firewall settings

By applying firewall settings, the server can be protected from known network attacks. Your application is trying to use HTTP, HTTPS, and SSH ports, so it's a good idea to block access to other ports. To install the Ansible galaxy role for your firewall, run the following command:

ansible-galaxy install geerlingguy.firewall

Provide the port details in the vars/main.yml file.

#Firewall Settings
firewall_state: started
firewall_enabled_at_boot: true
firewall_allowed_tcp_ports:
  - "443"
  - "65239"
  - “80"

Save the following block of code as install-firewall.yml.

- hosts: all
  vars_files:
    - vars/main.yml
  roles:
    - geerlingguy.firewall

To apply the firewall changes, run the following command:

ansible-playbook -i hosts.yml install-firewall.yml -b -v

Note: Apply the firewall changes to your ECS instance as well. To apply the changes, go to ECS> Security Groups> Add Rule.

image.png

A sample LEMP installation script can be found at https://github.com/ankyit/ansible-lemp-wordpress/tree/master/LEMP.

--The Prepare-client.sh file contains the basic installation script to prepare the ansible system with all the dependencies and required roles. --Update the server IP and ansible_user in hosts.yml (https://github.com/ankyit/ansible-lemp-wordpress/blob/master/LEMP/hosts.yml). --Use the prepare-lemp.yml (https://github.com/ankyit/ansible-lemp-wordpress/blob/master/LEMP/prepare-lemp.yml) file to install LEMP. please. --vars/main.yml (https://github.com/ankyit/ansible-lemp-wordpress/blob/master/LEMP/vars/main.yml) Update the required parameters in the file.

Part 2: Prepare a server for your domain with Cloudflare SSL

Prerequisites

1, LEMP server 2. Domain name using DNS in Cloudflare 3, SSL certificate 4, Website with database (This time for WordPress demo web

The above segment has detailed the preparation of the LEMP server. In this segment, I would like you to use it as a reference when introducing a WordPress site using Ansible.

Below is a high level structure for setting up your site deployment. The format can be defined and set as needed.

image.png

Here, the certs directory contains the SSL certificate and Key file. The sites-config folder contains NGINX settings. sites stores the files and folder structure of your website. Site variables are stored in the vars folder.

The hosts.yml file contains host information, and deploy-site.yml contains steps/tasks for deploying the site.

The deploy-site.yml file extends the functionality covered in the blog post.

Tasks from deploy-site.yml

The next block copies the certificate and key files from the certs folder to the/etc/nginx/ssl folder. Where {{site_url}} is a dynamic parameter whose value is replaced in place from vars/main.yml.

### {{site_url}} SSL Copy
    - name: copy {{site_url}} SSL files
      copy:
        src: ./certs/{{site_url}}.csr
        dest: /etc/nginx/ssl/{{site_url}}.csr
      become: yes

    - name: copy {{site_url}} SSL key files
      copy:
        src: ./certs/{{site_url}}.key
        dest: /etc/nginx/ssl/{{site_url}}.key
      become: yes

The following code block copies the website's Nginx configuration file and stores it in/etc/nginx/sites-available.

### {{site_url}} Nginx configuration
    - name: copy the nginx config file
      copy:
        src: ./site-config/{{site_url}}.cfg
        dest: /etc/nginx/sites-available/{{site_url}}.cfg
      become: yes

The following code block creates a symbolic link for the URL from sites-available to sites-enabled.

    - name: create symlink
      file:
        src: /etc/nginx/sites-available/{{site_url}}.cfg
        dest: /etc/nginx/sites-enabled/{{site_url}}.cfg
        state: link
      become: yes

The following code block creates a website folder in the location of/var/www /.

###  Create a directory for the website
    - file:
        path: /var/www/{{site_url}}
        state: directory
        mode: 0755

The following code block uses rsync to copy files from the site folder to/var/www /. Where delete yes deletes the file in the destination location if the file is deleted from the source location.

##{{site_url}} Website Copy
    - name: copy the content of the website
      synchronize:
        src: ./sites/
        dest: /var/www/{{site_url}}
        delete: yes

Create a database with the following code block.

###{{site_url}} Database Creation
    - name: Create a {{site_url}} database
      mysql_db:
        name: "{{site_db}}"
        state: present

The following code block creates a user and assigns DB privileges.

    - name: "Create a new user for {{site_url}}"
      mysql_user:
        name: "{{site_db_user}}"
        password: "{{site_db_password}}"
        priv: '{{site_db}}.*:ALL'
        state: present

The following block of code imports the database.

# ###Import database
    - name: import the database
      mysql_db:
        name: "{{site_db}}"
        state: import
        target: /var/www/{{site_url}}/{{db_file}}
        login_user: "{{site_db_user}}"
        login_password: "{{site_db_password}}”

The following code block sets directory permissions and sets them to www-data with 0755 permissions.

###Set Directory permissions
    - name: Set Directory permissions
      file: path=/var/www/ owner=www-data group=www-data mode=0755 state=directory recurse=yes

The following code block restarts NGINX and PHP-FPM.

## Restart NginX and PHP-fpm
    - name: restart nginx
      service:
        name: nginx
        state: restarted
      become: yes

    - name: restart PHP FPM
      service:
        name: php7.2-fpm
        state: restarted
      become: yes

スクリーンショット 2020-12-17 13.06.38.png

Note: All the scripts described here can be accessed from https://github.com/ankyit/ansible-lemp-wordpress.

Recommended Posts

Prepare a LEMP Ubuntu 18 server with Ansible Galaxy
Write a Reactive server with Micronaut
Launch a stub server with WireMock
[Ubuntu] Set up a Nukkit server
Ubuntu Server 20.04.1 Autoinstall with USB boot
A story of connecting to a CentOS 8 server with an old Ansible
Rip a CD to MP3 with Ubuntu 18.04 LTS
Prepare a scraping environment with Docker and Java
Yes, let's make a Minecraft server (Ubuntu 20.04 + Bedrock Server)
Create a web api server with spring boot
Set up a CentOS virtual server with Vagrant
ubuntu (AWS) LEMP
Play down with Raspberry PI4 as a server. Part 2
Prepare the environment for java11 and javaFx with Ubuntu 18.4