LAMP + zfs + mpm-itk + zfsnap

Instance creation

Instance

  • ovh public cloud : b2-7 @ gra-11
  • ubuntu 22.04
  • clef ssh
  • instance flexible (disque 50Go)
  • backup ou pas (si bkp externe)
  • réseau public
  • facturation à l'heure

Block storage

  • ovh block storage
  • 50 Gb @ classic
  • name : xxxx-data
  • attach @instance

Install

Install system utilities, set up zpool and zfs datasets

ssh ubuntu@IP
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install zfsutils-linux vim curl git wget
ls -al /dev/disk/by-id # get block storage id
sudo zpool create data /dev/disk/by-id/xxxxxx
sudo zfs set compression=on data
sudo zfs create data/mysql
sudo zfs create data/www

Install apache, php, mysql (lamp server components)

sudo apt-get install apache2 php mysql-server \
    libapache2-mod-php libapache2-mpm-itk \
    php-mysql php-gd php-mbstring php-zip php-opcache \
    php-xml php-json php-curl php-bz2 php-intl \
    phpmyadmin \
    certbot python3-certbot-apache

dpkg questions :

  • configure auto apache2 for phpmyadmin
  • configure database for phpmyadmin with dbconfig-common: yes, empty (random) password

Fix phpmyadmin permissions

As per mpm-itk phpmyadmin can be loaded as any user, all users shoud be in www-data group, and phpmyadmin tmp dir should be writable by www-data group

chmod g+w /var/lib/phpmyadmin/tmp/

Configure mysql

Move mysql data to /data/mysql

# Stop mysql and move data
sudo systemctl stop mysql
sudo chown mysql:mysql /data/mysql
sudo rsync -av /var/lib/mysql/ /data/mysql
sudo rm -rf /var/lib/mysql

# Change mysql datadir location
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
## set datadir = /data/mysql

# Change apparmor settings for usr.sbin.mysqld
sudo vi /etc/apparmor.d/usr.sbin.mysqld
## change all occurrences of /var/lib/mysql to /data/mysql

sudo systemctl reload apparmor
sudo systemctl start mysql

Add mysql admin user

sudo mysql
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;

Configure apache virtualhost

Create data dir, add dedicated user

sudo zfs create data/www/com.example.www
sudo addgroup --gid gggg example
sudo adduser --uid uuuu --gid gggg example
sudo adduser example www-data
sudo chown example:example data/www/com.example.www

Create http virtualhost

sudo vi /etc/apache2/sites-available/com.example.www.conf
<VirtualHost *:80>
    ServerName www.example.com
    ServerAdmin webmaster@example.com
    DocumentRoot /data/www/com.example.www
    AssignUserID example example
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    DirectoryIndex index.php index.phtml index.html index.htm
    <Directory /data/www/com.example.www>
            Options Indexes FollowSymLinks
            AllowOverride All
            Require all granted
            php_admin_value open_basedir "/data/www/com.example.www/:/tmp/"
    </Directory>
</VirtualHost>
# Enable site, reload server
sudo a2ensite com.example.www
sudo systemctl reload apache2
# Test site
curl http://www.example.com

Gen https config

To add a certificate (interactive)

sudo certbot
# add email / accept TOS / refuse newsletter on first run
# select domain
# it's done

To delete a certificate :

# disable ssl site
sudo a2dissite com.example.www-le-ssl
sudo certbot delete --cert-name www.example.com
sudo systemctl reload apache2

Import site steps

Create ssh key

sudo ssh-keygen -t rsa -b 4096
sudo cat /root/.ssh/id_rsa.pub
# Copy the pubkey to authorized_keys on remote server

Copy data

rsync -av orig.server:/path/to/www/ /data/www/com.example.www
# Eventually change owner/group recursively
chown -R example:example /data/www/com.example.www

Move mysql data

# On orig server
mysqldump -u dbuser -p dbname > /dumps/latest.sql

# On new server
sudo scp orig.server:/path/to/dumps/latest.sql /tmp/example.sql

# Create database and user (on first move)
sudo mysql
CREATE USER 'example'@'localhost' IDENTIFIED BY 'password';
DROP DATABASE IF EXISTS example;
CREATE DATABASE example;
GRANT ALL PRIVILEGES ON example.* TO 'example'@'localhost';
FLUSH PRIVILEGES
mysql -u example -p example < /tmp/example.sql
rm /tmp/example.sql

ZFS auto snapshots & db dumps

Install zfsnap

cd /usr/local/src
git clone https://github.com/zfsnap/zfsnap.git
cd zfsnap/tests
./run.sh
cd ..
ln -s /usr/local/src/zfsnap/sbin/zfsnap.sh /usr/local/sbin/zfsnap
mkdir -p /usr/local/share/man/man8
ln -s /usr/local/src/zfsnap/man/man8/zfsnap.8 /usr/local/share/man/man8/zfsnap.8

Create db dumps dir

zfs create data/dumps
addgroup bkpusers --gid 3000
adduser example bkpusers
chgrp bkpusers /data/dumps

Create zfsnap crontab

crontab -e
# add some lines, changing expiration, time and dates
0 4 * * * tar czf /data/dumps/etc.tar.gz /etc
10 4 * * * mysqldump --all-databases > /data/dumps/all-databases.sql
30 4 * * * zfsnap snapshot -rv -a 14d data
35 4 * * * zfsnqp destroy -rv data

Allow users to ssh with password

For non tecchy users

vi /etc/ssh/sshd_config
# set PasswordAuthentication to yes
systemctl restart ssh

Add monitoring

See monitoring