Archive for the 'sysadmin' Category


configuring varnish to use custom http headers

By default caches uses the field “Cache-Control” to get the TTL for objects they care about. In case of a server side cache the parameter “s-maxage” is responsible for the life time of an object. (see rfc2616). This is fine for almost all cases. The bad thing about this is a bad configured cache proxy also uses this parameter to get it’s caching informations. This causes the backend to have no control to invalidate such an object because it will remain in memory of such a bad configured cache.

So we decided to use a custom field in the http header to tell varnish how long an object should stay in cache. In the backend it was very easy to implement a few lines of code to set the custom field. I called it “Varnish-Control” . The field will contain an integer value which indicates the TTL in seconds. The main part of the work was to configure varnish to use this value instead of s-maxage form the field “Cache-Control”.

In words i did the following:

Once an item was fetched from the backend (so it was not found in the cache) I will set the TTL of the item and stuff it into the cache. Since the field “Varnish-Control” is useless for all request handling nodes on the way to the client i removed the field once the TTL was set.

The first approach was pretty simple:

sub vcl_fetch {
if (obj.http.Varnish-Control) {
set obj.ttl = 7d;
remove obj.http.Varnish-Control;
}
insert;
}

Unfortunately this solution did not care about the value I’ve set into “Varnish-Control” but uses a static value of seven days to cache items. This was not satisfying. So i tried to make it more dynamic. Since it is not possible to assign the value from obj.http.Varnish-Control to obj.ttl i had to use inline C code. This is done by using C{ … }C somewhere in the VCL file.

sub vcl_fetch {
if (obj.http.Varnish-Control) {
C{
char *ttl;
ttl = VRT_GetHdr(sp, HDR_OBJ, "\020Varnish-Control:");
VRT_l_obj_ttl(sp, atoi(ttl));
}C
remove obj.http.Varnish-Control;
}
insert;
}

Finding the right commands to access the header informations and write them into the TTL of the object was PITA. Anyway, I try to explain this two commands:

char *VRT_GetHdr(const struct sess *sp, enum gethdr_e where, const char *n)

  • The first parameter is the session pointer…nothing more to say about this.
  • The second parameter is a constant indicating from which object will be used to get the header informations. In this case it was “HDR_OBJ” which is equivalent to “obj” in plain vcl configuration scenarios. possible values are: HDR_REQ, HDR_RESP, HDR_OBJ and HDR_BEREQ.
  • The third parameter is the name of the field i like to access. NOTE: The field name has to be suffixed with a colon and it has to be prefixed with the length of the field name (including the colon). This value has to be noted octal.

void VRT_l_obj_ttl(const struct sess *, double)

  • The first parameter is again the session pointer.
  • The second parameter is the TTL as double.

Thats it!

All VRT_x commands will be available in this context. This commands can be found in varnish-cache/include/vrt.h and varnish-cache/include/vrt_obj.h

official varnish project

High Availability

lovely systems is running business critical software and it’s important for us and our customers that the entire system is fully redundant and high available.

in consequent of this we have a 3 steps plan:

  • load balancing with automatic failover
  • hot standby where load balancing isn’t possible
  • quick and easy recovery if data loss occurs

load balancing is alread implemented. i’ve written a german howto about it.

hot standby is finishing the last stability tests. again i’ve written two howto’s about drbd and heartbeat.

the backup setup is going productive in the near future. i’m going to write a howto about that in the next few days.

after this steps there shouldn’t be a bottleneck any more.

Importing an existing SSL Certificate to Openfire

After some trying it was easy to get openfire running with our official GoDaddy Wildcard SSL Certificate :)

Convert your key and cert to DER format (thanks to AgentBob):

  • openssl pkcs8 -topk8 -nocrypt -in lovelysystems.com.key -inform PEM -out lovelysystems.key.der -outform DER
  • openssl x509 -in _.lovelysystems.com.crt -inform PEM -out _.lovelysystems.com.crt.der -outform DER

Get some java utilities to create a java key store (yes java still rosucks, thanks to AgentBob again)

Create a new keystore (/root/keystore.ImportKey):

  • java ImportKey lovelysystems.com.key.der _.lovelysystems.com.crt.der

change the keytool passwords back to the defaults (from ‘importkey’ to ‘changeit’)

  • keytool -storepasswd -keystore /root/keystore.ImportKey
  • keytool -keypasswd -alias importkey -keystore keystore.ImportKey

Add the GoDaddy Intermediate Certificate:

  • wget –no-check-certificate https://certificates.godaddy.com/repository/sf_issuing.crt
  • keytool -import -alias intermed -file sf_issuing.crt -keystore /root/keystore -storepass changeit -trustcacerts

Move it to openfire (probably back up the old first) and restart openfire

  • mv /root/keystore.ImportKey /opt/openfire/resources/security/keystore
  • /opt/openfire/bin/openfire stop
  • /opt/openfire/bin/openfire start

In case of errors:

  •  tail -f -n 1000 /opt/openfire/logs/error.log

Hacking WordPress: hide behind another apache server

Howto hide a worpress instance behind a different apache server with the mod_rewrite.
I had the need to move my blog running wordpress 2.0.x to a different server, but keeping the domain name on the “old” server. I tried to do this with mod_rewrite and succeeded only partially :-(
after some hours of hacking around with mod_rewrite and wordpress itself i got i working and want to share my solution:
note: let’s call the origin server SERVER A and the “new” server running wordpress and mySQL SERVER B. SERVER A has only Apache 2 with mod_rewrite running, SERVER B has Apache, mySQL and PHP running.
Step 1: basic rewrite rules on SERVER A

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/blog/.*\.php$
RewriteCond %{REQUEST_URI} !^/blog/wp-.*
RewriteRule ^/blog(.*) http://<SERVER B>/<path to wordpress>/index.php$1 [L,P]

RewriteRule ^/blog$ http://<SERVER B>/<path to wordpress>/ [L,P]
RewriteRule ^/blog(.*)$ http://<SERVER B>/<path to wordpress>$1 [L,P]

note: my blog runs on http://<SERVER A>/blog/
Step 2: configure WordPress
login to wordpress (best done before moving wordpress to SERVER B) and go to the options -> general screen in wordpress admin and set these two values:
WordPress address (URI): http://<SERVER B>/<path to wordpress>
Blog address (URI): http://<SERVER A>/blog
Step 3: hack WordPress
now comes the part that took me hours to figure out. With all the above, wordpress almost worked, but index.php always threw a 404 not found error :-(
The problem was, that Wordpress uses $_SERVER['REQUEST_URI'] to build its links and stuff, but for my setup REQUEST_URI is <path to wordpress on SERVER B>… but this isn’t right, it should be simply /blog/…
this inserted into my config.php file does the trick:

$_SERVER['REQUEST_URI'] = str_replace(’/<path to wordpress on SERVER B>/’, ‘/blog/’, $_SERVER['REQUEST_URI']);

Step 4: there’s no step 4 ;-)

Technorati Tags: , , ,

Ubuntu Server insecurity?

i just found out that my Ubuntu Server 6.10 has login shells for almost all users set in the /etc/passwd file!

That’s a very bad idea because this maybe enabled someone to install “Data Cha0s Back Backdoor” on my machine :-(

I checked this with 2 other fresh Ubuntu Server 6.10 installations and both had the login shells for users like daemon, mail, www-data and so on. Especially www-data should not have a chance to create a shell in my opinion!

So i changed /bin/sh to /usr/sbin/nologin and hope this makes it a bit more secure.

Bye bye Schlund+Partner, Bye bye 1&1

After a collaboration for over 9 years it’s time to say bye bye to our former Hosting Partner Schlund+Partner (now integrated into the 1&1 Internet AG).During the last months their service and availability got worse and worse. The negative highlight was during the last days when parts of their mailsystem went offline once again (http://www.heise.de/newsticker/meldung/83828 and http://www.heise.de/newsticker/meldung/83916).

Telekom Austria

Lovely Systems is serving several Terrabyte of data per month. The combination of Amazons Elastic Compute Cloud (EC2) and the local datacenter of Telekom Austria in Bregenz is a ideal combination for our hosting services (Telekom Austria Advertisment Video, wmv :)).

1&1: sad, that you perform that bad. Oli, fRiSi, quodt: great, that you work night and day!

Amazon

Changing file encoding with Vim

I found a web page that showed a few funky characters. It must be an encoding problem so I thought about how to fix this. This is how I did.

First I wanted to know how the template file was encoded. To do that I opened Vim and ran “:set fileencoding”. Vim displayed “latin1″. To make the file utf-8 I ran “:set fileencoding=utf-8″ and saved it. The web page looked ok after that.
To verify the encoding one can use a hex editor. I used khexedit (KDE program) to see what my funny character was in hex. Before I changed the encoding the character was E5 in hex. Python can verify that å should be E5:

>>> u’å’.encode(’latin1′)
‘\xe5′

So the encoding is latin1. To verify that vim changed the file correctly one can check with khexedit after changing the file. khexedit now showed C3 A5 for this character. Checking with python again:

>>> u’å’.encode(’utf-8′)
‘\xc3\xa5′

C3 A5 seems to be correct hex for the å character in utf-8 encoding, so know I can be certain Vim did the right thing.

Amazon Elastic Compute Cloud powers Lovely Systems

We successfully deployed our first Zope3 applications on the promising Amazon EC2 cluster. Since my first post in October a lot of things happened. I read a very interesting article about the Jeff Bezo’s Riscy Bet and i’m still convinced that this type of service will be the future of hosting.
Finally I managed to create a Lovely AMI (Amazon Machine Image) based on Ubuntu 6.06.1 LTS to deploy our first application on EC2.
I followed jjc1138 and dougwinter on the AWS (Amazon Webservices) forum and Flex in his development blog.
continue reading the full article

Toying with Amazons Elastic Compute Cloud (EC2)

Yay, I got my invitation to use the Amazon Elastic Compute Cloud last week :)
First of all i needed to active the Service, uploaded my X.509 certificate. Congratulations Amazon, that’s the way to do it!

It took me 30 minutes to get a zope instance running :)

After that I downloaded the ec2 tools extracted them to /opt/ec2-api-tools

You’ll need the following environment variables (on OSX):

export EC2_HOME=/opt/ec2-api-tools
export EC2_PRIVATE_KEY=~/.ec2/pk-batlogg.pem
export EC2_CERT=~/.ec2/cert-batlogg.pem
export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Home
export PATH=”$PATH:/opt/ec2-api-tools/bin”

Then create a RSA key pair (i think the call stores the public key at amazon and shows you the private key):

/opt/ec2-api-tools-1.2-5692/bin/ec2-add-keypair lsa001-keypair

I saved it under the name id_rsa-lsa001-keypair

Here we go! Select an instance and start it.

ec2-describe-images shows some images to run:

IMAGE ami-5bae4b32 ec2-public-images/getting-started.manifest 206029621532 available public
IMAGE ami-68ae4b01 ec2-public-images/fedora-core4-base.manifest 206029621532 available public
IMAGE ami-69ae4b00 ec2-public-images/fedora-core4-apache-mysql.manifest 206029621532 available public
IMAGE ami-6dae4b04 ec2-public-images/fedora-core4-apache.manifest 206029621532 available public
IMAGE ami-6fae4b06 ec2-public-images/fedora-core4-mysql.manifest 206029621532 available public

let’s use the fedora-core4-base:

ec2-run-instances ami-5bae4b32 -k lsa001-keypair

after some minutes the machine was up and running:

ec2-describe-instances
RESERVATION r-b0d431d9 538162834475 default
INSTANCE i-c7b357ae ami-5bae4b32 domU-12-31-33-00-04-5D.usma1.compute.amazonaws.com running lsa001-keypair

open the firewall:

/opt/ec2-api-tools-1.2-5692/bin/ec2-authorize default -p 22
/opt/ec2-api-tools-1.2-5692/bin/ec2-authorize default -p 80
/opt/ec2-api-tools-1.2-5692/bin/ec2-authorize default -p 8080

ssh to the virtual host:

ssh -i id_rsa-lsa001-keypair root@domU-12-31-33-00-04-07.usma1.compute.amazonaws.com

that was easy :) now get zope up and running

yum install python
yum install subversion
yum install gcc
yum install python-devel
wget http://apt.ling.li/rpms/python-imaging/python-imaging-1.1.5-1.li.fc4.i586.rpm
yum install tk
rpm -ivh python-imaging-1.1.5-1.li.fc4.i586.rpm

useradd -m zope-media
su - zope-media
svn co https://svn.lovelysystems.com/repos/……./teleport.mediaportal/trunk .
make
make run

That’s it :)

http://domu-12-31-33-00-04-5d.usma1.compute.amazonaws.com:8080/++skin++VOL/teleport.mediaportal

Virtualization with XEN / Server Setup at Schlund+Partner

update 2006-12-20: new xen version, more detailled instructions

Thanks to the tip of dobee who recommended to use XEN for Virtualization of Linux Servers in our company I’ve been toying with it today during the last weeks.
However - there were some pitfalls until i’ve been able to work with it.

We’re running Root-Servers at Schlund+Partner - in this case a RootPlus Server with a Dual-Core Opteron 175, 4GB RAM and a 250GB RAID1.
We don’t use the pre-installed SuSE 64bit but decided to install Debian Sarge 64bit (minimal) install. That’s pretty nice at Schlund+Partner.

The Init-Tool
You can easily reset the machine to a default setup - half an hour later it’s finished :)

Picture 2

after that i tried to install the default XEN-installer, but the machine didn’t boot afterwards.

The Serial Console
Yes, the machine is in a Rackspace 300km away - but the Console Servers at Schlund allow to connect the machine through the serial console.
you just:

ssh uxxxxxxxxxx@sercon.rootmaster.info

and you are connected to your server through the serial port.

it seems like xen has no serial console support, at least there are problems with it - that’s the reason why i had no way to debug the boot-process

The Rescue-System
In case the Serial Console doesn’t help (because you have no kernel support for it :)) - you can power-cycle the server via Web-Interface.
But it’s more than power-cycle. Actually you can boot the machine (netboot/bootp) with a fail-safe ramdisk image.

Picture 3

After trying to create a initrd (to make sure all modules to access the boot-disk) are available at kernel load time i decided to build my own xen-kernel (I still suspect there were troubles with the 3ware SCSI RAID driver)

Installing necessary Debian Packages
sudo apt-get install bittornado
sudo apt-get bridge-utils
sudo apt-get install hotplug
sudo apt-get install udev
sudo apt-get install grub
sudo apt-get install gcc
sudo apt-get install bzip
sudo apt-get install zlib1g-dev
sudo apt-get install python2.3-dev
sudo apt-get install python2.4-dev
sudo apt-get install libncurses-dev

Getting the XEN Source
btdownloadcurses http://tx.downloads.xensource.com/torrents/xen-3.0.2-src.tgz.torrent

Building the Kernel
to make sure we compile the kernel with all necessary options i took the Schlund+Partner Kernel config as base:

cp /boot/config-2.6.16-rc6-060317a .config
make oldconfig

make linux-2.6-xen-config CONFIGMODE=menuconfig
make linux-2.6-xen-build
sudo make linux-2.6-xen-install

That’s it :) the machine booted! The serial console isn’t working atm. Now i’ll try to get the first host running :)