WordPress — Stack complète
Installe WordPress sur une stack Nginx + PHP-FPM (sury.org) + MariaDB en une seule commande.
Variables requises :
WP_DOMAIN— domaine du site (ex :monsite.fr)
Variables optionnelles :
WP_DIR— répertoire d'install (défaut :/var/www/$WP_DOMAIN)WP_DB_NAME— nom de la base (défaut :wordpress)WP_DB_USER— utilisateur DB (défaut :wpuser)
Ce que fait le script :
- Installe Nginx, PHP-FPM (dernière version via sury.org), MariaDB si absents
- Crée la base de données + utilisateur avec mot de passe aléatoire
- Télécharge et configure WordPress (wp-config.php + salts)
- Crée le vhost Nginx pour le domaine
- Configure les permissions (
www-data) - Affiche l'URL et les credentials à la fin
Après l'install : certbot --nginx -d $WP_DOMAIN
bash
#!/bin/bash
set -euo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERR]${NC} $*"; exit 1; }
[[ $EUID -ne 0 ]] && error "Ce script doit être exécuté en root."
[[ -z "${WP_DOMAIN:-}" ]] && error "Variable WP_DOMAIN requise. Ex : WP_DOMAIN=monsite.fr bash <(curl ...)"
export DEBIAN_FRONTEND=noninteractive
WP_DOMAIN="${WP_DOMAIN}"
WP_DIR="${WP_DIR:-/var/www/${WP_DOMAIN}}"
WP_DB_NAME="${WP_DB_NAME:-wordpress}"
WP_DB_USER="${WP_DB_USER:-wpuser}"
WP_DB_PASS=$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 24)
OS_CODE=$(grep -oP '(?<=^VERSION_CODENAME=).+' /etc/os-release)
info "=== WordPress pour $WP_DOMAIN ==="
# ── Nginx ─────────────────────────────────────────────────────────────────────
if ! command -v nginx &>/dev/null; then
info "=== Installation de Nginx ==="
apt-get update -qq && apt-get install -y nginx
fi
# ── PHP ───────────────────────────────────────────────────────────────────────
if ! command -v php &>/dev/null; then
info "=== Installation de PHP ==="
apt-get install -y apt-transport-https ca-certificates curl gnupg2
curl -fsSL https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /usr/share/keyrings/sury-php.gpg
echo "deb [signed-by=/usr/share/keyrings/sury-php.gpg] https://packages.sury.org/php/ $OS_CODE main" \
> /etc/apt/sources.list.d/sury-php.list
apt-get update -qq
fi
PHP_VER=$(apt-cache search '^php[0-9]\.[0-9]-fpm$' | awk '{print $1}' | grep -oP '[0-9]+\.[0-9]+' | sort -V | tail -1)
info "PHP $PHP_VER"
apt-get install -y \
php${PHP_VER}-fpm php${PHP_VER}-mysql php${PHP_VER}-curl \
php${PHP_VER}-gd php${PHP_VER}-mbstring php${PHP_VER}-xml \
php${PHP_VER}-zip php${PHP_VER}-intl php${PHP_VER}-bcmath \
php${PHP_VER}-imagick 2>/dev/null || \
apt-get install -y \
php${PHP_VER}-fpm php${PHP_VER}-mysql php${PHP_VER}-curl \
php${PHP_VER}-gd php${PHP_VER}-mbstring php${PHP_VER}-xml \
php${PHP_VER}-zip php${PHP_VER}-intl php${PHP_VER}-bcmath
# ── MariaDB ───────────────────────────────────────────────────────────────────
if ! command -v mariadb &>/dev/null && ! command -v mysql &>/dev/null; then
info "=== Installation de MariaDB ==="
apt-get install -y mariadb-server
systemctl enable --now mariadb
fi
# ── Base de données ───────────────────────────────────────────────────────────
info "=== Création de la base de données ==="
mariadb -u root <<SQL
CREATE DATABASE IF NOT EXISTS \`${WP_DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '${WP_DB_USER}'@'localhost' IDENTIFIED BY '${WP_DB_PASS}';
GRANT ALL PRIVILEGES ON \`${WP_DB_NAME}\`.* TO '${WP_DB_USER}'@'localhost';
FLUSH PRIVILEGES;
SQL
# ── Téléchargement WordPress ──────────────────────────────────────────────────
info "=== Téléchargement de WordPress ==="
apt-get install -y curl wget unzip
mkdir -p "$WP_DIR"
curl -fsSL https://wordpress.org/latest.tar.gz | tar -xz -C /tmp
cp -r /tmp/wordpress/. "$WP_DIR/"
rm -rf /tmp/wordpress
# ── Configuration wp-config.php ───────────────────────────────────────────────
info "=== Configuration WordPress ==="
cp "$WP_DIR/wp-config-sample.php" "$WP_DIR/wp-config.php"
SALTS=$(curl -fsSL https://api.wordpress.org/secret-key/1.1/salt/)
sed -i "s/database_name_here/${WP_DB_NAME}/" "$WP_DIR/wp-config.php"
sed -i "s/username_here/${WP_DB_USER}/" "$WP_DIR/wp-config.php"
sed -i "s/password_here/${WP_DB_PASS}/" "$WP_DIR/wp-config.php"
# Remplace le bloc de salts
PHP_SALT_START="define( 'AUTH_KEY'"
PHP_SALT_END="define( 'NONCE_SALT'"
ESCAPED_SALTS=$(echo "$SALTS" | sed 's/[&/\]/\\&/g')
perl -i -0pe "s/define\( 'AUTH_KEY'.*?define\( 'NONCE_SALT'.*?;\n/${ESCAPED_SALTS}\n/s" "$WP_DIR/wp-config.php" 2>/dev/null || true
# Forcer HTTPS
cat >> "$WP_DIR/wp-config.php" <<'PHP'
/* HTTPS */
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
define('FORCE_SSL_ADMIN', true);
PHP
# ── Permissions ───────────────────────────────────────────────────────────────
chown -R www-data:www-data "$WP_DIR"
find "$WP_DIR" -type d -exec chmod 755 {} \;
find "$WP_DIR" -type f -exec chmod 644 {} \;
# ── Vhost Nginx ───────────────────────────────────────────────────────────────
info "=== Configuration Nginx ==="
cat > "/etc/nginx/sites-available/${WP_DOMAIN}.conf" <<EOF
server {
listen 80;
listen [::]:80;
server_name ${WP_DOMAIN} www.${WP_DOMAIN};
root ${WP_DIR};
index index.php index.html;
access_log /var/log/nginx/${WP_DOMAIN}.access.log;
error_log /var/log/nginx/${WP_DOMAIN}.error.log;
client_max_body_size 64M;
location = /favicon.ico { log_not_found off; access_log off; }
location = /robots.txt { log_not_found off; access_log off; }
location ~ /\. { deny all; }
location ~* /(?:uploads|files)/.*\.php$ { deny all; }
location / {
try_files \$uri \$uri/ /index.php?\$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php${PHP_VER}-fpm.sock;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include fastcgi_params;
fastcgi_read_timeout 120;
}
location ~* \.(css|gif|ico|jpeg|jpg|js|png|woff2?|svg|ttf)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
log_not_found off;
}
}
EOF
ln -sf "/etc/nginx/sites-available/${WP_DOMAIN}.conf" "/etc/nginx/sites-enabled/${WP_DOMAIN}.conf"
nginx -t && systemctl reload nginx
systemctl restart "php${PHP_VER}-fpm"
# ── Sauvegarde credentials ────────────────────────────────────────────────────
CREDS_FILE="/root/.wp_${WP_DOMAIN//[^a-zA-Z0-9]/_}_credentials"
cat > "$CREDS_FILE" <<EOF
# WordPress — $WP_DOMAIN — $(date '+%d/%m/%Y')
WP_DIR = $WP_DIR
WP_DOMAIN = $WP_DOMAIN
DB_NAME = $WP_DB_NAME
DB_USER = $WP_DB_USER
DB_PASSWORD = $WP_DB_PASS
EOF
chmod 600 "$CREDS_FILE"
echo ""
info "=== WordPress installé ==="
echo ""
echo " URL : http://${WP_DOMAIN}/"
echo " Répertoire : $WP_DIR"
echo " Base DB : $WP_DB_NAME"
echo " Credentials : $CREDS_FILE"
echo ""
echo " Finalise l'install en ouvrant : http://${WP_DOMAIN}/"
echo ""
echo " SSL Let's Encrypt :"
echo " certbot --nginx -d ${WP_DOMAIN} -d www.${WP_DOMAIN}"
echo ""
warn "Conserve $CREDS_FILE en lieu sûr !"
echo ""