Installation manuelle

Installation entièrement manuelle : d'un VPS fraîchement acheté à un tableau de bord fonctionnel, étape par étape. La préparation du serveur, la création du site, la base de données, le config.php et le SSL sont détaillés ici. Les commandes propres à chaque outil de sécurité et au cron figurent dans le guide FAQ, liens au fil du texte.

Règle d'or : lorsque vous modifiez le SSH ou le pare-feu, ne fermez pas la connexion en cours tant que vous n'avez pas testé la nouvelle dans une fenêtre séparée. Si l'accès est malgré tout perdu, la plupart des hébergeurs proposent une console de secours (VNC/Recovery) dans leur panneau de gestion.

01. Un VPS Ubuntu/Debian acheté — par où commencer

Après l'achat, l'hébergeur envoie : l'adresse IP, le nom d'utilisateur (généralement root) et le mot de passe (ou une clé SSH). Cela suffit pour se connecter. Marche à suivre (chaque étape correspond à une section ci-dessous) :

  1. Se connecter au serveur en SSH ;
  2. Mettre à jour le système, définir le nom d'hôte et le fuseau horaire ;
  3. Créer un utilisateur standard disposant des droits sudo (ne pas travailler en root) ;
  4. Configurer la connexion par clé SSH et désactiver la connexion par mot de passe ;
  5. Activer le pare-feu et l'autoprotection ;
  6. (facultatif) installer le panneau d'administration HestiaCP — serveur web, BD, messagerie clés en main.

02. Première connexion en SSH

SSH est un terminal sécurisé vers le serveur. Remplacez 203.0.113.10 par votre propre IP.

203.0.113.10 est un exemple, une adresse inexistante (réservée à la documentation). Ne la saisissez pas telle quelle — remplacez-la par l'IP réelle de votre serveur, indiquée dans le courriel de votre hébergeur. Sinon la connexion échouera.

Windows 10/11 : ouvrez PowerShell ou le « Terminal » et utilisez le ssh intégré (ou les clients PuTTY / MobaXterm).
macOS / Linux : ouvrez le « Terminal ».

# Connexion en root (mot de passe fourni par l'hébergeur) : ssh root@203.0.113.10 # Si l'hébergeur a fourni un fichier-clé au lieu d'un mot de passe : ssh -i chemin/vers/cle root@203.0.113.10
Lors de la première connexion, SSH demande à propos de l'« authenticity of host » — saisissez yes. Le mot de passe ne s'affiche pas pendant la saisie (c'est normal). Si l'hébergeur a fourni un mot de passe temporaire, changez-le avec la commande passwd.

03. Mise à jour du système et configuration de base

Commencez par mettre à jour tous les paquets et définir le nom d'hôte et le fuseau horaire.

# Mettre à jour le système : apt update && apt upgrade -y # Utilitaires de base : apt install -y curl wget ufw fail2ban unattended-upgrades # Fuseau horaire (exemple) et nom d'hôte : timedatectl set-timezone Europe/Paris hostnamectl set-hostname myserver # Mises à jour de sécurité automatiques : dpkg-reconfigure -plow unattended-upgrades
Liste des fuseaux horaires — timedatectl list-timezones. Si une fenêtre bleue « Daemons using outdated libraries » apparaît à la fin de la mise à jour, sélectionnez tous les services (Espace) et appuyez sur OK, c'est sans danger.

04. Créer un utilisateur avec sudo

Travailler en permanence sous root n'est pas sûr. Créez un utilisateur normal et accordez-lui les droits sudo (exécution de commandes admin au besoin). Remplacez deploy par le nom de votre choix.

# Créer l'utilisateur (définit un mot de passe et demande des infos — Entrée possible) : adduser deploy # Ajouter au groupe sudo : usermod -aG sudo deploy # Vérifier (sous root) : su - deploy sudo whoami # doit afficher : root exit
Connectez-vous ensuite au serveur avec cet utilisateur : ssh deploy@203.0.113.10, et lancez les commandes d'administration avec le préfixe sudo.

05. Clés SSH et désactivation de la connexion par mot de passe

La connexion par clé est plus sûre que le mot de passe : un mot de passe peut être deviné, une clé quasiment pas. On crée d'abord la clé sur son ordinateur, on la copie sur le serveur, on vérifie la connexion — et seulement ensuite on désactive le mot de passe.

Étape 1. Créer une clé sur son ordinateur (Windows PowerShell / macOS / Linux) :

ssh-keygen -t ed25519 -C "my-laptop" # Entrée à toutes les questions (la clé ira dans ~/.ssh/id_ed25519)

Étape 2. Copier la clé publique sur le serveur :

# macOS / Linux: ssh-copy-id deploy@203.0.113.10 # Windows (PowerShell): type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh deploy@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

Étape 3. Vérifier la connexion par clé dans une nouvelle fenêtre — elle doit passer sans mot de passe :

ssh deploy@203.0.113.10
N'exécutez pas la Variante B tant que la connexion par clé n'est pas vérifiée et fonctionnelle (Étapes 1–3), et ne fermez pas la session active. Elle désactive la connexion par mot de passe pour tous les utilisateurs, y compris root. Sans clé fonctionnelle, vous perdrez totalement l'accès au serveur — vous ne pourrez le récupérer que via la console de l'hébergeur. Pas de clé — prenez la Variante A.

Étape 4. Renforcer l'accès SSH. Les réglages vont dans un fichier séparé, sans toucher au fichier principal. Choisissez la variante selon votre situation :

Variante A — fermer uniquement root, garder le mot de passe. Pas besoin de clé, aucun risque de perdre l'accès :

echo 'PermitRootLogin no' | sudo tee /etc/ssh/sshd_config.d/00-hardening.conf >/dev/null sudo systemctl restart ssh

Variante B — durcissement complet. Désactiver la connexion par mot de passe et ne laisser root que par clé. À n'exécuter que lorsque vous êtes certain que la connexion par clé fonctionne :

sudo tee /etc/ssh/sshd_config.d/00-hardening.conf >/dev/null <<'EOF' PubkeyAuthentication yes PasswordAuthentication no PermitRootLogin prohibit-password KbdInteractiveAuthentication no EOF sudo systemctl restart ssh
Dans les deux variantes, root par mot de passe est fermé. PermitRootLogin no interdit root complètement, prohibit-password — ne laisse la connexion que par clé (pour l'administration, connectez-vous avec deploy et utilisez sudo). Pour changer le port SSH, ajoutez la ligne Port 2222, mais ouvrez d'abord le nouveau port dans le pare-feu (section suivante) et vérifiez la connexion, sinon vous vous coupez l'accès.

06. Pare-feu de base et protection automatique

Fermez tout ce qui est superflu avec le pare-feu et activez fail2ban (il bannit les tentatives de force brute sur SSH). D'abord, autorisez SSH, sinon vous perdrez l'accès après l'activation d'UFW.

# Autoriser SSH (ou votre port si modifié) et le web : sudo ufw allow OpenSSH sudo ufw allow 80,443/tcp # Activer le pare-feu : sudo ufw enable sudo ufw status verbose # fail2ban — protection SSH contre la force brute (profil de base actif immédiatement) : sudo systemctl enable --now fail2ban sudo fail2ban-client status sshd
C'est le minimum. Les réglages opérationnels de fail2ban, la liste de blocage ipsum, l'UFW avancé et les autres outils se trouvent dans le groupe « Outils de sécurité » du guide. Le tableau de bord Arcivéo Monitor affichera clairement l'état de tout cela.

07. Installation du panneau HestiaCP (facultatif)

HestiaCP — panneau de gestion d'hébergement gratuit : il installe et configure le serveur web (nginx + apache), PHP, la base de données (MariaDB), la messagerie, le DNS et les certificats SSL, et fournit une interface web pour les sites. Pratique si vous ne souhaitez pas tout configurer manuellement et prévoyez d'héberger des sites (y compris le panneau Arcivéo Monitor lui-même).

Installez HestiaCP sur un serveur vierge (une version récente et prise en charge d'Ubuntu/Debian, au minimum ~1–2 Go de RAM), avant tout autre serveur web ou base de données — sinon des conflits surviendront. L'installation prend 10 à 20 minutes et redémarre le serveur.
# Télécharger l'installateur et le lancer : wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh sudo bash hst-install.sh

L'installateur demandera un email et un nom d'hôte, puis installera toute la pile. Après le redémarrage, le panneau est accessible à l'adresse https://YOUR_IP:8083 (l'installateur affiche l'identifiant et le mot de passe à la fin).

HestiaCP gère lui-même UFW et fail2ban — inutile de les configurer séparément, il s'en charge. Configurez tout de même les clés SSH et la désactivation du mot de passe (section précédente).

08. Configuration requise et ionCube

Le tableau de bord est une application PHP sur une pile LAMP/LEMP classique :

  • OS : Linux (Ubuntu/Debian recommandés) ;
  • Serveur web : nginx ou Apache avec PHP-FPM ;
  • PHP 8.0+ avec les extensions : pdo_mysql, openssl, curl, json, mbstring ;
  • ionCube Loader — extension PHP nécessaire au fonctionnement du tableau de bord ;
  • BD : MySQL 5.7+ ou MariaDB 10.3+ ;
  • HTTPS — obligatoire (la connexion et WebAuthn ne fonctionnent qu'en https) ;
  • sudo pour l'utilisateur du serveur web (ensemble restreint — étape 13).
# Vérifier la version de PHP et les extensions : php -v php -m | grep -iE 'pdo_mysql|openssl|curl|mbstring|ioncube'

Installation d'ionCube Loader (s'il n'est pas déjà présent). Sur un hébergement avec panneau (HestiaCP, cPanel), ionCube s'active par une case dans les paramètres PHP. Manuellement sous Ubuntu/Debian :

# Trouver la version de PHP et le répertoire des extensions : php -v EXTDIR=$(php -r 'echo ini_get("extension_dir");'); PHPVER=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;') # Télécharger et décompresser les loaders (64-bit) : cd /tmp wget -q https://downloads.ioncube.com/loader_downloads/ioncube_loaders_lin_x86-64.tar.gz tar xzf ioncube_loaders_lin_x86-64.tar.gz # Copier le loader correspondant à votre version de PHP dans le répertoire des extensions : sudo cp ioncube/ioncube_loader_lin_${PHPVER}.so "$EXTDIR"/ # Activer (CLI + PHP-FPM) et redémarrer : echo "zend_extension=ioncube_loader_lin_${PHPVER}.so" | sudo tee /etc/php/${PHPVER}/mods-available/ioncube.ini sudo phpenmod ioncube sudo systemctl restart php${PHPVER}-fpm # Vérification — la ligne "with the ionCube PHP Loader" apparaît dans la sortie : php -v
La version du loader doit correspondre à la version de PHP (par exemple ioncube_loader_lin_8.1.so pour PHP 8.1). Si vous utilisez plusieurs versions de PHP, activez le loader pour chacune.

09. Domaine et DNS

Pour ouvrir le tableau de bord à une adresse comme monitor.example.com et obtenir un SSL gratuit, il faut un domaine pointant vers votre serveur. Dans le panneau de gestion DNS, créez un enregistrement A :

Type: A Nom: monitor (sous-domaine → monitor.example.com) ou @ (racine du domaine → example.com) Valeur: 203.0.113.10 ← IP de votre serveur TTL: 3600

Après quelques minutes, vérifiez que le domaine pointe bien vers le serveur :

dig +short monitor.example.com # doit renvoyer votre IP # ou, si dig est absent : getent hosts monitor.example.com
Le certificat SSL Let's Encrypt n'est délivré que pour un domaine — le DNS doit pointer vers le serveur avant l'émission du certificat.

10. Créer le site et transférer les fichiers du panneau

Apache : DocumentRoot doit pointer vers la racine du panneau, PAS vers public/. Les styles (CSS/JS), sw.js, manifest.json se trouvent dans assets/ à côté de public/ et sont requis depuis la racine du site. Le .htaccess racine est le contrôleur frontal. Si, sous Apache, DocumentRoot pointe vers public/, le panneau s'ouvrira sans styles. Pour nginx seul, c'est l'inverse : public/ sert de racine et assets/ est servi par une règle distincte (voir le bloc nginx ci-dessous).
Les fichiers du panneau (archive de la distribution) se téléchargent après l'achat, dans l'espace client my.arciveo.com« Téléchargements ». Décompressez l'archive avant de la transférer.

1) Créez le répertoire du panneau et transférez-y le contenu de la distribution (afin d'y retrouver public/, assets/, config.php, etc.) :

sudo mkdir -p /var/www/monitor # puis transférer les fichiers de la distribution dans /var/www/monitor (FileZilla / WinSCP / scp)

2) Configurez le serveur web. Apache : DocumentRoot vers la racine du panneau (PAS vers /public) ; AllowOverride All est obligatoire. Le chemin du socket PHP-FPM est détecté automatiquement. Le bloc se colle dans le terminal en entier :

PHPSOCK=$(ls -1 /run/php/php*-fpm.sock 2>/dev/null | head -1) # détection auto du socket PHP-FPM sudo tee /etc/apache2/sites-available/monitor.conf > /dev/null <<'EOF' <VirtualHost *:80> ServerName monitor.example.com DocumentRoot /var/www/monitor <Directory /var/www/monitor> AllowOverride All Require all granted </Directory> <FilesMatch \.php$> SetHandler "proxy:unix:__PHPSOCK__|fcgi://localhost" </FilesMatch> </VirtualHost> EOF sudo sed -i "s#__PHPSOCK__#${PHPSOCK}#" /etc/apache2/sites-available/monitor.conf sudo a2dissite 000-default.conf sudo a2ensite monitor.conf sudo apache2ctl configtest sudo systemctl reload apache2

nginx : nginx n'a pas de .htaccess, on prend donc public/ comme racine et on sert assets/, sw.js, manifest.json (un niveau au-dessus) par une règle distincte :

PHPSOCK=$(ls -1 /run/php/php*-fpm.sock 2>/dev/null | head -1) # détection auto du socket PHP-FPM sudo tee /etc/nginx/sites-available/monitor.conf > /dev/null <<'EOF' server { listen 80; server_name monitor.example.com; root /var/www/monitor/public; index index.php; # assets, service worker et manifest sont un niveau au-dessus de public/ location ~ ^/(assets/|sw\.js|manifest\.json) { root /var/www/monitor; } location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:__PHPSOCK__; } } EOF sudo sed -i "s#__PHPSOCK__#${PHPSOCK}#" /etc/nginx/sites-available/monitor.conf sudo ln -s /etc/nginx/sites-available/monitor.conf /etc/nginx/sites-enabled/ sudo nginx -t && sudo systemctl reload nginx

Transfert des fichiers — SFTP/SCP (FileZilla, WinSCP) ou scp :

# Exemple via scp depuis l'ordinateur local : scp -r ./monitor/* deploy@203.0.113.10:/var/www/monitor/
Définissez les droits sur les fichiers — c'est une étape obligatoire. Si le transfert a été fait sous root ou par SFTP, les fichiers appartiennent à root et le serveur web (www-data) ne pourra pas les lire — le panneau s'ouvrira vide ou avec une erreur 403 (dans le journal : .htaccess unreadable / directory not executable). La commande ci-dessous corrige cela :
# On normalise les droits de tout le webroot : un répertoire créé par root est inaccessible # au serveur web (www-data) — sans cela, le panneau renvoie une page vide ou une 403. # Apache tourne sous www-data ; si vous avez un autre utilisateur web, remplacez-le. cd /var/www/monitor # On crée les dossiers de travail AVANT le chown — sinon les nouveaux répertoires resteront root:root # et avec chmod 750 le serveur web (www-data) ne pourra pas y écrire. sudo mkdir -p data/lynis data/logwatch tmp logs sudo chown -R www-data:www-data /var/www/monitor sudo find /var/www/monitor -type d -exec chmod 755 {} \; sudo find /var/www/monitor -type f -exec chmod 644 {} \; sudo chmod 640 /var/www/monitor/config.php sudo chmod 750 data tmp logs

3) Ouvrez-vous l'accès au transfert par SFTP. Après la commande ci-dessus, tous les fichiers appartiennent à www-data, alors que FileZilla / WinSCP se connectent sous votre propre utilisateur — le transfert échouera alors avec SSH_FX_PERMISSION_DENIED (Permission denied). Se connecter en root pour transférer n'est pas une option — la connexion root a été désactivée à l'étape 05. Choisissez l'une des deux variantes.

Variante A — une ACL pour votre utilisateur uniquement (recommandé). Vous seul obtenez le droit d'écriture ; le serveur web ne peut toujours pas réécrire le code du panneau :

sudo apt install -y acl # Droit d'écriture pour votre utilisateur sur tout le répertoire du panneau : sudo setfacl -R -m u:deploy:rwX /var/www/monitor # La même règle par défaut — pour les fichiers et dossiers créés plus tard : sudo setfacl -R -d -m u:deploy:rwX /var/www/monitor

Variante B — via le groupe www-data. Plus simple, mais le serveur web obtient lui aussi le droit d'écriture sur les fichiers du panneau : en cas de faille dans PHP, le code pourrait être remplacé. L'ordre des commandes compte — config.php et les dossiers de travail sont verrouillés en dernier :

sudo usermod -aG www-data deploy # Droit d'écriture au groupe + setgid (le bit 2) : les fichiers transférés par SFTP # restent dans le groupe www-data — sinon le panneau ne pourra pas les réécrire. sudo find /var/www/monitor -type d -exec chmod 2775 {} \; sudo find /var/www/monitor -type f -exec chmod 664 {} \; sudo chmod 640 /var/www/monitor/config.php sudo chmod 2750 /var/www/monitor/data /var/www/monitor/tmp /var/www/monitor/logs
Après la variante B, reconnectez-vous dans FileZilla (Serveur → Déconnexion, puis reconnectez-vous) — le nouveau groupe ne prend effet qu'à une nouvelle connexion, avant cela vous n'aurez toujours aucun droit. Vérification : id deploywww-data doit apparaître dans la liste des groupes ; ls -ld /var/www/monitor — droits drwxrwsr-x, la lettre s à la place de x signifie que setgid est activé.

11. Base de données

Créez la base et l'utilisateur, puis importez le schéma. Le bloc se colle en entier dans le terminal. monitor_db et monitor_user sont des noms d'exemple, vous pouvez choisir les vôtres ; retenez le nom de la base, l'utilisateur et le mot de passe — vous les saisirez dans config.php à l'étape suivante :

# 1. Base de données. Le mot de passe est défini UNE seule fois dans DBPASS et repris dans toutes les lignes. # Le bloc se colle EN ENTIER dans le terminal ; sudo mysql se connecte en root via le socket unix # (pas besoin du mot de passe root). N'utilisez PAS `sudo mysql -u root -p` interactif # avec copier-coller — au collage, les lignes SQL partiront dans l'invite du mot de passe et seront perdues. DBPASS='CHOOSE_A_PASSWORD' # ← modifiez uniquement cette ligne sudo mysql <<SQL CREATE DATABASE IF NOT EXISTS monitor_db CHARACTER SET utf8mb4; CREATE USER IF NOT EXISTS 'monitor_user'@'localhost' IDENTIFIED BY '$DBPASS'; GRANT ALL ON monitor_db.* TO 'monitor_user'@'localhost'; FLUSH PRIVILEGES; SQL # Vérification (doit afficher monitor_db) : mysql -u monitor_user -p"$DBPASS" -e "SHOW DATABASES;" # Saisissez ce même mot de passe dans config.php → DB_PASS.
Pas besoin d'importer le schéma — le tableau de bord crée lui-même les tables et le compte admin au premier accès dans le navigateur (à partir de database/db.sql) si la base est vide. L'import manuel du schéma n'est nécessaire que si l'auto-initialisation a échoué.
Si vous avez utilisé l'installateur navigateur public/start_db.phpsupprimez-le aussitôt après l'installation : il permet de recréer la base sans authentification. Tant que le fichier reste à la racine du tableau de bord ou dans public/, le tableau de bord affiche un avertissement rouge.

12. Configuration de config.php

config.php à la racine du panneau (/var/www/monitor/config.php) est le seul fichier à modifier manuellement. Tous les paramètres du panneau y sont définis par des constantes define(). Ouvrez-le dans un éditeur :

sudo nano /var/www/monitor/config.php

Renseignez vos valeurs aux endroits surlignés ; laissez le reste tel quel :

// --- Base de données (de l'étape 11) --- define('DB_HOST', 'localhost'); // laisser define('DB_NAME', 'db_name'); // créé à l'étape 11 define('DB_USER', 'user'); // créé à l'étape 11 define('DB_PASS', 'db_password'); // défini à l'étape 11 define('DB_CHARSET', 'utf8mb4'); // laisser // --- Application --- define('APP_URL', 'https://monitor.example.com'); // adresse du panneau, sans slash final define('TIMEZONE', 'Europe/Paris'); // votre fuseau horaire // --- Durée de session --- define('SESSION_LIFETIME', 28800); // inactivité avant reconnexion, s (28800 = 8 h)

Ce qu'il faut changer :

  • DB_NAME, DB_USER, DB_PASS — exactement les mêmes nom de base, utilisateur et mot de passe que ceux définis à la création de la BD à l'étape 11 (si vous avez gardé les exemples — monitor_db / monitor_user). Ne touchez pas à DB_HOST ni à DB_CHARSET.
  • APP_URL — adresse complète du panneau avec https://, sans slash final et sans www. Elle doit correspondre au domaine sur lequel vous activez la licence (étape 16), sinon la clé sera rejetée.
  • TIMEZONE — votre fuseau horaire (liste — timedatectl list-timezones). N'affecte que la façon dont le panneau affiche les dates ; n'affecte pas l'heure de lancement des tâches cron (là c'est le fuseau du système qui s'applique).
  • SESSION_LIFETIME — après combien de secondes d'inactivité le panneau redemande la connexion (8 heures par défaut). Ex. 3600 = 1 heure, 86400 = 1 jour.
  • Le bloc de journalisation des erreurs (display_errors, log_errors, error_log) — laissez-le par défaut.

Enregistrez le fichier (Ctrl+O, Enter, puis Ctrl+X) et redémarrez PHP-FPM — sinon, à cause d'OPcache, les changements ne s'appliqueront pas :

sudo systemctl restart php*-fpm
config.php est un fichier secret (il contient le mot de passe de la BD). Il se trouve à la racine du panneau, qui est aussi la racine web, mais il est protégé : droits 640 (définis à l'étape 10) et interdiction explicite dans le .htaccess racine. Ne le publiez pas dans des dépôts publics et ne l'envoyez pas au support avec le vrai mot de passe.
Analyse détaillée de tous les paramètres — dans la FAQ : « Fichier config.php — tous les paramètres du panneau ».

13. Configuration de sudo pour le serveur web

PHP s'exécute sous l'utilisateur du serveur web, qui n'a pas les droits sur les commandes système. L'accès est accordé de façon restreinte : sudo ciblé sur des utilitaires précis et lecture des logs via les groupes (sans sudo). Une compromission de la couche web ne donne pas root.

Dans les exemples, www-data est l'utilisateur standard d'Apache. Si le vôtre est différent (sur certains panels, PHP tourne sous un utilisateur dédié), remplacez-le partout. Pour le connaître : ps -o user= -C php-fpm | sort -u.

1. Créez /etc/sudoers.d/monitor via sudo visudo -f /etc/sudoers.d/monitor et collez (supprimez les lignes des modules non utilisés) :

# UFW — statut et règles (page « Pare-feu ») www-data ALL=(ALL) NOPASSWD: /usr/sbin/ufw status, /usr/sbin/ufw status verbose, /usr/sbin/ufw status numbered www-data ALL=(ALL) NOPASSWD: /usr/sbin/ufw allow [0-9]*, /usr/sbin/ufw deny [0-9]*, /usr/sbin/ufw --force delete [0-9]* # Fail2ban — statut, bannissement et débannissement (banned renvoie les bans de tous les jails en une commande ; # ban/unban sont nécessaires aux boutons du dashboard) www-data ALL=(ALL) NOPASSWD: /usr/bin/fail2ban-client status, /usr/bin/fail2ban-client status *, /usr/bin/fail2ban-client banned, /usr/bin/fail2ban-client set * banip *, /usr/bin/fail2ban-client set * unbanip * # Mises à jour de sécurité (carte « Mises à jour »). Lecture seule, mais bien en root : # le cache apt (~70 Mo) n'est accessible qu'à root, un non-root le reconstruit à chaque appel # (4,2 s CPU contre 0,01 s). Sans wildcard — exactement cette seule commande, n'installe rien. www-data ALL=(ALL) NOPASSWD: /usr/bin/apt list --upgradable # IPset (carte des attaques, dashboard) www-data ALL=(ALL) NOPASSWD: /usr/sbin/ipset list -t ipsum # CrowdSec www-data ALL=(ALL) NOPASSWD: /usr/bin/cscli decisions list *, /usr/bin/cscli alerts list *, /usr/bin/cscli bouncers list *, /usr/bin/cscli scenarios list * # Auditd — recherche d'événements + lecture des dernières lignes du journal (chemin exact) www-data ALL=(ALL) NOPASSWD: /usr/sbin/ausearch -m * www-data ALL=(ALL) NOPASSWD: /usr/bin/tail -n 300 /var/log/audit/audit.log # Monit / ModSecurity / AppArmor / PSAD www-data ALL=(ALL) NOPASSWD: /usr/bin/monit status www-data ALL=(ALL) NOPASSWD: /usr/sbin/apache2ctl -M www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-modsec www-data ALL=(ALL) NOPASSWD: /usr/sbin/aa-status www-data ALL=(ALL) NOPASSWD: /usr/sbin/psad --Status # Ports ouverts (les journaux noyau/SSH/Falco se lisent SANS sudo — via le groupe # systemd-journal, voir le point 2 ; il ne faut PAS donner sudo pour journalctl, c'est non sécurisé) www-data ALL=(ALL) NOPASSWD: /usr/bin/ss -tuln, /usr/sbin/ss -tuln, /bin/ss -tuln # PostgreSQL (uniquement si vous l'utilisez) — script fixe en lecture seule, # à créer d'après la FAQ « PostgreSQL ne s'affiche pas » ; sans lui, supprimez la ligne www-data ALL=(ALL) NOPASSWD: /usr/local/bin/monitor-pgstat
sudo chmod 440 /etc/sudoers.d/monitor sudo visudo -c # doit afficher "parsed OK"

2. Accès aux logs et au journal systemd. Les modules lisent /var/log/fail2ban.log, auth.log, ufw.log, apache2/*, aide directement (sur Debian/Ubuntu, ces logs appartiennent au groupe adm). Les événements noyau, SSH et Falco proviennent de journald via la commande journalctl sans sudo, grâce au groupe systemd-journal. Ajoutez l'utilisateur web aux deux groupes et redémarrez PHP-FPM :

sudo usermod -aG adm,systemd-journal www-data sudo systemctl restart php*-fpm # obligatoire, sinon les groupes ne s'appliquent pas

3. Si ClamAV ou Suricata écrivent leurs logs hors du groupe adm (parfois root:root), donnez l'accès via ACL :

sudo apt install acl sudo setfacl -R -m u:www-data:rX /var/log/clamav /var/log/suricata 2>/dev/null sudo setfacl -d -m u:www-data:rX /var/log/clamav /var/log/suricata 2>/dev/null

4. Wrapper ModSecurity. Le log d'audit du WAF (/var/log/apache2/modsec_audit.log) appartient à root avec les droits 640, l'utilisateur web ne peut pas le lire directement. La page ModSecurity récupère le mode du moteur, les événements et la liste des règles actives via un script fixe en lecture seule — c'est lui qui est autorisé dans sudoers par la ligne ci-dessus :

sudo tee /usr/local/bin/monitor-modsec >/dev/null <<'EOF' #!/bin/sh echo "ENGINE=$(grep -hE '^SecRuleEngine[[:space:]]+' /etc/modsecurity/*.conf 2>/dev/null | tail -1 | awk '{print $2}')" echo "---LOG---" tail -n 3000 /var/log/apache2/modsec_audit.log 2>/dev/null echo "---RULES---" for f in /etc/modsecurity/crs/rules/*.conf /usr/share/modsecurity-crs/rules/*.conf /etc/modsecurity/custom-rules.conf; do [ -f "$f" ] && { echo "===FILE:$(basename "$f")==="; cat "$f"; } done EOF sudo chown root:root /usr/local/bin/monitor-modsec sudo chmod 755 /usr/local/bin/monitor-modsec
Sans le fichier /etc/modsecurity/modsecurity.conf, le WAF lui-même ne fonctionne pas : le paquet n'installe que modsecurity.conf-recommended, et le moteur de règles reste désactivé — pour l'activer, voir FAQ → « Installation de ModSecurity ».
L'utilisateur dans toutes les lignes de sudoers doit correspondre à celui du pool FPM : sur un Apache/Debian standard, c'est www-data ; dans HestiaCP, le pool du site tourne sous le propriétaire du site (par exemple admin) — vérifiez avec grep -E '^user' /etc/php/*/fpm/pool.d/monitor.example.com.conf.

5. Si Nginx est placé devant Apache (HestiaCP, ISPmanager et autres panels — Nginx y proxifie PHP vers Apache et sert lui-même le statique). Les répertoires internes sont protégés par des fichiers .htaccess, mais Nginx ne les lit pas : il servira directement tout fichier statique (.json, .txt, .log, .dat), en contournant Apache. Les caches et données du panel fuiteront vers l'extérieur — par exemple tmp/modsec_cache.json avec les événements du WAF et les IP des attaquants. Ajoutez l'interdiction dans la configuration du site Nginx :

location ^~ /data/ { deny all; } location ^~ /tmp/ { deny all; } location ^~ /logs/ { deny all; } location ^~ /includes/ { deny all; } location ^~ /cron/ { deny all; } location ^~ /database/ { deny all; } location = /config.php { deny all; }
Le préfixe ^~ est obligatoire : il est sélectionné avant la règle regex pour le statique dans location /, sinon l'interdiction ne s'applique pas.
Dans HestiaCP, placez ceci dans un fichier séparé /home/<user>/conf/web/<domain>/nginx.ssl.conf_deny (et nginx.conf_deny pour HTTP) — la configuration du site inclut nginx.ssl.conf_* et ne réécrase pas ces fichiers lors de la reconstruction. Appliquer : sudo nginx -t && sudo systemctl reload nginx.
Vérification : curl -s -o /dev/null -w '%{http_code}\n' https://monitor.example.com/tmp/modsec_cache.json — doit renvoyer 403. Si Apache fonctionne sans Nginx (écoute lui-même sur 80/443), rien à ajouter — le .htaccess suffit.
Vérifiez les chemins des binaires avec which (par exemple which ufw cscli ausearch ss). Ne modifiez sudoers qu'avec visudo. La liste de toutes les bases MySQL s'active par un GRANT distinct (FAQ → « Une seule base est visible »).

14. Restriction d'accès par IP

Restreignez l'accès au monitor par adresse IP — même si l'URL est divulguée, la page de connexion ne s'ouvrira pas. Cela peut se faire au niveau du serveur web (exemple pour nginx ci-dessous) ou dans la panel elle-même (« Paramètres » → « Restriction d'accès par IP »). Si vous utilisez Apache, servez-vous de la restriction dans la panel.

Si le site nginx est déjà configuré selon l'étape 10, n'ajoutez pas un second location / — insérez les lignes allow/deny dans le bloc existant. Deux location / identiques dans un même server { } constituent une erreur de configuration, et nginx ne redémarrera pas.
# Dans la config nginx (à l'intérieur de server { }): # On garde le chemin ACME de Let's Encrypt ouvert, en contournant la restriction IP — # pour que l'émission et le renouvellement auto du SSL (étape 15) ne dépendent pas du filtre IP. location ^~ /.well-known/acme-challenge/ { allow all; } location / { allow 203.0.113.10; # ← indiquez votre IP allow 10.0.0.0/8; # réseau local (si nécessaire) deny all; try_files $uri $uri/ /index.php?$query_string; } # Recharger nginx : sudo nginx -t && sudo systemctl reload nginx

15. Émettre un certificat SSL (HTTPS)

Le tableau de bord fonctionne uniquement en HTTPS. La session de connexion utilise un cookie sécurisé, et WebAuthn (2FA) ne fonctionne qu'en HTTPS. Impossible de se connecter via http://.

Le certificat est gratuit (Let's Encrypt). Le DNS du domaine doit déjà pointer vers le serveur. La commande dépend du serveur web :

# Apache: sudo certbot --apache -d monitor.example.com # nginx — UNIQUEMENT si vous utilisez bien nginx. Sur Apache, NE PAS lancer : # apt installera nginx et occupera le port 80, conflit avec Apache. # sudo apt install python3-certbot-nginx # sudo certbot --nginx -d monitor.example.com # certbot inscrit lui-même le HTTPS dans la config et configure le renouvellement auto
Ce que certbot demande : e-mail → acceptation des Terms (Y) → transmission de l'e-mail à l'EFF (à votre discrétion). Ensuite il émet le certificat, inscrit <VirtualHost *:443>, configure la redirection http→https et le renouvellement auto.
Le DNS doit pointer vers le serveur AVANT de lancer certbot (vérification de propriété via le port 80). Vérification : dig +short monitor.example.com → IP du serveur. Ports 80/443 ouverts : sudo ufw allow 80,443/tcp.

Après l'émission : https://monitor.example.com s'ouvre avec le cadenas, http:// redirige vers https:// (APP_URL dans config.php déjà défini à l'étape 12).

16. Connexion et configuration initiale

Ouvrez https://monitor.example.com, connectez-vous avec admin / useradmin et suivez la liste de contrôle :

  1. Changer le mot de passe admin — section « Utilisateurs » dans le menu.
  2. Activer WebAuthn (2FA) — « Clés WebAuthn » → enregistrer une clé/passkey (nécessite HTTPS). Enregistrez-en deux d'emblée : en cas de perte de l'unique clé, la connexion par celle-ci sera impossible. En savoir plus.
  3. Restreindre l'accès par IP — « Paramètres » → « Restriction d'accès par IP » (saisissez votre IP avant d'activer, sinon vous vous bloquez l'accès).
  4. Saisir la licence — activez le code ARCIVEO-… de votre espace client sur votre domaine et collez la clé dans « Paramètres » → « Licence ». En savoir plus.
  5. Configurer les notifications — Telegram et/ou Email dans « Paramètres ». En savoir plus.
  6. Supprimer l'installateur public/start_db.php s'il subsiste (étape 11).

17. Outils de sécurité (facultatif)

Le tableau de bord fonctionne déjà. Les outils s'installent à la demande — vous n'installez que ce dont vous avez besoin, et le tableau de bord affiche aussitôt leur statut. Les commandes d'installation de chacun figurent dans la documentation (sections dédiées par outil) :

18. Cron et maintenance

À configurer une seule fois, également optionnel mais recommandé. Commandes détaillées dans le guide :

  1. Tâches cron (rapports, mise à jour des listes, vérifications) ;
  2. Sauvegarde ;
  3. Mise à jour et migration du panneau ;
  4. Récupération d'accès — en cas de perte de clé/mot de passe.
Quelque chose ne fonctionne pas ou affiche « aucune donnée » ? Consultez la rubrique « Diagnostic » du guide.
Arcivéo - Security Monitor © 2026