I recently purchased a VPS Classic from OVH to migrate my blog. Worked good on my previous host service, but was a shared service that means sometimes the access time to a page was too long (very very long!).
A difference on a VPS (Virtual Private Server) comparing to a simple host service, is that you need to manage all the server stuffs: it is an empty box you need to configure to do what want. Considering the base VPS I bought has just 512Mb of RAM I tried to select and tune all the services installed.
All the following instructions are for the CentOS Linux distribution.
Install the webserver
First of all you need to add some external (not base) repositories:
rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm cat > /etc/yum.repos.d/nginx.repo << EOF [nginx] name=nginx repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=0 enabled=1 EOF
Now you are ready to install all required packages:
yum --enablerepo=remi,remi-php55 install nginx php-fpm php-common php-mysqlnd php-xml php-gd php-pdo mysql-server
If all worked well, you environment is ready for your wordpress blog
Nginx (Engine X) web server does not include a module to use php as backend language, for this reason you should have an external "php server" to handle this kind of pages, for example php-fpm (PHP FastCGI Process Manager). In this setup we leave the configuration of php-fpm with all the defaults parameters (later we will tune it up...). That means it starts up with a TCP listener (127.0.0.1:9000) and we must configure nginx to send all http requests to it.
Create a file in /etc/nginx/conf.d named, for example, blog.conf. The following is my configuration file that is already optimized for the W3C TotalCache Plugin
As you can see in the latest location configuration, all requests to a php file will redirected to a fastcgi script (the php-fpm).
The important things to configure are:
- listen: address:port where your nginx webserver will listen for requests. Normally the base configuration listen 80 should work. On the OVH VPS you must specify the public ip address of your server to to prevent errors on nginx startup
- server_name: the variable to configure the virtual host of your webserver. That means all requests coming on your public ip address (the one configured in the listen variable) using the domain name specified in the server_name variable, will be handled by the current configuration. That also means you could have different website on the same nginx server; you just need to assign a different server name.
- root: the folder on your server containing files you want to serve through the webserver. For example all the wordpress files should be copied inside the folder configured here.
You are ready to extract wordpress (or any other php application) to the configured folder.
Start all services
Now you can test your configuration by starting up all the services:
service nginx start service php-fpm start service mysqld start chkconfig nginx on chkconfig php-fpm on chkconfig mysqld on
Going to the configured domain name, should allow you the access to your wordpress blog (or to the wordpress setup page if need to configure a new blog).
Depending on the traffic of your blog, you can try to tune it up to reduce the used resources.
For example, my blog has normally 200/300 visit per day from europe and USA, which is important to know the access time to the blog and "calculate" the simultaneous connections.
An important thing to understand is the meaning of "simultaneous": exactly in the same moment two (or more users) access to a website page (producing a request to the webserver, a php page compilation, ...). If you have a user that request a blog post and spends then 5 minutes reading it, in that 5 minutes you could have 2 or 3 other users accessing your blog. User are accessing simultaneously in the real life, but not for your application server: a reading user are not using resources from your server!
So... 200 users a day means you don't have many simultaneous connections (in theory, but is a thing you have to check), so you can configure the webserver (nginx and php-fpm) in consequence.
From nginx side, the important variables to start your tuning are workerprocesses and workerconnections: the first one configure how many nginx processes are created on your server (1 by default) and the second one indicates how many connections (clients) can handled by any process.
So you can calculate the number of clients allowed on your nginx with:
max clients = workerprocesses * workerconnections
On my server I leaved the default parameters for the nginx server, means 1 process with 1024 connections (file /etc/nginx/nginx.conf)
Why if I just say there are few concurrent users?
Another important thing to know is how a browser works with a web page.
If you don't tune the default configuration, the php "web server" can handle hundreds connections without problems, BUT, it will use "lot" of ram: more than 200Mb.
Is not really an high value, I know, but when you have a virtual machine with 512mb of RAM, means the php-fpm uses half of your RAM.
The important configuration part is the one concerning the child processes.
; Choose how the process manager will control the number of child processes. ; Possible Values: ; static - a fixed number (pm.max_children) of child processes; ; dynamic - the number of child processes are set dynamically based on the ; following directives: ; pm.max_children - the maximum number of children that can ; be alive at the same time. ; pm.start_servers - the number of children created on startup. ; pm.min_spare_servers - the minimum number of children in 'idle' ; state (waiting to process). If the number ; of 'idle' processes is less than this ; number then some children will be created. ; pm.max_spare_servers - the maximum number of children in 'idle' ; state (waiting to process). If the number ; of 'idle' processes is greater than this ; number then some children will be killed. ; Note: This value is mandatory.
A child process could handles a single user requests. So, for example, 200 processes means 200 simultaneous users.
On my server, after some tests, I'm using this configuration:
pm = dynamic pm.max_children = 4 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 2 pm.max_requests = 200
That means I can have maximum 4 concurrent connections to the php part (for security you can increase the max to an higher value): a php thread normally answer to a user in less then a second (!).
When php-fpm service start up it creates 2 child processes, the others will be created only if required. You should find the good number for your child processes and put this number into start_servers variable: having required processes ready allow a faster response to the users (no time needed to create a new process).
With this configuration I can assure that php-fpm processes took only 70Mb of ram on my server (any new php-fpm process takes about 24Mb of ram more), and when I have moments with "many" concurrent users could go up to about 120Mb.
[mmornati@vps38203 ~]$ sudo python ps_mem.py Private + Shared = RAM used Program 4.0 KiB + 27.5 KiB = 31.5 KiB dbus-daemon 36.0 KiB + 31.5 KiB = 67.5 KiB atd 24.0 KiB + 51.0 KiB = 75.0 KiB mingetty (6) 60.0 KiB + 24.0 KiB = 84.0 KiB mdadm 224.0 KiB + 62.5 KiB = 286.5 KiB crond 156.0 KiB + 147.0 KiB = 303.0 KiB master 4.0 KiB + 337.5 KiB = 341.5 KiB mysqld_safe 220.0 KiB + 137.0 KiB = 357.0 KiB qmgr 332.0 KiB + 35.0 KiB = 367.0 KiB init 484.0 KiB + 81.5 KiB = 565.5 KiB rsyslogd 728.0 KiB + 173.0 KiB = 901.0 KiB nrsysmond (2) 660.0 KiB + 368.5 KiB = 1.0 MiB bash 928.0 KiB + 431.5 KiB = 1.3 MiB sudo 1.4 MiB + 230.0 KiB = 1.7 MiB nginx (2) 1.2 MiB + 481.0 KiB = 1.7 MiB pickup 940.0 KiB + 1.8 MiB = 2.7 MiB sshd (3) 3.3 MiB + 483.5 KiB = 3.7 MiB fail2ban-server 6.4 MiB + 236.5 KiB = 6.6 MiB mysqld 7.7 MiB + 175.0 KiB = 7.9 MiB named 74.4 MiB + 4.7 MiB = 79.1 MiB php-fpm (3) --------------------------------- 109.1 MiB =================================
To create this useful configuration I follow this guide. If !1 then 0 it's an incredible technical blog :)