2012 West-Turkije, Reizen  Comments Off on West-Turkije
Sep 162012

Einde van de week gaan we drie weken het westen van Turkije verkennen. Als het goed is, is het nog prima weer in dit deel van de wereld. We vliegen naar de vijfduizend jaar oude, tweede grootste stad van Turkije, Izmir (ca. 2,5 miljoen inwoners). Waar we slapen en heen gaan, zien we wel, maar een bezoek aan Ephesus ligt voor de hand.

Amsterdam Izmir 21/9 14:05-18:35 PC298
Izmir Amsterdam 12/10 10:30-13:15 PC297

Pegasus Airlines

Jul 062012

Sometime ago I ported iodine to Android. It works, but it is not very stable and it is difficult to monitor if iodine is still running. MagicTunnel made it somewhat easier to manage, but didn’t solve the stability issue.

Since I found this unsatisfactory I developed my own DNS tunnel. The client is written in pure Java and the server is written in node.js. The client doesn’t even require root. My neighbour published the client application on Google Play and will take care of support and maintenance with me as second line. The source code is available on GitHub.

I am quite proud of this rather complex application!

DNS traffic is done through port 53 and iodine is element 53 of the periodic table.

How to setup a VPS as web server

 Computers and internet, Ubuntu, WordPress  Comments Off on How to setup a VPS as web server
Mar 112012

For my own record and maybe for your convenience I wrote down the steps to install a Debian/Ubuntu VPS as web server. This setup is optimized for low memory usage (128-512 MB). This means nginx instead of Apache, no DNS server and no e-mail server (only outgoing mail) and some MySQL, PHP and nginx tuning.

This setup guide has been tested for a VPS on OpenVZ, Xen and KVM and for Debian 6.0 (Squeeze), Debian 7 (Wheezy), Ubuntu 10.04 (Lucid Lynx) and 11.10 (Oneiric Ocelot). My favorite combination so far is OpenVZ and Debian 7.0 with the Dotdeb repository (fast virtualization, stable Linux and the latest server software).

This setup is handling > 60,000 page views per day (> 100,000 hits) for a dozen of sites on a dual core VPS (2 × 2.4 Ghz) with 512 MB memory with ease (little CPU usage, load average 0.1-0.2, and almost no swapping).

I will update this guide each time I learn something new. Currently I am using a larger VPS (2GB memory) and a more recent OS (Debian Wheezy), but this guide is still valid and very useful to me each time a setup a new VPS.

I use Hurricane Electric Free DNS Management, because I like the fast web interface, the possibility to set the TTL and because it is free (up to 50 domains), but be aware wildcard domains are not allowed (anymore). List of free DNS providers.

has been so kind to provide a VPS to test this guide.

Cheap, reliable VPS providers:

ServerMania is my favorite VPS provider, for the simple reason their support is excellent, so good I am even placing a banner by exception.
Server Mania - Hosting Empowered



Setup VPS

From the hosting control panel:
  • Configure the host name
  • Configure rDNS and SPF (for reliable e-mail)
    • Check: dig -x <IP>
    • Check: dig TXT <domain>
    • SPF wizard
  • Point a domain name to the VPS
  • Install a recent version of Debian or Ubuntu

Setup security

  • Login to the VPS:
    • ssh root@domain
  • Set new root password:
    • passwd
  • Fix the hostname when needed:
    • hostname <name>
    • nano /etc/hosts
  • apt-get update
  • apt-get upgrade
  • apt-get install nano sudo
  • Sometimes needed:
    • locale-gen en_US en_US.UTF-8
    • dpkg-reconfigure locales
    • dpkg-reconfigure tzdata
  • When IPv6 doesn’t work: nano /etc/gai.conf
precedence ::ffff:0:0/96  100
  • If you want more recent package versions, use Dotdeb with PHP 5.5
    • Don’t change to Dotdeb afterwards, because you will run into dependency problems!
  • mkdir /root/.ssh
  • chmod 700 /root/.ssh
  • nano /root/.ssh/authorized_keys
    • paste key from local computer
    • cat ~/.ssh/id_dsa.pub
  • ssh-keygen -t dsa
  • nano /etc/ssh/sshd_config
Port 22022
PasswordAuthentication no
ClientAliveInterval 120
ClientAliveCountMax 600
#Subsystem sftp /usr/lib/openssh/sftp-server
Subsystem sftp internal-sftp
Match Group users
ChrootDirectory /home
AllowTCPForwarding no
X11Forwarding no
ForceCommand internal-sftp
  • service ssh restart
  • chown root:root /home/*
  • apt-get install iptables
  • nano /etc/resolv.conf
  • mkdir /etc/fw
  • Download FirewallBuilder
    • use web server template
    • allow https in
    • allow port 22022 in (ssh)
    • allow port 587 out (ssmtp)
    • allow http/https out (for updates)
    • allow ntp out
    • allow ftp out
    • Install
  • nano /etc/rc.local
echo 1 >/proc/sys/net/ipv6/conf/eth0/disable_ipv6
sysctl net.ipv6.conf.all.disable_ipv6=1

You may way to use the harding rules from here.

  • nano /etc/default/useradd
  • apt-get install fail2ban
  • service fail2ban stop
  • nano /etc/default/fail2ban
  • nano /etc/fail2ban/jail.local
ignoreip = <your home/office IP>
action = %(action_mwl)s
destemail = <your e-mail address>

port     = 22022
  • service fail2ban start

Setup time

  • apt-get install ntpdate
  • nano /root/ntpdate.sh
/usr/sbin/ntpdate pool.ntp.org
  • chmod 755 /root/ntpdate.sh
  • crontab -e
0 9 * * * /root/ntpdate.sh >>/root/ntpdate.log 2>&1

Not needed/possible when shared Linux kernel (for example OpenVZ)

Setup servers

Remove pre-installed stuff:
  • apt-get purge sendmail* exim4* apache2* bind9 samba xinetd
Install new stuff:
  • apt-get install nginx php5-fpm php5-cli php5-curl php5-gd php5-mcrypt php5-intl php5-mysqlnd mysql-server
  • Use Dotdeb repository with PHP 5.5 (see before)

Setup MySQL

  • nano /etc/mysql/my.cnf
query_cache_size = 64M
query_cache_type = 1
key_buffer = 64M
table_cache = 1024
  • Debian:
  • service mysql restart
  • Debian 7: nano /etc/mysql/conf.d/extra.cnf
query_cache_size = 128M
query_cache_limit = 4M
query_cache_type = 1
key_buffer_size = 64M
table_open_cache = 1024

innodb = OFF
default-storage-engine = myisam
default-tmp-storage-engine = myisam
  • Piwik: nano config/config.ini.php
adapter = PDO_MYSQL
type = MyIsam

Note that some software doesn’t work correctly without InnoDB or MyIsam.

Setup PHP

  • nano /etc/php5/fpm/pool.d/www.conf
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 7
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
pm.status_path = /fpm_status
pm.max_requests = 500
request_terminate_timeout = 60s
  • nano /etc/php5/fpm/php.ini
cgi.fix_pathinfo = 0;
memory_limit = 256M;
user_ini.filename = ".user.ini"
upload_max_filesize = 4M
open_basedir = /home:/tmp
allow_url_fopen = Off
mail.add_x_header = Off
max_execution_time = 60

open_basedir = ...
  • Debian:
date.timezone = "Europe/Amsterdam"
  • nano /etc/php5/fpm/conf.d/05-opcache.ini
  • Get maximum size: sysctl kernel.shmmax
  • nano /etc/sysctl.conf
  • service php5-fpm restart

Setup nginx

  • nano /etc/nginx/nginx.conf
worker_processes 2;
server_tokens off;
client_max_body_size 4M;

The number of worker processes should reflect the number of CPUs.

  • Enabled GZIP:
#gzip on;
gzip_http_version 1.1;
gzip_vary on;
gzip_comp_level 1;
gzip_min_length 1100;
gzip_proxied any;
gzip_types text/plain text/css application/json application/x-javascript text/x$
gzip_buffers 16 8k;
gzip_disable "MSIE [1-6].(?!.*SV1)";

(you might want to use extra config files in /etc/nginx/conf.d)

  • service nginx restart

If you want to migrate from one server to another, you can do this:

server {
        listen 80;
        location / {
                proxy_pass http://a.b.c.d;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Host $http_host;
                proxy_redirect off;

server {
        listen 443 ssl spdy;
        ssl_certificate /etc/ssl/private/xxx.crt;
        ssl_certificate_key /etc/ssl/private/xxx.key;
        location / {
                proxy_pass https://a.b.c.d;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Host $http_host;
                proxy_redirect off;

Setup WordPress

  • Segregate users:
    • useradd <username>
    • passwd <username>
    • usermod -G users <username>
  • File permissions
find /home -type d -name 'wp-content' -exec mkdir -p {}/../assets \;
find /home -type d -name 'wp-content' -exec mkdir -p {}/gallery \;
find /home -type d -name 'wp-content' -exec mkdir -p {}/uploads \;
find /home -type d -name 'wp-content' -exec mkdir -p {}/upgrade \;

chown root:root /home
chown -R <username>:www-data <username>

find /home -type d -exec chmod 2750 {} \;
chmod 755 /home
find /home -type d -name '.ssh' -exec chmod -R 2700 {} \;
find /home -type d -name 'wp-content' -exec chmod -R 2770 {}/gallery \;
find /home -type d -name 'wp-content' -exec chmod -R 2770 {}/uploads \;
find /home -type d -name 'wp-content' -exec chmod -R 2770 {}/upgrade \;
find /home -type d -name 'wp-content' -exec chmod -R 2770 {}/upgrade \;
find /home/ -type f -exec chmod 0640 {} \;

Setup Piwik

9 * * * * su www-data -c "/usr/bin/php5 .../misc/cron/archive.php --url=http://example.org/"
>>.../piwik-archive.log 2>&1

Setup E-Mail

  • nano /etc/ssmtp/revaliases

Note that sending an e-mail is not retried with this method.

An alternative is to use nullmailer, which has an outgoing message queue at the expense of using a little more memory.

  • apt-get install nullmailer
  • nano /etc/nullmailer/remotes
smtp.gmail.com smtp --port=587 --starttls --user=you@gmail.com --pass=secret
smtp.mandrillapp.com smtp --port=587 --starttls --user=you@example.org --pass=API-token

Nullmailer supports secure SMTP since version 1.10, so you might need to check the version number.

  • nano /etc/nullmailer/pausetime
  • nano /etc/nullmailer/adminaddr

For Mandrill or similar:

  • nano /etc/nullmailer/defaultdomain
  • nano /etc/mailname
  • service nullmailer restart

For Google mail send limits, see here.

  • nano /etc/Muttrc
unset record

Don’t forget to setup rDNS and SPF. It is wise to regularly use an Email blacklist check.

Possible alternative: Msmtp (not tested)

Setup FTP

  • apt-get install proftpd
    • standalone
  • nano /etc/proftpd/proftpd.conf
SocketBindTight on
RequireValidShell off
UseReverseDNS off
IdentLookups off
UseIPv6 off
  • service proftpd restart

(needed for WordPress updates)


  • Backup databases:
mysqldump -u... -p... --all-databases | gzip -9 >$fn
scp -q -P 22022 $fn user@domain:/path/to/folder/
  • Restore databases:
gunzip <test.gz >/tmp/dump.sql
mysql -u... -p... </tmp/dump.sql
mysqladmin -u... -p... flush-privileges
  • You might need to restore the debian-sys-maint password:
    • nano /etc/mysql/debian.cnf
  • Backup files with rsync (apt-get install rsync)
rsync -avz -e 'ssh -p 22022' /etc/ user@domain:/path/to/folder/
rsync -avz -e 'ssh -p 22022' /var/lib/ user@domain:/path/to/folder/
rsync -avz -e 'ssh -p 22022' --exclude some/folder /home/ user@domain:/path/to/folder/
  • crontab -e
0 1 * * * /root/backup.sh >>/root/backup_`date +\%F`.log 2>&1
duplicity --exclude-filelist=duplicity.exclude --full-if-older-than 1W --allow-source-mismatch / rsync://user@host:22022//path/to/backup/folder
duplicity remove-older-than 1M --force rsync://user@host:22022//path/to/backup/folder

Some typical excludes for duplicity:

- /dev
- /proc
- /sys
- /tmp
- /run
- /mnt
- /media
- /var/log
- /lost+found
- /var/lib/mysql
- /var/lib/mongodb

You might need a backport of duplicity on Debian.

(duplicity tutorial, Full system backup)


  • apt-get install munin munin-node sysstat libwww-perl libipc-sharelite-perl libcache-cache-perl
  • perl -MCPAN -eshell
  • install IPC::ShareLite
  • nano /etc/munin/munin-node.conf
  • nano /etc/munin/plugin-conf.d/munin-node
env.url http://localhost/nginx_status

env.url http://localhost/fpm_status
env.phpbin php-fpm
  • ln -s /usr/share/munin/plugins/nginx_* /etc/munin/plugins
  • ln -s /usr/share/munin/plugins/mysql_* /etc/munin/plugins
  • rm /etc/munin/plugins/mysql_innodb
  • rm /etc/munin/plugins/iostats_ios
  • service munin-node restart
  • munin-node-configure –suggest
  • PHP5-FPM
  • Other plugins


  • nano /etc/sysctl.conf

(not possible on OpenVZ)


Be sure to lock these down behind a firewall / password.

Please let me know if you have any remarks or suggestions.

Sep 032011

We gaan terug naar één van de meest magische landen waar we tot nu toe geweest zijn: Peru. We gaan vijf weken het minder bezochte noordelijke deel van het land verkennen. Uitgestrekte, verlaten stranden, de mooiste bergen van de wereld en dichte oerwouden met mysterieuze geluiden.

Ik wil graag terug naar Huaraz, met in de nabijheid Huascarán (6768 meter), en naar TrujilloLa Ciudad de la Eterna Primavera (de stad van de eeuwige lente), met in de omgeving zeer interessante archeologische vindplaatsen, o.a. Chan Chan en las Huacas del Sol y de la Luna (de tempels van de zon en de maan). En als we het lef hebben, gaan we de brujos (tovenaars) en curanderos (genezers) in het afgelegen Huancabamba bezoeken.

Voor de eerste keer slapen we voor vertrek op Schiphol in Yotel. Op deze manier kunnen we wat vroeger vliegen en op tijd in Lima aankomen.

De eerste nacht slapen we in Pirwa Hostel Lima. Voor de veiligheid worden we op de luchthaven opgehaald.

21 sep 07:45 Amsterdam 10:30 Madrid IB3215 Airbus A321
13:10 Madrid 18:05 Lima IB6651 Airbus A340-600
26 okt 11:50 Lima 06:30+1 Madrid IB6658 Airbus A340-200
08:55+1 Madrid 11:25+1 Amsterdam IB3254 Airbus A321

Zo zullen we nog wel niet boarden …

Auto close old bbPress 1.x topics

 Computers and internet, WordPress  Comments Off on Auto close old bbPress 1.x topics
Aug 122011

I am using the fast and light bbPress 1.x stand-alone forum software for support on some of my WordPress plugins.

To reduce spam I added the following code to bb-config.php to automatically close old topics:

// Auto close topics older than 10 days
mysql_query('UPDATE bb_topics SET topic_open = 0 WHERE DATEDIFF(CURDATE(), topic_time) > 10');