One constantly posted question on LowEndBox and LowEndTalk is — how to get the same setup as LowEndBox, a WordPress site that runs on cheap VPS with 80MB of memory? Instead of doing a step-by-step explanation (damn I hate writing long blog posts), I decided to wrap it into a bash script that does it all.
![]() | ![]() |
![]() | ![]() |
It is based on my previous script here, and it has been tested on both Debian 5 “Lenny” and Ubuntu 10.04 “Lucid Lynx”. Sorry no other distributions are supported. It is currently hosted at github so feel free to branch it and tune it to your heart’s desire.
Usage
Here is a quick step by step on how to set up a WordPress blog running on Nginx, PHP/FastCGI and MySQL on a low end box. Let’s assume that you are going to set up a blog on hostname “blog.example.com“.
- Go and buy a cheap VPS. Yes, you know where to find cheap virtual servers under $7/month, don’t you? 🙂 I am using my 6 pound/year RackVM VPS with 128MB memory to test this script, and the performance turns out to be quite good. YMMV.
Make sure it is either a Debian or a Ubuntu distro though.
- After gaining root access to your VPS,
# wget --no-check-certificate https://github.com/lowendbox/lowendscript/raw/master/setup-debian.sh ... # bash setup-debian.sh system ... # bash setup-debian.sh exim4 ... # bash setup-debian.sh nginx ... # bash setup-debian.sh mysql ... # bash setup-debian.sh php ... # bash setup-debian.sh wordpress blog.example.com ...
- Now altering your DNS entry to point
blog.example.comto your new VPS (or alter your local/etc/hostsentry). Navigate to it from your browser, and you should be presented with WordPress set up page. Fill in your blog’s name, admin’s password and contact email, and your new WordPress is online!Just repeat the last step (running
bash setup-debian.sh wordpress <hostname>) to set up more blogs on the same box.
That’s it!
Software Stack
It’s pretty similar to my own stack that runs LowEndBox.com.
- dropbear to replace openssh. Invoked from xinetd.
- inetutils-syslogd to replace rsyslog.
- exim4 to replace sendmail (if installed). Re-configured to allow Internet delivery.
- cron
- nginx
- mysql. Re-configured to remove innodb support, remove query cache and reduce key buffer size.
- php with built-in FastCGI interface. Running only 1 child process and respawn after 5,000 requests.
The lowendscript is also
- Removing some commonly bundled applications that should not be there in the first place for a minimal distro (apache2, sendmail, bind9, samba, nscd, etc).
- MySQL root is given a new password (which can be found in
~root/.my.cnf) - Installing each WordPress site under /var/www/<hostname>. It will create appropriate database, users and password for the site.
I have to say that it is still “work in progress”, but if you want to figure out the internals please check the source code of that bash script.
Memory Usage
I am testing the same script on the following 3 systems:
- Ubuntu 10.04 64bit (RackVM)
- Debian 5 64bit (RackVM)
- Debian 5 32bit (VPSGuy)
They are all showing different memory usage. I am taking the snapshot of memory usage AFTER 10 page loads on the WordPress blog that has been created to ensure PHP process is fully loaded.
Ubuntu 10.04 64bit
root@ubuntu64:~# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.5 23300 1536 ? Ss 06:58 0:00 init
root 10124 0.0 0.5 23576 1496 ? Ss 07:34 0:00 dropbear -i
root 15742 0.0 0.7 17880 1944 pts/0 Ss 07:35 0:00 -bash
root 15754 0.0 0.4 14960 1084 pts/0 R+ 07:35 0:00 ps aux
root 24290 0.0 0.3 12508 788 ? S 07:22 0:00 /usr/sbin/syslo
root 24524 0.0 0.3 21064 1004 ? Ss 07:22 0:00 cron
root 25689 0.0 0.3 19512 972 ? Ss 07:22 0:00 /usr/sbin/xinet
mysql 26346 0.0 4.2 61812 11248 ? Ssl 07:23 0:00 /usr/sbin/mysql
www-data 27920 0.0 2.6 87768 7048 ? Ss 07:23 0:00 /usr/bin/php-cg
www-data 27922 0.5 15.0 122460 39432 ? S 07:23 0:04 /usr/bin/php-cg
103 30162 0.0 0.3 44356 1000 ? Ss 07:24 0:00 /usr/sbin/exim4
root 30267 0.0 0.3 28104 932 ? Ss 07:24 0:00 nginx: master p
www-data 30268 0.0 0.8 28744 2196 ? S 07:24 0:00 nginx: worker p
root@ubuntu64:~# free
total used free shared buffers cached
Mem: 262144 100500 161644 0 0 0
-/+ buffers/cache: 100500 161644
Swap: 0 0 0
Memory Usage: 98.1MB
Debian 5 64bit
debian64:~# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 10304 740 ? Ss 12:22 0:00 init [2]
106 1414 0.0 0.3 42708 1004 ? Ss 12:26 0:00 /usr/sbin/exim4
www-data 1655 0.0 2.5 72028 6560 ? Ss 12:26 0:00 /usr/bin/php-cg
www-data 1657 0.9 11.7 98500 30928 ? S 12:26 0:03 /usr/bin/php-cg
www-data 3126 0.0 0.7 28380 1912 ? S 12:29 0:00 nginx: worker p
root 7668 0.1 0.5 23340 1528 ? Rs 12:31 0:00 dropbear -i
root 7831 0.0 0.6 17472 1716 pts/0 Ss 12:32 0:00 -bash
root 7836 0.0 0.3 14720 980 pts/0 R+ 12:32 0:00 ps aux
root 20169 0.0 0.3 18540 936 ? Ss 12:22 0:00 /usr/sbin/cron
root 24462 0.0 0.2 12236 732 ? S 12:25 0:00 /usr/sbin/syslo
root 25637 0.0 0.3 19256 952 ? Ss 12:25 0:00 /usr/sbin/xinet
root 25694 0.0 0.5 28380 1552 ? Ss 12:25 0:00 nginx: master p
root 32427 0.0 0.2 3872 588 ? S 12:26 0:00 /bin/sh /usr/bi
mysql 32466 0.0 3.0 50420 8124 ? Sl 12:26 0:00 /usr/sbin/mysql
root 32468 0.0 0.2 3772 592 ? S 12:26 0:00 logger -p daemo
debian64:~# free
total used free shared buffers cached
Mem: 262144 61008 201136 0 0 0
-/+ buffers/cache: 61008 201136
Swap: 0 0 0
Memory Usage: 59.6MB
Debian 5 32bit
debian32:~# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 1980 688 ? Ss 23:34 0:00 init [2]
root 14064 0.0 0.1 1704 512 ? S 23:52 0:00 /bin/sh /usr/bi
mysql 14119 0.0 1.7 20056 6968 ? Sl 23:52 0:00 /usr/sbin/mysql
root 14120 0.0 0.1 1628 536 ? S 23:52 0:00 logger -p daemo
www-data 15968 0.0 1.2 16352 4996 ? Ss 23:53 0:00 /usr/bin/php-cg
www-data 15971 0.5 4.7 29436 18576 ? S 23:53 0:01 /usr/bin/php-cg
root 16040 0.0 0.3 2700 1464 ? Rs 23:53 0:00 dropbear -i
root 16119 0.0 0.1 1880 684 ? S 23:44 0:00 /usr/sbin/syslo
root 16133 0.0 0.3 2780 1536 pts/0 Ss 23:54 0:00 -bash
root 17728 0.0 0.2 2352 896 ? Ss 23:45 0:00 /usr/sbin/xinet
www-data 17758 0.0 0.3 5004 1488 ? S 23:54 0:00 nginx: worker p
root 27834 0.0 0.3 4548 1236 ? Ss 23:47 0:00 nginx: master p
root 28146 0.0 0.2 2296 896 pts/0 R+ 23:57 0:00 ps aux
102 32065 0.0 0.2 6104 900 ? Ss 23:49 0:00 /usr/sbin/exim4
debian32:~# free
total used free shared buffers cached
Mem: 262144 44272 217872 0 0 0
-/+ buffers/cache: 44272 217872
Swap: 0 0 0
Memory Usage: 43.2MB
So to put that in summary form
- Ubuntu 10.04 uses significantly more memory than Debian 5 (PHP5.3/MySQL5.1 vs. PHP5.2/MySQL5.0). So pick your distro wisely and maybe you don’t need the latest and greatest if your application does not need it.
- 32bit also uses quite a bit less than 64bit, running exactly the same version of stack. That pretty much confirms what I posted before.
And hopefully the above script is useful for your next WordPress splog farm 😛




@Rolando — no it does not default to your blog. You can add “listen 80” under “server” in the configuration file for that virtual host and Nginx will pick that up as the default virtual host.
Otherwise you can test by adding the IP address to your local /etc/hosts (or c:\windows\system32\drivers\etc\hosts if you are using Windoze).
@Minh — I still don’t believe there’s a cheap cure for DDoS unfortunately. You might need to buy bigger machine.
@AddictingGames88 — why do you need php5-fpm? Dynamic spawning of new FastCGI processes?
@LEA
Maybe Windows?
@LEA – PHP-PFM is said to be faster than PHP-CGI.
http://vpsbible.com/php/php-benchmarking-phpfpm-fastcgi-spawnfcgi/
Err. That post makes no sense. PHP-FPM uses exactly the same core as PHP-FastCGI, and I can’t see how you can get better performance on standard PHP function calls. It has a much better FastCGI process management though — useful if you want “adaptive process spawning” similar to mod_fcgi in Apache.
@Eric : How to solve FTP problem since
/usr/sbin/setsebool -P httpd_can_network_connect=1
-bash: /usr/sbin/setsebool: No such file or directory
Hi, i’m a newbie on this, i tried to upload file on wordpress and can’t because:
Unable to create directory /var/www/mydomain.com/wp-content/uploads/2010/09. Is its parent directory writable by the server?
I know if in the apache we can use suPhp, how to fix this in nginx? it’s risky if i make the directory writeable.
I also can’t using theme editor on wordpress and update plugins automatically
Thanks
@Nizar,
According to Eric@120, http://www.nerdgrind.com/wordpress-automatic-upgrade-plugin-failed-or-not-working/ is the way. However, when I perform “/usr/sbin/setsebool -P httpd_can_network_connect=1”, I get “-bash: /usr/sbin/setsebool: No such file or directory”
So, at the moment, I used the solution from http://desk.stinkpot.org:8080/tricks/index.php/2009/01/wordpress-wants-ftp-information-to-update-plugins/
@AddictingGames88
Thanks, i got it.
Need help on the following questions
1)How to add new user and disable root for DropBear?
2)If we will to install second WordPress, do we use a new ip address or the same ip as the first WordPress installation?
Hope someone can share the answer
@AddictingGames88
1. I don’t try it yet
2. If you can set the DNS for each subdomains, then you can easily install the second wordpress at the same IP
@Erawan Arif Nugroho,
2. I actually mean installing a second WordPress with a new domain name. Do I dns the new domain name to the same IP Address?
@AddictingGames88
Yes 🙂
Previously, I have 3 domain names, and I am hosting it in one VPS (with one IP)
Because the nginx will automatically maps the DNS requests to the directory in /var/www/domainname.com
@Erawan Arif Nugroho
That’s cool. I can save some money on IPs.
Hello,
Is it possible to install and configure GD?
Jack.
Err.
apt-get install php5-gdand then restart the PHP FastCGI processes?Thanks for the handy script! I have got two questions here:
1. Everything is running OK after the installation. However, after I reboot my VPS, it seems that neither mysql nor php is running:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 18 0 2464 1312 1108 S 0.0 0.5 0:00.16 init 15837 root 16 0 8272 2724 2160 S 0.0 1.0 0:00.07 sshd 32456 root 25 0 4764 692 252 S 0.0 0.3 0:00.00 nginx 32458 www-data 15 0 4916 1476 832 S 0.0 0.6 0:00.00 nginx 32463 root 18 0 5468 908 504 S 0.0 0.3 0:00.00 sshd2. When I set up WordPress, I used “www.mydomain.com” as the server name. Is there any way to config both “mydomain.com” and “www.mydomain.com” to my blog?
Thanks
1. They should be automatically restarted. Check whether php-cgi and mysql are in /etc/rc2.d
2. You can add a new file called /etc/nginx/sites-enabled/mydomain.com.conf
server { server_name mydomain.com; rewrite ^(.*)$ $scheme://www.mydomain.com$1 permanent; }LowEndAdmin, thanks again for your script and help.
It is actually true, I can access my site with SFTP without any extra FTP software. I use FireFTP add-on for Firefox, which supports SFTP too! On Windows, I was used to FAR Manager with WinSCP plug-in.
So I managed to make my VPS into a file host with nginx: I ordered a 256MB Xen VPS from 2HOST for $4.94 monthly (SATA variety, originally $5.49, code LEB10TB for 10% discount), did “” did the script up to nginx and uploaded my files. Alas, download speed from my server is around 100 kilobytes/s. If we download from two different computers, it gives us around 100 kilobytes/s each. I tried tweaking around with nginx configuration, but nothing helps.
When I ssh to server and download files with wget it goes 100 kilobytes/s from some locations. From some it is over megabyte/s.
Is the hosting provider throttling me? Can I do anything? Or maybe it’s just misconfiguration on my part?
My site: http://178.18.17.199/
file: http://178.18.17.199/firefox-4.0b6.tar.bz2
@Nickolai Leschov :
Well, many LEB readers are not using 2host services anymore.
Because thay are so slow, and at sometimes, they are down.
Mabe you can read the articles here :
http://www.lowendbox.com/blog/2host-4-04-128mb-xen-vps-with-10tb/
http://www.lowendbox.com/blog/2host-5-21-xen-vps-with-256mb/
Can the second site use a different IP from the first site? If so, how?
You might want to study a bit on Nginx configuration — this script is intended for those who know what they are doing to save time 🙂
You can use
server { server_name my-new-website.com; listen ipaddress:80; ... }to have the site on a different IP address.
Thanks for your reply. I will do a bit of study on Nginx configuration. I need different IP as I am moving existing live sites to new server without bring down the sites.
Help pls.. I installed the wp blog using the script, runs fine but im having an error in uploading my WP XML file to upload my posts etc. Error says “Zero Sized Reply” in my browser. Is that error related to the bootstrapscript?
Sorry guys ..i just forgot to set permissions in wp-content/uploads dir.
chmod 755 uploads/ fix it.
BTW i think we can still tune PHP to use less memory in /etc/php5/cgi/php.ini memory_limit = 128M
and set memory limit to 64.
That’s the maximum memory that PHP can use, but not necessarily the amount that it would use during an execution of a script.
ok ..after i rebooted my vps php-fcgi dont auto start. have i missed something in the script?
Any idea how to restart the PHP processes? I am having to restart the whole system at the moment.
To restart the PHP
I am now running cherokee in debian. And i am using debian “sid” repo. But cherokee is suffering very much. after few hours every time it shows “504 gateway timeout”. Then i need to do /etc/init.d/cherokee restart to solve this, but after a few hours problem again arises. When i am out of my home, my site remains unavailable for this 504 … error.
Now i want to switch to nginx using this script. I read the whole script and tried setting up nginx and php5-cgi but failed.
How can i make use of this script on an running server like me and any help for sid repo ?
Great script!
I’m using 49 MB on Debian with 2 wordpress sites. amazing.
Where I can edit nginx .c files? I can’t find them.
Weird comment organization… these comment is placed over the 9/10 ones..
Anyway, the NGINX seems to be installed via respiratory (apt-get)
If you wish to edit them you’ll need to compile NGINX manually.
Hi LEA,
I use Debian 5 x86 VPS and install LowEndBox shell as this blog said. I could run WordPress and display static webpage very well.
However, if I browse a PHP webpage under /var/www/nginx-default folder by browser, the browser would download the PHP file, not display it.
Could you please tell me how to fix it?
Thanks!
LEA, maybe you have anything like fail2ban preconfigured for dropbear?
Nope, although fail2ban should be quite configurable to parse syslog file to catch the dropbear error message. I just haven’t really had a need to it yet as most my VPS have port 22 firewalled to specific IPs.
Here is the fail2ban conf for dropbear
Edit fail2ban jail conf
——————————————————————–
# vim /etc/fail2ban/jail.conf
——————————————————————–
bantime = 3600
findtime = 300
## Add dropbear jail at end of file
[dropbear]
enabled = true
port = ssh
filter = dropbear
logpath = /var/log/messages
——————————————————————–
# cd /etc/fail2ban/filter.d
# vim dropbear.conf
——————————————————————–
# Fail2Ban configuration file
#
# Author: Francis Russell
[INCLUDES]
# Read common prefixes. If any customizations available — read them from
# common.local
before = common.conf
[Definition]
_daemon = dropbear
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile. The
# host must be matched by a group named “host”. The tag “” can
# be used for standard IP/hostname matching and is only an alias for
# (?:::f{4,6}:)?(?P\S+)
# Values: TEXT
#
# These match the unmodified dropbear messages. It isn’t possible to match the source of the
# ‘exit before auth’ messages from an unpatched dropbear.
#
failregex = ^%(__prefix_line)slogin attempt for nonexistent user (‘.*’)?from :.*\s*$
^%(__prefix_line)sbad password attempt for .+ from :.*\s*$
# The only line we need to match with the patched dropbear
# failregex = ^%(__prefix_line)sexit before auth from .*\s*$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =
——————————————————————–
Test fail2ban for dropbear
——————————————————————–
# fail2ban-regex /var/log/messages /etc/fail2ban/filter.d/dropbear.conf
@LEA,
Sorry again for a noob question. I changed the etc/hosts to point to my domain. How do I create a nameserver for it using the ip given? I just have one ip. For example, If I have to create 5 blogs, do I need 5 ips?
install bind/nsd3 dns server, you dont need 5 ip address, just use virtualhost.
Dont know anything about those or how to install them, but will google and try to find out.
Thanks a lot for the help.
check howtoforge.com 🙂
To create nameservers, you do need at least 2 IPs (though 1 IP would work by cheating). It’d be good to get a vps from another provider and set that up as secondary, and now you have redundant NS. 🙂
Err. Wrong answers.
Correct answer here: http://www.lowendbox.com/wiki/free-dns-providers
Pick one free DNS provider to serve your DNS, rather than doing it yourself with one single NS running on the box. I have used Zerigo and PointHQ both are of very high quality free service.
hey guys, any idea how to set dropbear to allow login using key authentication? i mean no password login, but pair of secret and public key. i did one before but using openssh, not sure how to do with dropbear, especially in this config. thanks. appreciate it 🙂
Hi, how can I change the limit of uploading file size,upload speed?
Two places that you need to change.
1. Nginx: client_max_body_size configuration parameter.
http://wiki.nginx.org/HttpCoreModule#client_max_body_size
2. PHP: Both “post_max_size” and “upload_max_filesize”
http://php.net/manual/en/ini.core.php#ini.post-max-size
http://php.net/manual/en/ini.core.php#ini.upload-max-filesize
I found there are two php.ini files under /etc/php5. Which one should I edit? /etd/php5/cgi/php.ini?
Yes. CGI one (rather than CLI, which is used when PHP is invoked on the command line).
This is great! How about adding a change to ownership of the new wordpress directory so that the plugin updates, etc. work properly:
chown -R www-data: /var/www/wpdirectory.com
No. Files shouldn’t be owned by the same owner as the web server. They shouldn’t be owned by root either (my script is a quick hack but you do need proper users). Files owned by web server means they can be overwritten by web server or your PHP process, if there’s a security breach…
Does this mean I should the ownership of the files to www-data on the server and the sites will still work without problems or any further work?
Sorry – I didn’t read that correctly. What should we do to secure our files and server then?
My principle is web server + any script environment (PHP for example) should not have write access to anything other than the ones you intend. For example PHP FastCGI processes should not be able to write to any PHP files. It should probably only be able to write to upload directories, which then need to be excluded from PHP execution…
Way too much to cover in terms of security.
I’ve done a similar installation, instead I’ve used PHP-FPM and Linode VPS. I’ve also written a step by step tutorial on it so that other people can get help with installing Nginx & WP together:
http://tutspundit.com/howto-install-nginx-php-fpm-mysql-php533-wordpress-ubuntu-part-1/
非常好.收藏了.
I modified a script called lnmp to use new version of nginx it installs
* Nginx 0.8.53
* PHP 5.2.14 ( Didn’t updated it to 5.3.x because some web scripts reported to be having problems with 5.3.X branch)
* Mysql 5.1.48
* PHPMyAdmin 3.3.7
* Eaccelerator (optional 1 click install)
* VsFTPd, PureFTPd (Optional 1 click install)
* PHP Suhousin Patch
It uses about 80MB of ram with 4 worker processes on my own site http://www.ruchirablog.com
Additional details of installation can be found here http://www.ruchirablog.com/nginx-autoinstaller/
Why is it that the content reminds me of some other identical the one which I just read elsewhere?
anyone know how to enable ipv6 in nginx?
–with-ipv6 option if you compile NGINX yourself.
Not sure whether it’s enabled when you get it via apt-get.
to check this just run
nginx -V 2>&1 | grep –color=auto with-ipv6
While testing sime things for a buddy, I had the chance to run the script on a fresh 256MB cloudthing at rackspace cloudserver setup with the debian image they offer.
Works w/o problems.
On the debian part I needed to install locales and dpkg-reconfigure them.
hello~i used lowendbox nginx php mysql;
can you help me to set rewrite for wordpress wp super cache?
http://xenbox.net/what-new/ngix-wordpress-wordpress-super-cache/
you can use this config
I had to do the wget line as this:
wget --no-check-certificate http://github.com/lowendbox/lowendscript/raw/master/setup-debian.shKept complaining about the cert not matching. Didn’t look into fixing the problem. Just wanted to get the file.
Yeah. Due to recent Firesheep controversy github has moved everything to HTTPS. Looks like they are using a GoDaddy wildcard SSL to cover *.github.com, which does not actually work in the case of github.com.
LowendAdmin, this script is still broken on Ubuntu. PHP will not start up after a reboot. I have tried 10.04, and 10.10. Please fix the script, as it only works properly on Debian (except the WordPress installation, that is broken on Debian, I have to manually create the folders)
tested today on debian lenny and everything (needs the –no-check-certificate) works fine, included wordpress setup.
maybe a small improvement would be to add the option to install an updated nginx version
http://wiki.nginx.org/InstallingFromDebianRepositories
Hey, thanks for this script. I’m new to the whole low end box thing and this helped me figure out how to get PHP working with nginx nicely (though I compiled nginx from source for newer features). Debian 5 32-bit with Drupal going is humming along at 42MB. I didn’t know it was possible to install Drupal without a gig of RAM.