Ceci est une ancienne révision du document !
web-01
Machine virtuelle
- Partie matérielle (virtuelle) KVM/QEMU
- 8 cœurs virtuels
- 16 Go de mémoire RAM
- 1 disque virtuel de 50 Go
- Accès au 1 Gbit/s
Topologie
Cette VM héberge tous les frontaux et applications web de Liberta. Historiquement, des services imposants comme Peertube ou Funkwhale disposaient de leur propre VM dédiée mais à l'usage cela s'est avéré être un gaspillage de ressources.
Ce serveur héberge donc les services :
- Castopod
- CryptPad
- Etherpad-Lite
- Funkwhale
- Nextcloud
- Peertube
- WriteFreely
Configuration
Système d'exploitation
- Debian stable (Debian 12 « Bookworm »)
Adressage IP
La route vers 10.10.10.0/24 via l'hyperviseur permet l'accès (par VPN) au réseau d'administration des VM.
# cat /etc/network/interfaces # This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The primary network interface allow-hotplug enp1s0 iface enp1s0 inet static address 192.168.10.5/24 gateway 192.168.10.1 dns-nameservers 213.133.99.99 213.133.100.100 213.133.98.98 dns-search liberta.vip up ip route add 10.10.10.0/24 via 192.168.10.1 dev enp1s0 iface enp1s0 inet6 static address 2a01:4f8:231:aa6::5 netmask 120 gateway 2a01:4f8:231:aa6::1
Paramètres réseau et swap dans sysctl
Dans /etc/sysctl.d/99-sysctl.conf
nous avons passé la « swappiness » à 0. La mémoire doit être donc complètement saturée avant de commencer à « swapper » sur le disque dur (pratique d'ailleurs sujet à débats dont nous avons conscience). Nous avons égalament activé le paramètre d'overcommit à 1 pour éviter que Nextcloud ne se prenne les foudres du « Out of Memory Killer » de Linux:
# Cloud : vm.overcommit_memory = 1 # swap à 0% de ram libre : vm.swappiness=0
Routage et filtrage avec iptables
Le paquet iptables-persistent
doit avoir été installé pour conserver les modifications du pare-feu entre chaque redémarrage.
Il est bien sûr extrêmement important de sécuriser SSH : interdire le login root avec mot de passe, utiliser de bons algorithmes de chiffrement, changer le port, n'autoriser qu'une IP distante (ou mieux, ne rien autoriser depuis internet et utiliser un VPN) et mettre en place un faux serveur SSH pour que les attaquants perdent leur temps à essayer de se connecter, sans vous faire perdre le vôtre (et ajouter un Fail2Ban évidemment). La recette reste secrète, désolé !
Cela dit, pour information une configuration similaire à la suivante est en place :
# /etc/ssh/sshd_config.d/liberta.conf # Common parameters: Port <un_port> Port <un_autre_port> AcceptEnv LANG LC_* ChallengeResponseAuthentication no KbdInteractiveAuthentication no PrintMotd no PasswordAuthentication no Subsystem sftp /usr/lib/openssh/sftp-server UsePAM yes X11Forwarding no # Port <un_port> configuration for IPv4/IPv6: Match Address="<adresse_ipv4_de_confiance>,127.0.0.0/8,<adresse_ipv6_de_confiance>,fd00::/8" LocalPort=<un_port> AllowUsers root <utilisateurice_de_confiance> # Port <un_autre_port> configuration for IPv4/IPv6: Match LocalPort=<un_autre_port> AllowUsers <utilisateurice_de_confiance>
Pour IPv4, l'hyperviseur s'occupe déjà de tout router et rediriger, nous n'avons besoin d'aucune règle.
En revanche, nous disposons d'une IPv6 routable et exposée sur internet ! Nous devons donc avoir des règles de pare-feu actives. Dans /etc/iptables-persistent/rules.v6
:
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "Accepter le trafic basique : ICMP, boucle locale et connexions établies, en entrée" -j ACCEPT -A INPUT -i lo -m comment --comment "Accepter le trafic basique : ICMP, boucle locale et connexions établies, en entrée" -j ACCEPT -A INPUT -d ::1/128 ! -i lo -m comment --comment "Accepter le trafic basique : ICMP, boucle locale et connexions établies, en entrée" -j REJECT --reject-with icmp6-port-unreachable -A INPUT -s 2a01:4f8:231:aa6::/120 -p tcp -m tcp --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -m comment --comment "Accepter le SSH depuis les autres VM" -j ACCEPT -A INPUT -p tcp -m tcp --dport 1984 --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -m comment --comment "Accepter le SSH" -j ACCEPT -A INPUT -s 2a01:4f8:231:aa6::/120 -p udp -m udp -m multiport --dports 53 -m comment --comment "Accepter les requêtes DNS (port 53) depuis les VM" -j ACCEPT -A INPUT -s 2a01:4f8:231:aa6::/120 -p udp -m udp -m multiport --dports 53 -m comment --comment "Accepter les requêtes DNS (port 53) depuis les VM" -j ACCEPT -A INPUT -s 2a01:4f8:231:aa6::/120 -p tcp -m tcp -m multiport --dports 53 -m comment --comment "Accepter les requêtes DNS (port 53) depuis les VM" -j ACCEPT -A INPUT -s 2a01:4f8:231:aa6::/120 -p tcp -m multiport --dports 2049 -m comment --comment "Bloquer les requêtes rpcbind/portmap en entrée depuis l\'extérieur" -j ACCEPT -A INPUT -s 2a01:4f8:231:aa6::/120 -p tcp -m multiport --dports 111 -m comment --comment "Bloquer les requêtes rpcbind/portmap en entrée depuis l\'extérieur" -j ACCEPT -A INPUT -s ::1/128 -p tcp -m tcp --dport 111 -m comment --comment "Bloquer les requêtes rpcbind/portmap en entrée depuis l\'extérieur" -j ACCEPT -A INPUT -s ::1/128 -p tcp -m tcp --dport 111 -m comment --comment "Bloquer les requêtes rpcbind/portmap en entrée depuis l\'extérieur" -j DROP -A INPUT -s 2a01:4f8:231:aa6::/120 -p tcp -m tcp -m multiport --dports 10050 -m comment --comment "Accepter les requêtes Zabbix passives (port 10050) depuis les VM" -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 4 -m comment --comment "On accepte l\'ICMPv6 indispensable au fonctionnement d\'IPv6" -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 128 -m comment --comment "On accepte l\'ICMPv6 indispensable au fonctionnement d\'IPv6" -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 129 -m comment --comment "On accepte l\'ICMPv6 indispensable au fonctionnement d\'IPv6" -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 134 -m hl --hl-eq 255 -m comment --comment "On accepte l\'ICMPv6 indispensable au fonctionnement d\'IPv6" -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 133 -m hl --hl-eq 255 -m comment --comment "On accepte l\'ICMPv6 indispensable au fonctionnement d\'IPv6" -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 136 -m hl --hl-eq 255 -m comment --comment "On accepte l\'ICMPv6 indispensable au fonctionnement d\'IPv6" -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 135 -m hl --hl-eq 255 -m comment --comment "On accepte l\'ICMPv6 indispensable au fonctionnement d\'IPv6" -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 128 -m conntrack --ctstate NEW -m limit --limit 1/sec --limit-burst 1 -m comment --comment "On refuse les trop nombreux ping" -j ACCEPT -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -m multiport --dports 80,443 -m comment --comment "Accepter le Web" -j ACCEPT -A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -m multiport --dports 1935 -m comment --comment "Accepter les ports pour Peertube" -j ACCEPT -A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 128 -m comment --comment "On refuse les trop nombreux ping" -j DROP -A INPUT -m conntrack --ctstate INVALID -m comment --comment "On refuse tout le reste en entrée" -j DROP -A INPUT -m comment --comment "On refuse tout le reste en entrée" -j REJECT --reject-with icmp6-port-unreachable -A INPUT -s 2620:0:1c00::/40 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2620:10d:c090::/44 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2880::/32 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff02::/47 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff19::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff1b::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff1c::/46 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff23::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff25::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff27::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff28::/46 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff2f::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff30::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff35::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff37::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff38::/46 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff3f::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff40::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff43::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff44::/47 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff48::/46 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff4d::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff4e::/47 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff50::/47 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff52::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2a03:2887:ff58::/47 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2c0f:ef78:3::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2c0f:ef78:5::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2c0f:ef78:6::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2c0f:ef78:9::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2c0f:ef78:d::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2c0f:ef78:e::/47 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2c0f:ef78:11::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP -A INPUT -s 2c0f:ef78:12::/48 -m comment --comment "Meta/Facebook/Instagram/Threads Adios!" -j DROP COMMIT
Paquets installés
Nous utilisons certains dépôts tiers : Node.js, Yarn, PHP (afin d'utiliser les plus récentes, actuellement la version 8.4) et les paquets de PostgreSQL :
deb [arch=amd64 signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main
deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main
deb [signed-by=/usr/share/keyrings/yarn-archive-keyring.gpg] https://dl.yarnpkg.com/debian/ stable main
deb [signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] https://packages.sury.org/php/ bookworm main
La liste des paquets :
# dpkg -l | grep '^i' |awk '{ print $2 }' | sed '/^$/d'| sort acl adduser alsa-topology-conf alsa-ucm-conf apparmor appstream apt apt-listchanges apt-transport-https apt-utils aspell aspell-fr base-files base-passwd bash bash-completion bind9-dnsutils bind9-host bind9-libs:amd64 binutils binutils-common:amd64 binutils-x86-64-linux-gnu bsdextrautils bsdutils build-essential busybox bzip2 ca-certificates certbot cloud-guest-utils composer console-setup console-setup-linux coreutils cpio cpp cpp-12 cron cron-daemon-common curl dash dbus dbus-bin dbus-daemon dbus-session-bus-common dbus-system-bus-common dbus-user-session debconf debconf-i18n debian-archive-keyring debian-faq debianutils debsuryorg-archive-keyring dictionaries-common diffutils dirmngr discover discover-data distro-info-data dmidecode dmsetup dnsutils doc-debian dpkg dpkg-dev e2fsprogs eject emacsen-common ethtool exiftags exiftran exuberant-ctags fail2ban fakeroot fdisk ffmpeg file findutils firmware-linux-free fontconfig fontconfig-config fonts-dejavu-core fonts-droid-fallback fonts-noto-mono fonts-urw-base35 fuse g++ g++-12 gcc gcc-12 gcc-12-base:amd64 gdbm-l10n gdisk geoip-database gettext gettext-base ghostscript gifsicle gir1.2-glib-2.0:amd64 gir1.2-packagekitglib-1.0 git git-man gnupg gnupg-l10n gnupg-utils gnupg2 gpg gpg-agent gpg-wks-client gpg-wks-server gpgconf gpgsm gpgv grep groff-base grub-common grub-pc grub-pc-bin grub2-common gsfonts gzip hdparm hicolor-icon-theme hostname htop i965-va-driver:amd64 icu-devtools ifrench-gut iftop ifupdown imagemagick imagemagick-6-common imagemagick-6.q16 inetutils-telnet init init-system-helpers initramfs-tools initramfs-tools-core installation-report intel-media-va-driver:amd64 iotop iproute2 iptables iptables-persistent iputils-ping isc-dhcp-client isc-dhcp-common iso-codes ispell javascript-common jpegoptim jq jsonlint kbd keyboard-configuration keyutils klibc-utils kmod krb5-locales laptop-detect less lib32gcc-s1 lib32stdc++6 libaacs0:amd64 libabsl20220623:amd64 libacl1:amd64 libalgorithm-diff-perl libalgorithm-diff-xs-perl:amd64 libalgorithm-merge-perl libaom3:amd64 libapparmor1:amd64 libappstream4:amd64 libapt-inst2.0:amd64 libapt-pkg5.0:amd64 libapt-pkg6.0:amd64 libarchive-zip-perl libarchive13:amd64 libargon2-1:amd64 libasan8:amd64 libasound2-data libasound2:amd64 libaspell15:amd64 libass9:amd64 libassuan0:amd64 libasyncns0:amd64 libatomic1:amd64 libattr1:amd64 libaudit-common libaudit1:amd64 libavahi-client3:amd64 libavahi-common-data:amd64 libavahi-common3:amd64 libavc1394-0:amd64 libavcodec59:amd64 libavdevice59:amd64 libavfilter8:amd64 libavformat59:amd64 libavif15:amd64 libavutil57:amd64 libbdplus0:amd64 libbinutils:amd64 libblas3:amd64 libblkid1:amd64 libbluray2:amd64 libbpf1:amd64 libbrotli1:amd64 libbs2b0:amd64 libbsd0:amd64 libbz2-1.0:amd64 libc-bin libc-dev-bin libc-devtools libc-l10n libc6-dev:amd64 libc6-i386 libc6:amd64 libcaca0:amd64 libcairo-gobject2:amd64 libcairo2:amd64 libcap-ng0:amd64 libcap2-bin libcap2:amd64 libcbor0.8:amd64 libcc1-0:amd64 libcdio-cdda2:amd64 libcdio-paranoia2:amd64 libcdio19:amd64 libchromaprint1:amd64 libcjson1:amd64 libclang-14-dev libclang-common-14-dev libclang-dev libclang-rt-14-dev:amd64 libclang1-14 libcodec2-1.0:amd64 libcom-err2:amd64 libconfig-inifiles-perl libcrypt-dev:amd64 libcrypt1:amd64 libcryptsetup12:amd64 libctf-nobfd0:amd64 libctf0:amd64 libcups2:amd64 libcurl3-gnutls:amd64 libcurl4:amd64 libdatrie1:amd64 libdav1d6:amd64 libdb5.3:amd64 libdbd-mariadb-perl libdbi-perl:amd64 libdbus-1-3:amd64 libdc1394-25:amd64 libde265-0:amd64 libdebconfclient0:amd64 libdecor-0-0:amd64 libdecor-0-plugin-1-cairo:amd64 libdeflate0:amd64 libdevmapper1.02.1:amd64 libdiscover2 libdjvulibre-text libdjvulibre21:amd64 libdns-export1104 libdpkg-perl libdrm-amdgpu1:amd64 libdrm-common libdrm-intel1:amd64 libdrm-nouveau2:amd64 libdrm-radeon1:amd64 libdrm2:amd64 libduktape207:amd64 libdw1:amd64 libedit2:amd64 libefiboot1:amd64 libefivar1:amd64 libelf1:amd64 libepoxy0:amd64 liberror-perl libestr0:amd64 libevent-core-2.1-7:amd64 libexif12:amd64 libexpat1-dev:amd64 libexpat1:amd64 libext2fs2:amd64 libfakeroot:amd64 libfastjson4:amd64 libfdisk1:amd64 libffi-dev:amd64 libffi6:amd64 libffi7:amd64 libffi8:amd64 libfftw3-double3:amd64 libfido2-1:amd64 libfile-fcntllock-perl libfile-find-rule-perl libflac12:amd64 libflite1:amd64 libfontconfig1:amd64 libfontenc1:amd64 libfreetype6:amd64 libfribidi0:amd64 libfstrm0:amd64 libfuse2:amd64 libgav1-1:amd64 libgbm1:amd64 libgc1:amd64 libgcc-12-dev:amd64 libgcc-s1:amd64 libgcrypt20:amd64 libgd3:amd64 libgdbm-compat4:amd64 libgdbm6:amd64 libgdk-pixbuf-2.0-0:amd64 libgdk-pixbuf2.0-bin libgdk-pixbuf2.0-common libgeoip1:amd64 libgfortran5:amd64 libgirepository-1.0-1:amd64 libgl1-mesa-dri:amd64 libgl1:amd64 libglapi-mesa:amd64 libglib2.0-0:amd64 libglib2.0-bin libglib2.0-data libglvnd0:amd64 libglx-mesa0:amd64 libglx0:amd64 libgme0:amd64 libgmp10:amd64 libgnutls30:amd64 libgomp1:amd64 libgpg-error0:amd64 libgpgme11:amd64 libgpm2:amd64 libgprofng0:amd64 libgraphite2-3:amd64 libgs-common libgs10-common libgs10:amd64 libgsm1:amd64 libgssapi-krb5-2:amd64 libgstreamer1.0-0:amd64 libharfbuzz0b:amd64 libheif1:amd64 libhogweed4:amd64 libhogweed6:amd64 libhwy1:amd64 libice6:amd64 libicu-dev:amd64 libicu72:amd64 libidn11:amd64 libidn12:amd64 libidn2-0:amd64 libiec61883-0:amd64 libigdgmm12:amd64 libijs-0.35:amd64 libimage-exiftool-perl libimagequant0:amd64 libimath-3-1-29:amd64 libip4tc0:amd64 libip4tc2:amd64 libip6tc0:amd64 libip6tc2:amd64 libiptc0:amd64 libisc-export1100:amd64 libisl23:amd64 libitm1:amd64 libjack-jackd2-0:amd64 libjansson4:amd64 libjbig0:amd64 libjbig2dec0:amd64 libjemalloc2:amd64 libjpeg-dev:amd64 libjpeg62-turbo-dev:amd64 libjpeg62-turbo:amd64 libjq1:amd64 libjs-jquery libjs-sphinxdoc libjs-underscore libjson-c3:amd64 libjson-c5:amd64 libjxl0.7:amd64 libjxr-tools libjxr0:amd64 libk5crypto3:amd64 libkeyutils1:amd64 libklibc:amd64 libkmod2:amd64 libkrb5-3:amd64 libkrb5support0:amd64 libksba8:amd64 liblapack3:amd64 liblcms2-2:amd64 libldap-2.5-0:amd64 libldap-common libldap-dev:amd64 libldap2-dev libldb2:amd64 liblerc4:amd64 liblilv-0-0:amd64 liblinear4:amd64 libllvm14:amd64 libllvm15:amd64 liblmdb0:amd64 liblocale-gettext-perl liblockfile-bin liblognorm5:amd64 liblqr-1-0:amd64 liblsan0:amd64 libltdl7:amd64 liblua5.3-0:amd64 liblz4-1:amd64 liblzma5:amd64 libmagic-dev:amd64 libmagic-mgc libmagic1:amd64 libmagickcore-6.q16-6-extra:amd64 libmagickcore-6.q16-6:amd64 libmagickwand-6.q16-6:amd64 libmariadb3:amd64 libmaxminddb0:amd64 libmbedcrypto7:amd64 libmd0:amd64 libmfx1:amd64 libmime-charset-perl libmnl0:amd64 libmount1:amd64 libmp3lame0:amd64 libmpc3:amd64 libmpfr6:amd64 libmpg123-0:amd64 libmysofa1:amd64 libncurses5:amd64 libncurses6:amd64 libncursesw6:amd64 libnetfilter-conntrack3:amd64 libnetpbm11:amd64 libnettle6:amd64 libnettle8:amd64 libnewt0.52:amd64 libnfnetlink0:amd64 libnfsidmap1:amd64 libnftnl11:amd64 libnghttp2-14:amd64 libnginx-mod-http-auth-pam libnginx-mod-http-dav-ext libnginx-mod-http-echo libnginx-mod-http-geoip libnginx-mod-http-image-filter libnginx-mod-http-subs-filter libnginx-mod-http-upstream-fair libnginx-mod-http-xslt-filter libnginx-mod-stream libnginx-mod-stream-geoip libnl-3-200:amd64 libnl-genl-3-200:amd64 libnorm1:amd64 libnpth0:amd64 libnsl-dev:amd64 libnsl2:amd64 libnss-nis:amd64 libnss-nisplus:amd64 libnss-systemd:amd64 libnuma1:amd64 libnumber-compare-perl libobjc-12-dev:amd64 libobjc4:amd64 libogg0:amd64 libonig5:amd64 libopenal-data libopenal1:amd64 libopenexr-3-1-30:amd64 libopenjp2-7:amd64 libopenmpt0:amd64 libopus0:amd64 libp11-kit0:amd64 libpackagekit-glib2-18:amd64 libpam-modules-bin libpam-modules:amd64 libpam-runtime libpam-systemd:amd64 libpam0g:amd64 libpango-1.0-0:amd64 libpangocairo-1.0-0:amd64 libpangoft2-1.0-0:amd64 libpaper-utils libpaper1:amd64 libpcap0.8:amd64 libpci3:amd64 libpciaccess0:amd64 libpcre2-8-0:amd64 libpcre3:amd64 libperl5.36:amd64 libpgm-5.3-0:amd64 libpipeline1:amd64 libpixman-1-0:amd64 libpkgconf3:amd64 libplacebo208:amd64 libpng16-16:amd64 libpocketsphinx3:amd64 libpolkit-agent-1-0:amd64 libpolkit-gobject-1-0:amd64 libpopt0:amd64 libposix-strptime-perl libpostproc56:amd64 libpq-dev libpq5:amd64 libproc2-0:amd64 libprocps7:amd64 libprotobuf-c1:amd64 libpsl5:amd64 libpulse0:amd64 libpython2.7-minimal:amd64 libpython2.7-stdlib:amd64 libpython3-dev:amd64 libpython3-stdlib:amd64 libpython3.11-dev:amd64 libpython3.11-minimal:amd64 libpython3.11-stdlib:amd64 libpython3.11:amd64 libquadmath0:amd64 librabbitmq4:amd64 librav1e0:amd64 libraw1394-11:amd64 libreadline8:amd64 librist4:amd64 librsvg2-2:amd64 librsvg2-common:amd64 librtmp1:amd64 librubberband2:amd64 libsamplerate0:amd64 libsasl2-2:amd64 libsasl2-dev libsasl2-modules-db:amd64 libsasl2-modules:amd64 libsdl2-2.0-0:amd64 libseccomp2:amd64 libselinux1:amd64 libsemanage-common libsemanage2:amd64 libsensors-config libsensors5:amd64 libsepol1:amd64 libsepol2:amd64 libserd-0-0:amd64 libshine3:amd64 libslang2:amd64 libsm6:amd64 libsmartcols1:amd64 libsmbclient:amd64 libsnappy1v5:amd64 libsndfile1:amd64 libsndio7.0:amd64 libsodium23:amd64 libsombok3:amd64 libsord-0-0:amd64 libsoxr0:amd64 libspeex1:amd64 libsphinxbase3:amd64 libsqlite3-0:amd64 libsratom-0-0:amd64 libsrt1.5-gnutls:amd64 libss2:amd64 libssh-gcrypt-4:amd64 libssh2-1:amd64 libssl-dev:amd64 libssl1.1:amd64 libssl3:amd64 libstdc++-12-dev:amd64 libstdc++6:amd64 libstemmer0d:amd64 libsvtav1enc1:amd64 libswresample4:amd64 libswscale6:amd64 libsystemd-shared:amd64 libsystemd0:amd64 libtalloc2:amd64 libtasn1-6:amd64 libtdb1:amd64 libterm-readkey-perl libtevent0:amd64 libtext-charwidth-perl:amd64 libtext-glob-perl libtext-iconv-perl:amd64 libtext-wrapi18n-perl libthai-data libthai0:amd64 libtheora0:amd64 libtiff6:amd64 libtinfo5:amd64 libtinfo6:amd64 libtirpc-common libtirpc-dev:amd64 libtirpc3:amd64 libtsan2:amd64 libtwolame0:amd64 libubsan1:amd64 libuchardet0:amd64 libudev1:amd64 libudfread0:amd64 libunicode-linebreak-perl libunistring2:amd64 libunwind8:amd64 liburing2:amd64 libusb-1.0-0:amd64 libutempter0:amd64 libuuid1:amd64 libuv1:amd64 libva-drm2:amd64 libva-x11-2:amd64 libva2:amd64 libvdpau-va-gl1:amd64 libvdpau1:amd64 libvidstab1.1:amd64 libvorbis0a:amd64 libvorbisenc2:amd64 libvorbisfile3:amd64 libvpx7:amd64 libvulkan1:amd64 libwayland-client0:amd64 libwayland-cursor0:amd64 libwayland-egl1:amd64 libwayland-server0:amd64 libwbclient0:amd64 libwebp7:amd64 libwebpdemux2:amd64 libwebpmux3:amd64 libwmflite-0.2-7:amd64 libwrap0:amd64 libx11-6:amd64 libx11-data libx11-xcb1:amd64 libx264-164:amd64 libx265-199:amd64 libxau6:amd64 libxcb-dri2-0:amd64 libxcb-dri3-0:amd64 libxcb-glx0:amd64 libxcb-present0:amd64 libxcb-randr0:amd64 libxcb-render0:amd64 libxcb-shape0:amd64 libxcb-shm0:amd64 libxcb-sync1:amd64 libxcb-xfixes0:amd64 libxcb1:amd64 libxcursor1:amd64 libxdmcp6:amd64 libxext6:amd64 libxfixes3:amd64 libxi6:amd64 libxkbcommon0:amd64 libxml2-dev:amd64 libxml2:amd64 libxmlb2:amd64 libxmlrpc-epi0:amd64 libxmuu1:amd64 libxpm4:amd64 libxrandr2:amd64 libxrender1:amd64 libxshmfence1:amd64 libxslt1-dev:amd64 libxslt1.1:amd64 libxss1:amd64 libxt6:amd64 libxtables12:amd64 libxv1:amd64 libxvidcore4:amd64 libxxf86vm1:amd64 libxxhash0:amd64 libyaml-0-2:amd64 libyuv0:amd64 libz3-4:amd64 libzimg2:amd64 libzip4:amd64 libzmq5:amd64 libzstd1:amd64 libzvbi-common libzvbi0:amd64 linux-base linux-image-6.1.0-37-amd64 linux-image-6.1.0-39-amd64 linux-image-amd64 linux-libc-dev:amd64 locales locate login logrotate logsave lsb-base lsb-release lsof lua-lpeg:amd64 mailcap make man-db manpages manpages-dev manpages-fr mariadb-client mariadb-client-core mariadb-common mawk media-types mesa-va-drivers:amd64 mesa-vdpau-drivers:amd64 mesa-vulkan-drivers:amd64 mime-support mount mysql-common nano ncal ncdu ncurses-base ncurses-bin ncurses-term net-tools netbase netcat-traditional netfilter-persistent netpbm nfs-common nfs-kernel-server nginx nginx-common nmap nmap-common nodejs ocl-icd-libopencl1:amd64 openssh-client openssh-server openssh-sftp-server openssl optipng os-prober packagekit packagekit-tools passwd patch pci.ids pciutils perl perl-base perl-modules-5.28 perl-modules-5.36 php-common php-composer-ca-bundle php-composer-class-map-generator php-composer-metadata-minifier php-composer-pcre php-composer-semver php-composer-spdx-licenses php-composer-xdebug-handler php-json-schema php-psr-container php-psr-log php-react-promise php-seld-signal-handler php-symfony-console php-symfony-deprecation-contracts php-symfony-filesystem php-symfony-finder php-symfony-process php-symfony-service-contracts php-symfony-string php8.4-apcu php8.4-apcu-dbgsym php8.4-bcmath php8.4-bz2 php8.4-cli php8.4-common php8.4-curl php8.4-fpm php8.4-gd php8.4-gmp php8.4-igbinary php8.4-imagick php8.4-intl php8.4-mbstring php8.4-mysql php8.4-opcache php8.4-pgsql php8.4-phpdbg php8.4-readline php8.4-redis php8.4-xml php8.4-xmlrpc php8.4-zip pinentry-curses pkexec pkg-config:amd64 pkgconf-bin pkgconf:amd64 pngquant pocketsphinx-en-us policykit-1 polkitd polkitd-pkla poppler-data powermgmt-base procps psmisc publicsuffix python-apt-common python-certbot-nginx python-is-python3 python2.7 python2.7-minimal python3 python3-acme python3-apt python3-blinker python3-brotli python3-certbot python3-certbot-dns-gandi python3-certbot-nginx python3-certifi python3-cffi-backend:amd64 python3-chardet python3-charset-normalizer python3-click python3-colorama python3-configargparse python3-configobj python3-cryptography python3-dbus python3-debconf python3-debian python3-debianbts python3-dev python3-distro python3-distutils python3-gi python3-gpg python3-httplib2 python3-icu python3-idna python3-josepy python3-jwt python3-lazr.restfulclient python3-lazr.uri python3-ldb python3-lib2to3 python3-minimal python3-mutagen python3-oauthlib python3-openssl python3-parsedatetime python3-pip python3-pip-whl python3-pkg-resources python3-pycryptodome python3-pycurl python3-pyinotify python3-pyparsing python3-pysimplesoap python3-pyxattr:amd64 python3-reportbug python3-requests python3-rfc3339 python3-samba python3-setuptools python3-setuptools-whl python3-six python3-software-properties python3-systemd python3-talloc:amd64 python3-tdb python3-tz python3-urllib3 python3-venv python3-wadllib python3-websockets python3-wheel python3-yaml python3.11 python3.11-dev python3.11-minimal python3.11-venv qemu-guest-agent readline-common reportbug rpcbind rpcsvc-proto rsync rsyslog rtmpdump runit-helper samba-common samba-common-bin samba-dsdb-modules:amd64 samba-libs:amd64 screen sed sensible-utils sgml-base shared-mime-info smbclient socat software-properties-common ssl-cert sudo sysstat systemd systemd-sysv systemd-timesyncd sysvinit-utils tar task-french task-ssh-server tasksel tasksel-data tcpdump traceroute tree tzdata ucf udev unzip usbutils usrmerge util-linux util-linux-extra util-linux-locales va-driver-all:amd64 vdpau-driver-all:amd64 vim vim-common vim-runtime vim-tiny wamerican wfrench wget whiptail whois wkhtmltox x11-common xauth xdg-user-dirs xfonts-75dpi xfonts-base xfonts-encodings xfonts-utils xkb-data xml-core xxd xz-utils yarn yt-dlp zabbix-agent2 zip zlib1g-dev:amd64 zlib1g:amd64 zstd
Stockage
Nous montons les partages ZFS de notre hyperviseur en NFS pour chaque application :
Dans /etc/fstab
:
# cloud_data ZFS NFS share: 192.168.10.1:/zdata/cloud_data /cloud_data nfs auto 0 0 # cryptpad_data ZFS NFS share: 192.168.10.1:/zdata/cryptpad_data /home/cryptpad/cryptpad_data nfs auto 0 0 # castpod_data ZFS NFS share: 192.168.10.1:/zdata/castopod_data /var/www/castopod/public/media nfs auto 0 0 # video_data ZFS NFS share: 192.168.10.1:/zdata/video_data /var/www/peertube/storage nfs auto 0 0 # audio_data ZFS NFS share: 192.168.10.1:/zdata/audio_data /var/www/funkwhale/data nfs auto 0 0
Partie logicielle
Toutes les applications web des services sont servies par le serveur / reverse-proxy Nginx dont voici les configurations pour chaque application ainsi que les configurations communes.
Nous avons décidé de bannir dans la configuration générale un certain nombre de pays nous noyant de spam et d'attaques en tout genre :
# cat /etc/nginx/nginx.conf user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 1024; multi_accept on; use epoll; } http { server_names_hash_bucket_size 64; # Liberta : no more reverse proxy: #set_real_ip_from 127.0.0.1; #set_real_ip_from 192.168.10.0/24; #real_ip_header X-Forwarded-For; #real_ip_recursive on; include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log warn; sendfile on; send_timeout 3600; tcp_nopush on; tcp_nodelay on; open_file_cache max=500 inactive=10m; open_file_cache_errors on; keepalive_timeout 65; reset_timedout_connection on; server_tokens off; resolver_timeout 5s; proxy_buffers 16 16k; proxy_buffer_size 16k; fastcgi_buffers 64 4K; client_max_body_size 8G; ## # Logging Settings ## rewrite_log on; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log notice; # Liberta : ban all countries except those: geoip_country /usr/share/GeoIP/GeoIP.dat; map $geoip_country_code $allowed_country { default no; AL yes; AD yes; AM yes; AT yes; BA yes; BE yes; BG yes; BY yes; CH yes; CY yes; CZ yes; DK yes; EE yes; FI yes; FR yes; FO yes; DE yes; GB yes; GE yes; GI yes; GR yes; HR yes; HU yes; IE yes; IM yes; IS yes; IT yes; LI yes; LV yes; LT yes; LU yes; MC yes; MD yes; ME yes; MK yes; MT yes; NL yes; NO yes; PL yes; PT yes; RO yes; SK yes; SI yes; ES yes; RS yes; RU yes; SE yes; SM yes; TR yes; UA yes; VA yes; XK yes; # Allowed countries list: # AL,AD,AM,AT,BA,BE,BG,BY,CH,CY,CZ,DK,EE,FI,FR,FO,DE,GB,GE,GI,GR,HR,HU,IE,IM,IS,IT,LI,LV,LT,LU,MC,MD,ME,MK,MT,NL,NO,PL,PT,RO,SK,SI,ES,RS,RU,SE,SM,TR,UA,VA,XK } ## # Virtual Host Configs ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
Nous avons créé le fichier commun /etc/nginx/letsencrypt_security.conf
afin de pouvoir générer et renouveler facilement des certificats TLS Let's Encrypt pour chacune de nos applications web.
Le fichier est agrémenté de directives de sécurité recommandées pour la plupart des applications (certaines modifient ces directives via leur propre configuration évidemment) :
# cat /etc/nginx/letsencrypt_security.conf # Security headers add_header X-XSS-Protection "1; mode=block" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer-when-downgrade" always; add_header Content-Security-Policy "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always; add_header Permissions-Policy "interest-cohort=()" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # Dotfiles location ~ /\.(?!well-known) { deny all; } # ACME-challenge location ^~ /.well-known/acme-challenge/ { root /var/www/_letsencrypt; }
Liberta (Site principal)
Le site de Liberta est en pur HTML et CSS.
Ce fichier contient la gestion globale du HTTP, lequel redirige tous les domaines vers HTTPS, notamment le site de Liberta qui est sur le sous-domaine www.
.
Nous listons volontairement notre répertoire img/
pour exposer nos images et pouvoir les utiliser facilement pour les includre sur nos pages ; c'est notamment utile pour insérer des images sur notre blog (WriteFreely ne le permet pas dans sa version communautaire malheureusement) :
# Configuration globale : # HTTP + redirect server { server_name _; listen 80; listen [::]:80; include letsencrypt_security.conf; location / { return 301 https://$host$request_uri; } } # Domaine liberta.vip sans sous-domaine : # HTTP + redirect server { server_name liberta.vip; listen 80; listen [::]:80; include letsencrypt_security.conf; location / { return 301 https://www.$host$request_uri; } } server { server_name liberta.vip; listen 443 ssl http2; listen [::]:443 ssl http2; ssl_certificate /etc/letsencrypt/live/liberta.vip-0001/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/liberta.vip-0001/privkey.pem; return 301 https://www.liberta.vip; } # Liberta (Pur HTML / CSS) # HTTP + redirect server { server_name www.liberta.vip; listen 80; listen [::]:80; include letsencrypt_security.conf; location / { return 301 https://$host$request_uri; } } server { server_name www.liberta.vip; listen 443 ssl http2; listen [::]:443 ssl http2; ssl_certificate /etc/letsencrypt/live/liberta.vip-0001/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/liberta.vip-0001/privkey.pem; # Secure headers add_header X-Frame-Options "SAMEORIGIN" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; add_header X-Xss-Protection "1; mode=block" always; add_header Content-Security-Policy "default-src 'self' 'unsafe-inline'; script-src www.liberta.vip; img-src *;"; add_header X-Content-Type-Options "nosniff" always; root /var/www/www.liberta.vip; access_log /var/log/nginx/www.liberta.vip_access.log; error_log /var/log/nginx/www.liberta.vip_error.log warn; index index.html; location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { allow all; log_not_found off; access_log off; } location = /img/ { allow all; log_not_found off; access_log off; autoindex on; } location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; } }
Nous ne fournirons pas tous les détails des configurations pour chaque application, lesquelles sont souvent appelées à changer lors des mises à jour et rendraient la maintenance de cette documentation fort fastidieuse.
À terme, nous prévoyons de publier notre configuration complète sur notre dépôt git, d'autant plus que nous désirons l'industrialiser / l'automatiser via ansible
.