I like playing around with VPS servers, you know… for science! And because it’s fun, it’s good practice to become a better sysadmin and gives me more freedom than a shared host. And admit it, being a sysadmin of your own little cluster is cool!
Documenting it in a blogpost will provide a place where I can write down how a perfect web server should be setup according to me, and a place to copy/paste commands when I’m reinstalling after too much messing around.
To get started, I personally prefer Debian 6.0 (Squeeze) as server-OS.
Please note I’m not a professional system-administrator. Everything here is based on my own experience and preference. I’m pretty sure there are a lot better ways to achieve this using fancy tools such as puppet, ansible, PaaS-solutions, etc. Eventually I’ll learn how to use all those tools as well, but until then, this works for me. :)
Before starting with anything related to web-serving, I setup the server a bit more friendly to me.
This means editing
1 2 3 4
And apt-gettin’ all the packages I require: (still logged in as root)
1 2 3 4 5 6 7
After having the basic packages I add a regular account to comment to my server, which I keep everywhere uniform to my username on my MacBook Pro. Which means I can leave off the
username@hostname when connecting.
I also create the group
web which will be assigned to developers that have access to the
apps-directory where all web-applications/sites will be located.
After this I disconnect and copy over my ssh keys (a good tutorial on that can be found at the WebFactional Docs).
1 2 3 4 5 6 7 8 9
I prefer to keep all my web-related files and logs under
1 2 3 4 5 6 7
This will create a tree like following:
/var/web ├── apps │ ├── nodejs │ ├── php │ ├── python │ ├── ruby │ ├── scala │ └── static ├── backups ├── conf │ ├── apache │ │ ├── sites-available │ │ └── sites-enabled │ ├── mysql │ ├── nginx │ │ ├── sites-available │ │ └── sites-enabled │ └── php ├── log -> ./logs ├── logs │ ├── apache │ ├── mysql │ └── nginx ├── root ├── tools └── vhosts
This allows a centralized and organized location for anything web related. (Which in my opinion is easier for backup or when moving servers). The vhosts directory will simply contain symlinks to the apps-folder.
cd /var/web/vhosts; ln -s ../apps/php/example/public ./example.com.
Getting RVM and installing Ruby 1.9.3
1 2 3 4 5 6
Nginx and Passenger
The easiest way I found to get passenger and Nginx working together was by installing passenger as a gem and letting
1 2 3 4 5 6
When this step completed successfully continue on by adding a init.d script for nginx:
1 2 3 4 5
Edit the location where to PID-file is stored in
/etc/init.d/nginx, in my case:
PIDSPATH=/opt/nginx/logs. You can alter this behavior in the nginx config file located in
And launch nginx!
sudo service nginx start
Using nginx and apache together
Next step is getting nginx and apache installed:
Nginx will be the main server and will be listening on port 80, apache will be listening on port 8080 and only accept connections passed trough by nginx. This because sometimes it’s easier to setup a site trough apache (htaccess rules still differ from a nginx configuration).
To begin the configuration for nginx.
Without any sites configured two files will be present in
000-examplewhich is the nodes root and will be shown upon visiting
999-apachewhich will proxy any request not covered by the config to apache.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Hosting this blog (which is a static site, powered by octropress) is done by following config:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
The weird numbering to sort the config files so the correct ones get’s loaded first and the fallback get’s loaded as last.
Moving on to apache!
For now, I’m a glad CloudFlare customer, but I only use their CDN-service and DNS-management tool. To make switching hosts easy I maintain next convention:
My main domain for my cluster, eg.:
example.com is an A-record, for each node,
node.example.com I have another A-record set to the matching IP.
*.node is a CNAME pointing to the matching node.
I’m exploring the possibilities of running my own DNS-servers in order to provide failover or perhaps using HAProxy though that would require a more expensive setup.
Problems that may occur
perl: warning: Setting locale failed.
Fix it using the Hard Way
[email protected]:~$ \curl -L https://get.rvm.io | sudo bash -s stable --rails --autolibs=enabled --ruby=1.9.3 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0curl: (60) SSL certificate problem: self signed certificate in certificate chain More details here: http://curl.haxx.se/docs/sslcerts.html curl performs SSL certificate verification by default, using a "bundle" of Certificate Authority (CA) public keys (CA certs). If the default bundle file isn't adequate, you can specify an alternate file using the --cacert option. If this HTTPS server uses a certificate signed by a CA represented in the bundle, the certificate verification probably failed due to a problem with the certificate (it might be expired, or the name might not match the domain name in the URL). If you'd like to turn off curl's verification of the certificate, use the -k (or --insecure) option.
Just as this rvm.io page describes
sudo apt-get install ca-certificates solves this problem and (should) solve future ssl-certificate problems.
W: Failed to fetch http://ftp.us.debian.org/debian-backports/dists/squeeze-backports/main/binary-i386/Packages.gz 404 Not Found [IP: 184.108.40.206 80] E: Some index files failed to download, they have been ignored, or old ones used instead.
The instructions to simple add
deb http://YOURMIRROR.debian.org/debian wheezy-backports main made me pick ftp.us.debian.org/debian-backports/ as mirror, which doesn’t seem
If you get an error message similar to:
setfacl: ./apps: Operation not supported you simply need to remount your
sudo mount -o remount,acl /.