How to set-up a VPS with nginx, PHP, mysql, phpMyAdmin, mail server, FTP, Webmin, Memcached and EAccelerator and then install WordPress

Here I explain how to set up a VPS with the features above and install WordPress on Ubuntu 10.04 LTS. It is always best to use a LTS (Long Term Support) version of Ubuntu since then you get security updates for 5 years, instead of 18 months. I got my VPS from IntoVPS, with 1024 MB of burstable RAM (512 MB guaranteed), 30GB disk space and 500GB monthly traffic for 10$/month. The steps I take here worked for me on this server, but if you have any problems either leave a comment or post in the forum.

1. Initial setup
First we have to get the server ready. I am assuming you have already logged in using PuTTY as root. First update the package repositary listing:
apt-get update
Now install any updates:
apt-get upgrade
Just in case:
apt-get install wget make
Now were ready to install nginx.
2. NGINX
nginx (pronounced “engine-x”) is a lightweight, fast and powerful HTTP server. More information here. If you are having second thoughts about switching to nginx, let´s put it this way: I still consider switching from Apache to nginx the best thing I´ve ever done to this VPS, and I can personally testify that WordPress, phpMyAdmin, Roundcube webmail and Simple Machines Forum work perfectly with nginx.
First we have to add the nginx repositary to the database, beacause at the time of writing the latest stable nginx is version 0.8.54 (Update: it is now 1.0.0), whereas the latest in the default Ubuntu repositary is 0.7. To add the repositary first we have to install python-software-properties:
apt-get install python-software-properties
Now add the repository:
add-apt-repository ppa:nginx/stable
Now update the database:
apt-get update
Now install nginx:
apt-get install nginx
We’ll configure it, and set up PHP5, in the next section.
3. PHP
If your planning to just serve static content from your server, you can stop here, or go on to set up the mail server. But if you´re going to install WordPress (or an other PHP application) then we have to install PHP.
(Update: see an alternative (better) way of installing PHP here)
First we install the PHP CGI and other components we may need:
apt-get install php5 php5-cgi php5-sqlite php5-tidy php5-xmlrpc php5-xs php5-dev
Now we have to create a PHP-FastCGI initialization script. Let´s first open the new file with nano:
nano /etc/init.d/php-fastcgi
Now paste the following code into the file (note: if you’re using PuTTY just copy this then right-click in the PuTTY window.) :
  1. #!/bin/bash
  2. BIND=127.0.0.1:9000
  3. USER=www-data
  4. PHP_FCGI_CHILDREN=6
  5. PHP_FCGI_MAX_REQUESTS=1000
  6. PHP_CGI=/usr/bin/php-cgi
  7. PHP_CGI_NAME=`basename $PHP_CGI`
  8. PHP_CGI_ARGS=“- USER=$USER PATH=/usr/bin PHP_FCGI_CHILDREN=$PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS=$PHP_FCGI_MAX_REQUESTS $PHP_CGI -b $BIND”
  9. RETVAL=0
  10. start() {
  11. echo -n “Starting PHP FastCGI: “
  12. start-stop-daemon –quiet –start –background –chuid “$USER”exec /usr/bin/env$PHP_CGI_ARGS
  13. RETVAL=$?
  14. echo “$PHP_CGI_NAME.”
  15. }
  16. stop() {
  17. echo -n “Stopping PHP FastCGI: “
  18. killall -q -w -u $USER $PHP_CGI
  19. RETVAL=$?
  20. echo “$PHP_CGI_NAME.”
  21. }
  22. case “$1″ in
  23. start)
  24. start
  25. ;;
  26. stop)
  27. stop
  28. ;;
  29. restart)
  30. stop
  31. start
  32. ;;
  33. *)
  34. echo “Usage: php-fastcgi {start|stop|restart}”
  35. exit 1
  36. ;;
  37. esac
  38. exit $RETVAL
Things you may want to change:
  • PHP_FCGI_CHILDREN on line 4: This is the number of worker processes that FastCGI spawns to handle PHP requests. The more connections per second your site recieves, the higher you should set this setting. Keep this in mind: Connections per second * Seconds it takes to generate the page = PHP_FCGI_CHILDREN. If you are running out of memory decrease this value.
  • PHP_FCGI_MAX_REQUESTS on line 5: This is the number of requests before the worker proces(es) are respawned (restarted). If you are having any problems with memory leaks, blank pages, etc., try decreasing this to 500.
Now save the file (usualy by pressing CTRL+O) and exit nano. We now have to make this file executable:
chmod +x /etc/init.d/php-fastcgi
Now start the script:
/etc/init.d/php-fastcgi start
Now we have enable PHP in nginx. First open the config file:
nano /etc/nginx/sites-available/default
Now make the following changes:
  • On line 25, add index.php just before the semi-colon (;).
  • Change localhost on line 28 to your domain. If you do not have a domain name leave it as it is.
  • Uncomment the following lines:
  1. location ~ .php$ {
  2. fastcgi_pass 127.0.0.1:9000;
  3. fastcgi_index index.php;
  4. include fastcgi_params;
  5. }
Your config file should now look like this:
  1. server {
  2. #listen 80; ## listen for ipv4; this line is default and implied
  3. #listen [::]:80 default ipv6only=on; ## listen for ipv6
  4. # Document root:
  5. root /usr/share/nginx/www;
  6. index index.html index.htm index.php;
  7. # Make site accessible from your-site.com and www.your-site.com (change to your domain name)
  8. server_name your-site.com www.your-site.com;
  9. location / {
  10. # First attempt to serve request as file, then
  11. # as directory, then fall back to index.html
  12. try_files $uri $uri/ /index.html;
  13. }
  14. location /doc {
  15. root /usr/share;
  16. autoindex on;
  17. allow 127.0.0.1;
  18. deny all;
  19. }
  20. location /images {
  21. root /usr/share;
  22. autoindex off;
  23. }
  24. #error_page 404 /404.html;
  25. # redirect server error pages to the static page /50x.html
  26. #
  27. #error_page 500 502 503 504 /50x.html;
  28. #location = /50x.html {
  29. # root /usr/share/nginx/www;
  30. #}
  31. # proxy the PHP scripts to Apache listening on 127.0.0.1:80
  32. #
  33. #location ~ .php$ {
  34. # proxy_pass http://127.0.0.1;
  35. #}
  36. # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
  37. #
  38. location ~ .php$ {
  39. fastcgi_pass 127.0.0.1:9000;
  40. fastcgi_index index.php;
  41. include fastcgi_params;
  42. }
  43. # deny access to .htaccess files, if Apache’s document root
  44. # concurs with nginx’s one
  45. #
  46. #location ~ /.ht {
  47. #deny all;
  48. #}
  49. }
Don’t forget to read the file to make shure everything is set up right.
Now restart nginx:
/etc/init.d/nginx restart
Now it´s time to create a test script:
nano /usr/share/nginx/www/test.php
Inside, insert the following:
<?php phpinfo() ?>
And save the file. Now go to your-site.com/test.php in your web browser. You should see a page with your PHP configuration information. We are now ready to install MySQL!
4. MySQL
Type:
apt-get install mysql-server mysql-client php5-mysql
And follow the instructions that appear on-screen. Now restart the PHP server:
/etc/init.d/php-fastcgi restart
Now it´s time to install phpMyAdmin
5. phpMyAdmin
phpMyAdmin is a browser-based MySQL database manager writen in PHP. First let´s install it:
apt-get install phpmyadmin
If the installer asks you what HTTP server to configure for, press enter without answering.
Now we have to be able to access phpMyAdmin through phpmyadmin.your-site.com. First create a new config file:
nano /etc/nginx/sites-available/phpmyadmin
And inside insert the following (don´t forget the right-click method):
  1. server {
  2. #listen 80; ## listen for ipv4; this line is default and implied
  3. #listen [::]:80 default ipv6only=on; ## listen for ipv6
  4. root /usr/share/phpmyadmin;
  5. index index.php index.html index.htm;
  6. # Make site accessible from http://localhost/
  7. server_name phpmyadmin.your-site.com;
  8. location / {
  9. # First attempt to serve request as file, then
  10. # as directory, then fall back to index.html
  11. try_files $uri $uri/ /index.html;
  12. }
  13. location /doc {
  14. root /usr/share;
  15. autoindex on;
  16. allow 127.0.0.1;
  17. deny all;
  18. }
  19. location /images {
  20. root /usr/share;
  21. autoindex off;
  22. }
  23. #error_page 404 /404.html;
  24. # redirect server error pages to the static page /50x.html
  25. #
  26. #error_page 500 502 503 504 /50x.html;
  27. #location = /50x.html {
  28. # root /usr/share/nginx/www;
  29. #}
  30. # proxy the PHP scripts to Apache listening on 127.0.0.1:80
  31. #
  32. #location ~ .php$ {
  33. # proxy_pass http://127.0.0.1;
  34. #}
  35. # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
  36. #
  37. location ~ .php$ {
  38. fastcgi_pass 127.0.0.1:9000;
  39. fastcgi_index index.php;
  40. include fastcgi_params;
  41. }
  42. # deny access to .htaccess files, if Apache’s document root
  43. # concurs with nginx’s one
  44. #
  45. #location ~ /.ht {
  46. # deny all;
  47. #}
  48. }
Change your-site.com on line 9 to your domain name. Don´t forget to set up the DNS record!!!
Now we have to enable this configuration using the following command:
ln -s /etc/nginx/sites-available/phpmyadmin /etc/nginx/sites-enabled/phpmyadmin
Now restart nginx and your done. Go to phpmyadmin.your-site.com in your web-browser and login with the username and password you specified in the MySQL installer (not the phpMyAdmin one).
6. Email server
Now it´s time to set up a Mail Transport Agent (MTA), in this case, Postfix; and a POP3/IMAP server, Dovecot, so we can read the mail. (Note: If your planning to use Google Apps for email, or not use your own email at all, you can skip this step.
First let´s install Postfix:
apt-get install postfix postfix-tls libsasl2-2 sasl2-bin libsasl2-modules popa3d
Follow the insructions on-screen until the installation completes. We´ll configure Postfix later. Now let´s install Dovecot:
apt-get install dovecot-imapd dovecot-pop3d dovecot-common
Open the config file:
nano /etc/dovecot/dovecot.conf
Find the following settings (using the CTRL+W function) and make shure they are set as below (uncomment if necesary):
protocols = imap pop3
ssl = no
mail_location = mbox:~/mail:INBOX=/var/mail/%u
pop3_uidl_format = %08Xu%08Xv
disable_plaintext_auth = no
Now replace this:
auth default {
With this:
auth default2 {
And just before that line add:
  1. auth default {
  2. mechanisms = plain login
  3. passdb pam {
  4. }
  5. userdb passwd {
  6. }
  7. socket listen {
  8. client {
  9. path = /var/spool/postfix/private/auth
  10. mode = 0660
  11. user = postfix
  12. group = postfix
  13. }
  14. }
  15. }
Now enter the Postfix config file:
nano /etc/postfix/main.cf
And insert at the end:
  1. smtpd_sasl_auth_enable = yes
  2. smtpd_sasl_local_domain = your-site.com
  3. smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination
  4. smtpd_sasl_security_options = noanonymous
Replacing your-site.com with your domain name.
Now add a new user to recieve and send email (If new user is joe then email address will be joe@your-site.com. Create as many users as you want):
adduser username
Now restart all components of the mail server:
  1. /etc/init.d/saslauthd restart
  2. /etc/init.d/postfix restart
  3. /etc/init.d/dovecot restart
Now you can access your email through your email client, or through any webmail package. I recomend Roundcube webmail, since it is easy to set up and use, stylish and works great with nginx!
7. FTP server
I use vsftpd (Very Secure File Transfer Protocol Daemon) beacause it´s lightning fast and very easy to set up. First let´s install it:
apt-get install vsftpd
Now let´s edit the config file:
nano /etc/vsftpd.conf
Replace the entire contents with:
  1. # Run standalone? vsftpd can run either from an inetd or as a standalone
  2. # daemon started from an initscript.
  3. listen=YES
  4. #
  5. # Run standalone with IPv6?
  6. # Like the listen parameter, except vsftpd will listen on an IPv6 socket
  7. # instead of an IPv4 one. This parameter and the listen parameter are mutually
  8. # exclusive.
  9. #listen_ipv6=YES
  10. #
  11. # Allow anonymous FTP? (Disabled by default)
  12. anonymous_enable=NO
  13. #
  14. # Uncomment this to allow local users to log in.
  15. local_enable=YES
  16. #
  17. # Uncomment this to enable any form of FTP write command.
  18. write_enable=YES
  19. #
  20. # Default umask for local users is 077. You may wish to change this to 022,
  21. # if your users expect that (022 is used by most other ftpd’s)
  22. #local_umask=022
  23. #
  24. # Uncomment this to allow the anonymous FTP user to upload files. This only
  25. # has an effect if the above global write enable is activated. Also, you will
  26. # obviously need to create a directory writable by the FTP user.
  27. #anon_upload_enable=YES
  28. #
  29. # Uncomment this if you want the anonymous FTP user to be able to create
  30. # new directories.
  31. #anon_mkdir_write_enable=YES
  32. #
  33. # Activate directory messages – messages given to remote users when they
  34. # go into a certain directory.
  35. dirmessage_enable=YES
  36. #
  37. force_dot_files=YES
  38. # If enabled, vsftpd will display directory listings with the time
  39. # in your local time zone. The default is to display GMT. The
  40. # times returned by the MDTM FTP command are also affected by this
  41. # option.
  42. use_localtime=YES
  43. #
  44. # Activate logging of uploads/downloads.
  45. xferlog_enable=YES
  46. #
  47. # Make sure PORT transfer connections originate from port 20 (ftp-data).
  48. connect_from_port_20=YES
  49. #
  50. # If you want, you can arrange for uploaded anonymous files to be owned by
  51. # a different user. Note! Using “root” for uploaded files is not
  52. # recommended!
  53. #chown_uploads=YES
  54. #chown_username=whoever
  55. #
  56. # You may override where the log file goes if you like. The default is shown
  57. # below.
  58. #xferlog_file=/var/log/vsftpd.log
  59. #
  60. # If you want, you can have your log file in standard ftpd xferlog format.
  61. # Note that the default log file location is /var/log/xferlog in this case.
  62. #xferlog_std_format=YES
  63. #
  64. # You may change the default value for timing out an idle session.
  65. idle_session_timeout=900
  66. #
  67. # You may change the default value for timing out a data connection.
  68. #data_connection_timeout=120
  69. #
  70. # It is recommended that you define on your system a unique user which the
  71. # ftp server can use as a totally isolated and unprivileged user.
  72. #nopriv_user=ftpsecure
  73. #
  74. # Enable this and the server will recognise asynchronous ABOR requests. Not
  75. # recommended for security (the code is non-trivial). Not enabling it,
  76. # however, may confuse older FTP clients.
  77. #async_abor_enable=YES
  78. #
  79. # By default the server will pretend to allow ASCII mode but in fact ignore
  80. # the request. Turn on the below options to have the server actually do ASCII
  81. # mangling on files when in ASCII mode.
  82. # Beware that on some FTP servers, ASCII support allows a denial of service
  83. # attack (DoS) via the command “SIZE /big/file” in ASCII mode. vsftpd
  84. # predicted this attack and has always been safe, reporting the size of the
  85. # raw file.
  86. # ASCII mangling is a horrible feature of the protocol.
  87. #ascii_upload_enable=YES
  88. #ascii_download_enable=YES
  89. #
  90. # You may fully customise the login banner string:
  91. ftpd_banner=Your welcome message
  92. #
  93. # You may specify a file of disallowed anonymous e-mail addresses. Apparently
  94. # useful for combatting certain DoS attacks.
  95. #deny_email_enable=YES
  96. # (default follows)
  97. #banned_email_file=/etc/vsftpd.banned_emails
  98. #
  99. # You may restrict local users to their home directories. See the FAQ for
  100. # the possible risks in this before using chroot_local_user or
  101. # chroot_list_enable below.
  102. #chroot_local_user=YES
  103. #
  104. # You may specify an explicit list of local users to chroot() to their home
  105. # directory. If chroot_local_user is YES, then this list becomes a list of
  106. # users to NOT chroot().
  107. #chroot_local_user=YES
  108. #chroot_list_enable=YES
  109. # (default follows)
  110. #chroot_list_file=/etc/vsftpd.chroot_list
  111. #
  112. # You may activate the “-R” option to the builtin ls. This is disabled by
  113. # default to avoid remote users being able to cause excessive I/O on large
  114. # sites. However, some broken FTP clients such as “ncftp” and “mirror” assume
  115. # the presence of the “-R” option, so there is a strong case for enabling it.
  116. #ls_recurse_enable=YES
  117. #
  118. # Debian customization
  119. #
  120. # Some of vsftpd’s settings don’t fit the Debian filesystem layout by
  121. # default. These settings are more Debian-friendly.
  122. #
  123. # This option should be the name of a directory which is empty. Also, the
  124. # directory should not be writable by the ftp user. This directory is used
  125. # as a secure chroot() jail at times vsftpd does not require filesystem
  126. # access.
  127. secure_chroot_dir=/var/run/vsftpd/empty
  128. #
  129. # This string is the name of the PAM service vsftpd will use.
  130. pam_service_name=vsftpd
  131. #
  132. pasv_min_port=44950
  133. pasv_max_port=45000
  134. # This option specifies the location of the RSA certificate to use for SSL
  135. # encrypted connections.
  136. #rsa_cert_file=/etc/ssl/private/vsftpd.pem
Things to change:
  • On line 91, type your welcome message.
  • On lines 132 and 133 are the minimum and maximum ports passive connections. You´ll need them if you install a firewall later. Change them to any unspecified port range (see what ports are unspecified here).
Now restart vsftpd:
restart vsftpd
You can now login to your server using FTP (using the user account you created before. Root logins will not work.)
8. Webmin
Webmin is a server control panel similar to cPanel and Plesk, but it is free. First get the download path for the latest .tar.gz version here. Then download and install it on your server:
  1. wget http://downloadpath/webmin-x.x.x.tar.gz
  2. tar xzf webmin-x.x.x.tar.gz
  3. cd /webmin
  4. ./setup.sh
After setup is complete go to your-site.com:10000 and login with the username and password you specified during the installation.
9.Things to set-up before continuing
Now is a good time to do certain tasks that should be performed.
First, I recommend, as a security precaution, to change the SSH port using Webmin (Servers > SSH server > Networking). Don´t forget to click apply changes after changing the port number, or to update the port number in the PuTTY configuration window.
We also have to add the user you use to make FTP connections to the www-data group, so that there isn´t any permission errors when we install WordPress. First go to System > Users and Groups and select the user account you use to make your FTP connections. Go to the Group membership section and set Primary Group to www-data. Now go to Secondary groups and add the group with the same name as the user account. Also add the sudo group if you want this user account to be able to use the sudo command. Now set Change group ID on files? to All files.
Group settingsSettings should look like this
Now click save. Do this to all user accounts you use to upload files via FTP. So now nginx has group access to your users files (In other words, permission 774 means full permissions for owner, full permissions for nginx (and therefore WordPress, etc…) and read permissions for everybody else. We do this so the server can modify files when we use things like WordPress. Now go to the SSH terminal and type:
chown -R username /usr/share/nginx/www
Replacing username with the user you´ve just added to the www-data group.
We`re now ready to set up Memcached
10. Memcached
Memcached is a general-purpose distributed memory caching system. It is very easy to install. Just type:
apt-get install memcached php5-memcached
And you´re done! Instructions on how to integrate it into WordPress here.

11. EAccelerator
EAccelerator is a caching extension for PHP that stores PHP scripts in their compiled state in shared memory.
First, we need to download the latest version of EAccelerator:
wget http://bart.eaccelerator.net/source/0.9.6.1/eaccelerator-0.9.6.1.tar.bz2
Now let´s compile and install it:
  1. tar xvjf eaccelerator-0.9.6.1.tar.bz2
  2. cd eaccelerator-0.9.6.1
  3. phpize
  4. ./configure –enable-eaccelerator=shared
  5. make
  6. make install
Now we have to enable it in the php.ini file. Open the php.ini file:
nano /etc/php5/cgi/php.ini
And insert this just after (PHP)
  1. zend_extension = “/usr/lib/php5/20090626/eaccelerator.so”
  2. eaccelerator.shm_size = “32″
  3. eaccelerator.cache_dir = “/var/cache/eaccelerator”
  4. eaccelerator.enable = “1″
  5. eaccelerator.optimizer = “1″
  6. eaccelerator.check_mtime = “1″
  7. eaccelerator.debug = “0″
  8. eaccelerator.filter = “”
  9. eaccelerator.shm_max = “0″
  10. eaccelerator.shm_ttl = “0″
  11. eaccelerator.shm_prune_period = “0″
  12. eaccelerator.shm_only = “0″
  13. eaccelerator.compress = “1″
  14. eaccelerator.compress_level = “9″
  15. eaccelerator.allowed_admin_path = “/usr/share/nginx/www/eaccelerator/control.php”
Now restart PHP:
/etc/init.d/php-fastcgi restart
Now we´ll enable the EAccelerator control panel:
  1. mkdir /usr/share/nginx/www/eaccelerator
  2. mv control.php /usr/share/nginx/www/eaccelerator
  3. chmod 644 /usr/share/nginx/www/eaccelerator/control.php
  4. nano /usr/share/nginx/www/eaccelerator/control.php
Now find the $user and $pw settings and change them to a username and password.
12. And finally… WordPress
We are now ready to install WordPress. First we´ll configure nginx so pretty permalinks work. Open the config file:
nano /etc/nginx/sites-available/default
Now find:
  1. location / {
  2. # First attempt to serve request as file, then
  3. # as directory, then fall back to index.html
  4. try_files $uri $uri/ /index.html;
And just after that (before the }) add:
  1. if (!-e $request_filename) {
  2. rewrite ^(.+)$ /index.php?q=$1 last;
  3. }
This will enable pretty permalinks. While we´re here we might as well block access to the wp-config.php file. Just before:
location /doc {
Add:
  1. location /wp-config.php {
  2. deny all;
  3. }
And also block access to the .htaccess files that come with some WordPress plugins (while we´re on the subject, .htaccess files don´t work with nginx, instead you use location blocks in the config file, as you´ve probably already figured out). Uncomment the following lines:
  1. location ~ /.ht {
  2. deny all;
  3. }
Now restart nginx:
/etc/init.d/nginx restart
Now we´re ready to install WordPress. Make shure you are logged in using the user account you added to the www-data group in step 9 (following this procedure wil install it in the root of your site):
  1. cd /usr/share/nginx/www
  2. wget http://wordpress.org/latest.tar.gz
  3. tar xzf latest.tar.gz
  4. cd wordpress
  5. mv * ..
  6. rm -rf wordpress
  7. chmod -R 755 /usr/share/nginx/www
  8. chmod -R 775 wp-content
  9. chmod 664 wp-config.php
Now login to phpMyAdmin, click on the permisions tab and create a new user account and database for WordPress. Then go to your-site.com/wp-admin/install.php and complete WordPress´famous 5-minute install.
After installing go to SSH and type
chmod 640 /usr/share/nginx/www/wp-config.php
And you´re done! By following this tutorial you have (hopefully) gone from a blank box to a sophisticatedly set-up VPS capable of handling almost anything. I hope that this tutorial is both accurate and easy to understand. If you have any problems please leave a comment below.

Comments

  1. It is a inspiring post and it has a significant meaning and thanks for sharing the information.
    Webmail Login

    ReplyDelete

Post a Comment

Popular posts from this blog

PHPMixBill V5 mikrotik Billing Solutions

How to install Asterisk and A2billing on Ubuntu Server 12.04LTS

odbcinst: SQLGetPrivateProfileString failed with