Page 5 the .conf files - configuring your web server.
The default .conf files included in the Dotdeb packages will almost work right out of the box. You will need to make a few adjustments.
Nginx and PHP-FPM
Before you set up the Nginx.conf files you need to decide your folder structure and where the root of your websites will live. I like to use /srv/www/sitename/public for the web root and /srv/www/sitename/logs for the error and access logs. The files in your web root need to be owned by the same user as Nginx runs under. The Debian way is to run the server as www-data.
mkdir /srv/www/yoursitename /srv/www/yoursitename/public /srv/www/yoursitename/logs chown www-data:www-data /srv/www/yoursitename/public/ -R
File: /etc/nginx/nginx.conf
Note: be wary of some of the copy and paste guides out there. The Slicehost and Linode tutorials are out of date and contain security vulnerabilities. If you don’t understand something question it and do your own research. The following files have been tested and are in use on real production servers.
user www-data; worker_processes 4; pid /var/run/nginx.pid; events { worker_connections 1024; # multi_accept on; } http { sendfile on; tcp_nopush on; tcp_nodelay on; server_tokens off; include mime.types; default_type application/octet-stream; index index.php index.htm index.html redirect.php; #Gzip gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_buffers 16 8k; gzip_http_version 1.1; gzip_disable "MSIE [1-6].(?!.*SV1)"; gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; #FastCGI fastcgi_intercept_errors on; fastcgi_ignore_client_abort on; fastcgi_buffers 8 16k; fastcgi_buffer_size 32k; fastcgi_read_timeout 120; fastcgi_index index.php; limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; ## # Virtual Host Configs ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; #Our individual site vhost server files will live here }
If your familiar with the Apache Vhost concept you will be fine with Nginx. The Nginx server files we create act as individual site vhost.conf files and can either be in one large file or for better organization you can create a separate file for each site. The Debian way is to create 2 directories under /etc/nginx/, sites-available for the files and sites-enabled for sym links pointing to the file in sites-available. This allows you to turn off a site without having to delete it if you ever need it again.
touch /etc/nginx/sites-available/your_domain.com ln -s /etc/nginx/sites-available/your_domain.com /etc/nginx/sites-enabled/your_domain.com cd /etc/nginx/sites-enabled ls -a :drwxr-xr-x 2 root root 4096 Jun 26 02:04 . drwxr-xr-x 5 root root 4096 Jun 26 01:50 .. lrwxrwxrwx 1 root root 40 Jun 26 01:59 your_domain.com -> /etc/nginx/sites-available/your_domain.com
File: /etc/nginx/sites-available/your_domain.com
This is for a single WordPress install. We are also including the W3 Total Cache Nginx rewrite rules in a separate file w3-total.conf. You will need to run touch /etc/nginx/w3-total.conf and chown www-data:www-data /etc/nginx/w3-total.conf and list the path in the W3 Total Cache general settings so it can write to the file. *Note: Anytime you make a change to an Nginx server file you will need to restart.
server { listen 80; server_name your_domain.com www.your_domain.com; root /srv/www/domain/public; access_log /srv/www/domain/logs/access.log; error_log /srv/www/domain/logs/error.log; client_max_body_size 8M; client_body_buffer_size 128k; #The section below contains your WordPress rewrite rules location / { try_files $uri $uri/ /index.php?q=$uri&$args; } location /search { limit_req zone=one burst=3 nodelay; rewrite ^ /index.php; } fastcgi_intercept_errors off; location ~* \.(?:ico|css|js|gif|jpe?g|png)$ { expires max; add_header Pragma public; add_header Cache-Control "public, must-revalidate, proxy-revalidate"; } #sample 301 redirect # location /2011/06/26/permalink/ { # rewrite //2011/06/26/permalink/ http://example.com/2011/06/27/permalink_redirecting_to/ permanent; # } #Send the php files to upstream to PHP-FPM #This can also be added to separate file and added with an include location ~ \.php { try_files $uri =404; #This line closes a big security hole #see: http://forum.nginx.org/read.php?2,88845,page=3 fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; fastcgi_pass 127.0.0.1:9000; } #Once you have your w3-total.conf file ready un-comment out the line below #include w3-total.conf;
You can now start your server and see if it works.
touch /srv/www/yoursite/public/index.php echo '<?php echo "<h1>Nginx Baby - It WORKS!!!!</h1>"; ?>' >> /srv/www/yoursite/public/index.php /etc/init.d/nginx start
For more Nginx server file examples see the WordPress.org Nginx Codex
Open a browser and go to your domain or ip and if you did everything right you should see:
WordPress Multisite, alternative configuration and multiple non WordPress vhosts
If you want to host a multisite setup or add additional websites to your server or VPS you can include the WordPress Multisite rewrite rules in a separate file and simplify your per site vhosts.
File: /etc/nginx/nginx.conf
<pre>user www-data; worker_processes 10; error_log /var/log/nginx/error.log; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log; sendfile on; # tcp_nopush on; keepalive_timeout 3; # tcp_nodelay on; # gzip on; client_max_body_size 13m; index index.php index.html index.htm; upstream php { # server 127.0.0.1:9000; server unix:/tmp/php-fpm.sock; } include sites-enabled/*; }
This is a sample vhost for a subdomain WordPress Multisite that uses the Domain Mapping Plugin along with a few static sites that are also hosted on the server.
server { listen 80; #Add a server_name entry for each mapped domain server_name star.main-multisite-domain.com *.main-multisite.com; server_name mapped-domain.com www.mapped-domain.com; server_name mapped-domain-2.com www.mapped-domain-2.com; server_name mapped-domain-3.com www.mapped-domain-3.com; root /srv/www/wordpress/public; access_log /srv/www/wordpress/logs/access.log; error_log /srv/www/wordpress/logs/error.log; index index.php index.html index.htm; #The Multisite rules are in the include below include global-wp-multi.conf; } #Begin Static Non WP Sites #Repeat the vhosts below for each additional static site. Make sure you make each one a root directory server { server_name static-non-wp-domain.com www.static-non-wp-domain.com; root /srv/www/static-non-wp-domain/public; error_log /srv/www/static-non-wp-domain/logs/error.log; index index.php index.html index.htm; }
File: /etc/nginx/global-wp-multi.conf
This is a default config file that will handle the rewrite rules for domain mapped subdomain multisites.
error_page 404 = @wordpress; log_not_found off; location / { try_files $uri $uri/ /index.php?$args; } rewrite /wp-admin$ $scheme://$host$uri/ permanent; location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires 24h; log_not_found off; } rewrite ^/files/(.+) /wp-includes/ms-files.php?file=$1 last; location ^~ /files/ { rewrite ^.*/files/(.+)$ /wp-includes/ms-files.php?file=$1 last; } include wp-total.conf; # Rewrite multisite '.../wp-.*' and '.../*.php'. if (!-e $request_filename) { rewrite ^/[_0-9a-zA-Z-]+(/wp-.*) $1 last; rewrite ^/[_0-9a-zA-Z-]+(/.*\.php)$ $1 last; } location @wordpress { fastcgi_pass php; fastcgi_param SCRIPT_FILENAME $document_root/index.php; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_NAME /index.php; } location ~ \.php$ { try_files $uri @wordpress; fastcgi_index index.php; fastcgi_pass php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; fastcgi_pass 127.0.0.1:9000; }
File: /etc/php5/conf.d/apc.ini
; configuration for php apc module extension = apc.so apc.enabled = 1 apc.shm_segments = 1 apc.shm_size = 512M apc.optimization = 0 apc.num_files_hint = 2700 apc.user_entries_hint = 2700 apc.ttl = 7200 apc.user_ttl = 3600 apc.gc_ttl = 600 apc.cache_by_default = 1 apc.slam_defense = 1 apc.use_request_time = 1 apc.mmap_file_mask = /dev/zero apc.file_update_protection = 2 apc.enable_cli = 0 apc.max_file_size = 2M apc.stat = 1 apc.write_lock = 1 apc.report_autofilter = 0 apc.include_once_override = 0 apc.rfc1867 = 0 apc.rfc1867_prefix = "upload_" apc.rfc1867_name = "APC_UPLOAD_PROGRESS" apc.rfc1867_freq = 0 apc.localcache = 1 apc.localcache.size = 1350 apc.coredump_unmap = 0 apc.stat_ctime = 0
Php.ini is located at /etc/php5/php.ini use the production defaults explained in the file.
File: /etc/my.cnf
The default is very long and well documented. Copy it to my.cnf.back and use this as a starting place (have at least 1GB Ram before using this file)
[client] port = 3306 socket = /var/run/mysqld/mysqld.sock [mysqld_safe] socket = /var/run/mysqld/mysqld.sock nice = 0 [mysqld] user = mysql pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock port = 3306 basedir = /usr datadir = /var/lib/mysql tmpdir = /tmp language = /usr/share/mysql/english skip-external-locking key_buffer = 16M max_allowed_packet = 16M thread_stack = 192K thread_cache_size = 16 myisam-recover = BACKUP max_connections = 100 table_cache = 256 thread_concurrency = 16 query_cache_limit = 4M query_cache_size = 128M general_log_file = /var/log/mysql/mysql.log general_log = 1 log_slow_queries = /var/log/mysql/mysql-slow.log long_query_time = 2 log-queries-not-using-indexes expire_logs_days = 10 max_binlog_size = 100M [mysqldump] quick quote-names max_allowed_packet = 16M [isamchk] key_buffer = 16M # * IMPORTANT: Additional settings that can override those from this file! # The files must end with '.cnf', otherwise they'll be ignored. # !includedir /etc/mysql/conf.d/
Whenever you make changes to a .conf file you need to restart the server to apply your changes.
/etc/init.d/mysql restart /etc/init.d/nginx restart
Next Page: Installing WordPress and W3 Total Cache
just checking one thing: the w3 total cache rewrite rules are only needed if using disk cache, right?
Yes you really only need the W3 rules for disc cache. They just add a finer level of control for the browser cache rules. I just updated the server file to show a full example of the W3 Rules using disk enhanced page cache and disk minify.
Hi,
Great post, thanks a lot for the information. From the title I got the impression, you were going into the details of multiple wp installs with one ngnix or via multiple xen installs.
Do you have any best practices about this? Or even some up to date ressources?
Thanks again for the great post.
Hi Costa,
Thanks for the feedback. I updated the post to include configuration files for a WordPress multisite and also hosting multiple sites on the server.
Hi,
Thanks a lot for the additional configuration information. It’s really helpful.
Regards
I’ve got a noob question about SSH keys. If I’ve installed the SSH key on the server it means that I can only login to it from my computer right? What if I don’t have my computer with me and have an emergency and need to SSH into the server?
Using SSH keys you will only be able to login if your computer contains a private key that matches a public key installed on the server. I prefer the added added security they provide but if you often need to access your server away from your computer then maybe a really strong password would be better for you.
If your using password authentication you can change the ssh port to prevent a majority of the brute force attempts. Also some VPS and dedicated server hosts have a java console you can use to access your server without having to use your ssh keys.
Just a note that “you are” is shortened to “you’re”, not “your”.
Otherwise, thanks for the great write up!
Hey Guys:
Awesome tutorial — my first foray into nginx w/ wordpress.
A couple things I got snagged on in the tutorial & the fixes:
> When installing everything the first ‘php5-mysql’ should be ‘mysql-server’ instead since there is already a php5-mysql package a little later in the command
> There’s a missing closing ‘}’ at the end of the file in the sites conf
> Upon trying to install wordpress I got “Your PHP installation appears to be missing the MySQL extension which is required by WordPress.” Fixed this by editing the php.ini inside the php-fpm dir.
>> I un-commented ‘extention=mysql.so’ as well as uncommenting ‘extention_dir = “./”‘ and changing ‘./’ to /usr/lib/php5/20090626+lfs and all was well.
Thanks again guys! Loving nginx so far!
Hi
Great guide thank you, I have one question about file ownerships/permissions.
Presumably everything in my site’s public folder needs to be owned by www-data and in the www-data group?
If so, how can I then upload and/or edit files when logged in as a non-root user? Do I just need to add my user to the www-data group?
Any advice much appreciated, I find this bit quite confusing!
Any recommendations for creating init scripts to ensure all the services start automatically after a reboot?
All the packages in this tutorial include the required init scripts.
-location ~ \.php {
+location ~ \.php$ {
-location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
+location ~* \.(ico|css|js|gif|jpe?g|png)$ {
-rewrite ^.*/files/(.+)$ /wp-includes/ms-files.php?file=$1 last;
+rewrite /files/(.+)$ /wp-includes/ms-files.php?file=$1 last;
Hi,
Thanks for your tutorial, I finally get my wordpress working on LEMP stack.
However, if any of your reader need the easy way to install wordpress, you can use https://github.com/buchin/WordPress-On-Lemper
Which is based on this tutorial.
It assumes you’ve installed nginx, php-fpm, and mysql, and need multipe WordPress installed on multiple domains.