From acbe11489c4aaf0f763bea035d3f82f8023ea763 Mon Sep 17 00:00:00 2001 From: Script Shadow Date: Wed, 8 Apr 2026 16:15:11 +0200 Subject: [PATCH] Initial commit: VPS tutorial complet (105 etapes) --- 01-prerequis.md | 57 +++++++++++ 02-config-base.md | 210 ++++++++++++++++++++++++++++++++++++++ 03-bis-hestiacp.md | 55 ++++++++++ 03-ispconfig.md | 67 ++++++++++++ 04-dns.md | 92 +++++++++++++++++ 05-webmin.md | 87 ++++++++++++++++ 06-monitoring.md | 163 +++++++++++++++++++++++++++++ 07-mail.md | 151 +++++++++++++++++++++++++++ 08-sni-mail.md | 78 ++++++++++++++ 09-docker.md | 102 ++++++++++++++++++ 10-services-docker.md | 93 +++++++++++++++++ 11-applications.md | 115 +++++++++++++++++++++ 12-backup.md | 100 ++++++++++++++++++ 13-securite.md | 122 ++++++++++++++++++++++ 14-deploiement-symfony.md | 86 ++++++++++++++++ 15-livekit.md | 109 ++++++++++++++++++++ 16-notes-pieges.md | 109 ++++++++++++++++++++ README.md | 52 ++++++++++ 18 files changed, 1848 insertions(+) create mode 100644 01-prerequis.md create mode 100644 02-config-base.md create mode 100644 03-bis-hestiacp.md create mode 100644 03-ispconfig.md create mode 100644 04-dns.md create mode 100644 05-webmin.md create mode 100644 06-monitoring.md create mode 100644 07-mail.md create mode 100644 08-sni-mail.md create mode 100644 09-docker.md create mode 100644 10-services-docker.md create mode 100644 11-applications.md create mode 100644 12-backup.md create mode 100644 13-securite.md create mode 100644 14-deploiement-symfony.md create mode 100644 15-livekit.md create mode 100644 16-notes-pieges.md create mode 100644 README.md diff --git a/01-prerequis.md b/01-prerequis.md new file mode 100644 index 0000000..76fbac3 --- /dev/null +++ b/01-prerequis.md @@ -0,0 +1,57 @@ +# 1. Prerequis et Choix + +## Choix de l'hebergeur VPS + +**Recommande : Contabo** (bon rapport qualite/prix) +- VPS S : 2 vCPU / 4 GB RAM (~5 EUR/mois) +- VPS M : 4 vCPU / 8 GB RAM (~10 EUR/mois) - recommande +- OS : Ubuntu 24.04 LTS + +## Choix du registrar + +**Recommande : OVH** +- Interface complete (glue records, NS personnalises, DNSSEC) +- Pas besoin de contacter le support pour les modifications +- Propagation DNS rapide + +**Eviter :** Cloud4Africa/MTN pour les .ci (support lent, interface buggee pour les NS personnalises) + +**Alternative :** Cloudflare (DNS gratuit, protection DDoS, mais pas de registrar pour tous les TLD) + +## Choix du panel + +### ISPConfig (utilise dans ce guide) +- Complet : multi-serveur, revendeur, quotas +- Plus lourd et interface ancienne +- Documentation : https://vps-installation.readthedocs.io/fr/latest/ + +### HestiaCP (recommande pour prochain VPS) +- Plus leger, interface moderne +- Mises a jour frequentes +- Un seul serveur uniquement +- Documentation : https://docs.hestiacp.com/ + +## Configuration initiale chez l'hebergeur + +1. Commander le VPS avec Ubuntu 24.04 +2. Noter l'IP publique IPv4 et IPv6 +3. Se connecter en SSH : `ssh root@` +4. Changer le mot de passe root : `passwd` + +## Configuration chez le registrar (OVH) + +1. Acheter le domaine +2. Creer les **glue records** : + - `ns1.` -> `` + - `ns2.` -> `` +3. Changer les **nameservers** vers : + - `ns1.` + - `ns2.` + +> **Note :** OVH verifie que le serveur DNS repond avant d'accepter le changement. Il faut d'abord installer ISPConfig et creer la zone DNS (etape 3-4). + +## Pour les domaines .ci chez MTN + +Les domaines .ci ne supportent pas les glue records vers le meme domaine. Solution : +- Utiliser les NS de votre domaine principal (ex: `ns1.z-ana.com` pour `stlab.ci`) +- Modifier les NS chez MTN vers `ns1.` et `ns2.` diff --git a/02-config-base.md b/02-config-base.md new file mode 100644 index 0000000..b469fee --- /dev/null +++ b/02-config-base.md @@ -0,0 +1,210 @@ +# 2. Configuration de Base + +## Creer un utilisateur + +```bash +adduser +usermod -a -G sudo +``` + +## Configurer /etc/hosts + +```bash +cat > /etc/hosts << 'EOF' +127.0.0.1 localhost +127.0.1.1 + + +# IPv6 +::1 localhost ip6-localhost ip6-loopback +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters +EOF +``` + +## Verifier le hostname + +```bash +hostnamectl set-hostname +hostname -f +# Doit afficher : +``` + +## Editeur par defaut + +```bash +apt install vim micro +update-alternatives --config editor +# Choisir micro ou vim +``` + +## Installer etckeeper + +```bash +apt update && apt install etckeeper +``` + +## Mettre a jour les sources apt + +Ubuntu 24.04 utilise le format deb822 (`/etc/apt/sources.list.d/ubuntu.sources`). +Verifier que `main universe restricted multiverse` et `backports` sont presents. + +```bash +apt update && apt dist-upgrade && apt autoremove +``` + +## Paquets de base + +```bash +apt install curl wget ntpdate apt-transport-https apt-listchanges apt-file apt-rdepends man +``` + +## Locale FR + +```bash +apt install locales +dpkg-reconfigure locales +# Selectionner fr_FR.UTF-8 +apt install task-french +``` + +## Debfoster + +```bash +apt install debfoster +debfoster +``` + +### Script keeper pour etckeeper + +Creer `/etc/etckeeper/pre-commit.d/35debfoster` : + +```bash +#!/bin/sh +set -e +LANG=C +export LANG + +shellquote() { + sed -e "s/'/'\"'\"'/g" -e "s/^/'/" -e "s/$/'/" +} + +if [ "$VCS" = git ] || [ "$VCS" = hg ] || [ "$VCS" = bzr ] || [ "$VCS" = darcs ]; then + debfoster -q -k /etc/keepers + chmod 600 /etc/keepers + sed -i "1i\\# debfoster file" /etc/keepers + sed -i "1i\\# Generated by etckeeper. Do not edit." /etc/keepers + if [ "$VCS" = git ]; then + git add keepers + fi +fi +``` + +```bash +chmod 755 /etc/etckeeper/pre-commit.d/35debfoster +etckeeper commit +``` + +## Mises a jour automatiques + +```bash +apt install unattended-upgrades +``` + +## Interdire le login root SSH + +```bash +# Verifier dans /etc/ssh/sshd_config : +PermitRootLogin no +``` + +## Sudo sans mot de passe + +```bash +addgroup --system sudonp +usermod -a -G sudonp +echo '%sudonp ALL=(ALL:ALL) NOPASSWD: ALL' > /etc/sudoers.d/010_sudonp +chmod 440 /etc/sudoers.d/010_sudonp +``` + +> **Important :** Deconnectez-vous et reconnectez-vous pour activer le groupe. + +## Neofetch + MOTD + +```bash +apt install neofetch +``` + +Creer `/etc/neofetch.conf` : + +```bash +print_info() { + info title + info underline + info "OS" distro + info "Host" model + info "Kernel" kernel + info "Uptime" uptime + info "Packages" packages + info "Shell" shell + info "CPU" cpu + info "CPU Usage" cpu_usage + prin "Load" "$(cat /proc/loadavg | awk '{print $1, $2, $3}')" + info "GPU" gpu + info "Memory" memory + info "Disk" disk + info "Local IP" local_ip + info "Public IP" public_ip + info "Users" users + info "Locale" locale + info cols +} + +title_fqdn="on" +memory_percent="on" +memory_unit="mib" +package_managers="on" +image_backend="ascii" +cpu_temp="on" +``` + +Creer `/etc/update-motd.d/20-neofetch` : + +```bash +#!/bin/sh +neofetch --config /etc/neofetch.conf +``` + +```bash +chmod 755 /etc/update-motd.d/20-neofetch +``` + +## Script MOTD mises a jour + +```bash +apt install python3-apt +``` + +Creer `/etc/update-motd.d/30-updates` avec le script Python de detection des mises a jour (voir scripts/setup_motd_updates.py). + +```bash +chmod 755 /etc/update-motd.d/30-updates +``` + +## Installer dselect + +```bash +apt install dselect +``` + +## Ajouter un fichier de swap (4 Go) + +```bash +fallocate -l 4G /swapfile +chmod 600 /swapfile +mkswap /swapfile +swapon /swapfile +echo '/swapfile swap swap defaults 0 0' >> /etc/fstab +echo 'vm.swappiness = 5' >> /etc/sysctl.conf +sysctl -p +``` diff --git a/03-bis-hestiacp.md b/03-bis-hestiacp.md new file mode 100644 index 0000000..6d5302f --- /dev/null +++ b/03-bis-hestiacp.md @@ -0,0 +1,55 @@ +# 3-bis. HestiaCP (Alternative a ISPConfig) + +## Pourquoi HestiaCP ? + +| Aspect | ISPConfig | HestiaCP | +|--------|-----------|----------| +| Interface | Ancienne | Moderne, intuitive | +| Performance | Plus lourd | Plus leger, plus rapide | +| Multi-serveur | Oui | Non | +| Mises a jour | Lentes | Frequentes | +| Communaute | Grande, ancienne | Plus petite, plus active | + +**Recommande pour un seul serveur.** + +## Installation + +```bash +wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh +bash hst-install.sh +``` + +Options recommandees : +- Apache + Nginx (Nginx en proxy) +- MariaDB +- Bind9 +- Exim + Dovecot + ClamAV + SpamAssassin +- Let's Encrypt + +## Configuration post-installation + +L'installeur configure automatiquement : +- Firewall (iptables) +- SSL Let's Encrypt pour le panel +- Bind9 pour DNS +- Mail complet + +## Acces + +``` +https://:8083 +``` + +## Documentation + +- Site : https://hestiacp.com/ +- Docs : https://docs.hestiacp.com/ +- GitHub : https://github.com/hestiacp/hestiacp + +## Differences avec ce guide + +Si vous utilisez HestiaCP, les sections DNS, Mail, et Sites Web seront differentes dans l'interface mais les concepts restent les memes : +- Creer une zone DNS avec les templates +- Creer un site web avec SSL Let's Encrypt +- Creer un domaine mail avec DKIM/DMARC +- Les services Docker (Portainer, Wireguard, etc.) restent identiques diff --git a/03-ispconfig.md b/03-ispconfig.md new file mode 100644 index 0000000..dbfce18 --- /dev/null +++ b/03-ispconfig.md @@ -0,0 +1,67 @@ +# 3. ISPConfig + +## Installation + +```bash +wget -O - https://get.ispconfig.org | sh -s -- --use-ftp-ports=40110-40210 --unattended-upgrades +``` + +> **Important :** Notez les identifiants admin et le mot de passe MySQL root affiches a la fin. + +## Resoudre les conflits + +Si Apache ne demarre pas, verifier si un autre service occupe le port 80 : + +```bash +ss -tlnp | grep ':80' +``` + +Si c'est Caddy ou Nginx : + +```bash +systemctl stop caddy && systemctl disable caddy +systemctl restart apache2 +``` + +## Desactiver UFW + +ISPConfig gere le firewall via iptables. Ne pas utiliser UFW en parallele. + +```bash +ufw disable +``` + +## Configurer le firewall ISPConfig + +Dans ISPConfig > **System > Firewall** : + +**Open TCP ports :** +``` +20,21,22,25,53,80,110,143,443,465,587,993,995,2812,3306,4190,8080,8081,10000,50022,40110:40210,7880,7881,5349 +``` + +**Open UDP ports :** +``` +53,7882,3478,51820 +``` + +## Configuration initiale ISPConfig + +### Main config +- **System > Main config > Sites :** + - Create subdomains as web site : **Yes** + - Create aliasdomains as web site : **Yes** +- **System > Main config > Mail :** + - Renseigner email et nom administrateur + +### Content Filter (Rspamd) +- **System > Server Config > votre serveur > Mail :** + - Content Filter : **Rspamd** + +## Acces + +``` +https://:8080 +``` + +> **Piege :** Certains hebergeurs (Contabo) bloquent le port 8080 au niveau firewall externe. Verifier l'acces et debloquer si necessaire. diff --git a/04-dns.md b/04-dns.md new file mode 100644 index 0000000..4668c57 --- /dev/null +++ b/04-dns.md @@ -0,0 +1,92 @@ +# 4. DNS + +## Templates DNS + +Creer deux templates dans ISPConfig > **DNS > DNS Templates** : + +### Template IPV4 autoNS + +**Fields :** Domain, IP Address, Email, DKIM, DNSSEC + +``` +[ZONE] +origin={DOMAIN}. +ns=ns1.. +mbox={EMAIL}. +refresh=7200 +retry=540 +expire=604800 +minimum=3600 +ttl=3600 + +[DNS_RECORDS] +A|{DOMAIN}.|{IP}|0|3600 +A|www|{IP}|0|3600 +A|mail|{IP}|0|3600 +A|autoconfig|{IP}|0|3600 +A|autodiscover|{IP}|0|3600 +A|webmail|{IP}|0|3600 +CNAME|ftp|{DOMAIN}|0|3600 +CNAME|smtp|{DOMAIN}|0|3600 +CNAME|pop3|{DOMAIN}|0|3600 +CNAME|imap|{DOMAIN}|0|3600 +NS|{DOMAIN}.|ns1..|0|3600 +NS|{DOMAIN}.|ns2..|0|3600 +MX|{DOMAIN}.|mail.{DOMAIN}.|10|3600 +TXT|{DOMAIN}.|v=spf1 mx a ~all|0|3600 +SRV|_imaps._tcp|0 1 993 mail.{DOMAIN}|0|3600 +SRV|_submission._tcp|0 1 465 mail.{DOMAIN}|0|3600 +``` + +### Template IPV6 autoNS + +Meme chose que IPV4 + ajout des AAAA : + +**Fields :** Domain, IP Address, IPv6 Address, Email, DKIM, DNSSEC + +Ajouter dans [DNS_RECORDS] : +``` +AAAA|{DOMAIN}.|{IPV6}|0|3600 +AAAA|www|{IPV6}|0|3600 +AAAA|mail|{IPV6}|0|3600 +AAAA|autoconfig|{IPV6}|0|3600 +AAAA|autodiscover|{IPV6}|0|3600 +AAAA|webmail|{IPV6}|0|3600 +``` + +> **Important :** Les NS pointent vers `ns1.` (votre domaine principal), pas `ns1.{DOMAIN}`. Cela evite les problemes de glue records pour les domaines heberges. + +## Creer une zone DNS + +ISPConfig > **DNS > Add DNS Zone > DNS Wizard** + +- Template : Template IPV6 autoNS +- Domain : `` +- IP : `` +- IPv6 : `` +- Email : votre email +- DKIM : cocher +- DNSSEC : decocher (activer plus tard) + +## Configurer les NS chez le registrar + +### OVH + +1. Creer les glue records : `ns1.` et `ns2.` -> `` +2. Changer les nameservers vers `ns1.` et `ns2.` + +> **Note :** OVH verifie que Bind9 repond avant d'accepter. Creer la zone DNS dans ISPConfig d'abord. + +### Domaines .ci (MTN/Cloud4Africa) + +Pointer les NS vers le domaine serveur principal : +- `ns1.` +- `ns2.` + +## Verification + +```bash +dig @8.8.8.8 NS +short +dig @8.8.8.8 A +short +dig @8.8.8.8 mail. A +short +``` diff --git a/05-webmin.md b/05-webmin.md new file mode 100644 index 0000000..066c495 --- /dev/null +++ b/05-webmin.md @@ -0,0 +1,87 @@ +# 5. Webmin + +## Installation + +```bash +curl -o setup-repos.sh https://raw.githubusercontent.com/webmin/webmin/master/setup-repos.sh +sh setup-repos.sh +rm setup-repos.sh +apt update && apt install webmin +``` + +## Configurer le compte admin + +Remplacer `root` par `` dans : +- `/etc/webmin/miniserv.users` +- `/etc/webmin/webmin.acl` + +```bash +sed -i 's/root:/:/' /etc/webmin/miniserv.users +sed -i 's/root:/:/' /etc/webmin/webmin.acl +service webmin restart +``` + +## Desactiver SSL natif (utiliser proxy Apache) + +Webmin a des problemes avec SSL sur certaines versions. Utiliser un proxy Apache : + +```bash +sed -i 's/ssl=1/ssl=0/' /etc/webmin/miniserv.conf +``` + +Ajouter dans `/etc/webmin/config` : +``` +webprefixnoredir=1 +relative_redir=1 +``` + +Ajouter dans `/etc/webmin/miniserv.conf` : +``` +referers=webmin. +redirect_port=443 +redirect_ssl=1 +``` + +```bash +systemctl restart webmin +``` + +## Creer le sous-domaine + +1. DNS : A record `webmin` -> `` +2. ISPConfig > Sites > Subdomain (vhost) : + - Hostname : `webmin` + - Domain : `` + - Web folder : `webmin` + - SSL + Let's Encrypt + - Rewrite HTTP to HTTPS + +3. Apache Directives : +```apache + +Order deny,allow +Allow from all + + +ProxyRequests Off +ProxyPass /stats ! +ProxyPass /.well-known/acme-challenge ! + +SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 +ProxyPreserveHost On + +ProxyPass / http://localhost:10000/ +ProxyPassReverse / http://localhost:10000/ + +RedirectMatch ^/$ https://webmin. +``` + +## Ajouter le port au firewall + +ISPConfig > System > Firewall : ajouter `10000` aux TCP ports. + +## Acces + +``` +https://webmin. +``` diff --git a/06-monitoring.md b/06-monitoring.md new file mode 100644 index 0000000..cc2ea71 --- /dev/null +++ b/06-monitoring.md @@ -0,0 +1,163 @@ +# 6. Monitoring + +## Munin + +### Installation + +```bash +apt install libcgi-fast-perl libapache2-mod-fcgid +a2enmod fcgid +apt install munin munin-node munin-plugins-extra logtail libcache-cache-perl +``` + +### Plugins MySQL + +```bash +cd /etc/munin/plugins +ln -s /usr/share/munin/plugins/mysql_ mysql_ +ln -s /usr/share/munin/plugins/mysql_bytes mysql_bytes +ln -s /usr/share/munin/plugins/mysql_innodb mysql_innodb +ln -s /usr/share/munin/plugins/mysql_isam_space_ mysql_isam_space_ +ln -s /usr/share/munin/plugins/mysql_queries mysql_queries +ln -s /usr/share/munin/plugins/mysql_slowqueries mysql_slowqueries +ln -s /usr/share/munin/plugins/mysql_threads mysql_threads +``` + +### Base de donnees Munin + +```sql +CREATE SCHEMA munin_innodb; +USE munin_innodb; +CREATE TABLE something (anything int) ENGINE=InnoDB; +GRANT SELECT ON munin_innodb.* TO 'munin'@'localhost' IDENTIFIED BY 'munin'; +FLUSH PRIVILEGES; +``` + +### Configuration + +Editer `/etc/munin/munin.conf` : +- Decommenter `dbdir`, `htmldir`, `logdir`, `rundir`, `tmpldir` +- Remplacer `[localhost.localdomain]` par `[munin.]` + +### Apache auth + +```bash +a2enconf munin +htpasswd -c /etc/munin/munin-htpasswd admin +``` + +Editer `/etc/apache2/conf-enabled/munin.conf` avec auth basic (voir scripts/setup_munin_config.py). + +### Auto-configure plugins + +```bash +cd /etc/munin/plugins +munin-node-configure --shell --families=contrib,auto | sh -x +service munin-node restart +service apache2 restart +``` + +## Monit + +### Installation + +```bash +apt install monit +``` + +### Configuration + +Creer `/etc/monit/conf.d/monitrc.local` : + +``` +set daemon 60 +set logfile syslog facility log_daemon +set mailserver localhost +set mail-format { from: monit@ } +set alert +set httpd port 2812 and + SSL ENABLE + PEMFILE /usr/local/ispconfig/interface/ssl/ispserver.pem + allow admin:"" +``` + +### Fichiers de monitoring + +Creer dans `/etc/monit/conf-enabled/` les fichiers pour : mariadb, pureftpd, named, sshd, apache2, memcached, ntpd, dovecot, postfix, redis. + +Voir `scripts/setup_monit.py` pour le script complet. + +```bash +mkdir /var/www/html/monit +echo "hello" > /var/www/html/monit/token +service apache2 restart +service monit restart +``` + +Ajouter port 2812 au firewall ISPConfig. + +## Grafana + Prometheus + +### Installation + +```bash +echo "deb https://packages.grafana.com/oss/deb stable main" >> /etc/apt/sources.list.d/grafana.list +cd /etc/apt/trusted.gpg.d && wget https://packages.grafana.com/gpg.key -O grafana.asc +apt update +apt install grafana prometheus prometheus-mysqld-exporter prometheus-apache-exporter prometheus-bind-exporter prometheus-process-exporter +``` + +### Configurer Grafana sur port 3100 + +Editer `/etc/grafana/grafana.ini` : +```ini +http_port = 3100 +``` + +### Configurer Prometheus + +Editer `/etc/prometheus/prometheus.yml` — ajouter les jobs : prometheus, node, dns-master, apache, process, mysql. + +> **Piege :** Ne pas dupliquer les jobs (erreur "found multiple scrape configs with job name"). + +### Sous-domaine Grafana + +DNS A `grafana` -> ``, puis sous-domaine ISPConfig avec proxy vers `http://localhost:3100/`. + +### Demarrer + +```bash +systemctl enable grafana-server && systemctl start grafana-server +service prometheus restart +``` + +Login par defaut : **admin / admin** + +## Loki + Promtail + +### Loki + +```bash +cd /usr/local/bin +# Telecharger la derniere version depuis https://github.com/grafana/loki/releases/ +wget -O loki.zip +unzip loki.zip && mv loki-linux-amd64 loki && chmod 755 loki && rm loki.zip +``` + +Creer `/etc/config-loki.yml` et `/etc/systemd/system/loki.service`. + +> **Piege :** Loki v3 a un format de config different de v2. Utiliser `schema: v13` et `store: tsdb`. + +### Promtail + +```bash +# Promtail n'existe plus dans Loki v3, utiliser la derniere v2 +wget https://github.com/grafana/loki/releases/download/v2.9.10/promtail-linux-amd64.zip -O promtail.zip +unzip promtail.zip && mv promtail-linux-amd64 promtail && chmod 755 promtail && rm promtail.zip +``` + +Creer `/etc/config-promtail.yml` et `/etc/systemd/system/promtail.service`. + +### Ajouter Loki dans Grafana + +Configuration > Data Sources > Add > Loki > URL : `http://127.0.0.1:3101` diff --git a/07-mail.md b/07-mail.md new file mode 100644 index 0000000..3407c5c --- /dev/null +++ b/07-mail.md @@ -0,0 +1,151 @@ +# 7. Mail + +## Desactiver amavisd + +```bash +systemctl stop amavisd-new 2>/dev/null +systemctl disable amavisd-new 2>/dev/null +``` + +## Configurer Rspamd + +Voir `scripts/setup_rspamd.py` pour le script complet. Fichiers crees : + +- `/etc/rspamd/local.d/classifier-bayes.conf` — apprentissage Bayes + Redis +- `/etc/rspamd/local.d/redis.conf` — serveur Redis +- `/etc/rspamd/local.d/metrics.conf` — seuils spam +- `/etc/rspamd/local.d/history_redis.conf` — historique +- `/etc/rspamd/local.d/url_reputation.conf` — reputation URLs +- `/etc/rspamd/local.d/mx_check.conf` — verification MX +- `/etc/rspamd/local.d/neural.conf` — reseau de neurones +- `/etc/rspamd/local.d/neural_group.conf` — groupes neurones +- `/etc/rspamd/local.d/milter_headers.conf` — headers spam +- `/etc/rspamd/local.d/arc.conf` — protocole ARC +- `/etc/rspamd/local.d/antivirus.conf` — ClamAV +- `/etc/rspamd/local.d/groups.conf` — groupes antivirus +- `/etc/rspamd/local.d/antivirus_group.conf` — detection virus + +```bash +a2enmod proxy +systemctl restart apache2 +systemctl restart rspamd +``` + +## Dovecot Sieve (apprentissage spam/ham) + +Voir `scripts/setup_dovecot_sieve.py`. Configure : +- Deplacement vers Junk = apprend comme spam +- Deplacement depuis Junk = apprend comme ham +- Quota warning a 90% + +Installer les plugins necessaires : +```bash +apt install dovecot-sieve dovecot-managesieved +``` + +## Creer le domaine mail + +ISPConfig > **Email > Domain > Add new Domain** +- Domain : `` +- Enable DKIM : cocher +- Generate DKIM Private-key + +## Ajouter DMARC + +ISPConfig > DNS > Zones > `` > Records > TXT : +- Hostname : `_dmarc` +- Text : `v=DMARC1;p=reject;sp=quarantine;pct=100;rua=mailto:` + +## Verifier SPF + +Doit deja exister (cree par le template) : +``` +TXT . v=spf1 mx a ~all +``` + +## Configurer Postfix + +```bash +# Verifier dans /etc/postfix/main.cf : +myhostname = mail. +``` + +## Sous-domaine webmail (Roundcube) + +1. DNS A `mail` -> `` +2. ISPConfig > Sites > Subdomain (vhost) : `mail.` +3. Apache Directives : + +```apache + +Order deny,allow +Allow from all + + +ProxyRequests Off +ProxyPass /stats ! +ProxyPass /.well-known/acme-challenge ! + +SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 +SSLProxyEngine On +ProxyPreserveHost On +SSLProxyVerify none +SSLProxyCheckPeerCN off +SSLProxyCheckPeerName off +SSLProxyCheckPeerExpire off + +ProxyPass /webmail https://localhost:8080/webmail/ +ProxyPass / https://localhost:8080/webmail/ +ProxyPassReverse / https://localhost:8080/webmail/ + +RedirectMatch ^/$ https://mail. +``` + +## Sous-domaine Rspamd + +Meme principe avec proxy vers `https://:8081/rspamd/`. + +## Autoconfig (Thunderbird/Android) + +1. Sous-domaine `autoconfig.` avec Apache Directives : + +```apache + + SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost" + + + + SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost" + + +AddHandler application/x-httpd-php .php .xml .json + + + CheckCaseOnly on + CheckSpelling on + +``` + +2. Creer le fichier `autoconfig/mail/config-v1.1.xml` (voir scripts/setup_autoconfig.py) + +3. Mettre a jour PHP-FPM : ajouter `.xml .json` dans `security.limit_extensions` + +## Autodiscover (Outlook) + +Meme sous-domaine pointant vers le meme dossier `autoconfig`. Creer `autoconfig/Autodiscover/Autodiscover.xml`. + +## Creer une boite mail + +ISPConfig > **Email > Email Mailbox > Add new Mailbox** + +## Tester l'envoi + +```bash +echo "Test" | mail -s "Test" -r contact@ votre@email.com +``` + +## MAILER_DSN pour Symfony + +``` +MAILER_DSN=smtp://127.0.0.1:25?auto_tls=false +``` diff --git a/08-sni-mail.md b/08-sni-mail.md new file mode 100644 index 0000000..06ca18c --- /dev/null +++ b/08-sni-mail.md @@ -0,0 +1,78 @@ +# 8. SNI Mail Multi-Domaines + +## Probleme + +Par defaut, Dovecot/Postfix servent un seul certificat SSL pour tous les domaines mail. Les clients (iPhone, Gmail app) refusent la connexion si le certificat ne correspond pas au serveur configure. + +## Solution : SNI (Server Name Indication) + +### Dovecot SNI + +Editer `/etc/dovecot/dovecot.conf`, apres la ligne `ssl_prefer_server_ciphers = no` ajouter : + +``` +# SNI per domain +local_name mail. { + ssl_cert = -le.crt + ssl_key = -le.key +} + +local_name mail. { + ssl_cert = -le.crt + ssl_key = -le.key +} +``` + +> **Piege :** Ne pas mettre le SNI dans `conf.d/10-ssl.conf` — ISPConfig ou le `dovecot.conf` principal ecrase les valeurs. Toujours ajouter directement dans `dovecot.conf`. + +### Trouver les certificats + +ISPConfig stocke les certificats LE dans le dossier SSL du site : +```bash +find /var/www/clients/ -name "mail.-le.*" +``` + +Format : `/var/www/clients/clientX/webY/ssl/mail.-le.crt` et `.key` + +### Postfix SNI + +Creer `/etc/postfix/sni_map` : + +``` +mail. /chemin/vers/mail.-le.key /chemin/vers/mail.-le.crt +mail. /chemin/vers/mail.-le.key /chemin/vers/mail.-le.crt +``` + +```bash +postmap -F hash:/etc/postfix/sni_map +``` + +Ajouter dans `/etc/postfix/main.cf` : +``` +tls_server_sni_maps = hash:/etc/postfix/sni_map +``` + +### Redemarrer + +```bash +systemctl restart dovecot +systemctl restart postfix +``` + +### Verification + +```bash +echo | openssl s_client -connect :993 -servername mail. 2>&1 | grep "subject=" +# Doit afficher : subject=CN = mail. + +echo | openssl s_client -connect :993 -servername mail. 2>&1 | grep "subject=" +# Doit afficher : subject=CN = mail. +``` + +## Certificat par defaut ISPConfig + +Le certificat dans `/usr/local/ispconfig/interface/ssl/ispserver.crt` est utilise pour : +- ISPConfig panel (port 8080) +- Dovecot/Postfix par defaut (quand SNI ne match pas) + +Garder le certificat du domaine principal du serveur (``) comme defaut. diff --git a/09-docker.md b/09-docker.md new file mode 100644 index 0000000..0b787b9 --- /dev/null +++ b/09-docker.md @@ -0,0 +1,102 @@ +# 9. Docker + +## Installation + +Si Docker n'est pas deja installe : + +```bash +apt-get update +apt-get install ca-certificates curl +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc +chmod a+r /etc/apt/keyrings/docker.asc + +echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null + +apt update +apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin +``` + +Verifier : +```bash +docker run hello-world +``` + +## Docker Swarm + +```bash +docker swarm init +docker node ls +``` + +## Portainer + +1. DNS A `portainer` -> `` +2. Sous-domaine ISPConfig `portainer.` avec proxy : + +```apache + +Order deny,allow +Allow from all + + +ProxyRequests Off +ProxyPass /stats ! +ProxyPass /.well-known/acme-challenge ! + +SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 +ProxyPreserveHost On + +ProxyPass / http://localhost:9050/ +ProxyPassReverse / http://localhost:9050/ + +RedirectMatch ^/$ https://portainer. +``` + +3. Installer : + +```bash +docker volume create portainer_data +docker run -d -p 9050:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest +``` + +4. Acceder : `https://portainer.` — creer le compte admin. + +## Yacht + +1. DNS A `yacht` -> `` +2. Sous-domaine ISPConfig avec proxy vers `http://localhost:8061/` + +3. Installer : + +```bash +docker volume create yacht_data +docker run -d -p 8061:8000 --name=yacht -v /var/run/docker.sock:/var/run/docker.sock --restart=always -v yacht_data:/config selfhostedpro/yacht +``` + +4. Login par defaut : `admin@yacht.local` / `pass` — changer immediatement. + +## Modele Apache Directives pour proxy Docker + +Pour tous les services Docker accessibles via sous-domaine : + +```apache + +Order deny,allow +Allow from all + + +ProxyRequests Off +ProxyPass /stats ! +ProxyPass /.well-known/acme-challenge ! + +SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 +ProxyPreserveHost On + +ProxyPass / http://localhost:/ +ProxyPassReverse / http://localhost:/ + +RedirectMatch ^/$ https://. +``` + +> **Piege :** Apres creation du sous-domaine, supprimer le fichier `standard_index.html` si la page par defaut ISPConfig s'affiche. Aussi verifier que SSL/Let's Encrypt est bien coche. diff --git a/10-services-docker.md b/10-services-docker.md new file mode 100644 index 0000000..d6d3ade --- /dev/null +++ b/10-services-docker.md @@ -0,0 +1,93 @@ +# 10. Services Docker + +## Wireguard (VPN) + +1. DNS A `wireguard` -> `` +2. Sous-domaine ISPConfig avec proxy vers `http://localhost:51821/` +3. Ouvrir port 51820/udp dans firewall ISPConfig + +4. Generer le hash du mot de passe : +```bash +docker run --rm python:3-alpine sh -c "pip install bcrypt -q && python3 -c \"import bcrypt; print(bcrypt.hashpw(b'', bcrypt.gensalt()).decode())\"" +``` + +5. Installer (en une ligne, remplacer le hash) : +```bash +docker run -d --name=wg-easy -e LANG=fr -e WG_HOST= -e "PASSWORD_HASH=" -e PORT=51821 -e WG_PORT=51820 -v /etc/wg-easy:/etc/wireguard -p 51820:51820/udp -p 51821:51821/tcp --cap-add=NET_ADMIN --cap-add=SYS_MODULE --sysctl="net.ipv4.conf.all.src_valid_mark=1" --sysctl="net.ipv4.ip_forward=1" --restart unless-stopped ghcr.io/wg-easy/wg-easy +``` + +> **Piege :** Les versions recentes de wg-easy exigent `PASSWORD_HASH` (bcrypt) au lieu de `PASSWORD`. + +## Vaultwarden (gestionnaire de mots de passe) + +1. DNS A `vaultwarden` -> `` +2. Sous-domaine ISPConfig avec proxy vers `http://localhost:1280/` + +3. Generer le hash admin : +```bash +echo -n "" | argon2 "$(openssl rand -base64 32)" -e -id -k 19456 -t 2 -p 1 +``` + +4. Installer (echapper les `$` du hash avec `\$`) : +```bash +docker volume create vaultwarden_data +docker run -d -p 1280:80 --name=vaultwarden --restart=always -v vaultwarden_data:/data:rw -e ROCKET_ENV=staging -e ROCKET_PORT=80 -e ROCKET_WORKERS=10 -e SMTP_HOST=127.0.0.1 -e SMTP_FROM=vaultwarden@ -e SMTP_PORT=25 -e SMTP_SECURITY=off -e WEBSOCKET_ENABLED=true -e "ADMIN_TOKEN=" -e SIGNUPS_ALLOWED=false -e DOMAIN=https://vaultwarden. vaultwarden/server:latest +``` + +5. Activer temporairement les inscriptions via `/admin`, creer son compte, desactiver. + +## Heimdall (dashboard) + +1. DNS A `heimdall` -> `` +2. Sous-domaine ISPConfig avec proxy HTTPS vers `https://localhost:1281/` + +```apache +SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 +SSLProxyEngine On +ProxyPreserveHost On +SSLProxyVerify none +SSLProxyCheckPeerCN off +SSLProxyCheckPeerName off +SSLProxyCheckPeerExpire off + +ProxyPass / https://localhost:1281/ +ProxyPassReverse / https://localhost:1281/ +``` + +3. Installer : +```bash +docker volume create heimdall_data +docker run -d -p 1281:443 --name=heimdall --restart=always -v heimdall_data:/config:rw -e PGID=1000 -e PUID=1000 linuxserver/heimdall +``` + +## Guacamole (bureau a distance) + +1. DNS A `guacamole` -> `` +2. Creer base de donnees `guacamole` dans ISPConfig +3. Sous-domaine ISPConfig avec proxy : + +```apache +ProxyPass /guacamole http://localhost:8085/guacamole +ProxyPassReverse /guacamole http://localhost:8085/guacamole +RedirectMatch ^/$ https://guacamole./guacamole +``` + +4. Installer : +```bash +docker run -d --name guacamole-guacd --restart=always guacamole/guacd +docker run -d --name guacamole-web --restart=always --link guacamole-guacd:guacd -e MYSQL_HOSTNAME=172.17.0.1 -e MYSQL_PORT=3306 -e MYSQL_DATABASE= -e MYSQL_USER= -e MYSQL_PASSWORD= -p 8085:8080 guacamole/guacamole +``` + +5. Importer le schema : +```bash +docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql | mysql -u root +``` + +6. Autoriser l'acces depuis Docker : +```bash +mysql -u root -e "GRANT ALL PRIVILEGES ON .* TO ''@'172.17.0.%' IDENTIFIED BY ''; FLUSH PRIVILEGES;" +``` + +7. Login par defaut : `guacadmin` / `guacadmin` — creer un admin et supprimer guacadmin. + +> **Piege :** Tomcat 10 natif est incompatible avec Guacamole 1.5.5. Utiliser Docker a la place. diff --git a/11-applications.md b/11-applications.md new file mode 100644 index 0000000..62b800e --- /dev/null +++ b/11-applications.md @@ -0,0 +1,115 @@ +# 11. Applications Web + +## Wordpress + +1. DNS A `wordpress` -> `` +2. Sous-domaine ISPConfig `wordpress.` (SSL, LE, PHP-FPM, HTTPS redirect) +3. Creer base de donnees `wordpress` (user + database dans ISPConfig) +4. Identifier le proprietaire : +```bash +ls -la /var/www/wordpress./ | head -5 +# Noter webX:clientY +``` + +5. Installer : +```bash +cd /tmp +wget -O wordpress.tar.gz https://wordpress.org/latest.tar.gz +tar -xzf wordpress.tar.gz +mv wordpress/* /var/www/wordpress./wordpress/ +rm wordpress.tar.gz && rm -rf wordpress +chown -R webX:clientY /var/www/wordpress./wordpress/ +``` + +6. Acceder : `https://wordpress.` et suivre l'assistant. + +> **Piege :** Si la page par defaut ISPConfig s'affiche, verifier que SSL/LE est coche. Supprimer `standard_index.html` si present. + +## Nextcloud + +1. Installer les prerequis PHP : +```bash +apt install php-cgi php-curl +``` + +2. Modifier `/etc/php/8.3/fpm/php.ini` : +```ini +memory_limit = 512M +upload_max_filesize = 500M +post_max_size = 500M +max_execution_time = 300 +``` + +3. DNS A `nextcloud` -> `` +4. Sous-domaine ISPConfig (SSL, LE, PHP-FPM, HTTPS redirect, Webstatistics: None) +5. Creer base de donnees `nextcloud` + +6. Telecharger l'installeur : +```bash +wget -O /var/www/nextcloud./nextcloud/setup-nextcloud.php https://download.nextcloud.com/server/installer/setup-nextcloud.php +chown webX:clientY /var/www/nextcloud./nextcloud/setup-nextcloud.php +``` + +7. Acceder : `https://nextcloud./setup-nextcloud.php` + - Repertoire : `.` + - Choisir MariaDB, renseigner la base + +## Gitea + +1. DNS A `gitea` -> `` +2. Sous-domaine ISPConfig avec proxy vers `http://localhost:3000/` +3. Creer base de donnees `gitea` + +4. Installer : +```bash +# Creer l'utilisateur +adduser --system --disabled-password --group --shell /bin/bash --home /home/gitea gitea + +# Repertoires +mkdir -p /var/lib/gitea/{data,log} /etc/gitea /run/gitea +chown -R gitea:gitea /var/lib/gitea /run/gitea +chown -R root:gitea /etc/gitea +chmod -R 750 /var/lib/gitea +chmod 770 /etc/gitea + +# Telecharger (derniere version) +VERSION=$(wget -qO- https://api.github.com/repos/go-gitea/gitea/releases/latest | grep tag_name | cut -d'"' -f4 | tr -d v) +wget "https://dl.gitea.com/gitea/${VERSION}/gitea-${VERSION}-linux-amd64" -O /usr/local/bin/gitea +chmod 755 /usr/local/bin/gitea +``` + +5. Creer `/etc/systemd/system/gitea.service` : +```ini +[Unit] +Description=Gitea (Git with a cup of tea) +After=syslog.target +After=network.target +Requires=mysqld.service +[Service] +Type=simple +User=gitea +Group=gitea +WorkingDirectory=/var/lib/gitea/ +RuntimeDirectory=gitea +ExecStart=/usr/local/bin/gitea web -c /etc/gitea/app.ini +Restart=always +Environment=USER=gitea HOME=/home/gitea GITEA_WORK_DIR=/var/lib/gitea +[Install] +WantedBy=multi-user.target +``` + +```bash +systemctl daemon-reload +systemctl enable gitea.service +systemctl start gitea.service +``` + +6. Acceder : `https://gitea./install` et configurer. + +7. Securiser apres installation : +```bash +chmod 750 /etc/gitea +chown root:gitea /etc/gitea/app.ini +chmod 640 /etc/gitea/app.ini +systemctl restart gitea +``` diff --git a/12-backup.md b/12-backup.md new file mode 100644 index 0000000..dc4a66e --- /dev/null +++ b/12-backup.md @@ -0,0 +1,100 @@ +# 12. Backup Rsync + +## Prerequis + +- Serveur de stockage distant avec acces SSH +- Cle SSH configuree pour l'acces sans mot de passe + +## Configurer l'acces SSH + +```bash +# Copier la cle SSH de l'utilisateur vers root (le script tourne en root via cron) +mkdir -p /root/.ssh +cp /home//.ssh/id_* /root/.ssh/ +cp /home//.ssh/known_hosts /root/.ssh/ +``` + +Tester : +```bash +ssh -p @ "echo OK" +``` + +## Creer la config + +Creer `/etc/vps-backup.env` : + +```bash +REMOTE_USER= +REMOTE_HOST= +REMOTE_PORT= +REMOTE_BASE=/backups +DB_BACKUP_DIR=/tmp/vps-db-backup +``` + +```bash +chmod 600 /etc/vps-backup.env +``` + +## Creer les repertoires distants + +```bash +ssh -p @ "mkdir -p /backups/{db,etc,ispconfig,www}" +``` + +## Script de backup + +Creer `/usr/local/bin/vps-backup.sh` : + +```bash +#!/bin/bash + +source /etc/vps-backup.env + +DATE=$(date +%Y%m%d_%H%M%S) +LOG="/var/log/vps-backup.log" + +echo "[$DATE] Backup started" >> $LOG + +# Dump databases +mkdir -p $DB_BACKUP_DIR +rm -f $DB_BACKUP_DIR/*.sql.gz $DB_BACKUP_DIR/*.tar.gz + +for DB in $(mysql -N -e "SHOW DATABASES" | grep -v -E "^(information_schema|performance_schema|sys)$"); do + mysqldump --single-transaction --routines --triggers "$DB" | gzip > "$DB_BACKUP_DIR/${DB}.sql.gz" +done + +# Compresser en tar +tar -czf "$DB_BACKUP_DIR/all-databases-${DATE}.tar.gz" -C $DB_BACKUP_DIR --exclude="*.tar.gz" . || true +rm -f $DB_BACKUP_DIR/*.sql.gz + +# Sync +rsync -avz -e "ssh -p $REMOTE_PORT" $DB_BACKUP_DIR/*.tar.gz $REMOTE_USER@$REMOTE_HOST:$REMOTE_BASE/db/ || echo "[$DATE] DB sync failed" >> $LOG +rsync -avz --delete -e "ssh -p $REMOTE_PORT" /etc/ $REMOTE_USER@$REMOTE_HOST:$REMOTE_BASE/etc/ || echo "[$DATE] etc sync failed" >> $LOG +rsync -avz --delete -e "ssh -p $REMOTE_PORT" /usr/local/ispconfig/ $REMOTE_USER@$REMOTE_HOST:$REMOTE_BASE/ispconfig/ || echo "[$DATE] ispconfig sync failed" >> $LOG +rsync -avz --delete -e "ssh -p $REMOTE_PORT" /var/www/ $REMOTE_USER@$REMOTE_HOST:$REMOTE_BASE/www/ || echo "[$DATE] www sync failed" >> $LOG + +rm -rf $DB_BACKUP_DIR + +DATE_END=$(date +%Y%m%d_%H%M%S) +echo "[$DATE_END] Backup completed" >> $LOG +``` + +```bash +chmod 755 /usr/local/bin/vps-backup.sh +``` + +## Cron quotidien + +```bash +crontab -e +# Ajouter : +0 2 * * * /usr/local/bin/vps-backup.sh +``` + +## Tester + +```bash +sudo /usr/local/bin/vps-backup.sh +``` + +> **Piege :** Le script tourne en root via cron. La cle SSH de root doit etre configuree pour l'acces distant. diff --git a/13-securite.md b/13-securite.md new file mode 100644 index 0000000..b796cc3 --- /dev/null +++ b/13-securite.md @@ -0,0 +1,122 @@ +# 13. Securite + +## Certificats Let's Encrypt pour les outils + +### ISPConfig + +Les certificats sont dans `/var/www/clients/clientX/webY/ssl/-le.crt` et `.key`. + +```bash +SSL_DIR="/var/www/clients/client1/web7/ssl" +ISP_SSL="/usr/local/ispconfig/interface/ssl" + +cp $SSL_DIR/-le.crt $ISP_SSL/ispserver.crt +cp $SSL_DIR/-le.key $ISP_SSL/ispserver.key + +# Creer PEM (cert + key) +cat $ISP_SSL/ispserver.crt $ISP_SSL/ispserver.key > $ISP_SSL/ispserver.pem + +systemctl restart apache2 +``` + +### Postfix / Dovecot + +Les certificats sont automatiquement utilises via le PEM ISPConfig. Pour le SNI multi-domaines, voir [08-sni-mail.md](08-sni-mail.md). + +## phpMyAdmin securise + +### Changer l'URL et ajouter HTTP Auth + +1. Desactiver l'alias global : +```bash +a2disconf phpmyadmin +``` + +2. DNS A `dbmanage` -> `` +3. Sous-domaine ISPConfig `dbmanage.` (SSL, LE, PHP-FPM, HTTPS redirect) +4. Apache Directives : + +```apache +Alias / /usr/share/phpmyadmin/ + + + Options SymLinksIfOwnerMatch + DirectoryIndex index.php + + AuthType Basic + AuthName "Database Management - Restricted Access" + AuthUserFile /etc/phpmyadmin/htpasswd.setup + Require valid-user + + + php_admin_value upload_tmp_dir /var/lib/phpmyadmin/tmp + php_admin_value open_basedir /usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/:/usr/share/php/:/usr/share/javascript/ + + + + + Require all denied + + + + Require all denied + + + + Require all denied + +``` + +5. Creer le mot de passe HTTP Auth : +```bash +htpasswd -c /etc/phpmyadmin/htpasswd.setup admin +``` + +### Fail2ban pour phpMyAdmin + +Creer `/etc/fail2ban/filter.d/phpmyadmin.conf` : +``` +[Definition] +failregex = ^ -.*"(GET|POST).*/dbmanage.* + user denied.*client: +ignoreregex = +``` + +Creer `/etc/fail2ban/jail.d/phpmyadmin.conf` : +``` +[phpmyadmin] +enabled = true +port = http,https +filter = phpmyadmin +logpath = /var/log/apache2/access.log +maxretry = 5 +bantime = 3600 +findtime = 600 +``` + +```bash +systemctl restart fail2ban +``` + +### Creer un admin DB + +```bash +mysql -u root -e "CREATE USER 'dbadmin'@'localhost' IDENTIFIED BY ''; GRANT ALL PRIVILEGES ON *.* TO 'dbadmin'@'localhost' WITH GRANT OPTION; FLUSH PRIVILEGES;" +``` + +## DNSSEC + +### Activer dans ISPConfig + +DNS > Zones > `` > Zone settings > Sign Zone (DNSSEC) > Save + +Recuperer les DS-Data affiches. + +### Ajouter chez le registrar + +**OVH :** DS Records > Ajouter +- Key tag, Algorithm 13, Digest type 2 (SHA-256), Digest + +> **Piege OVH :** OVH peut retourner "Error while checking DNSKEYS" avec des NS personnalises. Retenter ou contacter le support. + +**MTN (.ci) :** Envoyer les DS records au support car l'interface bug. diff --git a/14-deploiement-symfony.md b/14-deploiement-symfony.md new file mode 100644 index 0000000..bb03e4d --- /dev/null +++ b/14-deploiement-symfony.md @@ -0,0 +1,86 @@ +# 14. Deploiement Symfony + +## Creer le site dans ISPConfig + +1. DNS A `` -> `` (ou zone DNS dediee) +2. Site web ISPConfig : `` (SSL, LE, PHP-FPM, HTTPS redirect) +3. Creer base de donnees dans ISPConfig + +## Apache Directives pour Symfony + +Dans l'onglet Options du site : + +```apache +DocumentRoot /var/www//web/public + +/web/public> + AllowOverride All + Require all granted + FallbackResource /index.php + +``` + +## Lien symbolique + +```bash +ln -s /var/www/clients/clientX/webY/web /var/www/ +``` + +## Permissions + +```bash +# Identifier le proprietaire +ls -la /var/www// | head -5 +# Noter webX:clientY + +# Ajouter votre user au groupe client +usermod -a -G clientY + +# Donner l'acces groupe +chmod 750 /var/www/clients/clientX/webY/web + +# ACL pour acces complet +apt install acl +setfacl -R -m u::rwx /var/www/clients/clientX/webY/web +setfacl -R -d -m u::rwx /var/www/clients/clientX/webY/web +``` + +> **Important :** Apres connexion SSH, executer `newgrp clientY` pour activer le groupe. + +## Cloner le projet + +```bash +git clone git@github.com:.git /tmp/ +cp -r /tmp//. /var/www/clients/clientX/webY/web/ +chown -R webX:clientY /var/www/clients/clientX/webY/web/ +rm -rf /tmp/ +``` + +## Installer les dependances + +```bash +cd /var/www/ +composer install +``` + +## Configuration .env + +```bash +# Base de donnees +DATABASE_URL="mysql://:@localhost:3306/" + +# Mail (Postfix local) +MAILER_DSN=smtp://127.0.0.1:25?auto_tls=false +``` + +## Migrations + +```bash +php bin/console doctrine:migrations:migrate --no-interaction +``` + +## Cache + +```bash +php bin/console cache:clear +``` diff --git a/15-livekit.md b/15-livekit.md new file mode 100644 index 0000000..70ab2f0 --- /dev/null +++ b/15-livekit.md @@ -0,0 +1,109 @@ +# 15. LiveKit (Teleconsultation Video) + +## Prerequis + +- Docker installe +- Sous-domaine pour LiveKit (ex: `video.`) +- Certificats SSL + +## DNS et sous-domaine + +1. DNS A `video` -> `` (dans la zone du projet) +2. Sous-domaine ISPConfig `video.` (SSL, LE, PHP-FPM) + +## Ports firewall + +ISPConfig > System > Firewall, ajouter : +- TCP : `7880,7881,5349` +- UDP : `7882,3478` + +## Recuperer les certificats + +```bash +# Trouver les certificats generes par ISPConfig +find /var/www/clients/ -name "video.-le.*" + +# Copier +mkdir -p /chemin/projet/docker/livekit/certs +cp /var/www/clients/clientX/webY/ssl/video.-le.crt /chemin/projet/docker/livekit/certs/fullchain.pem +cp /var/www/clients/clientX/webY/ssl/video.-le.key /chemin/projet/docker/livekit/certs/privkey.pem +chown -R : /chemin/projet/docker/livekit/certs/ +``` + +> **Piege :** Verifier que la cle privee correspond au certificat : +> ```bash +> openssl x509 -noout -pubkey -in certs/fullchain.pem | md5sum +> openssl ec -pubout -in certs/privkey.pem 2>/dev/null | md5sum +> # Les deux md5 doivent etre identiques +> ``` + +## Configuration + +### .env + +```bash +LIVEKIT_API_KEY= +LIVEKIT_API_SECRET= +TZ=Africa/Abidjan +LIVEKIT_CPU_LIMIT=2.0 +LIVEKIT_MEM_LIMIT=2G +``` + +### livekit-prod.yaml + +```yaml +port: 7880 + +redis: + address: localhost:6380 # Port different du Redis systeme (6379) + +rtc: + udp_port: 7882 + tcp_port: 7881 + allow_tcp_fallback: true + use_external_ip: false + node_ip: + +turn: + enabled: true + tls_port: 5349 + udp_port: 3478 + domain: video. + cert_file: /etc/livekit/tls/fullchain.pem + key_file: /etc/livekit/tls/privkey.pem + +room: + auto_create: true + empty_timeout: 300 + max_participants: 2 + +webhook: + api_key: + urls: + - https:///api/v1/teleconsultation/livekit-webhook +``` + +> **Piege :** Le Redis du container doit tourner sur un port different (6380) du Redis systeme (6379) quand on utilise `network_mode: host`. + +## Demarrer + +```bash +cd /chemin/projet/docker/livekit +docker compose -f docker-compose.prod.yml up -d +``` + +## Verifier + +```bash +docker logs djeliba_livekit_server --tail 10 +# Chercher "starting LiveKit server" et "Starting TURN server" +``` + +## Symfony .env + +``` +TELECONSULTATION_PROVIDER=livekit +LIVEKIT_URL=wss://video.:7880 +LIVEKIT_API_KEY= +LIVEKIT_API_SECRET= +``` diff --git a/16-notes-pieges.md b/16-notes-pieges.md new file mode 100644 index 0000000..a33cd40 --- /dev/null +++ b/16-notes-pieges.md @@ -0,0 +1,109 @@ +# 16. Notes et Pieges + +## Pieges frequents + +### UFW vs ISPConfig +Ne jamais utiliser UFW avec ISPConfig. ISPConfig gere le firewall via iptables. Desactiver UFW : `ufw disable`. + +### Ports bloques par l'hebergeur +Contabo bloque certains ports non-standard au niveau de son firewall externe. Toujours tester l'acces depuis l'exterieur apres ouverture d'un port. + +### Page "Welcome to your website" ISPConfig +Apres creation d'un sous-domaine, la page par defaut ISPConfig peut s'afficher. Solutions : +1. Verifier que SSL/Let's Encrypt est bien coche +2. Supprimer `standard_index.html` : `find /var/www/ -path "**standard_index*" -delete` + +### DNS Templates : NS personnalises +Les templates DNS doivent pointer les NS vers le domaine serveur principal (ex: `ns1.z-ana.com`) et non `ns1.{DOMAIN}`. Sinon les domaines heberges auront des problemes de delegation. + +### Domaines .ci chez MTN +- Les glue records vers le meme domaine ne fonctionnent pas dans l'interface +- Solution : pointer les NS vers le domaine principal du serveur +- Le support est lent — prevoir des delais + +### Dovecot SNI +Le SNI doit etre configure dans `dovecot.conf` principal, pas dans `conf.d/10-ssl.conf`. ISPConfig ecrase les fichiers `conf.d`. + +### Redis conflit de ports +Si vous installez un service Docker avec Redis en `network_mode: host`, utiliser un port different (ex: 6380) pour eviter le conflit avec le Redis systeme (6379). + +### Guacamole et Tomcat 10 +Guacamole 1.5.5 n'est pas compatible avec Tomcat 10 (Ubuntu 24.04). Utiliser Docker a la place. + +### wg-easy PASSWORD vs PASSWORD_HASH +Les versions recentes de wg-easy exigent un hash bcrypt (`PASSWORD_HASH`) au lieu du mot de passe en clair (`PASSWORD`). + +### MAILER_DSN Symfony +Pour envoyer des mails via Postfix local : `smtp://127.0.0.1:25?auto_tls=false`. Sans `auto_tls=false`, Symfony tente STARTTLS qui echoue localement. + +### Permissions Symfony +Apres connexion SSH, executer `newgrp clientX` pour activer le groupe et acceder au dossier du projet. + +### Certificat ISPConfig vs mail +Le certificat dans `ispserver.crt` est utilise pour le panel ISPConfig ET Dovecot/Postfix par defaut. Garder le certificat du domaine principal. Le SNI gere les certificats specifiques par domaine mail. + +### Propagation DNS +- OVH : quasi instantanee +- MTN/Cloud4Africa (.ci) : peut prendre des heures +- Utiliser `dig @8.8.8.8 A +short` pour verifier + +## Ports utilises + +| Port | Service | Protocole | +|------|---------|-----------| +| 22/50022 | SSH | TCP | +| 25 | SMTP | TCP | +| 53 | DNS | TCP+UDP | +| 80 | HTTP | TCP | +| 110 | POP3 | TCP | +| 143 | IMAP | TCP | +| 443 | HTTPS | TCP | +| 465 | SMTP SSL | TCP | +| 587 | SMTP submission | TCP | +| 993 | IMAP SSL | TCP | +| 995 | POP3 SSL | TCP | +| 2812 | Monit | TCP | +| 3000 | Gitea | TCP | +| 3100 | Grafana | TCP | +| 3101 | Loki | TCP | +| 3306 | MariaDB | TCP | +| 3478 | TURN UDP | UDP | +| 5349 | TURN TLS | TCP | +| 6379 | Redis systeme | TCP | +| 6380 | Redis LiveKit | TCP | +| 7880 | LiveKit signal | TCP | +| 7881 | LiveKit TCP | TCP | +| 7882 | LiveKit UDP | UDP | +| 8061 | Yacht | TCP | +| 8080 | ISPConfig | TCP | +| 8081 | ISPConfig apps | TCP | +| 8085 | Guacamole | TCP | +| 9050 | Portainer | TCP | +| 9080 | Promtail | TCP | +| 9090 | Prometheus | TCP | +| 10000 | Webmin | TCP | +| 51820 | Wireguard | UDP | +| 51821 | wg-easy interface | TCP | +| 1280 | Vaultwarden | TCP | +| 1281 | Heimdall | TCP | + +## Architecture des sous-domaines + +| Sous-domaine | Service | Proxy vers | +|-------------|---------|-----------| +| mail.* | Roundcube | localhost:8080/webmail/ | +| rspamd.* | Rspamd | localhost:8081/rspamd/ | +| autoconfig.* | Config mail auto | Fichiers XML directs | +| autodiscover.* | Config Outlook | Fichiers XML directs | +| webmin.* | Webmin | localhost:10000 | +| portainer.* | Portainer | localhost:9050 | +| yacht.* | Yacht | localhost:8061 | +| grafana.* | Grafana | localhost:3100 | +| wireguard.* | Wireguard | localhost:51821 | +| vaultwarden.* | Vaultwarden | localhost:1280 | +| heimdall.* | Heimdall | localhost:1281 (HTTPS) | +| guacamole.* | Guacamole | localhost:8085/guacamole | +| dbmanage.* | phpMyAdmin | Direct (Alias) | +| wordpress.* | Wordpress | Direct | +| nextcloud.* | Nextcloud | Direct | +| gitea.* | Gitea | localhost:3000 | diff --git a/README.md b/README.md new file mode 100644 index 0000000..c5b8e3a --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# Guide d'Installation VPS Complet + +Guide pas-a-pas pour configurer un serveur VPS de zero avec panel de gestion, mail, Docker, monitoring et services. + +## Variables a personnaliser + +Avant de commencer, notez vos valeurs : + +| Variable | Exemple | Votre valeur | +|----------|---------|-------------| +| `` | 62.169.29.111 | | +| `` | 2a02:c207:2316:3066::1 | | +| `` | z-ana.com | | +| `` | mail | | +| `` | mail.z-ana.com | | +| `` | scriptshadow | | +| `` | 50022 | | +| `` | admin@z-ana.com | | + +## Sommaire + +1. [Prerequis et choix](01-prerequis.md) - Hebergeur, registrar, OS +2. [Configuration de base](02-config-base.md) - Hostname, apt, locale, swap, MOTD +3. [ISPConfig](03-ispconfig.md) - Installation et configuration +4. [HestiaCP (Alternative)](03-bis-hestiacp.md) - Alternative a ISPConfig +5. [DNS](04-dns.md) - Templates, zones, glue records +6. [Webmin](05-webmin.md) - Administration systeme +7. [Monitoring](06-monitoring.md) - Munin, Monit, Grafana, Prometheus, Loki +8. [Mail](07-mail.md) - Rspamd, DKIM, DMARC, Roundcube, autoconfig +9. [SNI Mail](08-sni-mail.md) - Certificats multi-domaines +10. [Docker](09-docker.md) - Docker, Swarm, Portainer, Yacht +11. [Services Docker](10-services-docker.md) - Wireguard, Vaultwarden, Heimdall, Guacamole +12. [Applications](11-applications.md) - Wordpress, Nextcloud, Gitea +13. [Backup](12-backup.md) - Script rsync quotidien +14. [Securite](13-securite.md) - Certificats LE, phpMyAdmin, Fail2ban, DNSSEC +15. [Deploiement Symfony](14-deploiement-symfony.md) - Projet Symfony sur Apache +16. [LiveKit](15-livekit.md) - Teleconsultation video +17. [Notes et pieges](16-notes-pieges.md) - Lecons apprises + +## Temps estime + +- Configuration de base + ISPConfig : ~2h +- Mail complet : ~1h +- Docker + services : ~2h +- Monitoring : ~1h +- Total : ~6-8h pour un serveur complet + +## Prerequis + +- VPS Ubuntu 24.04 (Contabo ou equivalent) +- Domaine chez OVH (recommande) ou autre registrar +- Acces root au VPS