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