This is a step by step guide on how to set up your own unmanaged server or vps to run as a WordPress Performance server environment. Using this setup you will have the ability to host a large WordPress Multisite set up or numerous single installs. This guide assumes you have a basic understanding of using SSH via the Mac Terminal app or Putty for Windows and requires an unmanaged dedicated server or VPS hosting account with either the 32 or 64 bit Debian kernal available.
In my last guide I touted a Nginx reverse proxy cache with WordPress and Apache as the ultimate WordPress performance stack but since then I have found that there is really no reason to use Apache unless you have a specific need for it. Nginx has matured and works great with the WordPress rewrite engine and even W3 Total Cache now includes Nginx rewrite rules for page cache, minify and browser caching.
If you ever decide that managing you own web server isn’t for you then I highly recommend WP Engine WordPress Hosting WP Engine runs on Nginx and they handle all the caching for you.
Choosing a web host with Debian “squeeze” images available
Debian 6 aka “squeeze” is considered the grandfather of Linux distors and Debian is known for relatively strict adherence to the Unix and free software philosophies. Debian is also distributed with access to repositories containing thousands of software packages ready for installation and use.
Most of the large managed hosting companies don’t give you the option of choosing your Linux distro so your going to need to find one that does. The reason for this is that it’s much easier for a hosting company to provide support using cPanel or Parallels Virtuozzo VPS virtualization. Virtuozzo allows them to squeeze many more VPSs on a box and control the resources and your limited to guess what - Cent OS.
Your going to need a provider that offers Xen virtualization. Xen is a powerful open source virtualization platform that supports a wide range of guest operating systems including Linux - Debian, Ubuntu, Free BSD, Cent OS, Fedora and more. When you set up your account have your provider load the Debian 6 aka “squeeze” image on your VPS or install it on your dedicated server. If you have over 2GB memory go for the 64 bit version.
I use Softlayer (formally The Planet) for my dedicated server because of the state of the art data centers and major broadband backbone it’s connected to. It also has a very powerful back end portal and allows you to connect to your box over a private VPN. Linode, Slicehost, and VPS.net are also very good choices. I would stay away from Media Temple and Rackspace as I’ve had problems with both and they’ve had well documented security vulnerabilities in the past.
Your provider will either provide you with an ip address and password to connect to your server for the first time or give you access to a control panel that you can use to load the image.
Some hosts include the network setup on the image others provide a java ssh console to connect. If your only provided the java console you will need to set up the networking settings.
*Note: all entries in this article that require opening a file assume the nano text editor, some of you might prefer vim or if your a real Linux Ninja Emacs (If you use Emacs you don’t need to read this article .) If you prefer vim just substitue vi for nano.
If your provider pre-installed the image for you skip to Security.
nano /etc/network/interfaces
This is the file that contains the connection settings for each of the network cards on your server. You will need your ip address and the gateway address which is to the router. Your host should provide these for you.
auto lo iface lo inet loopback auto eth0 inet static address xx.xx.xxx.xxx netmask 255.255.255.0 gateway xx.xx.xxx.xxx
Ctrl-x will close your file and prompt you to save.
Next we will install the secure shell server
apt-get install openssh-server /etc/init.d/ssh status : sshd is running.
With networking and ssh setup you will be able to connect via ssh using Terminal or Putty
ssh [email protected]
Enter your password at the prompt and accept the key fingerprint prompt which will add your new server or vps to your local known_hosts file.
Securing your server
The first step is securing your server. To properly secure your server you need to disable password auth and use ssh keys to access your server. Your key authorization will also be used for adding files via an SFTP program like Transmit. We will also be updating all the packages and configuring the firewall using ufw.
apt-get update apt-get upgrade-distro
Disable password authentication in the sshd_config file.
nano /etc/ssh/sshd_config Protocol 2 PasswordAuthentication no UseDNS no
Open another terminal window to generate the ssh keys on your LOCAL machine.
mkdir ~/.ssh cd ~/.ssh ssh-keygen -t rsa
You will be prompted for a password to further secure your key and a name to save it under. Unless you all ready have existing keys just press enter to accept the default name of id_rsa / id_rsa.pub. The id_rsa.pub file is your public key and will need to be moved to the server.
scp ~/.ssh/id_rsa.pub [email protected]:
You will be prompted for your server password and your public key file will be in your root directory. Now will move it to the correct place and add it to the authorized_keys file. Close your 2nd terminal window and go back to the one you were using and connected to the server with.
mkdir ~/.ssh mv ~/id_rsa.pub ~/.ssh/authorized_keys chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys
Now we will configure the firewall using ufw. UFW is an uncomplicated firewall that acts as an interface to control the servers iptables without the confusing syntax. It is shipped with Ubuntu but for Debian you will need to install: apt-get install ufw.
The following commands will open up the ports for ssh, web, smtp (php-mail), and mysql. You can add rules for any of the network services defined in the /etc/services file or roll your own custom rules.
ufw allow ssh ufw allow www ufw allow https ufw allow mysql ufw enable ufw status :To Action From -- ------ ---- 22 ALLOW Anywhere 80 ALLOW Anywhere 443 ALLOW Anywhere 3306 ALLOW Anywhere
Now we will restart ssh and test our connection. VERY IMPORTANT don’t disconnect your current ssh session! Test by opening another terminal window. If your on Mac you will get a keychain notice for your key password. Click the remember button so you won’t have to enter it every time.
Current terminal window
/etc/init.d/ssh reload
New Terminal window
ssh [email protected] :Linux DebianLinux-001 2.6.32-5-amd64 #1 SMP Mon Mar 7 21:35:22 UTC 2011 x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Tue Jul 12 21:40:45 2011 from 108-71-13-85.lightspeed.hstntx.sbcglobal.net root@servername ~:
If you were successful give your self a pat on the back and close your original terminal window.
The Performance Stack - Nginx, PHP-FPM, MySQL
In the past, with Debian 5, it was very frustrating trying to stay up to date with the latest versions of PHP, MySQL and Nginx because the packages were always so outdated. Debian 6 shipped with up to date versions but if you want the latest performance packages your going to need the Dotdeb repositories.
Dotdeb is a repository containing packages to turn your Debian boxes into powerful, stable and up-to-date LAMP servers :
- PHP 5.3
- useful PHP extensions : APC, imagick, Pinba, xcache, Xdebug, XHprof…
- MySQL 5.1 and its performant InnoDB plugin,
- Maatkit…
Add the Dotdeb repos to /etc/apt/sources.list
deb http://packages.dotdeb.org stable all deb-src http://packages.dotdeb.org stable all
Now fetch the appropriate GnuPG keys
wget http://www.dotdeb.org/dotdeb.gpg cat dotdeb.gpg | apt-key add -
Run apt-get update and you should see your server connecting to the dot deb mirrors.
Note: Dotdob is a one man operation maintained by Guillaume Plessis, @W_a_s_t_e on Twitter. If you benefit or prosper from his packages consider donating
Install Nginx, PHP-FPM, MySQL, APC
apt-get install nginx-full php5-fpm php5 php5-mysql php5-apc php5-mysql php5-xsl php5-xmlrpc php5-sqlite php5-snmp php5-curl
You will be prompted to accept installs and apt-get will make sure all dependencies are met and install additional packages if needed. When you get to the MySQL install a semi-graphical interface will pop up. Make sure you choose a password for the root mysql user.
If you have made it this far go grab a beer or an espresso you deserve it, Systems Administrator.
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 "<br ?--></pre> <h1>Nginx Baby - It WORKS!!!!</h1> <pre> "; ?>' >> /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
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
WordPress via svn and setting up W3 Total Cache
The server is ready to install WordPress
Create your database
mysql -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 5340 to server version: 3.23.54 Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> CREATE DATABASE databasename; Query OK, 1 row affected (0.00 sec) mysql> GRANT ALL PRIVILEGES ON databasename.* TO "user_name"@"localhost" -> IDENTIFIED BY "password"; Query OK, 0 rows affected (0.00 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.01 sec) mysql> EXIT Bye
Install WordPress via SVN
cd /srv/www/yourdomain/public svn co http://core.svn.wordpress.org/tags/3.2.1 .
Add your database info to wp-config.php and install by visiting yourdomain.com/wp-admin/install.php
Use the Compatibility Check in W3 Total Cache to make sure everything is set up right. Yours will look similar to this one.
Set page cache and minify to disk enhanced. Object and database to APC. You can experiment with page cache via APC but with Nginx disk enhanced will most likely be faster.
Final thoughts
If your doing this for the first time set up a test install to get the hang of if before you rely on this for a production set up or client site. Using Debian and the apt-get repos it’s pretty easy to manage your own dedicated server or VPS and you can lose the cPanel training wheels. Not only will your page load times drop you will have a good feeling of accomplishment.
To maintain your packages run apt-get update and apt-get upgrade every once in a while and you can follow @dotdeb on Twitter to stay up to date with upgrades.
Feel free to leave a comment or question. I would love to hear how this set up works for you.
Resources and further reading
5:18 am
just checking one thing: the w3 total cache rewrite rules are only needed if using disk cache, right?
6:19 am
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.
5:09 am
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.
5:24 pm
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.
5:35 pm
Hi,
Thanks a lot for the additional configuration information. It’s really helpful.
Regards
10:43 am
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?
8:37 pm
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.
3:31 am
Just a note that “you are” is shortened to “you’re”, not “your”.
Otherwise, thanks for the great write up!
1:58 pm
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!
12:42 pm
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!
4:51 pm
Any recommendations for creating init scripts to ensure all the services start automatically after a reboot?
2:43 pm
All the packages in this tutorial include the required init scripts.
3:17 am
ym2VWY lazejnxrlaoy
1:43 am
-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;
8:02 am
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.
2:42 pm
For anyone else that finds this page, you may want to compare this install with http://www.lowendbox.com/blog/wordpress-cheap-vps-lowendscript/ as the lowendbox config gets rid of things that are not needed for installs on small vps accounts.
Chris
1:03 am
Hi,
Images in the post are not loading. Can you please rectify this? Thanks for the tutorial.
4:42 pm
Hi, using your guide to try and become a sys admin :). Anyway, got stuck on the security bit. Have a windows machine so I used puttygen to make keys, got it moved over to the right spot, changed the things in the sshd_config I thought I was supposed to but can’t get in (using pageant).. Any thoughts?
5:01 pm
Woohoo, figured it out… The file that puttygen created had some extra stuff in it. I nano’d in in the terminal you so wisely told us to keep open. deleted the contents, then pasted the actual code from the puttygen window and BAM. It’s working
10:20 am
Great tutorial. I have a couple of questions though, hope you can help:
1. I plan to have multiple WP sites, one of which will be multisite with subdomains. Which nginx.conf should I use?
2. Curious to know how much memory this tutorial assumes.
Thanks so much!!
1:16 am
Great piece. One correct. SoftLayer is NOT “formerly ThePlanet”. SoftLayer was a fantastic host long before they *acquired* ThePlanet.
1:19 am
Also, to add: “there is no need for Apache” is not true for most production environments. When Nginx gets real rewrite functionality, the ability to have mod_security equivalents etc, *without* a gazillion “IF” conditions in the config file (which according to Nginx itself slows down the server considerably) that’s when Nginx can survive on its own. Until then, sure there are websites running only Nginx with PHP-FPM, but they have sacrificed a lot of production quality stuff.
4:00 am
For putty users on windows, here’s a tutorial on how to configure auto login.
http://www.windowstipspage.com/2011/11/putty-auto-login-ssh-keys.html
3:02 am
Once you move to production, you can turn apc.stat = 1 to 0, for a bit of performance gain as APC won’t check every PHP file if it has changed recently
3:51 am
In this tutorial failure, can not be successfully installed.
Best to write a more detailed tutorial, thank you!
11:47 am
Just found this tutorial and managed to get the WordPress install working just fine. Great tutorial, thanks.
However, I have one small problem, namely WordPress 3.5.1 friendly URLs. The nginx re-write rules seems to prepend index.php onto all the permalink options, and if I have the 404 error option (the one where you mention the security hole), I just get 404 pages whenever I try to visit any content in the site.
If I comment out that rule, they work, but they look like http://debiantest.com/index.php/sample-page/
How do I get rid of the “index.php” from the rewrite rule and stop receiving 404 errors on all the pages/posts? I’ve tried various other sites for solutions, as this is apparently quite common, but even the recommended solution by the nginx developers doesn’t work.
Thanks in advance
1:54 pm
I worked with WordPress for many years but this guide and the use of W3Cache and others are no longer needed. Here is a link to a newer, better guide.
http://www.jimwestergren.com/wordpress-with-maximum-performance-and-speed/