Production Services on Arch Linux

From Wiki³
IconUNDER CONSTRUCTION: The document is currently being modified!
Icon See also: KVM on Arch Linux 

Icon Introduction

The following are additional (optional) write-ups for setting up specific services inside of VMs.

Icon NGINX

Login to the nginx virtual machine and shut it down. Then edit the virtual machine on the host.

# virsh edit nginx

Add a mountpoint for the nginx directory on the host.

<filesystem type='mount' accessmode='mapped'>
<source dir='/www/nginx'/>
<target dir='neutron-nginx'/>
</filesystem>

Restart the nginx machine and login via ssh.

# virsh start nginx

Create a directory for nginx files.

# sudo mkdir /nginx

Set the directory to mount on boot.

filename: /etc/fstab
neutron-nginx /nginx 9p trans=virtio 0 0

Reboot the machine to make sure the mounting works.

Install nginx-mainline.

# pacaur -S nginx-mainline

Enable http and https in nftables.

filename: /etc/nftable.conf
tcp dport {http,https} accept

Restart nftables to apply the new rules.

# sudo systemctl restart nftables

Start and enable the nginx service.

# sudo systemctl enable nginx
# sudo systemctl start nginx

You should be able to visit the IP address of the machine and see the nginx default page.

For configuration first create blank configs and directories needed.

# sudo touch /nginx/nginx.conf /nginx/http.conf
# sudo mkdir /nginx/logs /nginx/conf.d /nginx/https

Set permissions accordingly.

# sudo chown -R http:http /nginx/*

Edit the main nginx config, replace all of it with a single include.

filename: /etc/nginx/nginx.conf
include /nginx/nginx.conf

Create the actual main configuration, use sudo to edit the configs.

# sudoedit /nginx/nginx.conf
 
filename: /nginx/nginx.conf
user http;
worker_processes auto;
worker_cpu_affinity auto;
pcre_jit on;

events {
worker_connections 4096;
}

error_log /nginx/logs/nginx-error.log;

include /nginx/http.conf;

Create the http block configuration.

filename: /nginx/http.conf
http {
include mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /nginx/logs/nginx-access.log main;

sendfile on;
tcp_nopush on;
aio threads;
charset utf-8;
keepalive_timeout 65;
gzip on;
gzip_disable "msie6";
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
include /nginx/conf.d/*.conf;
}

Then create configs for each website in /nginx/conf.d/ with the naming scheme *.conf. There is a great post on Stack Overflow[1] about achieving an A+ rating with 100 points in every category on SSL Labs.

Icon PHP

Install the packages required for PHP.

# pacaur -S php php-fpm php-gd php-intl php-mcrypt php-sqlite imagemagick

Open up the main php-fpm config.

filename: /etc/php/php-fpm.conf
error_log = /nginx/logs/php-fpm.log

Then edit the config for your server instance.

filename: /etc/php/php-fpm.d/www.conf
listen.allowed_clients = 127.0.0.1
...
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /nginx/logs/php.log
php_admin_value[memory_limit] = 256M
php_admin_value[post_max_size] = 2048M
php_admin_value[upload_max_filesize] = 2048M
php_admin_value[date.timezone] = America/Toronto

Open up the PHP config /etc/php/php.ini and enable the modules: bz2, exif, gd, gettext, iconv, intl, mcrypt, mysqli, pdo_mysql, sockets, sqlite3 by commenting out the extension lines. Start and enable the php-fpm service.

# sudo systemctl enable php-fpm
# sudo systemctl start php-fpm

Import all of the web files and update the configs in conf.d for all websites.

Icon SSL

Using SSL encryption is a must. First install the required packages.

# pacaur -S certbot

Bring down nginx temporarily.

# sudo systemctl stop nginx

Use certbot to get a certificate for all domains needed.

# sudo certbot certonly --agree-tos --standalone --email your@address.com --rsa-key-size 4096 -d domain.com,www.domain.com,subdomain.domain.com

Generate a dhparam.

# sudo openssl dhparam -out /etc/letsencrypt/live/kyau.net/dhparam4096.pem 4096

Start back up nginx.

# sudo systemctl start nginx

A timer can then be setup to run certbot twice daily.

filename: /etc/systemd/system/certbot.timer
[Unit]
Description=Twice daily renewal of Let's Encrypt's certificates

[Timer]
OnCalendar=0/12:00:00
RandomizedDelaySec=1h
Persistent=true

[Install]
WantedBy=timers.target

Also create the service for certbot.

filename: /etc/systemd/system/certbot.service
[Unit]
Description=Let's Encrypt renewal

[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --pre-hook "/usr/bin/systemctl stop nginx.service" --post-hook "/usr/bin/systemctl start nginx.service" --quiet --agree-tos

Enable and start the timer.

# sudo systemctl enable certbot.timer
# sudo systemctl start certbot.timer

Icon SQL

Create a directory on the host machine for the nginx and sql server.

# sudo mkdir /www/sql /www/nginx

Make sure it has the right permissions.

# sudo chown -R kvm:kvm /www

Edit the sql virtual machine to mount the folder inside of the VM.

# sudo virsh edit sql
 

<filesystem type='mount' accessmode='passthrough'>
<source dir='/www/sql'/>
<target dir='neutron-sql'/>
</filesystem>

Shutdown the virtual machine, then restart it back up.

Login to the sql virtual machine and create a directory for SQL.

# mkdir /sql

Mount the partition from the HOST system.

# mount neutron-sql /sql -t 9p -o trans=virtio

Also set this to mount on boot.

filename: /etc/fstab
neutron-sql /sql 9p trans=virtio 0 0

After the directory is mounted make sure it has the right permissions.

# sudo chown mysql:mysql /sql
# sudo chmod 770 /sql

Install mariadb.

# pacaur -S mariadb

Initialize the SQL database directory.

# sudo mysql_install_db --user=mysql --basedir=/sql/base --datadir=/sql/db

Modify the MySQL global config to support a different basedir, bind to IPv6 in addition to IPv4 and disable filesystem access.

filename: /etc/mysql/my.cnf

[mysqld]
bind-address = ::
port = 3306
socket = /run/mysqld/mysqld.sock
datadir = /sql/db
local-infile = 0

tmpdir = /tmp/

Enable and start the systemd service.

# sudo systemctl enable mariadb
# sudo systemctl start mariadb

Run the MySQL post-install security check, change the remove password and remove all demo/test related material.

# sudo mysql_secure_installation

Icon User Setup

Open mysql and change the root username and allow access from the nginx virtual machine.

# mysql -u root -p
 
MariaDB> RENAME USER 'root'@'localhost' to 'kyau'@'localhost';
MariaDB> RENAME USER 'root'@'127.0.0.1' to 'kyau'@'127.0.0.1';
MariaDB> RENAME USER 'root'@'::1' to 'kyau'@'::1';
MariaDB> GRANT ALL PRIVILEGES ON *.* TO 'kyau'@'142.44.172.255' IDENTIFIED BY 'my-password' WITH GRANT OPTION;
MariaDB> FLUSH PRIVILEGES;

Confirm the changes by listing all users.

MariaDB> SELECT User,Host,Password FROM mysql.user;

Icon UTF8MB4

Optionally, enable UTF8MB4 support, which is recommended over UTF8 as it will provide full unicode support.

filename: /etc/mysql/my.cnf
[client]
default-character-set = utf8mb4

[mysqld]
collation_server = utf8mb4_unicode_ci
character_set_client = utf8mb4
character_set_server = utf8mb4
skip-character-set-client-handshake

[mysql]
default-character-set = utf8mb4

Icon Importing Databases

Head over to the current SQL server and export the needed database.

# mysqldump -u kyau -p --databases <db1> <db2>… > backup.sql

Import them to the new database server.

# mysql -u kyau -p
MariaDB> source backup.sql

Icon Database Maintenance

MariaDB includes mysqlcheck to check, analyze, repair and optimize database tables.

To check all tables in all databases:

# mysqlcheck --all-databases -u root -p -m

To analyze all tables in all databases:

# mysqlcheck --all-databases -u root -p -a

To repair all tables in all databases:

# mysqlcheck --all-databases -u root -p -r

To optimize all tables in all databases:

# mysqlcheck --all-databases -u root -p -o

To check if any tables require upgrades:

# mysqlcheck --all-databases -u root -p -g

If any tables require upgrades, it is recommended to run a full upgrade (this should also be done in-between major MariaDB version releases).

# mysql_upgrade -u root -p

Icon Firewall

Add rules to the firewall to allow access from the nginx virtual machine to MySQL.

filename: /etc/nftables.conf
ip saddr 142.44.172.255 tcp dport 3306 ct state new,established counter accept

Icon References

  1. ^ Stack Overflow. How do you score A+ with 100 on all categories on SSL Labs test with Let's Encrypt and Nginx?