# Installation du serveur yeswiki.pro
On est connecté en tant que root, une petite mise en bouche
```
apt update
apt upgrade -y
dpkg-reconfigure locales # cocher fr_fr.UTF8 et en_US.UTF8, puis en_US.UTF8 par défaut
apt install tree curl wget htop vim parted mc lshw git tmux -y # quelques paquets essentiels
cd /usr/local/bin ;curl https://getmic.ro | bash # un editeur de texte sympa
```
On met le bon host
`sudo hostnamectl set-hostname yeswiki.pro --static`
`sudo vim /etc/hosts` mettre `yeswiki.pro` pour les ip4 et ip6 `reboot`
## Config disques RAID software
`lshw -class disk -short` donne :
```
H/W path Device Class Description
======================================================
/0/100/1f.2/0 /dev/sda disk 480GB SAMSUNG MZ7LM480
/0/100/1f.2/1 /dev/sdb disk 480GB SAMSUNG MZ7LM480
/0/100/1f.2/2 /dev/sdc disk 6001GB HGST HUS726060AL
/0/100/1f.2/3 /dev/sdd disk 6001GB HGST HUS726060AL
```
Oh surprise d'Hetzner
```
root@yeswiki ~ # lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 447.1G 0 disk
├─sda1 8:1 0 4G 0 part
│ └─md0 9:0 0 4G 0 raid1 [SWAP]
├─sda2 8:2 0 1G 0 part
│ └─md1 9:1 0 1022M 0 raid1 /boot
└─sda3 8:3 0 442.1G 0 part
└─md2 9:2 0 442G 0 raid1 /
sdb 8:16 0 447.1G 0 disk
├─sdb1 8:17 0 4G 0 part
│ └─md0 9:0 0 4G 0 raid1 [SWAP]
├─sdb2 8:18 0 1G 0 part
│ └─md1 9:1 0 1022M 0 raid1 /boot
└─sdb3 8:19 0 442.1G 0 part
└─md2 9:2 0 442G 0 raid1 /
sdc 8:32 0 5.5T 0 disk
├─sdc1 8:33 0 4G 0 part
│ └─md0 9:0 0 4G 0 raid1 [SWAP]
├─sdc2 8:34 0 1G 0 part
│ └─md1 9:1 0 1022M 0 raid1 /boot
└─sdc3 8:35 0 442.1G 0 part
└─md2 9:2 0 442G 0 raid1 /
sdd 8:48 0 5.5T 0 disk
├─sdd1 8:49 0 4G 0 part
│ └─md0 9:0 0 4G 0 raid1 [SWAP]
├─sdd2 8:50 0 1G 0 part
│ └─md1 9:1 0 1022M 0 raid1 /boot
└─sdd3 8:51 0 442.1G 0 part
└─md2 9:2 0 442G 0 raid1 /
```
### Réparation de la config d'Hetzner qui fait un RAID 1 sur 4 disques...
```
mdadm --detail /dev/md0 # pour voir les infos détaillées
mdadm --manage /dev/md0 --fail /dev/sdc1
mdadm --manage /dev/md0 --fail /dev/sdd1
mdadm --manage /dev/md0 --remove /dev/sdc1
mdadm --manage /dev/md0 --remove /dev/sdd1
mdadm --grow /dev/md0 --raid-devices=2
mdadm --manage /dev/md1 --fail /dev/sdc2
mdadm --manage /dev/md1 --fail /dev/sdd2
mdadm --manage /dev/md1 --remove /dev/sdc2
mdadm --manage /dev/md1 --remove /dev/sdd2
mdadm --grow /dev/md1 --raid-devices=2
mdadm --manage /dev/md2 --fail /dev/sdc3
mdadm --manage /dev/md2 --fail /dev/sdd3
mdadm --manage /dev/md2 --remove /dev/sdc3
mdadm --manage /dev/md2 --remove /dev/sdd3
mdadm --grow /dev/md2 --raid-devices=2
```
On fait une grosse partition pour les homes, prete pour du RAID 1, et en ext4
```
parted -a optimal /dev/sdc mklabel gpt
parted -a optimal /dev/sdd mklabel gpt
parted -a optimal /dev/sdc mkpart primary ext4 0% 100%
parted -a optimal /dev/sdd mkpart primary ext4 0% 100%
parted -a optimal /dev/sdc set 1 raid on
parted -a optimal /dev/sdd set 1 raid on
mdadm --create /dev/md4 --level=1 --raid-devices=2 /dev/sd[cd]1
mkfs.ext4 /dev/md4
mount /dev/md4 /home
```
`vi /etc/fstab`
```
/dev/md4 /home ext4 defaults 0 0
```
On sauve la conf
`mdadm --detail --scan >> /etc/mdadm/mdadm.conf`
Mise à jour filesystem
`update-initramfs -u`
Checker
`cat /proc/mdstat`
`update-grub2`
## Sécurité
### SSH
`apt install sudo openssh-server -y`
on change de mot de passe root
`passwd`
on crée le user admin avec les droits sudo
```
adduser admin # ajouter un user admin
usermod -a -G sudo admin # ajouter le user admin au groupe sudo
```
on met les clés publiques de personnes ayant un droit d'acces au compte admin
`vi /home/admin/.ssh/authorized_keys`
on configure ssh pour interdire l'acces root, n'autoriser que l'acces par clé ssh, et on change de port ssh standard par 4222
`vi /etc/ssh/sshd_config`
```
Port 4222
PermitRootLogin no
MaxAuthTries 3
PasswordAuthentication no
PubkeyAuthentication yes
X11Forwarding no
```
On redémarrer le service pour prendre en compte les changements
`service sshd restart`
### Firewall
`apt install ufw -y`
on n'autorise que les ports web 80 443 et ssh 4222
```
ufw allow 80 #http
ufw allow 443 #https
ufw allow 4222 #ssh
ufw enable # demarre le service
ufw logging on # garde les logs
ufw status verbose #infos precises
```
### Fail2ban
`apt install fail2ban sendmail-bin sendmail -y`
`cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local`
`vi /etc/fail2ban/jail.local`
```
bantime = 720m
findtime = 120m
maxretry = 3
banaction = ufw
banaction_allports = ufw
destemail = contact@yeswiki.pro
sender = fail2ban@yeswiki.pro
```
On relance le service
`fail2ban-client reload`
### Quota système pour les users
cf. <https://wiki.archlinux.org/title/Disk_quota> et <https://www.drydeadfish.co.uk/linux_disk_quotas/>
`apt install quota -y`
`vi /etc/fstab`
```
# /dev/md/4
/dev/md4 /home ext4 defaults,usrjquota=quota.user,grpjquota=quota.group,jqfmt=vfsv0 0 0
```
`mount -o remount /home`
`quotacheck -cgum /home`
`quotaon /home`
pour mémoire, vue d'ensemble des quatos : `repquota -a`
pour 2Go de quota pour le user toto `setquota -u toto 2000000 2000000 0 0 -a /dev/loop0`
> ask mose if ca fait grincer les dents
## Install lemp server
`apt-get install apt-transport-https gnupg2 ca-certificates -y`
le dépot Sury permet d'avoir des versions récentes de php et de multiples versions
`wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
sh -c 'echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'`
`apt-get update -y`
`apt-get install nginx mariadb-server mariadb-client php php-cli php-curl php-common php-mysql php-xml php-gd php8.1-opcache php-fpm php-mbstring php-tokenizer php-json php-mcrypt php-imagick php-bcmath php-zip wget unzip curl -y`
### Configurer Nginx
cf. <https://github.com/h5bp/server-configs-nginx> : un ensemble de bonnes pratiques de configuration de nginx
```
service nginx stop
cd /etc
mv nginx nginx-origin
git clone https://github.com/h5bp/server-configs-nginx.git nginx
service nginx start
```
on change le fichier des certificats de base pour yeswiki.pro
`vi /etc/nginx/h5bp/tls/certificate_files.conf`
```
ssl_certificate /etc/letsencrypt/live/yeswiki.pro/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yeswiki.pro/key.pem;
ssl_trusted_certificate /etc/letsencrypt/live/yeswiki.pro/ca.pem;
```
On crée un template nginx de base pour les domaines en "domaine.yeswiki.pro"
`vi /etc/nginx/conf.d/templates/domain.yeswiki.pro.conf`
```
# ----------------------------------------------------------------------
# | Config file for example.com host |
# ----------------------------------------------------------------------
server {
listen [::]:80;
listen 80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
server {
listen [::]:443 ssl http2;
listen 443 ssl http2;
server_name www.example.com;
include h5bp/tls/ssl_engine.conf;
include h5bp/tls/certificate_files.conf;
include h5bp/tls/policy_strict.conf;
return 301 $scheme://example.com$request_uri;
}
server {
# listen [::]:443 ssl http2 accept_filter=dataready; # for FreeBSD
# listen 443 ssl http2 accept_filter=dataready; # for FreeBSD
listen [::]:443 ssl http2;
listen 443 ssl http2;
# The host name to respond to
server_name example.com;
include h5bp/tls/ssl_engine.conf;
include h5bp/tls/certificate_files.conf;
include h5bp/tls/policy_strict.conf;
# Path for static files
root /home/userexample/example.com;
# Custom error pages
include h5bp/errors/custom_errors.conf;
# Include the basic h5bp config set
include h5bp/basic.conf;
access_log /var/log/nginx/example.com-access.log;
error_log /var/log/nginx/example.com-error.log error;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm-userexample.sock;
fastcgi_index index.php;
include fastcgi.conf;
}
}
```
tweak nginx.conf
keepalive_timeout 40s;
client_max_body_size 1G;
acme.sh pour les certificats ssl
infos cf. <https://kb.virtubox.net/knowledgebase/how-to-issue-wildcard-ssl-certificate-with-acme-sh-nginx/>
`curl https://get.acme.sh | sh -s email=contact@yeswiki.pro`
puis sortir de la session bash et revenir pour avoir acces à la commande bash
un certificat wildcard
`acme.sh --issue -d yeswiki.pro -d *.yeswiki.pro --dns -k ec-384 \
--yes-I-know-dns-manual-mode-enough-go-ahead-please
`
mettre les 2 entrées DNS txt demandées pour la domaine TODO: automatiser avec l'API Gandi <https://github.com/acmesh-official/acme.sh/wiki/dnsapi#18-use-gandi-livedns-api>
`acme.sh --renew -d yeswiki.pro \
--yes-I-know-dns-manual-mode-enough-go-ahead-please --ecc --force
`
On converti en certificats utilisables pour nginx
`mkdir -p /etc/letsencrypt/live/yeswiki.pro`
`acme.sh --install-cert -d yeswiki.pro --ecc \
--cert-file /etc/letsencrypt/live/yeswiki.pro/cert.pem \
--key-file /etc/letsencrypt/live/yeswiki.pro/key.pem \
--fullchain-file /etc/letsencrypt/live/yeswiki.pro/fullchain.pem \
--ca-file /etc/letsencrypt/live/yeswiki.pro/ca.pem \
--reloadcmd "systemctl restart nginx.service"`
pour installer un nouveau site
```
cd /etc/nginx/conf.d/
cp templates/domain.yeswiki.pro.conf <mondomaine.ext>.conf
sed -i 's/example.com/<mondomaine.ext>/g' <mondomaine.ext>.conf
sed -i 's/userexample/<monuser>/g' <mondomaine.ext>.conf
service nginx reload
```
pour désactiver un site, il faut mettre un point devant le nom du site
```
cd /etc/nginx/conf.d/
cp <mondomaine.ext>.conf .<mondomaine.ext>.conf # cf le point . devant
service nginx reload
```
### Configurer php
`vi /etc/php/8.1/fpm/php.ini` changer :
```
cgi.fix_pathinfo=0
date.timezone = Europe/Paris
max_execution_time = 90
max_input_time = 90
max_input_vars = 10000
upload_max_filesize = 1G
post_max_size = 1G
memory_limit = 1G
```
On redémarre le service pour prendre en compte les changements
`service php8.1-fpm restart`
Ajout de composer
```
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '55ce33d7678c5a611085589f1f3ddf8b3c52d662cd01d4ba75c0ee0459970c2200a51f492d557530c71c15d8dba01eae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
sudo mv composer.phar /usr/local/bin/composer
```
### Tuning mariadb
`mysql_secure_installation`
empècher l'acces root depuis l'extérieur, passer en socket et virer les base et comptes de test.
Augmenter la taille max des paquets mysql (pour matomo)
`vi /etc/mysql/mariadb.conf.d/50-server.cnf`
```
[mysqld]
max_allowed_packet = 1G # décommenter cette valeur
```
### Installation de nodejs (pour yarn)
```
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
apt-get install -y nodejs
corepack enable # apparement suffirait pour yarn
curl --compressed -o- -L https://yarnpkg.com/install.sh | bash
```
### Installer phpmyadmin
On ajoute un user pour cloisonner
```
groupadd phpmyadmin
useradd -g phpmyadmin phpmyadmin
```
#### Installation de phpmyadmin dans /opt/phpmyadmin
```
cd /opt
wget https://files.phpmyadmin.net/phpMyAdmin/5.2.0/phpMyAdmin-5.2.0-all-languages.zip
unzip phpMyAdmin-5.2.0-all-languages.zip
mv phpMyAdmin-5.2.0-all-languages phpmyadmin
rm phpMyAdmin-5.2.0-all-languages.zip
chown phpmyadmin:phpmyadmin phpmyadmin -R
sudo -u phpmyadmin cp config.sample.inc.php config.inc.php
vi config.inc.php # mettre une passphrase de 32 chars
```
#### Config php-fpm
vi /etc/php/8.1/fpm/pool.d/phpmyadmin.conf
```
[phpmyadmin]
user = phpmyadmin
group = phpmyadmin
listen = /var/run/php-fpm-phpmyadmin.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 75
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.process_idle_timeout = 10s
```
`service php8.1-fpm restart`
#### Config nginx
```
cd /etc/nginx/conf.d/
cp templates/domain.yeswiki.pro.conf sql.yeswiki.pro.conf
sed -i 's/example.com/sql.yeswiki.pro/g' sql.yeswiki.pro.conf
sed -i 's/userexample/phpmyadmin/g' sql.yeswiki.pro.conf
## changer le root pour /opt/phpmyadmin au lieu de /home/phpmyadmin/sql.yeswiki.pro
service nginx reload
```
### Installer Matomo
On ajoute un user pour cloisonner
```
groupadd matomo
useradd -g matomo matomo
```
#### Installation de matomo dans /opt/matomo
```
cd /opt
wget https://builds.matomo.org/matomo.zip
unzip matomo.zip
rm matomo.zip
rm 'How to install Matomo.html'
chown matomo:matomo matomo -R
```
#### Config php-fpm
`vi /etc/php/8.1/fpm/pool.d/matomo.conf`
```
[matomo]
user = matomo
group = matomo
listen = /var/run/php-fpm-matomo.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 75
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.process_idle_timeout = 10s
```
`service php8.1-fpm restart`
#### Config nginx
```
cd /etc/nginx/conf.d/
cp templates/domain.yeswiki.pro.conf stats.yeswiki.pro.conf
sed -i 's/example.com/stats.yeswiki.pro/g' stats.yeswiki.pro.conf
sed -i 's/userexample/matomo/g' stats.yeswiki.pro.conf
## changer le root pour /opt/matomo au lieu de /home/matomo/sql.yeswiki.pro
```
ajout de la config nginx recommandée <https://github.com/matomo-org/matomo-nginx#readme>
```
add_header Referrer-Policy origin always; # make sure outgoing links don't show the URL to the Matomo instance
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
## only allow accessing the following php files
location ~ ^/(index|matomo|piwik|js/index|plugins/HeatmapSessionRecording/configs)\.php$ {
include fastcgi.conf;
try_files $fastcgi_script_name =404; # protects against CVE-2019-11043. If this line is already included in your snippets/fastcgi-php.conf you can comment it here.
fastcgi_param HTTP_PROXY ""; # prohibit httpoxy: https://httpoxy.org/
fastcgi_pass unix:/var/run/php-fpm-matomo.sock;
}
## deny access to all other .php files
location ~* ^.+\.php$ {
deny all;
return 403;
}
## serve all other files normally
location / {
try_files $uri $uri/ =404;
}
## disable all access to the following directories
location ~ ^/(config|tmp|core|lang) {
deny all;
return 403; # replace with 404 to not show these directories exist
}
location ~ /\.ht {
deny all;
return 403;
}
location ~ js/container_.*_preview\.js$ {
expires off;
add_header Cache-Control 'private, no-cache, no-store';
}
location ~ \.(gif|ico|jpg|png|svg|js|css|htm|html|mp3|mp4|wav|ogg|avi|ttf|eot|woff|woff2|json)$ {
allow all;
## Cache images,CSS,JS and webfonts for an hour
## Increasing the duration may improve the load-time, but may cause old files to show after an Matomo upgrade
expires 1h;
add_header Pragma public;
add_header Cache-Control "public";
}
location ~ ^/(libs|vendor|plugins|misc|node_modules) {
deny all;
return 403;
}
## properly display textfiles in root directory
location ~/(.*\.md|LEGALNOTICE|LICENSE) {
default_type text/plain;
}
```
`service nginx reload`
#### Config DB
`mysql -u root -p`
```
CREATE USER 'matomo'@'localhost' IDENTIFIED BY '<mot de passe>';
GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT ON matomo.* TO 'matomo'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;
```
> Suivre l'installateur depuis <https://stats.yeswiki.pro>
#### Config matomo
force ssl
`vi /opt/matomo/config/config.ini.php`
```
[General]
force_ssl = 1
```
Cron
`touch /var/log/matomo-archive.log`
`chown matomo:matomo /var/log/matomo-archive.log`
`vi /etc/cron.d/matomo-archive`
```
MAILTO="contact@yeswiki.pro"
5 * * * * matomo /usr/bin/php /opt/matomo/console core:archive --url=http://stats.yeswiki.pro/ > /var/log/matomo-archive.log
```
### Application qui genere les yeswiki
On ajoute la source pour tous les wikis dans /opt/yeswiki , avec git histoire de pouvoir changer de version facilement
```
cd /opt/
git clone https://github.com/YesWiki/yeswiki.git
cd yeswiki
git checkout tags/v4.2.4 # derniere version de production
make install
```
https://codeberg.org/YesWiki-Pro/yeswiki-installer
### Backup MYSQL local
cf. https://tzanalastuce.com/automysqlbackup-sauvegarde-automatique-dune-base-de-donnees-mariadb-ou-mysql/
```
apt install automysqlbackup -y
vi /etc/default/automysqlbackup
```