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 😛




@eM – I’m sure you can do that manually. Simply remove nginx (apt-get remove nginx) and then use the following guide to install lighttpd.
http://www.lowendbox.com/blog/yes-you-can-run-18-static-sites-on-a-64mb-link-1-vps/
Using Ubuntu 64bit, only using 65mb of RAM, doing nothing but running APT-GET Upgrade and Update before, and running the above script.
free -m
total used free shared buffers cached
Mem: 2048 65 1982 0 0 0
-/+ buffers/cache: 65 1982
Swap: 0 0 0
@LEB
What was your reason starting dropbear with xinetd?
I see your notes about “easier to configure” in your script… but someone expect things in /etc/default/ may be confused.
@terii — well that’s just my setup, because I am actually using xinetd for a few other things so instead of running dropbear in daemon mode + xinetd, I’ll just run dropbear in inetd mode, forked from xinetd.
fang:/var/www# free -m
total used free shared buffers cached
Mem: 256 49 206 0 0 0
-/+ buffers/cache: 49 206
Swap: 0 0 0
This is after a few PHP pageviews. Debian 5 64 bit. 2 PHP FCGI Children and recycling them after 50 requests.
I should note though, that that is a MyBB forum not WordPress running on that server.
I modified it a little to add the ability to set up a database, directory and configure nginx without installing wordpress.
It’s located at http://freevps.tk/downloads/setup-debian.sh and the line to run make it is setup-debian.sh domain {domain}
Obviously you replace {domain} with your domain name.
is there an easier way to chroot sftp or ssh of dropbear?
is the change of host key popup during sftp normal?
Thanks for the benchmark. I knew 32-bit uses less memory than 64-bit, but I was curious about how big is the difference. Now I’ve got a clue about numbers. It is around 38% for your setup — not a negligible number.
Hey thanks for posting on Reddit 😛
The difference also varies depending on your software stack, and 38% more would actually be on the low end of the differences — I have seen apps use up a lot more on x86_64.
Some monolithic apps would require large memory foot prints. For example big MySQL installation that needs more than 2GB. Or MongoDB as it uses mmap files. Otherwise I usually just stick to 32bit on my VPS.
Hi, first I would like to say that this script is awesome =)
I have no problem running wordpress via the bash setup-debian.sh wordpress myblog.example.com. PHP seems to work fine on the wordpress blog.
But when I tried to put info.php in /var/www. It just won’t run. It will not parse the php file at all. The source is displayed.
I’m an nginx noobie, what do I have to do to make php work at /var/www and possibly elsewhere. Thanks.
@superbarney:
The problem will be that fastcgi parameterers are not passed in the main nginx configuration I supposed. Accordingly to the lowendbox script, the parameters are added to “/etc/nginx/fastcgi_php” therefore if you want php to work in your root location; You will have to do a “include /etc/nginx/fastcgi_php” in the main nginx configuration which I think should be located at “/etc/nginx/”
Or I think a more maintainable method will be to create another virtual host (For the root directory) and add it into your main ngix configuration. This way you could easily maintain the configuration for each different domains you have on the box.
Thanks for making our lives even more easier with this script!
LowEndAdmin, can you please add Pure-FTPd configuration to this script?
First thing, I wanted to try serving files from my VPS. So I installed nginx to serve files pure-ftpd for uploading files via ftp to nginx’ home directory. But alas, I couldn’t make ftp work however I tried!
@Nickolai — wouldn’t SFTP an better alternative? It should work with Dropbear or OpenSSH. More secure and less hassle with firewalls.
@LowEndAdmin: Maybe it would; I really don’t know. I have no experience here; I think I picked an idea that Pure-FTPd is good on some forum.
Do you mean sftp(1)? http://www.openbsd.org/cgi-bin/man.cgi?query=sftp
It seems to be a client, am I supposed to install sftp-server(8) for a server? http://www.openbsd.org/cgi-bin/man.cgi?query=sftp-server
It would be nice if you added this to a script.
@Allen:
Thanks for the tip but I had a feeling that was the case and did “include /etc/nginx/fastcgi_php” for the vhost that has already been setup for root, which is /etc/nginx/sites-available/default. That is if I’m not mistaken.
After adding that line, I get “No input file specified” as the error message on my browser. =/
I can’t figure out why the wordpress dir is able to use php flawlessly and not root (or possibly elsewhere)
@Nickolai — SFTP is available as long as you have SSH installed (which should already be there when the VPS is setup). For a free client use WinSCP. Or you can use something like SSHFS on Linux, or Expandrive to mount the remote SFTP server as a local drive.
@superbarney
Not sure what are you actually going to do, but “No input file specified” equals to error occured at the end of PHP. You’d probablly see if the path is correct, or you may try to chmod files to 755.
@@Nickolai
Yup! SFTP usually comes installed as a feature with the ssh server that you are using. In this case, dropbear does support sftp protocol. You can use FileZilla (Free of course!) and while you are at the site manager, you can add in to use the sftp protocol.
I think if you are planning to serve a couple of users using FTP. Then I think getting a separate ftp server will be more appropriate than sftp. (I dunno why, but it just seems so, haha). If you are just working alone and wishes to transfer files then sftp will works as fine.
great article thanks.
It would be so nice, if You update nginx version 🙂 in your pack, nginx version is 0.6, but the newest version is 0.7.
@marikh – The LowEndScripts uses apt-get/dpkg for installing Nginx.
@marikh
Try http://www.lowendtalk.com/topic/tutorial-i-made-on-compiling-the-newest-version-of-php-nginx-for-lowendboxs
For compiling the newest version of both nginx and PHP, and including APC support.
@marikh — unless you want the latest features I normally just stick to the distro default so it gets automated security updates. I still have boxes running Ubuntu 8.04 with Nginx 0.5.33. As I am not a Nginx wiz and use probably the most simple functionality it does not really matter to me…
I have used your script and it works. Thanks very much. The one thing I am trying to accomplish but have been unable to do is to have the configs in one place for nginx and use sites-enabled at will.
On another centos server, using php-fpm and nginx, I was able to setup the server with only the nginx.conf file and then adding a subdomain that works for php and wordpress install was as simple as adding another subdirectory to /usr/share/nginx/sites-enabled and installing wordpress in it.
However, I prefer your installation, because for some reason, a wordpress plugin that is needed for me errors out in the php-fpm (php 5.3.3) but works fine in your scripted version. I have not been able to figure out why. (the centos php 5.3.3 server also seems to use more memory)
However, the simplest thing to me would seem to be to configure the debian system to use the conf and sites enabled to do the same thing as my centos server and thus solve all my problems at once.
My nginx.conf is as follows (I have tried to modify it to the best of my abilities)
####################################################################### # # This is the main Nginx configuration file. # ####################################################################### #---------------------------------------------------------------------- # Main Module - directives that cover basic functionality # # http://wiki.nginx.org/NginxHttpMainModule # #---------------------------------------------------------------------- user www-data; worker_processes 2; error_log /var/log/nginx/error.log; #error_log /var/log/nginx/error.log notice; #error_log /var/log/nginx/error.log info; pid /var/run/nginx.pid; #---------------------------------------------------------------------- # Events Module # # http://wiki.nginx.org/NginxHttpEventsModule # #---------------------------------------------------------------------- events { worker_connections 1024; } #---------------------------------------------------------------------- # HTTP Core Module # # http://wiki.nginx.org/NginxHttpCoreModule # #---------------------------------------------------------------------- http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; # Load config files from the /etc/nginx/conf.d directory #include /etc/nginx/conf.d/*.conf; # # The default server # server { listen 80; server_name www.myrootdomain.com myrootdomain.com *.myrootdomain.com; #charset koi8-r; access_log /var/log/nginx/$host.access.log; location / { root /usr/share/nginx/sites-enabled/$host; index index.html index.htm index.php; } error_page 404 /404.html; location = /404.html { root /usr/share/nginx/sites-enabled/$host; } # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/sites-enabled/$host; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ { root /usr/share/nginx/sites-enabled/$host; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /usr/share/nginx/sites-enabled/$host$fastcgi_script_name; include fastcgi_params; } # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } } *****************************************This works fine on my centos php-fpm server but returns not found errors on the scripted debian.
I really need to be able to add subdomains just by putting the subdomain.myrootdomain.com directory and files in **/sites-enabled/
I would really appreciate some help here. I have been pulling my hair out for a week now trying to get it to work.
I think it wasn’t working because the lowendscript uses unix:/var/run/www/php.sock for FastCGI, whereas your script uses TCP port localhost:9000.
Unix domain socket is slightly faster and good enough for a single box setup.
I should add that your blog is adding http:// to my www
In the server_name line I do NOT have http, just the www . myrootdomain . com
I point this out only to avoid confusion.
So how do I make mine use the php.sock for fastcgi? I could not find anything in any of the confs your scripts created that points to that.
Or is there something in the script that I could change to make it work? Your script really is the simplest LEMP install on the net.
Thank you also for the rapid reply.
My script creates a file called /etc/nginx/fastcgi_php and all the PHP/WordPress sites include that…
I think I fixed it. Let me try and make some adjustments and test it out further.
I am still bleary eyed from lack of sleep, but I will try to test it out.
Bobby, have you figured it out? I need to change it from php.sock to TCP port as well but I can’t seem to get it working.
What changes did you make?
Thanks.
Thank you for the excellent guide, however there is one significant niggling issue. Everything works on first install (Ubuntu 10.04 x86), but after I restart it, I get 502 Bad Gateway. The only way it seems to fix it is to run “bash setup-debian.sh php”, after that it works fine. I tried wiping my VPS and doing it all over again, and the same issue occurs. PHP appears to be in the startup scripts folder, but restarting the php service gives me an error that it cant access /var/www/php.pid
It seems these changes magically get wiped (the folders too), after each restart.
Please help me out LEA
Thanks in advance
I have the same issue.Anyone?
Great work LowEndBoxAdmin
I did a clean install on VPS.NET SAN 2.0 VPS with Basic Debian 5.0 (x64) and followed your steps described above. For the last step, I wasn’t sure if I should use addictinggames.com or http://www.addictinggames.com In the end I decide to use
bash setup-debian.sh wordpress http://www.addictinggames88.com
After completing the wordpress login info, the home page still show a welcome nginx. I followed the rewrite above, but didn’t work. I then change the wordpress/site address under general setting to http://www.addictinggames88.com and the home page was able to load.
A VPS reboot and top show 77496k RAM used. Memory usage after 1 load of the home page is 97348k RAM used.
I have some questions.
1) Do I have to install VSFTPD? If I have to, how do I install?
I need to add at least 10 WordPress Plugins, but I don’t seem to be able to do it within the admin area. It asked for the FTP info, I used the SSH info, it didn’t work.
2) How to upgrade Nginx to 0.8.50?
Nginx version is 0.6.32. I was asked to update to the latest v0.8.50 on one of my VPS as v0.6.32 is not safe.
3) How to replace PHP/FastCGI with PHP/PHP-FPM? If using PHP-FPM, I also need to upgrade PHP to 5.3.3? If I have do, how do I install?
A benchmark test show that PHP-FPM is faster than FastCGI
http://vpsbible.com/php/php-benchmarking-phpfpm-fastcgi-spawnfcgi/
4) How to install APC on Debian?
I like Centos because of yum
5) Will you do a bash script for Centos?
For now, only Centos allow me to scale SAN 2.0 VPS without reboot.
You don’t like Centos because of yum. You like it because you don’t understand Linux enough to make an educated decision.
So, didn’t smart people started from scratch and from zero?
Don’t tell me, that you’re born as a genius, and do nothing without learning.
If yes, then you should teach all of the newbie here, so they can be as genius as you
Eric,
According to my VPS support, Nginx 0.6.32 is the problem and I was asked to upgrade to the latest version.
About the wordpress asking for the ftp details, make sure it has full access to the wordpress directory and is owned by the same user who is running the php files.
(www-data if you used this script.)
@dmmcintyre3,
If I use this script, FTP Username = www-data, what about the FTP Password?
FTP problem solved.
http://desk.stinkpot.org:8080/tricks/index.php/2009/01/wordpress-wants-ftp-information-to-update-plugins/
@AddictingGames88
This is a better way of getting wordpress to work.
http://www.nerdgrind.com/wordpress-automatic-upgrade-plugin-failed-or-not-working/
Well. Real WordPress users use subversion to manage their WordPress and plugin installations so `svn switch` would do the upgrade 🙂
Hello,
I wanted test webserver for my vps (for learning) so I put “testblog” as hostname (No domain) but when I go to http://myip/testblog it says “404 not found”
Do I have to adjust default.conf & testblog.conf ?
also very much thanks for this script and blog.
Hi LEA:
Do you have any tips to protect Nginx webserver from Ddos attack? Your script is great for me, but today i get ddos and i dont know how to solve this 🙁
LEA,
I installed your lowendscript and upgraded php to 5.3.3 with
http://www.21andy.com/blog/20100912/1948.html
and
replaced package to http://php53.dotdeb.org
It works fine with php-cgi. When I switch to php5-fpm, it looks fine, but apache benchmark is not as good. I probably missed out something. Can we have a tutorial on how to switch from php-cgi to php5-fpm?