🔝 Retour au Sommaire
Sur les systèmes Linux, particulièrement Ubuntu, deux serveurs web dominent le marché : Apache et Nginx. Chacun a ses forces, et FreePascal fonctionne parfaitement avec les deux grâce au support CGI et FastCGI.
| Aspect | Apache | Nginx |
|---|---|---|
| Architecture | Processus par connexion | Événementiel asynchrone |
| Performance | Bonne (< 1000 req/s) | Excellente (> 10000 req/s) |
| Mémoire | Plus gourmand | Très léger |
| Configuration | Fichiers .htaccess | Fichiers centralisés |
| Modules | Très nombreux | Moins nombreux |
| Facilité | Plus simple pour débuter | Syntaxe plus complexe |
| CGI/FastCGI | Support natif excellent | Excellent via proxy |
| Fichiers statiques | Bon | Excellent |
| Usage type | Applications complètes | Reverse proxy, API |
Recommandation :
- Apache : Idéal pour débuter, configuration plus intuitive
- Nginx : Meilleur pour production haute performance
Dans ce tutoriel, nous couvrirons les deux solutions en détail.
Avant toute installation, mettez à jour votre système :
sudo apt update
sudo apt upgrade -ySi ce n'est pas déjà fait :
# FreePascal
sudo apt install -y fpc
# Outils de développement
sudo apt install -y build-essential git
# Vérification
fpc -version# Créer la structure
sudo mkdir -p /var/www/apps
sudo mkdir -p /var/www/apps/monapp/{bin,public,logs}
# Permissions (www-data est l'utilisateur par défaut d'Apache/Nginx)
sudo chown -R $USER:www-data /var/www/apps
sudo chmod -R 755 /var/www/appsStructure obtenue :
/var/www/
├── html/ (site par défaut)
└── apps/
└── monapp/
├── bin/ (exécutables FreePascal)
├── public/ (fichiers statiques CSS, JS, images)
└── logs/ (logs de l'application)
# Installation du serveur Apache
sudo apt install -y apache2
# Installation du module FastCGI
sudo apt install -y libapache2-mod-fcgid
# Vérifier que Apache est actif
sudo systemctl status apache2Test : Ouvrir un navigateur et aller à http://localhost ou http://[IP-du-serveur]
Vous devriez voir la page par défaut d'Apache.
/etc/apache2/
├── apache2.conf (configuration principale)
├── sites-available/ (sites disponibles)
│ ├── 000-default.conf (site par défaut)
│ └── monapp.conf (votre site)
├── sites-enabled/ (liens symboliques vers sites actifs)
├── mods-available/ (modules disponibles)
├── mods-enabled/ (modules actifs)
└── conf-available/ (configurations additionnelles)
Commandes essentielles :
# Activer/désactiver un site
sudo a2ensite monapp # Activer
sudo a2dissite monapp # Désactiver
# Activer/désactiver un module
sudo a2enmod fcgid # Activer FastCGI
sudo a2dismod fcgid # Désactiver
# Recharger la configuration
sudo systemctl reload apache2
# Redémarrer Apache
sudo systemctl restart apache2
# Voir les logs
sudo tail -f /var/log/apache2/error.log
sudo tail -f /var/log/apache2/access.logCréer l'application : webapp.lpr
program WebAppCGI;
{$mode objfpc}{$H+}
uses
SysUtils, Classes;
function GetCGIVar(const VarName: String): String;
begin
Result := GetEnvironmentVariable(VarName);
end;
var
Name: String;
QueryString: String;
begin
// En-têtes HTTP
WriteLn('Content-Type: text/html; charset=utf-8');
WriteLn;
// Récupérer les paramètres
QueryString := GetCGIVar('QUERY_STRING');
if Pos('name=', QueryString) > 0 then
Name := Copy(QueryString, Pos('name=', QueryString) + 5, 100)
else
Name := 'Visiteur';
// Page HTML
WriteLn('<!DOCTYPE html>');
WriteLn('<html lang="fr">');
WriteLn('<head>');
WriteLn(' <meta charset="utf-8">');
WriteLn(' <title>Application FreePascal sur Apache</title>');
WriteLn(' <style>');
WriteLn(' body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; }');
WriteLn(' h1 { color: #2c3e50; }');
WriteLn(' .info { background: #ecf0f1; padding: 15px; border-radius: 5px; }');
WriteLn(' </style>');
WriteLn('</head>');
WriteLn('<body>');
WriteLn(' <h1>Bonjour ', Name, ' !</h1>');
WriteLn(' <p>Cette application FreePascal fonctionne sur Apache/Ubuntu.</p>');
WriteLn(' <div class="info">');
WriteLn(' <strong>Informations de la requête :</strong><br>');
WriteLn(' URI : ', GetCGIVar('REQUEST_URI'), '<br>');
WriteLn(' Méthode : ', GetCGIVar('REQUEST_METHOD'), '<br>');
WriteLn(' Serveur : ', GetCGIVar('SERVER_SOFTWARE'), '<br>');
WriteLn(' IP client : ', GetCGIVar('REMOTE_ADDR'));
WriteLn(' </div>');
WriteLn('</body>');
WriteLn('</html>');
end.Compiler :
fpc -MObjFPC -Scghi webapp.lprDéployer :
# Copier l'exécutable
sudo cp webapp /var/www/apps/monapp/bin/
# Rendre exécutable
sudo chmod +x /var/www/apps/monapp/bin/webapp
# Vérifier les permissions
ls -la /var/www/apps/monapp/bin/webappCréer le fichier de configuration : /etc/apache2/sites-available/monapp.conf
sudo nano /etc/apache2/sites-available/monapp.confContenu :
<VirtualHost *:80>
ServerName monapp.local
ServerAdmin webmaster@localhost
DocumentRoot /var/www/apps/monapp/public
# Répertoire pour les fichiers statiques
<Directory /var/www/apps/monapp/public>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
# Configuration CGI
ScriptAlias /cgi-bin/ /var/www/apps/monapp/bin/
<Directory /var/www/apps/monapp/bin>
Options +ExecCGI
AddHandler cgi-script .cgi
SetHandler cgi-script
Require all granted
</Directory>
# Logs
ErrorLog ${APACHE_LOG_DIR}/monapp-error.log
CustomLog ${APACHE_LOG_DIR}/monapp-access.log combined
</VirtualHost>Activer le site :
# Activer le module CGI
sudo a2enmod cgi
# Activer le site
sudo a2ensite monapp
# Recharger Apache
sudo systemctl reload apache2Tester :
# Accès direct (si vous êtes sur le serveur)
curl http://localhost/cgi-bin/webapp
# Avec paramètre
curl "http://localhost/cgi-bin/webapp?name=Alice"FastCGI offre de bien meilleures performances que CGI.
Application FastCGI : webappfcgi.lpr
program WebAppFastCGI;
{$mode objfpc}{$H+}
uses
fphttpapp, httpdefs, httproute, fpjson, SysUtils;
var
RequestCount: Integer = 0;
procedure HandleHome(ARequest: TRequest; AResponse: TResponse);
begin
Inc(RequestCount);
AResponse.Content := Format(
'<!DOCTYPE html>' +
'<html><head><title>FastCGI</title>' +
'<style>body{font-family:Arial;max-width:800px;margin:50px auto;}</style>' +
'</head><body>' +
'<h1>Application FastCGI FreePascal</h1>' +
'<p>Processus persistant - Performances maximales !</p>' +
'<p><strong>Requêtes traitées :</strong> %d</p>' +
'<p><strong>Heure serveur :</strong> %s</p>' +
'</body></html>',
[RequestCount, FormatDateTime('yyyy-mm-dd hh:nn:ss', Now)]
);
end;
procedure HandleAPI(ARequest: TRequest; AResponse: TResponse);
var
JSONObj: TJSONObject;
begin
JSONObj := TJSONObject.Create;
try
JSONObj.Add('status', 'ok');
JSONObj.Add('message', 'FastCGI opérationnel');
JSONObj.Add('requests', RequestCount);
JSONObj.Add('timestamp', FormatDateTime('yyyy-mm-dd"T"hh:nn:ss', Now));
AResponse.ContentType := 'application/json';
AResponse.Content := JSONObj.AsJSON;
finally
JSONObj.Free;
end;
end;
begin
HTTPRouter.RegisterRoute('/', @HandleHome);
HTTPRouter.RegisterRoute('/api', @HandleAPI);
Application.Title := 'WebApp FastCGI';
Application.Initialize;
Application.Run;
end.Compiler :
fpc -MObjFPC -Scghi webappfcgi.lpr
sudo cp webappfcgi /var/www/apps/monapp/bin/
sudo chmod +x /var/www/apps/monapp/bin/webappfcgiConfiguration Apache pour FastCGI : /etc/apache2/sites-available/monapp-fcgi.conf
<VirtualHost *:80>
ServerName monapp.local
ServerAdmin webmaster@localhost
DocumentRoot /var/www/apps/monapp/public
# Fichiers statiques
<Directory /var/www/apps/monapp/public>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
# Configuration FastCGI
<IfModule mod_fcgid.c>
# Socket Unix pour communication
FcgidIPCDir /var/lib/apache2/fcgid/sock
# Limites et timeouts
FcgidMaxRequestsPerProcess 10000
FcgidMaxProcesses 10
FcgidMinProcessesPerClass 2
FcgidIdleTimeout 600
FcgidProcessLifeTime 3600
FcgidIOTimeout 120
# Wrapper FastCGI
ScriptAlias /fcgi-bin/ /var/www/apps/monapp/bin/
<Directory /var/www/apps/monapp/bin>
Options +ExecCGI
SetHandler fcgid-script
Require all granted
</Directory>
# Rediriger tout vers l'application FastCGI
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /fcgi-bin/webappfcgi/$1 [QSA,L]
</IfModule>
ErrorLog ${APACHE_LOG_DIR}/monapp-fcgi-error.log
CustomLog ${APACHE_LOG_DIR}/monapp-fcgi-access.log combined
</VirtualHost>Activer :
# Modules nécessaires
sudo a2enmod fcgid
sudo a2enmod rewrite
# Activer le site
sudo a2ensite monapp-fcgi
# Désactiver l'ancien si nécessaire
sudo a2dissite monapp
# Recharger
sudo systemctl reload apache2Tester :
curl http://localhost/
curl http://localhost/apiLe compteur de requêtes devrait augmenter (preuve que le processus est persistant) !
Pour de meilleures performances, utilisez un socket Unix plutôt que TCP.
Script de démarrage : /var/www/apps/monapp/bin/start-fcgi.sh
#!/bin/bash
SOCKET_PATH="/var/run/monapp.sock"
APP_PATH="/var/www/apps/monapp/bin/webappfcgi"
# Supprimer l'ancien socket
rm -f $SOCKET_PATH
# Démarrer l'application en mode FastCGI sur socket Unix
$APP_PATH &
# Attendre que le socket soit créé
sleep 2
# Permissions
chmod 666 $SOCKET_PATH
echo "FastCGI démarré sur $SOCKET_PATH"Rendre exécutable :
sudo chmod +x /var/www/apps/monapp/bin/start-fcgi.sh# Installation
sudo apt install -y nginx
# Vérifier le statut
sudo systemctl status nginxTest : http://localhost devrait afficher la page par défaut de Nginx.
/etc/nginx/
├── nginx.conf (configuration principale)
├── sites-available/ (sites disponibles)
│ └── default
├── sites-enabled/ (liens symboliques)
│ └── default -> ../sites-available/default
├── conf.d/ (configurations additionnelles)
└── snippets/ (fragments réutilisables)
Commandes essentielles :
# Tester la configuration
sudo nginx -t
# Recharger
sudo systemctl reload nginx
# Redémarrer
sudo systemctl restart nginx
# Voir les logs
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.logNginx ne supporte pas CGI classique, uniquement FastCGI. C'est une bonne chose : FastCGI est bien plus performant !
Configuration Nginx : /etc/nginx/sites-available/monapp
server {
listen 80;
server_name monapp.local;
root /var/www/apps/monapp/public;
index index.html;
# Logs
access_log /var/log/nginx/monapp-access.log;
error_log /var/log/nginx/monapp-error.log;
# Fichiers statiques
location /static/ {
alias /var/www/apps/monapp/public/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Application FastCGI
location / {
# Inclure les paramètres FastCGI standard
include fastcgi_params;
# Socket Unix (plus rapide)
fastcgi_pass unix:/var/run/monapp.sock;
# Ou TCP/IP
# fastcgi_pass 127.0.0.1:9000;
# Paramètres FastCGI
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
# Timeouts
fastcgi_read_timeout 60s;
fastcgi_send_timeout 60s;
# Buffers
fastcgi_buffer_size 128k;
fastcgi_buffers 256 4k;
fastcgi_busy_buffers_size 256k;
}
}Activer le site :
# Créer le lien symbolique
sudo ln -s /etc/nginx/sites-available/monapp /etc/nginx/sites-enabled/
# Tester la configuration
sudo nginx -t
# Recharger
sudo systemctl reload nginxPour que l'application FastCGI démarre automatiquement au boot.
Créer un service systemd : /etc/systemd/system/monapp-fcgi.service
sudo nano /etc/systemd/system/monapp-fcgi.serviceContenu :
[Unit]
Description=Application FastCGI FreePascal - MonApp
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/apps/monapp/bin
# Supprimer l'ancien socket
ExecStartPre=/bin/rm -f /var/run/monapp.sock
# Démarrer l'application
ExecStart=/var/www/apps/monapp/bin/webappfcgi
# Redémarrage automatique
Restart=always
RestartSec=5
# Limites de ressources
LimitNOFILE=65536
MemoryLimit=512M
# Variables d'environnement
Environment="APP_ENV=production"
Environment="APP_LOG_LEVEL=info"
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=monapp-fcgi
[Install]
WantedBy=multi-user.targetActiver et démarrer :
# Recharger systemd
sudo systemctl daemon-reload
# Activer au démarrage
sudo systemctl enable monapp-fcgi
# Démarrer
sudo systemctl start monapp-fcgi
# Vérifier le statut
sudo systemctl status monapp-fcgi
# Voir les logs
sudo journalctl -u monapp-fcgi -fCommandes utiles :
# Démarrer
sudo systemctl start monapp-fcgi
# Arrêter
sudo systemctl stop monapp-fcgi
# Redémarrer
sudo systemctl restart monapp-fcgi
# Voir l'état
sudo systemctl status monapp-fcgi
# Logs en temps réel
sudo journalctl -u monapp-fcgi -f
# Logs des dernières 100 lignes
sudo journalctl -u monapp-fcgi -n 100Si vous préférez utiliser TCP (plus flexible pour répartition de charge) :
Modifier l'application FreePascal :
begin
Application.Address := '127.0.0.1';
Application.Port := 9000;
Application.Initialize;
Application.Run;
end.Configuration Nginx :
location / {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000; # TCP au lieu de socket Unix
# ... reste identique
}Configuration pour des URLs comme /users/123 :
server {
listen 80;
server_name monapp.local;
root /var/www/apps/monapp/public;
# Logs
access_log /var/log/nginx/monapp-access.log;
error_log /var/log/nginx/monapp-error.log;
# Fichiers statiques
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# API et routes dynamiques
location / {
# Essayer fichier statique d'abord, sinon FastCGI
try_files $uri @fcgi;
}
location @fcgi {
include fastcgi_params;
fastcgi_pass unix:/var/run/monapp.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $uri;
fastcgi_read_timeout 60s;
}
}sudo nano /etc/hostsAjouter :
127.0.0.1 monapp.local
127.0.0.1 api.monapp.local
Maintenant vous pouvez accéder à http://monapp.local dans votre navigateur.
Apache :
# /etc/apache2/sites-available/app1.conf
<VirtualHost *:80>
ServerName app1.local
DocumentRoot /var/www/apps/app1/public
# ... configuration FastCGI ...
</VirtualHost>
# /etc/apache2/sites-available/app2.conf
<VirtualHost *:80>
ServerName app2.local
DocumentRoot /var/www/apps/app2/public
# ... configuration FastCGI ...
</VirtualHost>Nginx :
# /etc/nginx/sites-available/app1
server {
listen 80;
server_name app1.local;
# ... configuration ...
}
# /etc/nginx/sites-available/app2
server {
listen 80;
server_name app2.local;
# ... configuration ...
}# Installation
sudo apt install -y certbot
# Pour Apache
sudo apt install -y python3-certbot-apache
# Pour Nginx
sudo apt install -y python3-certbot-nginxPour Apache :
sudo certbot --apache -d monapp.example.comPour Nginx :
sudo certbot --nginx -d monapp.example.comRenouvellement automatique :
Certbot installe automatiquement un cron/timer pour renouveler les certificats.
Vérifier :
sudo systemctl status certbot.timer
# Test de renouvellement
sudo certbot renew --dry-runApache : /etc/apache2/sites-available/monapp-ssl.conf
<VirtualHost *:443>
ServerName monapp.example.com
DocumentRoot /var/www/apps/monapp/public
# SSL
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/monapp.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/monapp.example.com/privkey.pem
# Configuration FastCGI
# ... (identique à HTTP)
</VirtualHost>
# Redirection HTTP → HTTPS
<VirtualHost *:80>
ServerName monapp.example.com
Redirect permanent / https://monapp.example.com/
</VirtualHost>Activer :
sudo a2enmod ssl
sudo a2ensite monapp-ssl
sudo systemctl reload apache2Nginx :
# Redirection HTTP → HTTPS
server {
listen 80;
server_name monapp.example.com;
return 301 https://$server_name$request_uri;
}
# HTTPS
server {
listen 443 ssl http2;
server_name monapp.example.com;
# Certificats SSL
ssl_certificate /etc/letsencrypt/live/monapp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/monapp.example.com/privkey.pem;
# Configuration SSL moderne
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Headers de sécurité
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
root /var/www/apps/monapp/public;
# Configuration FastCGI
location / {
include fastcgi_params;
fastcgi_pass unix:/var/run/monapp.sock;
# ... reste de la config
}
}/etc/apache2/apache2.conf - Ajustements :
# Nombre de workers
<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 3000
</IfModule>
# Ou mieux, utiliser mpm_event (plus performant)
<IfModule mpm_event_module>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 150
MaxConnectionsPerChild 3000
</IfModule>
# Compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
</IfModule>
# Cache
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>Activer les modules :
sudo a2enmod deflate
sudo a2enmod expires
sudo a2enmod headers
sudo a2enmod mpm_event
sudo systemctl restart apache2/etc/nginx/nginx.conf :
user www-data;
worker_processes auto; # Un par cœur CPU
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
# Performance
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# Timeouts
keepalive_timeout 65;
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;
# Buffers
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 10m;
large_client_header_buffers 2 1k;
# Compression Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml+rss;
# Cache fichiers ouverts
open_file_cache max=200000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# Logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
# Inclure les configurations des sites
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}Redémarrer :
sudo nginx -t
sudo systemctl restart nginx# Dernières erreurs
sudo tail -f /var/log/apache2/error.log
# Requêtes en temps réel
sudo tail -f /var/log/apache2/access.log
# Statistiques du jour
sudo cat /var/log/apache2/access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -10
# Codes de statut
sudo awk '{print $9}' /var/log/apache2/access.log | sort | uniq -c | sort -nr# Dernières erreurs
sudo tail -f /var/log/nginx/error.log
# Requêtes en temps réel
sudo tail -f /var/log/nginx/access.log
# Top 10 IPs
sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
# URLs les plus demandées
sudo awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10Installation :
sudo apt install -y htop net-toolsSurveiller les ressources :
# Processus en temps réel
htop
# Connexions réseau actives
sudo netstat -tulpn | grep nginx
sudo netstat -tulpn | grep apache2
# Nombre de connexions par état
sudo netstat -an | grep :80 | awk '{print $6}' | sort | uniq -c | sort -nrCréer : /usr/local/bin/monapp-monitor.sh
#!/bin/bash
# Couleurs
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
APP_NAME="monapp-fcgi"
SOCKET_PATH="/var/run/monapp.sock"
echo "=== Monitoring MonApp ==="
echo "Date: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
# 1. Vérifier le service systemd
echo -n "Service $APP_NAME: "
if systemctl is-active --quiet $APP_NAME; then
echo -e "${GREEN}✓ Actif${NC}"
else
echo -e "${RED}✗ Inactif${NC}"
fi
# 2. Vérifier le socket
echo -n "Socket $SOCKET_PATH: "
if [ -S "$SOCKET_PATH" ]; then
echo -e "${GREEN}✓ Présent${NC}"
else
echo -e "${RED}✗ Absent${NC}"
fi
# 3. Processus
echo ""
echo "Processus:"
ps aux | grep webappfcgi | grep -v grep | awk '{printf " PID: %s | CPU: %s%% | MEM: %s%% | RSS: %s KB\n", $2, $3, $4, $6}'
# 4. Mémoire et CPU
echo ""
echo "Ressources système:"
free -h | grep Mem | awk '{printf " Mémoire: %s utilisé / %s total (%s disponible)\n", $3, $2, $7}'
uptime | awk '{printf " Load average: %s\n", substr($0, index($0,"average:")+9)}'
# 5. Espace disque
echo ""
echo "Espace disque /var:"
df -h /var | tail -1 | awk '{printf " %s utilisé / %s total (%s disponible) - %s\n", $3, $2, $4, $5}'
# 6. Connexions réseau
echo ""
echo "Connexions réseau:"
NGINX_CONN=$(netstat -an | grep :80 | grep ESTABLISHED | wc -l)
echo " Connexions établies: $NGINX_CONN"
# 7. Logs récents
echo ""
echo "Dernières erreurs (5 dernières lignes):"
if [ -f "/var/log/nginx/error.log" ]; then
sudo tail -5 /var/log/nginx/error.log | sed 's/^/ /'
elif [ -f "/var/log/apache2/error.log" ]; then
sudo tail -5 /var/log/apache2/error.log | sed 's/^/ /'
else
echo " Aucun log trouvé"
fi
# 8. Health check HTTP
echo ""
echo -n "Health check HTTP: "
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/health 2>/dev/null)
if [ "$HTTP_CODE" = "200" ]; then
echo -e "${GREEN}✓ OK (200)${NC}"
elif [ -z "$HTTP_CODE" ]; then
echo -e "${RED}✗ Pas de réponse${NC}"
else
echo -e "${YELLOW}⚠ Code $HTTP_CODE${NC}"
fi
echo ""
echo "=== Fin du rapport ==="Rendre exécutable :
sudo chmod +x /usr/local/bin/monapp-monitor.shUtilisation :
sudo /usr/local/bin/monapp-monitor.shAutomatiser avec cron (toutes les 5 minutes dans un log) :
sudo crontab -eAjouter :
*/5 * * * * /usr/local/bin/monapp-monitor.sh >> /var/log/monapp-monitoring.log 2>&1Ajouter dans votre application FreePascal :
uses
fphttpapp, httpdefs, httproute, fpjson, SysUtils, Unix;
var
AppStartTime: TDateTime;
TotalRequests: Int64 = 0;
procedure HandleHealth(ARequest: TRequest; AResponse: TResponse);
var
JSONObj: TJSONObject;
UptimeSeconds: Int64;
LoadAvg: array[0..2] of Double;
begin
JSONObj := TJSONObject.Create;
try
// Statut général
JSONObj.Add('status', 'ok');
JSONObj.Add('timestamp', FormatDateTime('yyyy-mm-dd"T"hh:nn:ss', Now));
// Uptime
UptimeSeconds := Round((Now - AppStartTime) * 86400);
JSONObj.Add('uptime_seconds', UptimeSeconds);
JSONObj.Add('uptime_human', Format('%d jours %d heures',
[UptimeSeconds div 86400, (UptimeSeconds mod 86400) div 3600]));
// Statistiques requêtes
JSONObj.Add('total_requests', TotalRequests);
if UptimeSeconds > 0 then
JSONObj.Add('requests_per_second',
FormatFloat('0.00', TotalRequests / UptimeSeconds));
// Load average (Linux uniquement)
{$IFDEF LINUX}
if getloadavg(@LoadAvg[0], 3) = 3 then
begin
JSONObj.Add('load_average_1min', FormatFloat('0.00', LoadAvg[0]));
JSONObj.Add('load_average_5min', FormatFloat('0.00', LoadAvg[1]));
JSONObj.Add('load_average_15min', FormatFloat('0.00', LoadAvg[2]));
end;
{$ENDIF}
// Mémoire
JSONObj.Add('memory_allocated_mb',
Round(GetHeapStatus.TotalAllocated / (1024 * 1024)));
// Version
JSONObj.Add('version', '1.0.0');
AResponse.ContentType := 'application/json';
AResponse.Content := JSONObj.AsJSON;
AResponse.Code := 200;
finally
JSONObj.Free;
end;
end;
procedure RequestMiddleware(ARequest: TRequest; AResponse: TResponse);
begin
Inc(TotalRequests);
end;
begin
AppStartTime := Now;
// Enregistrer le endpoint de santé
HTTPRouter.RegisterRoute('/health', @HandleHealth);
// Middleware pour compter les requêtes
Application.OnRequest := @RequestMiddleware;
Application.Initialize;
Application.Run;
end.Installation :
sudo apt install -y goaccessUtilisation :
# Analyse interactive des logs Nginx
sudo goaccess /var/log/nginx/access.log --log-format=COMBINED
# Générer un rapport HTML
sudo goaccess /var/log/nginx/access.log \
--log-format=COMBINED \
-o /var/www/apps/monapp/public/stats.html
# Temps réel
sudo goaccess /var/log/nginx/access.log \
--log-format=COMBINED \
--real-time-html \
-o /var/www/apps/monapp/public/stats.htmlAccéder aux statistiques : http://monapp.local/stats.html
Installation :
# Script d'installation automatique
bash <(curl -Ss https://my-netdata.io/kickstart.sh)Accès : http://localhost:19999
Netdata fournit :
- CPU, mémoire, disque en temps réel
- Processus et applications
- Nginx/Apache monitoring
- Alertes configurables
Pour un monitoring professionnel avec métriques et dashboards.
Installation Prometheus :
sudo apt install -y prometheusExporter des métriques depuis FreePascal :
procedure HandleMetrics(ARequest: TRequest; AResponse: TResponse);
var
Metrics: TStringList;
begin
Metrics := TStringList.Create;
try
// Format Prometheus
Metrics.Add('# HELP monapp_requests_total Total requests');
Metrics.Add('# TYPE monapp_requests_total counter');
Metrics.Add(Format('monapp_requests_total %d', [TotalRequests]));
Metrics.Add('# HELP monapp_uptime_seconds Uptime in seconds');
Metrics.Add('# TYPE monapp_uptime_seconds gauge');
Metrics.Add(Format('monapp_uptime_seconds %d',
[Round((Now - AppStartTime) * 86400)]));
Metrics.Add('# HELP monapp_memory_bytes Memory usage in bytes');
Metrics.Add('# TYPE monapp_memory_bytes gauge');
Metrics.Add(Format('monapp_memory_bytes %d',
[GetHeapStatus.TotalAllocated]));
AResponse.ContentType := 'text/plain; version=0.0.4';
AResponse.Content := Metrics.Text;
finally
Metrics.Free;
end;
end;
// Enregistrer
HTTPRouter.RegisterRoute('/metrics', @HandleMetrics);Installation et configuration :
# Installation
sudo apt install -y ufw
# Règles de base
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Autoriser SSH (important !)
sudo ufw allow ssh
sudo ufw allow 22/tcp
# Autoriser HTTP et HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Activer le firewall
sudo ufw enable
# Vérifier le statut
sudo ufw status verboseLimiter les connexions SSH (protection brute-force) :
sudo ufw limit sshInstallation :
sudo apt install -y fail2banConfiguration : /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.localContenu :
[DEFAULT]
# Bannir pour 1 heure
bantime = 3600
# Fenêtre de 10 minutes
findtime = 600
# 5 tentatives max
maxretry = 5
# Email d'alerte (optionnel)
destemail = admin@example.com
sendername = Fail2Ban
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
[nginx-limit-req]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
[apache-auth]
enabled = true
port = http,https
logpath = /var/log/apache*/*error.log
[apache-noscript]
enabled = true
port = http,https
logpath = /var/log/apache*/*error.logDémarrer et activer :
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# Vérifier le statut
sudo fail2ban-client status
# Statut d'une jail spécifique
sudo fail2ban-client status sshdCréer un utilisateur dédié pour l'application :
# Créer l'utilisateur sans login shell
sudo useradd -r -s /bin/false monapp
# Changer le propriétaire
sudo chown -R monapp:www-data /var/www/apps/monapp
# Permissions
sudo chmod 750 /var/www/apps/monapp/bin
sudo chmod 770 /var/www/apps/monapp/logsModifier le service systemd :
[Service]
User=monapp
Group=www-dataNginx :
# Dans http {}
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=general_limit:10m rate=50r/s;
server {
# API limitée
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
# ... FastCGI config
}
# Limite générale
location / {
limit_req zone=general_limit burst=100 nodelay;
# ... FastCGI config
}
}Apache (avec mod_evasive) :
sudo apt install -y libapache2-mod-evasive
sudo a2enmod evasiveConfiguration : /etc/apache2/mods-enabled/evasive.conf
<IfModule mod_evasive20.c>
DOSHashTableSize 3097
DOSPageCount 5
DOSSiteCount 100
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 60
DOSEmailNotify admin@example.com
</IfModule>Nginx :
# Headers de sécurité communs
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Masquer la version Nginx
server_tokens off;Apache :
# Dans la configuration du site ou .htaccess
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "no-referrer-when-downgrade"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
# Masquer la version Apache
ServerTokens Prod
ServerSignature OffCréer : /usr/local/bin/deploy-monapp.sh
#!/bin/bash
set -e # Arrêter en cas d'erreur
APP_NAME="monapp"
APP_USER="monapp"
APP_PATH="/var/www/apps/$APP_NAME"
BINARY_NAME="webappfcgi"
SERVICE_NAME="monapp-fcgi"
BACKUP_PATH="/var/backups/monapp"
# Couleurs
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
echo -e "${GREEN}=== Déploiement de $APP_NAME ===${NC}"
echo "Date: $(date '+%Y-%m-%d %H:%M:%S')"
# 1. Vérifications préalables
echo -e "\n${YELLOW}[1/8] Vérifications...${NC}"
if [ ! -f "$BINARY_NAME" ]; then
echo -e "${RED}Erreur: Binaire $BINARY_NAME non trouvé${NC}"
exit 1
fi
if ! systemctl is-active --quiet $SERVICE_NAME; then
echo -e "${YELLOW}Avertissement: Service non actif${NC}"
fi
# 2. Backup
echo -e "\n${YELLOW}[2/8] Création du backup...${NC}"
BACKUP_DATE=$(date '+%Y%m%d_%H%M%S')
mkdir -p $BACKUP_PATH
if [ -f "$APP_PATH/bin/$BINARY_NAME" ]; then
cp "$APP_PATH/bin/$BINARY_NAME" "$BACKUP_PATH/${BINARY_NAME}_$BACKUP_DATE"
echo "Backup créé: ${BINARY_NAME}_$BACKUP_DATE"
fi
# 3. Arrêt du service
echo -e "\n${YELLOW}[3/8] Arrêt du service...${NC}"
sudo systemctl stop $SERVICE_NAME
sleep 2
# 4. Copie du nouveau binaire
echo -e "\n${YELLOW}[4/8] Copie du binaire...${NC}"
sudo cp $BINARY_NAME $APP_PATH/bin/
sudo chown $APP_USER:www-data $APP_PATH/bin/$BINARY_NAME
sudo chmod 750 $APP_PATH/bin/$BINARY_NAME
# 5. Vérification des permissions
echo -e "\n${YELLOW}[5/8] Vérification des permissions...${NC}"
sudo chown -R $APP_USER:www-data $APP_PATH
sudo chmod 750 $APP_PATH/bin
sudo chmod 770 $APP_PATH/logs
# 6. Nettoyage
echo -e "\n${YELLOW}[6/8] Nettoyage...${NC}"
# Supprimer l'ancien socket
sudo rm -f /var/run/monapp.sock
# Nettoyer les vieux logs (> 30 jours)
find $APP_PATH/logs -name "*.log" -mtime +30 -delete
# 7. Redémarrage du service
echo -e "\n${YELLOW}[7/8] Redémarrage du service...${NC}"
sudo systemctl start $SERVICE_NAME
sleep 3
# 8. Vérification
echo -e "\n${YELLOW}[8/8] Vérification...${NC}"
if systemctl is-active --quiet $SERVICE_NAME; then
echo -e "${GREEN}✓ Service actif${NC}"
else
echo -e "${RED}✗ Service inactif${NC}"
echo "Logs récents:"
sudo journalctl -u $SERVICE_NAME -n 20 --no-pager
exit 1
fi
# Health check
sleep 2
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/health 2>/dev/null)
if [ "$HTTP_CODE" = "200" ]; then
echo -e "${GREEN}✓ Health check OK${NC}"
else
echo -e "${RED}✗ Health check échoué (code: $HTTP_CODE)${NC}"
exit 1
fi
# Nettoyer les anciens backups (garder 10 derniers)
ls -t $BACKUP_PATH/${BINARY_NAME}_* | tail -n +11 | xargs -r rm
echo -e "\n${GREEN}=== Déploiement réussi ===${NC}"
echo "Version déployée: $(stat -c %y $APP_PATH/bin/$BINARY_NAME)"Rendre exécutable :
sudo chmod +x /usr/local/bin/deploy-monapp.shUtilisation :
# Compiler votre application
fpc -O3 -MObjFPC -Scghi webappfcgi.lpr
# Déployer
sudo /usr/local/bin/deploy-monapp.sh.github/workflows/deploy.yml :
name: Deploy to Ubuntu Server
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install FreePascal
run: |
sudo apt update
sudo apt install -y fpc
- name: Compile application
run: |
fpc -O3 -MObjFPC -Scghi webappfcgi.lpr
- name: Deploy to server
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
SERVER_HOST: ${{ secrets.SERVER_HOST }}
SERVER_USER: ${{ secrets.SERVER_USER }}
run: |
# Configuration SSH
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H $SERVER_HOST >> ~/.ssh/known_hosts
# Copie du binaire
scp webappfcgi $SERVER_USER@$SERVER_HOST:/tmp/
# Déploiement
ssh $SERVER_USER@$SERVER_HOST 'sudo /usr/local/bin/deploy-monapp.sh'Playbook Ansible : deploy.yml
---
- name: Deploy FreePascal Application
hosts: webservers
become: yes
vars:
app_name: monapp
app_path: /var/www/apps/monapp
service_name: monapp-fcgi
tasks:
- name: Create backup
copy:
src: "{{ app_path }}/bin/webappfcgi"
dest: "/var/backups/monapp/webappfcgi_{{ ansible_date_time.iso8601_basic_short }}"
remote_src: yes
ignore_errors: yes
- name: Stop service
systemd:
name: "{{ service_name }}"
state: stopped
- name: Copy new binary
copy:
src: ./webappfcgi
dest: "{{ app_path }}/bin/webappfcgi"
owner: monapp
group: www-data
mode: '0750'
- name: Start service
systemd:
name: "{{ service_name }}"
state: started
daemon_reload: yes
- name: Wait for service
wait_for:
path: /var/run/monapp.sock
timeout: 30
- name: Health check
uri:
url: http://localhost/health
status_code: 200
register: health_check
retries: 5
delay: 2Exécution :
ansible-playbook -i inventory deploy.ymlCauses possibles :
- Service FastCGI non démarré
- Socket inexistant ou mauvaises permissions
- Application plantée
Diagnostic :
# Vérifier le service
sudo systemctl status monapp-fcgi
# Vérifier le socket
ls -la /var/run/monapp.sock
# Logs
sudo journalctl -u monapp-fcgi -n 50
sudo tail -50 /var/log/nginx/error.logSolutions :
# Redémarrer le service
sudo systemctl restart monapp-fcgi
# Vérifier les permissions du socket
sudo chmod 666 /var/run/monapp.sock
# Test manuel de l'application
sudo -u monapp /var/www/apps/monapp/bin/webappfcgi# Corriger les permissions
sudo chown www-data:www-data /var/run/monapp.sock
sudo chmod 666 /var/run/monapp.sock
# Ou ajouter nginx/apache au groupe monapp
sudo usermod -a -G monapp www-dataVérifier les dépendances :
# Lister les bibliothèques requises
ldd /var/www/apps/monapp/bin/webappfcgi
# Installer les dépendances manquantes
sudo apt install -y libssl1.1 libmysqlclient21Nginx :
location / {
fastcgi_read_timeout 300s; # 5 minutes
fastcgi_send_timeout 300s;
# ...
}Apache :
FcgidIOTimeout 300
FcgidBusyTimeout 300Configuration logrotate : /etc/logrotate.d/monapp
sudo nano /etc/logrotate.d/monappContenu :
/var/www/apps/monapp/logs/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 monapp www-data
sharedscripts
postrotate
systemctl reload monapp-fcgi > /dev/null 2>&1 || true
endscript
}
Test :
sudo logrotate -f /etc/logrotate.d/monappScript de mise à jour sûre :
#!/bin/bash
echo "=== Mise à jour du système ==="
# 1. Backup de la configuration
sudo cp -r /etc/nginx /etc/nginx.backup.$(date +%Y%m%d)
sudo cp -r /etc/apache2 /etc/apache2.backup.$(date +%Y%m%d)
# 2. Mise à jour des paquets
sudo apt update
sudo apt upgrade -y
# 3. Nettoyage
sudo apt autoremove -y
sudo apt autoclean
# 4. Vérifier les services
sudo systemctl status nginx
sudo systemctl status apache2
sudo systemctl status monapp-fcgi
echo "Mise à jour terminée"La configuration d'Apache ou Nginx sur Ubuntu pour des applications FreePascal nécessite :
✅ Installation correcte du serveur web et modules FastCGI
✅ Configuration optimisée pour la production
✅ Service systemd pour gestion automatique
✅ SSL/HTTPS avec Let's Encrypt
✅ Monitoring actif et logs configurés
✅ Sécurité renforcée (firewall, fail2ban, rate limiting)
✅ Scripts de déploiement automatisés
✅ Backup et plans de restauration
Avec cette configuration complète, vos applications FreePascal fonctionneront de manière stable, performante et sécurisée sur Ubuntu avec Apache ou Nginx.
| Critère | Apache | Nginx | Recommandation |
|---|---|---|---|
| Débutant | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | Apache |
| Performance | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Nginx |
| Mémoire | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Nginx |
| Configuration | ⭐⭐⭐⭐ | ⭐⭐⭐ | Apache |
| Modules | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | Apache |
| FastCGI | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Nginx |
| Reverse Proxy | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Nginx |
Verdict :
- Apprentissage et petits projets → Apache
- Production haute performance → Nginx
- Les deux sont excellents pour FreePascal !
Dans la section suivante, nous explorerons le Brook Framework pour développer des API REST modernes avec FreePascal.