Webserver Setup mit Nginx, Percona und PHP-FPM

In diesem Beitrag notiere ich kurz wie ich aktuell einen neuen Webserver unter Debian Squeeze einrichte. Er dient in erster Line als Reminder für mich selbst daher sind die Erklärungen auf das Wesentliche beschränkt. Vielleicht sind aber trozdem ein paar nützliche Informationen dabei weshalb ich mich dazu entschlossen habe einen Blogeintrag daraus zu machen. Ich werde versuchen den Beitrag hin und wieder zu aktualiseren (z.B. demnächst für Debian Wheezy).

Inhalt

Vorbereitung

Erklärung: Hier ändere ich den SSH-Port, lege einen neuen User an welcher sich mit einem Key authentifiziert. Der direkte Login mit dem User root wird deaktiviert. Bei Änderungen am sshd empiehlt es sich während der ganzen Zeit einen zweite root-shell göffnet zu lassen für denn Fall, dass man sich nach einem sshd Neustart nicht mehr einloggen kann.

Neuen User anlegen:

useradd -m -s /bin/bash <username>

Authentifizierung (nur) über Key ermöglichen:

cd /home/<username>
mkdir .ssh
cd .ssh
touch authorized_keys
chown <username>:<username> authorized_keys
nano authorized_keys

Key in die authorized_keys einfügen. Save & Close.

SSH-Port ändern:

nano /etc/ssh/sshd_config
Port 1313

Root Login deaktivieren:

PermitRootLogin no

Login für User ohne Passwort deaktivieren:

PermitEmptyPasswords no

Save & Close

Sshd neustarten:

/etc/init.d/ssh restart

SFTP

Erklärung: Ich nutze die in OpenSSH enthaltene SFTP Funktionalität. Damit können chrooted sftp-only Accounts angelegt werden. Um neue "SFTP Accounts" anzulegen müssen diese später nur der Gruppe "sftponly" zugewiesen werden.

SFTP-Subsystem aktivieren:

nano /etc/ssh/sshd_config
#Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem       sftp    internal-sftp

Chroot für Gruppe sftponly konfigurieren:

Match Group sftponly
    ChrootDirectory %h
    ForceCommand internal-sftp
    AllowTcpForwarding no

Hinweis: MatchGroup am Ende der Datei (nach UsePAM) einfügen. Save & Close.

Gruppe für SFTP-User hinzufügen:

addgroup sftponly

Sshd neustarten:

/etc/init.d/ssh restart

Webserver

Erklärung: Ich verwende den Nginx Webserver aus dem dotdeb.org Repository.

dotdeb.org Repository hinzufügen:

nano /etc/apt/sources.list
deb http://packages.dotdeb.org squeeze all
deb-src http://packages.dotdeb.org squeeze all

dotdeb.org GnuPG key hinzufügen:

wget http://www.dotdeb.org/dotdeb.gpg
cat dotdeb.gpg | sudo apt-key add -

Paketquellen aktualisieren:

apt-get update

Nginx installieren:

apt-get install nginx

Webserver Konfiguration ergänzen:

nano /etc/nginx/nginx.conf
http {
    ...
    types_hash_max_size 2048;
    client_max_body_size 16M;
    fastcgi_buffers 8 16k;
    fastcgi_buffer_size 32k;
}

Save & Close. Hier kann natürlich wesentlich mehr an die eigenen Bedürfnisse angepasst werden. Datenbank

Erklärung: Ich verwende Percona. Ein MySQL Drop-In.

Percona Repository hinzufügen:

nano /etc/apt/sources.list
deb http://repo.percona.com/apt squeeze main
deb-src http://repo.percona.com/apt squeeze main

Save & Close.

Percona GnuPG Key hinzufügen:

gpg --keyserver  hkp://keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A
gpg -a --export CD2EFD2A | sudo apt-key add -

Percona installieren:

apt-get install percona-server-server-5.5

PHP (php-fpm)

Ich verwende PHP-FPM. Dafür nutze ich pro Projekt einen User-Account (SFTP siehe oben). Für jeden Account wird jeweils ein FPM-Pool konfiguriert. So laufen die php-fpm Prozesse mit dem gleichen Account mit dem auch die Dateien per SFTP hochgeladen werden und es kommt zu keinerlei "Rechte-Problemen".

PHP installieren:

apt-get install php5-cli php5-common php5-mysql php5-suhosin php5-gd php5-dev php5-curl php5-mcrypt php5-fpm php-pear php-apc

Webroot anlegen:

mkdir /var/www

Projekt SFTP-User anlegen:

useradd-d /var/www/sample_project -G sftponly -m -s /bin/false sample_project
passwd sample_project

Webprojekt-Ordner anlegen:

mkdir /var/www/sample_project
mkdir /var/www/sample_project/www
chown sample_project:sample_project /var/www/sample_project/www

Es sollte nun möglich sein sich mit dem User "sample_project" via SFTP einzuloggen.

FPM-Pool anlegen:

mv /etc/php5/fpm/pool.d/www.conf /etc/php5/fpm/sample_project.conf
nano /etc/php5/fpm/pool.d/sample_project.conf

Pool-Name anpassen:

[sample_project]

User/Group anpassen:

user = sample_project
group = sample_project

Listen Socket anpassen:

listen = 127.0.0.1:9001

Für jeden Pool muss ein anderer Port gewählt werden!

Weitere Anpassungen nach Bedarf. Die Sample-Config ist gut dokumentiert. Save & Close.

PHP-FPM restart:

/etc/init.d/php5-fpm restart

Projekt Vhost anlegen:

nano /etc/nginx/sites-available/sample_project
server {
    listen 80;
    server_name sample_project.net;

    root /var/www/sample_project/www;
    index index.php index.htm index.html;

    # basic seo/sef urls:
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ .php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass   127.0.0.1:9001;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME /var/www/sample_project/www$fastcgi_script_name;
        include fastcgi_params;
    }
}

Darauf achten, dass der fastcgi_pass Port mit dem php-fpm Pool übereinstimmt. Save & Close.

Vhost aktivieren und Nginx neustarten:

ngxensite sample_project
/etc/init.d/nginx restart

Backups

Erklärung: Hier nutze ich Duply um ein verschüsseltes Backup des www-roots sowie einen Datenbank-Dump auf einen anderen Server zu schieben. Dabei wird einmal pro Tag ein inkrementelles sowie einmal pro Monat ein komplettes Backup erstellt.

Duply installieren:

apt-get install duply

Backup Profil anlegen:

duply www_complete create

GPG Key für Verschlüsselung erstellen:

gpg --gen-key

GPG Key-ID notieren.

Backup Konfiguration anpassen:

nano /root/.duply/www_complete/conf

GPG Key-ID und Passwort eintragen:

GPG_KEY='123ABC123A'
GPG_PW='password'

Backup-Ziel anpassen:

TARGET='ftp://ftp.someserver.com/some/backup/path'
TARGET_USER='ftpuser'
TARGET_PASS='ftppassword'

Hier nach Bedarf anpassen, SSH, FTP, etc.

Backup-Quelle anpassen:

SOURCE='/var/www'

Save & Close.

Datenbank-Dump vor dem Backup:

nano /root/.duply/www_complete/pre
/usr/bin/mysqldump -u root -pPASSWORD --all-databases > /var/www/db.sql

Save & Close.

Datenbank Dump nach Backup wieder löschen:

nano /root/.duply/www_complete/post
rm /var/www/db.sql

Save & Close.

Cronjobs für Backups anlegen:

crontab -e
MAILTO=your@mail.com
0 3 2-31 * * /usr/bin/duply www_complete backup
0 1 1 * *       /usr/bin/duply www_complete pre_full_purge-full_post --force

Save & Close.

Damit ist mein aktuell Basis-Setup abgeschlossen. Ergänzungen, Hinweise etc. bitte in die Kommentare.