Outils pour utilisateurs

Outils du site


serveurs:nginx:php

(Basé sur une distribution ArchLinux)

Installation de base (non chrootée)

Installer nginx + php-fpm :

pacman -S nginx php-fpm

La configuration de nginx pour la partie PHP :

        location ~ \.php$ {
            try_files $uri =404;
            root           /home/<user>/www;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_param  SCRIPT_FILENAME  /home/<user>/www$fastcgi_script_name;
            fastcgi_index  index.php;
            include        fastcgi_params;
        }

(ne pas oublier de modifier tous les root)

Dans /etc/rc.conf, ajouter php-fpm et nginx aux services à démarrer :

DAEMONS=(syslog-ng network netfs sshd crond php-fpm nginx)

Dans /etc/php/php-fpm.conf, décommenter la ligne suivante :

include=/etc/php/fpm.d/*.conf

Créer /etc/php/fpm.d/<user>.conf :

[<user>]

listen = 127.0.0.1:9000

user  = <user>
group = <user>

pm = dynamic
pm.max_children      = 50
pm.start_servers     = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500

pm.status_path = /fpm-status
ping.path      = /fpm-ping

request_terminate_timeout = 10s
request_slowlog_timeout   = 10s

slowlog = /home/<user>/www/logs/php-fpm.log

#chroot = /home/<user>/www
#chdir  =

env[TMP] = /home/<user>/www/tmp

php_admin_value[error_log] = /home/<user>/www/logs/php.log

Commandes complémentaires à exécuter :

  • en tant qu'utilisateur :
mkdir -p /home/<user>/www/logs
chown -R :http /home/<user>/www
find /home/<user>/www/ -type f -exec chmod g+r {} \;
find /home/<user>/www/ -type d -exec chmod g+rx {} \;
chmod 0755 /home/<user>
  • en tant que root :
usermod -aG http <user>
usermod -aG http http

Démarrer à la main les services à moins d'attendre le prochain (re)démarrage :

/etc/rc.d/php-fpm start
/etc/rc.d/nginx start

chrooter

  • Décommenter la ligne chroot de /etc/php/fpm.d/<user>.conf
  • Modifier la ligne fastcgi_param de SCRIPT_FILENAME dans le fichier de configuration de nginx (/etc/nginx/conf/nginx.conf) de façon à avoir :
                fastcgi_param  SCRIPT_FILENAME  $fastcgi_script_name;
  • Ajouter, à la suite de celle ci-dessus :
    fastcgi_param DOCUMENT_ROOT /;
  • Dans /etc/nginx/conf/fastcgi_params, commenter celle-ci :
    fastcgi_param  DOCUMENT_ROOT      $document_root;

Pour chaque site/utilisateur :

  • créer un serveur nginx (bloc server)
  • créer une configuration php-fpm propre (en commençant par modifier la directive listen : le port ou le socket doit être différent)

FTP

pacman -S vsftpd

Dans /etc/vsftpd.conf, apporter les changements suivants :

anonymous_enable=YES

A changer en NO

local_umask=022

A changer en 027

Décommenter les lignes :

local_enable=YES
write_enable=YES
chroot_local_user=YES

Autoriser les entrées au serveur FTP (tcpwrapper) en modifiant /etc/hosts.allow :

vsftpd: ALL

Démarrage du service : ajouter vsftpd aux DAEMONS (/etc/rc.conf) :

DAEMONS = (... vsftpd)

Attendre le prochain (re)démarrage sinon, démarrer manuellement le service par :

/etc/rc.d/vsftpd start

SSH

Installer ssh :

pacman -S openssh

Éditer /etc/ssh/sshd_config, ajouter/remplacer :

ChrootDirectory %h

Autoriser les connexions ssh (tcpwrapper) en ajoutant à /etc/hosts.allow :

sshd: ALL

Démarrage automatique du service : ajouter sshd au tableau DAEMONS de /etc/rc.conf :

DAEMONS = (... sshd)

Attendre le prochain (re)démarrage de la machine, sinon le démarrer manuellement :

/etc/rc.d/sshd start

À faire

  • du plus "propre" : créer/utiliser un groupe dédié ?, revoir l'aborescence de la partie chrootée (plus "profonde") ?
  • services (SSH ?, FTP ?)
  • tout ce qui est lié au chroot (résolution des noms ?, accès à MySQL ?, changer le répertoire temporaire TMP ?, locale(s) ?)

MySQL :

# Activer le pilote MySQL de PDO
echo 'extension=pdo_mysql.so' >> /etc/php/conf.d/mysql.ini
pacman -S mysql
/etc/rc.d/mysqld start && mysql_secure_installation
# Ajouter mysqld au DAEMONS
# --
# Dans PHP : utiliser l'adresse IP extérieure de la machine
# Pour MySQL :
# - commenter skip-networking dans /etc/mysql/my.cnf
# - créer les comptes MySQL pour les permettre d'y accéder en conséquence (grant all privileges on <db>.* to <user>@'192.168.0.%' identified by '<mdp>';)
# - whitelister les entrées MySQL dans tcpwrapper (/etc/hosts.allow) en y ajoutant : mysqld: 192.168.0.0/255.255.255.0

Résolution DNS :

mkdir /home/<user>/www/etc
cp /etc/{resolv,nsswitch}.conf /home/<user>/www/etc/
mkdir /home/<user>/www/lib
cp /lib/libnss_dns.so.2 /home/<user>/www/lib/
# A moins de retirer la valeur "files" de la ligne "hosts:" de /home/<user>/www/etc/nsswitch.conf
touch /home/<user>/www/etc/hosts
cp /lib/libnss_files.so.2 /home/<user>/www/lib/

Création des utilisateurs par script

#!/bin/bash

BINARIES=(bash cat cp mv rm grep ls mkdir chmod chown chgrp ps tar touch echo cat kill less)

# TODO:
# - les services en cours : nginx, php-fpm
# - les services à faire : mysql : mysql -u root -p < create database db_${USERNAME}; grant all privileges ... ?)
# - /etc/bash* à copier ?
# - la(les) locale(s) ?
# - le domaine ?

# 1,1 utilisateur <=> 1,N sites/serveurs <=> 1,? bdd

# http://publications.jbfavre.org/web/php-fpm-apps-server-nginx.fr

declare -r PROGNAME=`basename $0`
declare -r SHORTOPTS="g:u:p:s"
declare -r LONGOPTS="group:,user:,path:,ssh"
declare -r DATADIR=$(dirname $(readlink -f "${BASH_SOURCE}"))
SSH=false

usage() {
    echo "Usage: ${PROGNAME} [ -u <login> ] [ -g <groupe http> ] [ -p <chroot path> ]"
    exit 2
}

OPTS=$(getopt -o $SHORTOPTS --long $LONGOPTS -n "${PROGNAME}" -- "$@")

[ $? -eq 0 ] || usage

eval set -- "$OPTS"

while true; do
    case "$1" in
        -u|--user)
            USERNAME=$2
            shift 2;;
        -p|--path)
            CHROOTPATH=$2
            shift 2;;
        -g|--group)
            HTTPGROUP=$2
            shift 2;;
        -s|--ssh)
            SSH=true
            shift;;
        --)
            shift; break;;
    esac
done

[ -n "${USERNAME}" ] || usage
[ $# -eq 0 ] || usage

CHROOTPATH=${CHROOTPATH:-"/home/${USERNAME}"}
HTTPGROUP=${HTTPGROUP:-"http"}
declare -r SU="su - ${USERNAME} -c"


PORT=$(grep -rhE '^[[:blank:]]*listen[[:blank:]]*=[[:blank:]]*([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}:' /etc/php/ | cut -d : -f 2 | sort -rn | head -1)
if [ -z "${PORT}" ]; then
    PORT=9001
else
    ((PORT++))
fi

FPM_TPL=$(cat <<EOF_FPM_TPL
[${USERNAME}]

listen = 127.0.0.1:${PORT}
listen.allowed_clients = 127.0.0.1

user  = ${USERNAME}
group = ${USERNAME}

pm = dynamic
pm.max_children      = 50
pm.start_servers     = 20
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests      = 500

pm.status_path = /fpm-status
ping.path      = /fpm-ping

request_terminate_timeout = 10s
request_slowlog_timeout   = 10s

slowlog = ${CHROOTPATH}/www/logs/php-fpm.log

chroot = ${CHROOTPATH}/www
#chdir  = /docroot/

env[TMP]    = /tmp
env[TEMP]   = /tmp
env[TMPDIR] = /tmp

php_admin_value[error_log] = /logs/php.log
EOF_FPM_TPL
)

NGINX_TPL=$(cat <<EOF_NGINX_TPL
server {
    listen 80;
    server_name TODO;
    root ${CHROOTPATH}/www;

    access_log ${CHROOTPATH}/www/logs/access.log vhosts;
    error_log  ${CHROOTPATH}/www/logs/error.log info;

    location = /fpm-status {
        fastcgi_pass 127.0.0.1:${PORT};
        include fastcgi.conf;
        allow 127.0.0.1;
        deny all;
    }

    location / {
        root ${CHROOTPATH}/www/docroot;
    }

    location ~ \.php$ {
        try_files     $uri =404;
        root          ${CHROOTPATH}/www;
        fastcgi_pass  127.0.0.1:${PORT};
        fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT /;
        fastcgi_index index.php;
        include       fastcgi_params;
    }
}
EOF_NGINX_TPL
)

echo "===> php-fpm configuration :"
echo -e "${FPM_TPL}"

echo "===> Nginx configuration :"
echo -e "${NGINX_TPL}"

exit

useradd -d "${CHROOTPATH}" -m -G "${HTTPGROUP}" -s /bin/bash -U "${USERNAME}"
passwd "${USERNAME}"

if [ $SSH ]; then
    chmod 0775 "${CHROOTPATH}"
    chown root "${CHROOTPATH}"
else
    chmod 0755 "${CHROOTPATH}"
fi

$SU "mkdir -p ${CHROOTPATH}/dev/"
mknod "${CHROOTPATH}/dev/null" c 1 3 -m 0666
mknod "${CHROOTPATH}/dev/zero" c 1 5 -m 0666
mknod "${CHROOTPATH}/dev/random" c 1 8 -m 0444
mknod "${CHROOTPATH}/dev/urandom" c 1 9 -m 0444
mknod "${CHROOTPATH}/dev/tty" c 5 0 -m 0755
mkdir -p "${CHROOTPATH}/dev/pts/"
mknod "${CHROOTPATH}/dev/pts/0" c 136 0 -m 666
mknod "${CHROOTPATH}/dev/pts/1" c 136 1 -m 666 

$SU "mkdir -p ${CHROOTPATH}/etc/"
$SU "echo -n > ${CHROOTPATH}/etc/group"
for group in $(groups "${USERNAME}"); do
    $SU "grep '^${group}:' /etc/group | sed 's/:[^:]*$/:${USERNAME}/' >> '${CHROOTPATH}/etc/group'"
done
$SU "grep '^${USERNAME}:' /etc/passwd > '${CHROOTPATH}/etc/passwd'"

$SU "echo '127.0.0.1 localhost' > '${CHROOTPATH}/etc/hosts'"
for lib in $(grep '^hosts:' /etc/nsswitch.conf | cut -d ' ' -f 2-); do
    $SU "install -D '/lib/libnss_${lib}.so.2' '${CHROOTPATH}/lib/libnss_${lib}.so.2'"
done
$SU "grep '^hosts:' /etc/nsswitch.conf > '${CHROOTPATH}/etc/nsswitch.conf'"

for bin in "${BINARIES[@]}"; do
    bin=$(which "${bin}")
    if [ -n "${bin}" ]; then
        for lib in $(ldd ${bin} 2>/dev/null | sed "s|.*=>\(.*\)|\1|"); do
            if [ -n "${lib}" ]; then
                notls=$(echo ${lib} | sed 's|/lib/tls.*/\(lib.*\)|/lib/\1|')
                [ -e "${notls}" ] && lib="${notls}"
                if [ -f "${lib}" ]; then
                    $SU "install -D '${lib}' '${CHROOTPATH}${lib}'"
                fi
            fi
        done
        for lib in $(strings "${bin}" | grep 'ld.*\.so'); do
            $SU "install -D '${lib}' '${CHROOTPATH}${lib}'"
        done
        $SU "install -D '${bin}' '${CHROOTPATH}${bin}'"
    fi
done

read -p "Recharger la configuration de Nginx maintenant ? [o/N] " answer
[[ $answer = [oOyY] ]] && /etc/rc.d/nginx reload
read -p "Recharger la configuration de php-fpm maintenant ? [o/N] " answer
[[ $answer = [oOyY] ]] && /etc/rc.d/php-fpm reload

Test rapide du chroot :

chroot --userspec=<user> /home/<user> /bin/bash
serveurs/nginx/php.txt · Dernière modification: 08/12/2014 16:28 (modification externe)