Production Services on Arch Linux
UNDER CONSTRUCTION: The document is currently being modified! |
Introduction
The following are additional (optional) write-ups for setting up specific services inside of VMs.
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.
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.
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.
include /nginx/nginx.conf |
Create the actual main configuration, use sudo to edit the configs.
# sudoedit /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.
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.
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.
error_log = /nginx/logs/php-fpm.log |
Then edit the config for your server instance.
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.
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.
[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.
[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 |
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.
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.
… [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 |
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; |
UTF8MB4
Optionally, enable UTF8MB4 support, which is recommended over UTF8 as it will provide full unicode support.
[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 … |
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 |
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 |
Firewall
Add rules to the firewall to allow access from the nginx virtual machine to MySQL.
ip saddr 142.44.172.255 tcp dport 3306 ct state new,established counter accept |
References
- ^ Stack Overflow. How do you score A+ with 100 on all categories on SSL Labs test with Let's Encrypt and Nginx?