Yet another web developer blog

Configure Ubuntu with Virtialmin, nginx, Let's encrypt, and proxy to PHP-FPM, Node.js

Here are steps for quick configure fresh-installed Ubuntu Server to manage Nginx Virtualhosts with PHP (using PHP-FPM) and Proxy to Node.JS apps.

1. Make a swapfile, you can set custom SIZE_GB:

SIZE_GB=2; swapoff /swapfile; rm /swapfile; dd if=/dev/zero of=/swapfile bs=1024M count=$SIZE_GB; chmod 600 /swapfile; mkswap /swapfile; swapon /swapfile; echo '/swapfile none swap sw 0 0' | tee -a /etc/fstab

2. Install common useful tools and change some default settings:

# Common tools
sudo apt install -y aptitude mc htop openssh-server curl net-tools apt-transport-https ca-certificates curl software-properties-common nginx git tmux mosh rsync pv
# PHP FPM server
sudo apt install -y php-fpm php-cli php-gd php-bcmath php-curl
# Cloud tools
sudo apt install -y cloud-utils-growpart

Set right hostname and locale:

hostnamectl set-hostname HOST.DOMAIN
# localectl set-locale LANG=ru_RU.UTF-8; timedatectl set-timezone Europe/Moscow
localectl set-locale LANG=en_US.UTF-8; timedatectl set-timezone Europe/Moscow

Disable GRUB counter at boot - set in file/etc/default/grub:

GRUB_RECORDFAIL_TIMEOUT=1

Also you may fill in /etc/cloud/cloud.cfg setting preserve_hostname: true to disable changing hostname from cloud config.

In mc settings set checkboxes for Use internal edit (for normal work of Ctrl+O in editor) and Use internal view.

Command for resize partition to max available space (if you grow disk size in VPS settings): growpart /dev/vda 2; resize2fs /dev/vda2

3. Install Docker

sudo apt install apt-transport-https ca-certificates curl software-properties-common; curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -; sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable"; sudo apt install docker-ce -y

4. Install fresh node.js

curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -; curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -; echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list; sudo apt install -y yarn nodejs 

5. Install Let's Encrypt

sudo add-apt-repository -y ppa:certbot/certbot; sudo apt-get install -y python3-certbot-nginx

And add daily cron job for refresh certificates:

sudo cat > /etc/cron.weekly/certbot-renew <<EOL
#!/bin/bash

certbot renew --nginx
service nginx reload
EOL
sudo chmod a+x /etc/cron.weekly/certbot-renew

Example of generating certificate for host: sudo certbot --nginx -d example.com -d www.example.com

6. Install and configure Virtualmin server:

curl -O http://software.virtualmin.com/gpl/scripts/install.sh; sudo chmod +x install.sh; sudo ./install.sh -m -b LEMP

And make some changes to default settings:

Virtualmin config >> Defaults for new domains:

  • Home directory base = /srv
  • Domain name style in username = Full domain name
  • Password field type = Randomly generated password

Edit Server Template » Default Settings » PHP Options:

  • Default PHP execution mode = FPM

System Settings - Account Plans:

  • Enable "Allow sub-servers not under this domain?" if needed.

Features and Plugins - switch off:
I recommend to use external mail server, such as mail.yandex.com, instead of self-hosted one, and disable too old features such as FTP (use SFTP instead, AWstats and protected directories):

  • BIND DNS domain
  • Mail for domain
  • ProFTPD virtual FTP
  • AWstats reporting
  • Protected web directories

7. Extend default limits of comon services:

PHP general settings - in file /etc/php/7.X/fpm/conf.d/99-XXX.ini:

[PHP]
upload_max_filesize = 256M
post_max_size = 256M

PHP pool settings in file /etc/php/7.X/fpm/pool.d/XXX.conf (repeat for each virtualserver):

php_value[max_execution_time] = 120

php_flag[display_errors] = On
php_flag[display_startup_errors] = On

pm = ondemand
pm.process_idle_timeout = 1800s

Nginx - in file /etc/nginx/conf.d/XXX.conf:

client_max_body_size 256m;
fastcgi_buffer_size 32k;
fastcgi_buffers 4 32k;
fastcgi_read_timeout 300;
fastcgi_intercept_errors on;

MySQL - in file /etc/mysql/mysql.conf.d/z_XXX.cnf

[mysqld]
max_allowed_packet=128M
ignore-db-dir=lost+found

8. Example of creating user-controllable autostart service:

Enable autostart of systemd user's services without real login (you need to repeat this for each user):

sudo loginctl enable-linger LOGIN

Login as virtualhost user and create service file: mkdir -p ~/.config/systemd/user; mcedit ~/.config/systemd/user/GHOST.service and fill the content from example:

[Unit]
AssertPathExists=/home/ghost/ghost

[Service]
WorkingDirectory=/home/ghost/ghost
Environment=GHOST_NODE_VERSION_CHECK=false
ExecStart=/usr/bin/npm start --production
Restart=always
PrivateTmp=true
NoNewPrivileges=true

[Install]
WantedBy=default.target

And enable service:

systemctl --user enable GHOST.service