Wechseln zu: Navigation, Inhalt, Suche

Permalink

0

HowTo: Nginx mit PHP5-FPM, MySQL und PostgreSQL unter Debian Squeeze installieren

Bei einem vServer kann man selbst wählen, welchen Webserver und welche Datenbanksysteme man verwenden möchte. Ich habe mich daher für Nginx mit PHP5-FPM, sowie MySQL und PostgreSQL entschieden. Um dies alles auf einem Server mit 256 MB RAM zu betreiben sind dann allerdings noch ein paar Modifikationen notwendig.

Bild von Aleks Dorohovich auf Unsplash, lizenziert unter CC0 1.0

Bild von Aleks Dorohovich auf Unsplash, lizenziert unter CC0 1.0

Zuerst werden die nicht benötigten Pakete entfernt:

sudo /etc/init.d/apache2 stop
sudo /etc/init.d/samba stop
sudo apt-get -y purge apache2 apache2-doc apache2-mpm-prefork apache2-utils apache2.2-bin apache2.2-common samba-common samba

Dann kann man die Paketquellen und Schlüssel hinzufügen:

sudo echo "deb http://packages.dotdeb.org squeeze all" > /etc/apt/sources.list.d/squeeze-dotdeb.list
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys --recv-key 89DF5277

Anschließend werden die Pakete installiert, wobei PHP-Module natürlich auch später noch nachinstalliert werden können:

sudo apt-get update
sudo apt-get -y install nginx mysql-server postgresql php5 php5-fpm php-pear php-apc php5-common php5-mcrypt php5-mysql php5-pgsql php5-cli php5-gd php5-curl php5-xmlrpc

PostgreSQL einrichten

Als erstes meldet man sich mit dem Systembenutzer postgres bei PostgreSQL an und vergibt für den Datenbankbenutzer postgres ein Passwort:

sudo -u postgres psql
\password postgres

Die PostgreSQL-Umgebung kann man anschließend mit \q verlassen. Nun wird festgelegt, wer auf die Datenbanken zugreifen kann:

sudo vi /etc/postgresql/8.4/main/pg_hba.conf
# "local" is for Unix domain socket connections only
local all all md5

Zudem empfiehlt es sich, die Puffer-Größe anzupassen, sodass sie zum verfügbaren Arbeitsspeicher passt:

sudo vi /etc/postgresql/8.4/main/postgresql.conf
shared_buffers = 16MB

MySQL einrichten

Während der Installation des MySQL-Servers hat man bereits das Passwort des root-Nutzers festgelegt. Es empfiehlt sich außerdem, die Sicherheit der Installation zu verbessern, in dem man mysql_secure_installation ausführt:

sudo /usr/bin/mysql_secure_installation
sudo /etc/init.d/mysql stop
sudo rm /etc/mysql/my.cnf
sudo vi /etc/mysql/my.cnf

Basierend auf /usr/share/doc/mysql-server-5.5/examples/my-medium.cnf.gz habe ich für MySQL dann die folgende Konfiguration eingerichtet:

my.cnf
[client]
port		= 3306
socket		= /var/run/mysqld/mysqld.sock

[mysqld]
port		= 3306
socket		= /var/run/mysqld/mysqld.sock
pid-file = /var/run/mysqld/mysqld.pid
skip-external-locking
key_buffer_size = 16M
max_allowed_packet = 1M
table_open_cache = 64
sort_buffer_size = 512K
net_buffer_length = 8K
read_buffer_size = 256K
read_rnd_buffer_size = 512K
myisam_sort_buffer_size = 8M
log-bin=mysql-bin
binlog_format=mixed
server-id	= 1
character-set-server=utf8
collation-server=utf8_general_ci
skip-innodb
default-storage-engine=MyISAM

[mysqldump]
quick
max_allowed_packet = 16M

[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size = 20M
sort_buffer_size = 20M
read_buffer = 2M
write_buffer = 2M

[mysqlhotcopy]
interactive-timeout

Um Arbeitsspeicher zu sparen, habe ich dabei unter anderem die Storage-Engine InnoDB deaktiviert. Anschließend kann man alle Dienste neustarten, an denen man Modifikationen durchgeführt hat:

sudo /etc/init.d/mysql restart
sudo /etc/init.d/postgresql restart
sudo /etc/init.d/php5-fpm restart
sudo /etc/init.d/nginx restart

PHP-FPM einrichten

Ist anschließend die RAM Nutzung zu hoch, so kann man die Voreinstellungen von PHP-FPM noch modifizieren:

sudo vi /etc/php5/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 3
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.max_requests = 32

Danach ist es wieder notwendig, den Dienst neuzustarten:

sudo /etc/init.d/php5-fpm restart

Nginx einrichten

Die Einstellungen in der Server-Konfigurationsdatei nginx.conf sind die Grundlage für die namensbasierten Virtual Hosts. Ich habe mich hierbei an diesem Artikel von Sergej Müller orientiert:

sudo rm /etc/nginx/nginx.conf
sudo vi /etc/nginx/nginx.conf

nginx.conf
user www-data;
worker_processes 4;
worker_rlimit_nofile 4096;
pid /var/run/nginx.pid;

# [ debug | info | notice | warn | error | crit ]
error_log /var/log/nginx/error.log;

#google_perftools_profiles /tmp/profile/;

events {
	worker_connections 2048;
	# use [ kqueue | rtsig | epoll | /dev/poll | select | poll ] ;
	use epoll;
	multi_accept on;
}

http {
	server_names_hash_bucket_size 64;

	## Size Limits
	client_max_body_size    10M;
	client_header_buffer_size   32k;
	client_body_buffer_size     128k;
	large_client_header_buffers 64 8k;

	## Timeouts
	client_body_timeout   3m;
	client_header_timeout 3m;
	send_timeout      3m;
	#expires          24h;
	keepalive_timeout     120 120;

	## General Options
	ignore_invalid_headers   on;
	keepalive_requests       100;
	limit_conn_zone $binary_remote_addr zone=one:5m;
	recursive_error_pages    on;
	sendfile         on;
	server_name_in_redirect  off;
	server_names_hash_max_size 512;
	server_tokens        off;
	set_real_ip_from 127.0.0.1;
	real_ip_header X-Forwarded-For;

	## TCP options
	#tcp_nopush on;
	tcp_nodelay off;
	#send_lowat 12000;

	include mime.types;
	default_type application/octet-stream;

	access_log /var/log/nginx/access.log;

	log_format main '$remote_addr - $remote_user [$time_local] $status '
	'\"$request\" $body_bytes_sent \"$http_referer\" '
	'\"$http_user_agent\" \"http_x_forwarded_for\"';

	## Cache
	open_file_cache max=1000 inactive=24h;
	open_file_cache_valid    24h;
	open_file_cache_min_uses 2;
	open_file_cache_errors   on;

	## SSL Settings
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	## Compression
	gzip          on;
	gzip_static       on;
	gzip_disable      "MSIE [1-6]\.(?!.*SV1)";
	gzip_buffers      16 8k;
	gzip_comp_level   6;
	gzip_http_version 1.1;
	gzip_min_length   0;
	gzip_proxied      any;
	gzip_types text/plain text/css text/xml text/javascript application/json application/xml application/xml+rss application/x-javascript image/x-icon application/x-perl application/x-httpd-cgi application/javascript text/x-js font/ttf font/opentype application/vnd.ms-fontobject image/svg+xml;
	gzip_vary     on;

	output_buffers   10 128k;
	postpone_output  1500;

	include /etc/nginx/sites-enabled/*.conf;
}

Anschließend kann man pro Domain oder Subdomain jeweils einen eigenen Document-Root-Ordner und eigene Konfigurationen anlegen:

sudo mkdir -p /var/www/domain.de/web
sudo mkdir -p /var/www/domain.de/log
sudo chown -R www-data:www-data /var/www

Im Verzeichnis sites-available legt man die Virtual-Host-Konfigurationen an und legt dann einen symbolischen Link darauf in sites-enabled an:

sudo mkdir -p /etc/nginx/sites-available/
sudo mkdir -p /etc/nginx/sites-enabled/

Dies hat den Vorteil, dass man einzelne Konfigurationen aktivieren und deaktivieren kann:

sudo vi /etc/nginx/sites-available/domain.de.conf
sudo ln -s /etc/nginx/sites-available/domain.de.conf /etc/nginx/sites-enabled/

Exemplarische Virtual-Host-Konfigurationen

Im folgenden ein paar einfache Konfigurationsbeispiele:

simple-domain.de.conf
server {
	listen 80 default_server;
	#listen [::]:80 default_server;
	server_name domain.de *.domain.de;

	root  /var/www/domain.de/web;

	access_log /var/www/domain.de/log/access.log;
	error_log /var/www/domain.de/log/error.log;

    location / {
		index  index.php index.html index.htm;
    }

	location ~ \.php$ {
		fastcgi_pass  127.0.0.1:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include       fastcgi_params;
	}
}

simple-domain.de-ssl.conf
server {
	listen 443 default_server ssl spdy;
	#listen [::]:443 default_server ssl spdy;
	server_name domain.de *.domain.de;

	ssl on;
	ssl_certificate      /etc/ssl/certs/domain.de.pem;
	ssl_certificate_key  /etc/ssl/private/domain.de.key;
	ssl_session_timeout 5m;
	ssl_prefer_server_ciphers on;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # not possible to do exclusive
	ssl_ciphers 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA';
	add_header Strict-Transport-Security max-age=31556926;
	# use this only if all subdomains support HTTPS!
	# add_header Strict-Transport-Security "max-age=31556926; includeSubDomains";
	ssl_ecdh_curve secp384r1;
	ssl_dhparam /etc/nginx/ssl/group16.pem;
	ssl_session_cache shared:SSL:10m;

	root  /var/www/domain.de/web;

	access_log /var/www/domain.de/log/access.log;
	error_log /var/www/domain.de/log/error.log;

    location / {
		index  index.php index.html index.htm;
    }

	location ~ \.php$ {
		fastcgi_pass  127.0.0.1:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include       fastcgi_params;
	}
}

redirect-domain.de.conf
server {
	listen 80;
	#listen [::]:80;
	server_name otherdomain.de *.otherdomain.de;

	#return 301 $scheme://domain.de$request_uri;
	return 302 $scheme://domain.de$request_uri;
}

download.domain.de.conf
server {
	listen 80;
	#listen [::]:80;
	server_name download.domain.de;


	## ROOT
	root /var/www/download.domain.de/web;


	## LOGS
	access_log /var/www/download.domain.de/log/access.log;
	error_log /var/www/download.domain.de/log/error.log;


	# DEFAULT INDEX
	index index.php index.html index.htm;


	## RESSOURCES
	location ~ \.(?:ico|png|jpe?g|css|js)$ {
		expires 31d;

		add_header Pragma "public";
		add_header Cache-Control "public, must-revalidate, proxy-revalidate";

		#location ~ \.(?!ico).+$ {
		#	valid_referers none blocked server_names ~(wpseo.|google.|yahoo.|bing.|facebook.|fbcdn.|pinterest.);
		#	if ( $invalid_referer ) {
		#		return 444;
		#	}
		#}
	}


	## PHP FILES
	#location ~ \.php$ {
	#	fastcgi_pass  127.0.0.1:9000;
	#	fastcgi_index index.php;
	#	fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	#	include       fastcgi_params;
	#}


	## GZIP
	gzip_static on;


	## CHARSET
	charset utf-8;


	## INDEX LOCATION
	location / {
		## Browser-Cache
		expires 1h;

		try_files $uri @rewrite;
	}


    ## REWRITE LOCATION
	location @rewrite {
		#return 301 $scheme://domain.de$request_uri;
		return 302 $scheme://domain.de$request_uri;
	}
}

download.domain.de-ssl.conf
server {
	listen 443 ssl spdy;
	#listen [::]:443 ssl spdy;
	server_name download.domain.de;


	## SSL
	ssl on;
	ssl_certificate      /etc/ssl/certs/domain.de.pem;
	ssl_certificate_key  /etc/ssl/private/domain.de.key;
	ssl_session_timeout 5m;
	ssl_prefer_server_ciphers on;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # not possible to do exclusive
	ssl_ciphers 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA';
	add_header Strict-Transport-Security max-age=31556926;
	# use this only if all subdomains support HTTPS!
	# add_header Strict-Transport-Security "max-age=31556926; includeSubDomains";
	ssl_ecdh_curve secp384r1;
	ssl_dhparam /etc/nginx/ssl/group16.pem;
	ssl_session_cache shared:SSL:10m;


	## ROOT
	root /var/www/download.domain.de/web;


	## LOGS
	access_log /var/www/download.domain.de/log/access.log;
	error_log /var/www/download.domain.de/log/error.log;


	# DEFAULT INDEX
	index index.php index.html index.htm;


	## RESSOURCES
	location ~ \.(?:ico|png|jpe?g|css|js)$ {
		expires 31d;

		add_header Pragma "public";
		add_header Cache-Control "public, must-revalidate, proxy-revalidate";

		#location ~ \.(?!ico).+$ {
		#	valid_referers none blocked server_names ~(wpseo.|google.|yahoo.|bing.|facebook.|fbcdn.|pinterest.);
		#	if ( $invalid_referer ) {
		#		return 444;
		#	}
		#}
	}


	## PHP FILES
	#location ~ \.php$ {
	#	fastcgi_pass  127.0.0.1:9000;
	#	fastcgi_index index.php;
	#	fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
	#	include       fastcgi_params;
	#}


	## GZIP
	gzip_static on;


	## CHARSET
	charset utf-8;


	## INDEX LOCATION
	location / {
		## Browser-Cache
		expires 1h;

		try_files $uri @rewrite;
	}


    ## REWRITE LOCATION
	location @rewrite {
		#return 301 $scheme://domain.de$request_uri;
		return 302 $scheme://domain.de$request_uri;
	}
}

wordpress-domain.de.conf
server {
	## INIT
	listen 80 default_server;
	#listen [::]:80 default_server;
	server_name domain.de *.domain.de;


	## ROOT
	root /var/www/domain.de/web;


	## LOGS
	access_log /var/www/domain.de/log/access.log;
	error_log /var/www/domain.de/log/error.log;


	# DEFAULT INDEX
	index index.php;


	## SECURITY
	if ( $request_method !~ ^(GET|HEAD|POST)$ ) {
		return 444;
	}
	location ~ /(\.|wp-config.php|liesmich.html|readme.html) {
		return 444;
	}


	## REWRITES
	#location ~ ^/(\d+)/$ {
	#	return 301 /?p=$1;
	#}


	## RESSOURCES
	location ~ \.(?:ico|png|jpe?g|css|js)$ {
		expires 31d;

		add_header Pragma "public";
		add_header Cache-Control "public, must-revalidate, proxy-revalidate";

		#location ~ \.(?!ico).+$ {
		#	valid_referers none blocked server_names ~(wpseo.|google.|yahoo.|bing.|facebook.|fbcdn.|pinterest.);
		#	if ( $invalid_referer ) {
		#		return 444;
		#	}
		#}
	}


	## REDIRECT INDEX
	location / { 
		try_files $uri $uri/ /index.php;
	}


	## PHP FILES
	location ~ \.php$ {
		fastcgi_pass  127.0.0.1:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include       fastcgi_params;
	}


	## AUTH ADMIN
	location = /wp-login.php {
		#auth_basic            "Restricted";
		#auth_basic_user_file  /var/www/domain.de/.htpasswd;

		fastcgi_pass  127.0.0.1:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include       fastcgi_params;
	}
}

wordpress-cachify-hdd-domain.de.conf
server {
	## INIT
	listen 80 default_server;
	#listen [::]:80 default_server;
	server_name domain.de *.domain.de;


	## ROOT
	root /var/www/domain.de/web;


	## LOGS
	access_log /var/www/domain.de/log/access.log;
	error_log /var/www/domain.de/log/error.log;


	# DEFAULT INDEX
	index index.php;


	## SECURITY
	if ( $request_method !~ ^(GET|HEAD|POST)$ ) {
		return 444;
	}
	location ~ /(\.|wp-config.php|liesmich.html|readme.html) {
		return 444;
	}


	## REWRITES
	#location ~ ^/(\d+)/$ {
	#	return 301 /?p=$1;
	#}


	## RESSOURCES
	location ~ \.(?:ico|png|jpe?g|css|js)$ {
		expires 31d;

		add_header Pragma "public";
		add_header Cache-Control "public, must-revalidate, proxy-revalidate";

		#location ~ \.(?!ico).+$ {
		#	valid_referers none blocked server_names ~(wpseo.|google.|yahoo.|bing.|facebook.|fbcdn.|pinterest.);
		#	if ( $invalid_referer ) {
		#		return 444;
		#	}
		#}
	}


	## PHP FILES
	location ~ \.php$ {
		fastcgi_pass  127.0.0.1:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include       fastcgi_params;
	}


	## AUTH ADMIN
	location = /wp-login.php {
		#auth_basic            "Restricted";
		#auth_basic_user_file  /var/www/domain.de/.htpasswd;

		fastcgi_pass  127.0.0.1:9000;
		fastcgi_index index.php;
		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		include       fastcgi_params;
	}


	## GZIP
	gzip_static on;


	## CHARSET
	charset utf-8;


	## INDEX LOCATION
	location / {
		if ( $query_string ) {
			return 405;
		}
		if ( $request_method = POST ) {
			return 405;
		}
		if ( $request_uri ~ /wp-admin/ ) {
			return 405;
		}
		if ( $http_cookie ~ (wp-postpass|wordpress_logged_in|comment_author)_ ) {
			return 405;
		}

		error_page 405 = @nocache;
		
		## Browser-Cache
		expires 1h;

		try_files /wp-content/cache/cachify/${host}${uri}index.html @nocache;
	}


	## NOCACHE LOCATION
	location @nocache {
		try_files $uri $uri/ /index.php?$args;
	}
}

Zur Aktivierung von IPv6 kommentiert man einfach die Listen-Direktiven mit ipv6only=on ein. Nach einem Neustart von Nginx sollte die Seite dann unter der entsprechenden Domain verfügbar sein:

sudo /etc/init.d/nginx restart

Hat man die Virtual-Host-Konfiguration abgeschlossen, so kann man sofort loslegen und Dateien in den Document-Root-Ordner legen oder beispielsweise eine Datenbank in MySQL anlegen und WordPress konfigurieren.

Schreibe einen Kommentar