<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5600017894340887470</id><updated>2026-04-16T08:40:52.753-07:00</updated><category term="drupal 7"/><category term="i18n"/><category term="drupal"/><category term="varnish"/><category term="devops"/><category term="javascript"/><category term="stupidity"/><category term="C"/><category term="apache"/><category term="automation"/><category term="debian"/><category term="doh"/><category term="exploits"/><category term="extending"/><category term="fabfile"/><category term="fabric"/><category term="ha"/><category term="handheld"/><category term="haproxy"/><category term="high availability"/><category term="hook_node_operations"/><category term="keepalived"/><category term="l()"/><category term="linux"/><category term="mobila enheter"/><category term="mobile"/><category term="pathauto"/><category term="performance"/><category term="php"/><category term="random"/><category term="security"/><category term="squeeze"/><category term="statistics"/><category term="statistik"/><category term="sverige"/><category term="sweden"/><category term="token"/><category term="web"/><category term="webb"/><title type='text'>Christopher Cato - my old blog posts on tech</title><subtitle type='html'>Random code stuff.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>24</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-9096835162939374099</id><published>2014-06-11T03:21:00.001-07:00</published><updated>2014-06-11T03:21:13.963-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="drupal 7"/><category scheme="http://www.blogger.com/atom/ns#" term="i18n"/><title type='text'>Translating the Site Name in Drupal 7</title><content type='html'>&lt;div style=&quot;background-color: white; border: 0px; clear: both; color: #444444; font-family: &#39;Lucida Grande&#39;, &#39;DejaVu Sans&#39;, &#39;Bitstream Vera Sans&#39;, Verdana, Arial, sans-serif; font-size: 14px; line-height: 18.200000762939453px; margin-bottom: 1em; padding: 0px; vertical-align: baseline;&quot;&gt;
Allmost all parts of Drupal are easily translatable but a select few are hidden. The Site name and Slogan are a couple of those.&lt;/div&gt;
&lt;div style=&quot;background-color: white; border: 0px; clear: both; color: #444444; font-family: &#39;Lucida Grande&#39;, &#39;DejaVu Sans&#39;, &#39;Bitstream Vera Sans&#39;, Verdana, Arial, sans-serif; font-size: 14px; line-height: 18.200000762939453px; margin-bottom: 1em; padding: 0px; vertical-align: baseline;&quot;&gt;
To translate a Drupal 7 Site name you have to activate &#39;Variable translation&#39; module (which is in the same package as i18n) and the required ones (like &#39;Variable store&#39;).&lt;/div&gt;
&lt;div style=&quot;background-color: white; border: 0px; clear: both; color: #444444; font-family: &#39;Lucida Grande&#39;, &#39;DejaVu Sans&#39;, &#39;Bitstream Vera Sans&#39;, Verdana, Arial, sans-serif; font-size: 14px; line-height: 18.200000762939453px; margin-bottom: 1em; padding: 0px; vertical-align: baseline;&quot;&gt;
After you install these modules, go to Configuration -&amp;gt; Multilingual settings -&amp;gt; Variables tab and choose &#39;Site name&#39; (?q=admin/config/regional/i18n/variable). Then go to Configuration -&amp;gt; System -&amp;gt; Site information (?q=admin/config/system/site-information) and select the language you. Change the &#39;Site name&#39; field and save.&lt;/div&gt;
&lt;div style=&quot;background-color: white; border: 0px; clear: both; color: #444444; font-family: &#39;Lucida Grande&#39;, &#39;DejaVu Sans&#39;, &#39;Bitstream Vera Sans&#39;, Verdana, Arial, sans-serif; font-size: 14px; line-height: 18.200000762939453px; margin-bottom: 1em; padding: 0px; vertical-align: baseline;&quot;&gt;
You&#39;ll find the translated site name in &#39;variable_store&#39; table.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/9096835162939374099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2014/06/translating-site-name-in-drupal-7.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/9096835162939374099'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/9096835162939374099'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2014/06/translating-site-name-in-drupal-7.html' title='Translating the Site Name in Drupal 7'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-3728141704709713961</id><published>2014-06-06T05:25:00.000-07:00</published><updated>2014-06-11T07:03:13.167-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="exploits"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><title type='text'>Script ads and their inherent security flaws</title><content type='html'>Ad networks have built a reputation as spammers and spyware-peddlers constantly busy shuffling the latest hot banners onto your screens. But lurking amongst those banners is a big security hole that can fill your site with bad content, steal data or even use your visitors as bots.&lt;br /&gt;
But, how is that possible one might ask. Well, if you&#39;re at all familiar with the anatomy of ad scripts you will see that they do a couple of things upon loading. First and foremost they display ads. Ads like in flash, images or html code. Second, they register impressions and clicks for the ads. None of this is dangerous in itself allthough Flash is inherently insecure due to the way Flash is allowed to interact with your browser and the underlying OS.&lt;br /&gt;
&lt;br /&gt;
So, what&#39;s the danger in this? Well, let&#39;s talk about a common scenario. You run site X. It is a well-known site that gets say 30K unique visitors per day. Most of these visitors don&#39;t use AdBlock and all of them except a few &lt;strike&gt;IT professionals&lt;/strike&gt;&amp;nbsp;foilhats don&#39;t run NoScript. Your site displays ads from one of the ad networks by inserting their provided script tags in your site. &lt;br /&gt;
Your site is secure, you think. Not true! Your site is as secure as the remote scripts you load.&lt;br /&gt;
&lt;br /&gt;
Once a hacker gains access to the ad networks server either by a dns exploit, host spoofing or social engineering he replaces the ad with his own code, making sure the ad still functions while adding another script to the mix. Since you included this in your own code, your site is now open to several exploits. Here are a few possible scenarios.&lt;br /&gt;
&lt;br /&gt;
DOM Hijacking &lt;br /&gt;
Once a visitor has loaded the ad scripts and the payload is in effect, the hacker can now display any content in the browser by replacing your DOM elements. It could be subtle manipulations or just vandalism. He is in control of the DOM the script is included in. This is mitigated in part by using iframes.&lt;br /&gt;
&lt;br /&gt;
Cross Site Scripting (XSS)&lt;br /&gt;
If you use a web-based content system chances are you will be displaying the ad while logged in to your site. With a little homework, the attacker knows which system you are using and can therefore load any url or post any form that requires login credentials. You are logged in so the payload will be able to access everything you can. This is also mitigated by using iframes.&lt;br /&gt;
&lt;br /&gt;
Distributed Denial Of Service (DDOS)&lt;br /&gt;
Since almost all of your visitors display the ad, it&#39;s a small feat for the attacker to craft a script that will use javascripts AJAX to enlist your 30K visitors in a botnet. By forcing each visitor to repeatedly load a resource from a target site he will in effect be delivering a huge amount of traffic that will bring the target down.&lt;br /&gt;
&lt;br /&gt;
Consider this simple payload that will overload a server until the client closes the session:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;while(somecondition){&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;var x = document.createElement(&#39;img&#39;);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp;x.src = &#39;http://xxx.xxx/img.jpg?&#39; + Math.floor(Math.random() * 10000000);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; document.getElementsByTagName(&#39;body&#39;)[0].appendChild(x);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
CPU cycle theft&lt;br /&gt;
There are already several available javascript bitcoin miners that could be used in such an exploit. Since there is no real CPU or memory limits on iframes or scripts they could theoretically be quite successful. Especially if they manage to somehow enlist the GPU. Maybe hash calculations could be funneled through WebGL?&lt;br /&gt;
&lt;br /&gt;
I can see several other scenarios where an attacker could utilize your ad network to deliver exploit code.&lt;br /&gt;
So the real question is how secure the networks are in reality.&lt;br /&gt;
&lt;br /&gt;
Prevention&lt;br /&gt;
DOM/XSS by using iframes. DDOS and CPU theft might not be possible other than by monitoring a client view of your website and ensuring that resource usage and network traffic is normal.&lt;br /&gt;
CSP (Content Security Policy) might solve the problems if it gets enough traction with the browser devs&amp;nbsp;&lt;a href=&quot;http://content-security-policy.com/&quot; rel=&quot;nofollow&quot;&gt;http://content-security-policy.com/&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/3728141704709713961/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2014/06/script-ads-and-their-inherent-security.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/3728141704709713961'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/3728141704709713961'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2014/06/script-ads-and-their-inherent-security.html' title='Script ads and their inherent security flaws'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-402956367882011819</id><published>2014-06-06T04:30:00.000-07:00</published><updated>2014-06-06T04:58:48.526-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="automation"/><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="fabfile"/><category scheme="http://www.blogger.com/atom/ns#" term="fabric"/><category scheme="http://www.blogger.com/atom/ns#" term="varnish"/><title type='text'>Fabric fabfile for Varnish deploy and ban </title><content type='html'>This is the file I use for deploying new vcls and purging stuff from my caches. I&#39;ve got load balancing with haproxy set up in front of three caches so deploy or purge needs to be done on all three caches pretty much at the same time. I&#39;ve set up ssh keys on the hosts so I won&#39;t have to stuff the fabfile with passwords and such.&lt;br /&gt;
&lt;br /&gt;
For more on my load balancing proxy set up, see &lt;a href=&quot;http://christophercato.blogspot.se/2012/09/haproxy-and-keepalived-on-debian.html&quot;&gt;this post&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The fabfile is kept in the same directory as I keep the default.vcl for the hosts.&lt;br /&gt;
&lt;br /&gt;
To purge an url:&amp;nbsp;&lt;i&gt;fab purgeUrl:&amp;lt;urlpattern&amp;gt;&lt;/i&gt;&lt;br /&gt;
To purge a host: &amp;nbsp;&lt;i&gt;fab purgeHost:&amp;lt;hostnamepattern&amp;gt;&lt;/i&gt;&lt;br /&gt;
To deploy default.vcl: &amp;nbsp;&lt;i&gt;fab deploy&lt;/i&gt;&lt;br /&gt;
&lt;div&gt;
&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;from __future__ import with_statement&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;import os.path&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;import time&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;from fabric.api import *&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;from fabric.contrib.project import *&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Environments&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;def dev():&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; env.hosts = [&#39;host1&#39;,&#39;host2&#39;,&#39;host3&#39;]&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; env.user = &#39;root&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; env.path = &#39;/etc/varnish&#39;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&quot;Default to &#39;dev&#39; environment&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;dev()&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Tasks - Deployment&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;def deploy():&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; require(&#39;path&#39;, provided_by=[dev])&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with cd(env.path):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; put(&#39;default.vcl&#39;,&#39;default.vcl&#39;)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; programname = str(time.time())&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; run(&#39;varnishadm -Tlocalhost:6082 -S/etc/varnish/secret vcl.load &#39; + programname + &#39; /etc/varnish/default.vcl&#39;)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; run(&#39;varnishadm -Tlocalhost:6082 -S/etc/varnish/secret vcl.use &#39; + programname)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;

&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;def purgeHost(myHost):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; require(&#39;path&#39;, provided_by=[dev])&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with cd(env.path):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; run(&#39;varnishadm -Tlocalhost:6082 -S/etc/varnish/secret ban req.http.host == &#39;+ myHost)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;def purgeUrl(myUrl):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; require(&#39;path&#39;, provided_by=[dev])&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; with cd(env.path):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; run(&#39;varnishadm -Tlocalhost:6082 -S/etc/varnish/secret ban &quot;req.url ~ &#39;+ myUrl +&#39;&quot;&#39;)&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/402956367882011819/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2014/06/fabric-fabfile-for-varnish-purge-ban.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/402956367882011819'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/402956367882011819'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2014/06/fabric-fabfile-for-varnish-purge-ban.html' title='Fabric fabfile for Varnish deploy and ban '/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-8042734274699532124</id><published>2014-06-06T04:07:00.000-07:00</published><updated>2014-06-06T04:07:15.223-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="drupal 7"/><category scheme="http://www.blogger.com/atom/ns#" term="pathauto"/><category scheme="http://www.blogger.com/atom/ns#" term="php"/><category scheme="http://www.blogger.com/atom/ns#" term="token"/><title type='text'>Bulding a custom token for url aliases (or anything else)</title><content type='html'>Tokens are a great resource in Drupal when it comes to creating url aliases, replacing text in emails, creating Rules actions or pretty much anything when it comes to automation.&lt;br /&gt;
&lt;br /&gt;
Here&#39;s how to create a custom token for nodes that will perform an action on a field from the node and return it as a replacement.&lt;br /&gt;
&lt;br /&gt;
We start out by informing Drupal that we provide a token applicable to nodes. You can replace node with any entity bundle name to provide tokens for them.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;/**&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp;* Implements hook_token_info().&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp;* Provides Drupal with a list of our tokens to present in the UI&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;function example_token_info() {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; $info = array();&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; // Define a new token for nodes.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; // &quot;node&quot; can be replaced with other entity names&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; $info[&#39;tokens&#39;][&#39;node&#39;][&#39;reverse&#39;] = array(&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &#39;name&#39; =&amp;gt; t(&#39;Reverse category term name&#39;),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &#39;description&#39; =&amp;gt; t(&#39;Outputs a reversed term name.&#39;),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; );&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; // Any other tokens follow here&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; return $info;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: inherit;&quot;&gt;We continue by implementing the hook_tokens method to provide methods for performing the token replacements.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;/**&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp;* Implements hook_tokens() .&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp;* Takes care of the actual replacement of the token&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp;*/&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;function example_tokens($type, $tokens, array $data = array(), array $options = array()) {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; $replacements = array();&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; if ($type == &#39;node&#39;) {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; // Loop through the available tokens.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; foreach ($tokens as $name =&amp;gt; $original) {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; // Find our custom tokens by name.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; switch ($name) {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; case &#39;reverse&#39;:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Load field from node.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $fielditems = field_get_items(&#39;node&#39;,$data[&#39;node&#39;],&#39;field_category&#39;);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if ($fielditems[0][&#39;value&#39;]) {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Load the term.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $term = taxonomy_term_load($fielditems[0][&#39;value&#39;]);&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Replace placeholder with reversed term name.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $replacements[$original] = strrev($term-&amp;gt;name);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // No category assigned, replace with &#39;&#39;.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $replacements[$original] = &#39;&#39;;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; break;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; // All done.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; return $replacements;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
That&#39;s it. You are now replacing tokens like nobody&#39;s business.</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/8042734274699532124/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2014/06/bulding-custom-token-for-url-aliases-or.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/8042734274699532124'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/8042734274699532124'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2014/06/bulding-custom-token-for-url-aliases-or.html' title='Bulding a custom token for url aliases (or anything else)'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-9106834586637821226</id><published>2014-06-05T05:19:00.001-07:00</published><updated>2014-06-05T05:19:52.097-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="drupal 7"/><category scheme="http://www.blogger.com/atom/ns#" term="i18n"/><category scheme="http://www.blogger.com/atom/ns#" term="stupidity"/><title type='text'>Why Display Suite is a bad idea</title><content type='html'>&lt;h3&gt;
And why Code Fields are an even worse idea&lt;/h3&gt;
You start out with three content types and a couple of view modes and everything is hunky-dory. Then the customer has some specific requirements and you say to your self – &quot;Hey, that&#39;s kind of a weird thing to do but what the heck, I&#39;ll just do a code field and get it done!&quot;&lt;br /&gt;
Of course, this continues throughout the project and you keep adding view modes and code fields to fulfil the reqs because once you&#39;ve started down the DS + code fields road there&#39;s just no stopping it.&lt;br /&gt;
&lt;br /&gt;
A year later, the Customer comes back with some new requirements. The site is going to be relaunched with multiple languages. And you&#39;re like – &quot;Fuck yeah! i18n FTW!&quot;. Until you realize that all those sweet code fields are all like UND UND UND UND and you really should have written those umpteen gazillion tpls instead.&lt;br /&gt;
&lt;br /&gt;
So, Display Suite? No.&lt;br /&gt;
Code Fields? No.&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/9106834586637821226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2014/06/why-display-suite-is-bad-idea.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/9106834586637821226'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/9106834586637821226'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2014/06/why-display-suite-is-bad-idea.html' title='Why Display Suite is a bad idea'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-1855266844289054811</id><published>2014-06-04T12:43:00.003-07:00</published><updated>2014-06-04T12:43:46.331-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="drupal 7"/><category scheme="http://www.blogger.com/atom/ns#" term="i18n"/><title type='text'>Apache Solr Search and FacetAPI translation</title><content type='html'>To be able to translate the strings &quot;Displaying: 1-10 of 20&quot; and the other parts of the current search blocks you need to install&amp;nbsp;&lt;a href=&quot;https://drupal.org/project/facetapi_i18n&quot; target=&quot;_blank&quot;&gt;facetapi_i18n&lt;/a&gt;. After installing it you need to visit your config for the current search block and hit Save. Then go to your facet configuration and hit Save. Last but not least you need to refresh the strings for translation.&lt;br /&gt;
&lt;br /&gt;
Oh, and btw, the text &quot;Displaying...&quot; will be triple encoded and output escaped html if you don&#39;t patch facetapi_i18n with &lt;a href=&quot;https://drupal.org/files/double-encoding-fix-1741444-9.patch&quot; target=&quot;_blank&quot;&gt;this&lt;/a&gt; patch referenced in this issue&amp;nbsp;&lt;a href=&quot;https://drupal.org/node/1741444&quot; target=&quot;_blank&quot;&gt;https://drupal.org/node/1741444&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/1855266844289054811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2014/06/apache-solr-search-and-facetapi.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/1855266844289054811'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/1855266844289054811'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2014/06/apache-solr-search-and-facetapi.html' title='Apache Solr Search and FacetAPI translation'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-3138750603301969931</id><published>2014-06-03T14:25:00.002-07:00</published><updated>2014-06-05T01:37:03.287-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="drupal 7"/><category scheme="http://www.blogger.com/atom/ns#" term="i18n"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><title type='text'>Drupal and Ajax, now with language negotiation...</title><content type='html'>Sometimes I just want to kick myself! I was struggling to set the language for a module that gets called via Ajax and that prints out the contents of a view (with supposedly the correct field language set) but the field language always went for default language...&lt;br /&gt;
&lt;br /&gt;
Well, turns out, sometimes it&#39;s Just Not That Hard.&lt;br /&gt;
&lt;br /&gt;
Set up the language negotiation to use prefixes and then just prefix the url with the desired language like /lang/arg&lt;br /&gt;
&lt;br /&gt;
Menu hook from the module:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;function example_menu(){&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;$items = array();&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;$items[&#39;example/ajaxview&#39;] = array(&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;title&#39; =&amp;gt; &#39;Ajax View Loader&#39;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;page callback&#39; =&amp;gt; &#39;example_loadview&#39;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;access arguments&#39; =&amp;gt; array(&#39;access content&#39;),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;type&#39; =&amp;gt; MENU_CALLBACK&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;$items[&#39;sv/example/ajaxview&#39;] = array(&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;title&#39; =&amp;gt; &#39;Ajax View Loader&#39;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;page callback&#39; =&amp;gt; &#39;example_loadview&#39;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;access arguments&#39; =&amp;gt; array(&#39;access content&#39;),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;type&#39; =&amp;gt; MENU_CALLBACK&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;);&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;$items[&#39;en/example/ajaxview&#39;] = array(&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;title&#39; =&amp;gt; &#39;Ajax View Loader&#39;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;page callback&#39; =&amp;gt; &#39;example_loadview&#39;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;access arguments&#39; =&amp;gt; array(&#39;access content&#39;),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;type&#39; =&amp;gt; MENU_CALLBACK&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;$items[&#39;de/example/ajaxview&#39;] = array(&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;title&#39; =&amp;gt; &#39;Ajax View Loader&#39;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;page callback&#39; =&amp;gt; &#39;example_loadview&#39;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;access arguments&#39; =&amp;gt; array(&#39;access content&#39;),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;type&#39; =&amp;gt; MENU_CALLBACK&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;return $items;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
The callback:&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;function example_loadview($arg){&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; // Print the output from a view that takes a contextual argument&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; print views_embed_view(&#39;myajaxview&#39;, &#39;my_display_id, $arg);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; exit;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Calling the function from javascript (Drupal keeps a note of the path prefix used in Drupal.settings.pathPrefix)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;var url = &quot;/&quot; + Drupal.settings.pathPrefix + &quot;example/ajaxview/&quot; + arg;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;$.get(url, function (data) {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; alert(data); // Or do something with it&lt;br /&gt;});&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The language negotiation will do the rest of the heavy lifting.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/3138750603301969931/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2014/06/drupal-and-ajax-now-with-language.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/3138750603301969931'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/3138750603301969931'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2014/06/drupal-and-ajax-now-with-language.html' title='Drupal and Ajax, now with language negotiation...'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-1782646287703698245</id><published>2014-06-03T09:36:00.000-07:00</published><updated>2014-06-03T09:36:18.395-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="doh"/><category scheme="http://www.blogger.com/atom/ns#" term="drupal 7"/><category scheme="http://www.blogger.com/atom/ns#" term="i18n"/><category scheme="http://www.blogger.com/atom/ns#" term="stupidity"/><title type='text'>String just won&#39;t translate?</title><content type='html'>... make sure you&#39;re not overwriting it with your fancy-pants javascript functions... :)</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/1782646287703698245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2014/06/string-just-wont-translate.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/1782646287703698245'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/1782646287703698245'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2014/06/string-just-wont-translate.html' title='String just won&#39;t translate?'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-987611136395300436</id><published>2014-06-03T09:33:00.000-07:00</published><updated>2014-06-03T09:34:13.939-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="drupal"/><category scheme="http://www.blogger.com/atom/ns#" term="drupal 7"/><category scheme="http://www.blogger.com/atom/ns#" term="i18n"/><category scheme="http://www.blogger.com/atom/ns#" term="l()"/><title type='text'>Getting the path of a translated node</title><content type='html'>for those pesky hardcoded links in tpls&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;global $language;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;$translations = translation_path_get_translations(&quot;node/42&quot;);&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;/*&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;Returns the paths of all translations of a node, based on its Drupal path:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;array(2) {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [&quot;de&quot;]=&amp;gt;string(7) &quot;node/42&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [&quot;en&quot;]=&amp;gt;string(7) &quot;node/43&quot;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;*/&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;print l(t(&#39;Link Title&#39;), $translations[$language-&amp;gt;language]);&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;//l() will return the alias to node/42&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/987611136395300436/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2014/06/getting-path-of-translated-node.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/987611136395300436'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/987611136395300436'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2014/06/getting-path-of-translated-node.html' title='Getting the path of a translated node'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-3424239546118792690</id><published>2014-05-28T06:09:00.001-07:00</published><updated>2014-05-28T06:10:25.248-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="drupal"/><category scheme="http://www.blogger.com/atom/ns#" term="drupal 7"/><category scheme="http://www.blogger.com/atom/ns#" term="extending"/><category scheme="http://www.blogger.com/atom/ns#" term="hook_node_operations"/><title type='text'>Adding new node operations for the content overview screen</title><content type='html'>Extending the list of operations available for batch processing on /admin/content is quite easy. This goes in a module called example.module&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;function example_node_operations() {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; $operations = array(&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &#39;example_magic_operation_1&#39; =&amp;gt; array(&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;label&#39; =&amp;gt; t(&#39;Works magic on your nodes&#39;),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;callback&#39; =&amp;gt; &#39;example_operation&#39;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;callback arguments&#39; =&amp;gt; array(&#39;bulkupdate&#39;, array(&#39;message&#39; =&amp;gt; TRUE)),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; ),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &#39;example_magic_operation_2&#39; =&amp;gt; array(&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;label&#39; =&amp;gt; t(&#39;Works even more magic on your nodes&#39;),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;callback&#39; =&amp;gt; &#39;example_operation_2&#39;,&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;callback arguments&#39; =&amp;gt; array(&#39;bulkupdate&#39;, array(&#39;message&#39; =&amp;gt; TRUE)),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; ),&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; );&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; return $operations;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;// This function gets an array of nids from what was selected&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;// on the /admin/content screen&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;function example_operation(array $nids, $op, array $options = array()) {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; foreach ($nids as $nid) {&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; &amp;nbsp; // Work your magic here&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace; font-size: x-small;&quot;&gt;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/3424239546118792690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2014/05/adding-new-node-operations-for-content.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/3424239546118792690'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/3424239546118792690'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2014/05/adding-new-node-operations-for-content.html' title='Adding new node operations for the content overview screen'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-1052640238550664853</id><published>2014-05-21T02:58:00.001-07:00</published><updated>2014-05-21T03:49:59.375-07:00</updated><title type='text'>Drupal 7 translation gotchas</title><content type='html'>&lt;h2&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;Don&#39;t slip.&lt;/span&gt;&lt;/h2&gt;
&lt;b&gt;Entity Reference&lt;/b&gt; fields have no clue about languages. To them, everything is Language Neutral. Don&#39;t expect them to display the referenced entitys translation. Safest bet is to either translate the field or do field translation on the referenced entitys.&lt;br /&gt;
&lt;br /&gt;
Content loaded (from Drupal) via &lt;b&gt;Ajax&lt;/b&gt; will not work with the language system. You need to either pass the language code as an argument or set it globally at some other point in your process.&lt;br /&gt;
I&#39;ve done two fixes on this, one being that I pass the nodeid as an argument and check it for language. Another is in the preprocess_node function in template.php adding the following:&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace; font-size: x-small;&quot;&gt;drupal_add_js(&#39;jQuery(document).ready(function () { window.nodeid=&quot;&#39;.$vars[&#39;node&#39;]-&amp;gt;nid.&#39;&quot;;window.lang=&quot;&#39;.$vars[&#39;node&#39;]-&amp;gt;language.&#39;&quot; });&#39;, &#39;inline&#39;);&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Taxonomy Menu&lt;/b&gt; will beat you with a stick everytime you edit any term. You need to regenerate the menu or else your listings that are based on the vocabulary you&#39;re using for the taxonomy menu will fail miserably.&lt;br /&gt;
&lt;br /&gt;
Don&#39;t forget to update any&amp;nbsp;&lt;b&gt;Display Suite Code Fields &lt;/b&gt;you&#39;ve used as you&#39;ve probably left enough UND in there to sound like a german techno parade. And this is the time when you kick yourself and wonder why you ever went down the code field route in the first place. It&#39;s a &lt;b&gt;bad bad idea&lt;/b&gt; that starts with that one odd field that just needs some special treatment since the client requires it. Then you end up with 30 code fields with hardcoded UND UND UND UND...&lt;br /&gt;
&lt;br /&gt;
Using &lt;b&gt;Drupal.t()? &lt;/b&gt;Don&#39;t forget that Drupal can&#39;t build it&#39;s string index for this function unless everything you&#39;re using the function in gets added as files with drupal_add_js()&lt;br /&gt;
&lt;br /&gt;
One basic gotcha that I ran across is that &lt;b&gt;t() expects english as the input&lt;/b&gt; language regardless of you sites source language. Which is kind of backwards since I&#39;m Swedish and my source language and default language is Swedish. Well well.&lt;br /&gt;
&lt;br /&gt;
Here are some links I&#39;ve found useful:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.lullabot.com/blog/article/localized-and-multi-lingual-content-drupal-7&quot;&gt;http://www.lullabot.com/blog/article/localized-and-multi-lingual-content-drupal-7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://renaudjoubert.com/en/article/how-setup-multilingual-website-drupal-7&quot;&gt;http://renaudjoubert.com/en/article/how-setup-multilingual-website-drupal-7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://api.drupal.org/api/drupal/includes!common.inc/function/l/7&quot;&gt;https://api.drupal.org/api/drupal/includes!common.inc/function/l/7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/t/7&quot;&gt;https://api.drupal.org/api/drupal/includes!bootstrap.inc/function/t/7&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/1052640238550664853/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2014/05/drupal-7-translation-gotchas.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/1052640238550664853'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/1052640238550664853'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2014/05/drupal-7-translation-gotchas.html' title='Drupal 7 translation gotchas'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-671882345452231659</id><published>2012-09-28T06:16:00.000-07:00</published><updated>2012-10-02T07:53:19.826-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="apache"/><category scheme="http://www.blogger.com/atom/ns#" term="debian"/><category scheme="http://www.blogger.com/atom/ns#" term="ha"/><category scheme="http://www.blogger.com/atom/ns#" term="haproxy"/><category scheme="http://www.blogger.com/atom/ns#" term="high availability"/><category scheme="http://www.blogger.com/atom/ns#" term="keepalived"/><category scheme="http://www.blogger.com/atom/ns#" term="linux"/><category scheme="http://www.blogger.com/atom/ns#" term="performance"/><category scheme="http://www.blogger.com/atom/ns#" term="squeeze"/><category scheme="http://www.blogger.com/atom/ns#" term="varnish"/><title type='text'>HAProxy and Keepalived on Debian Squeeze for failover and loadbalancing</title><content type='html'>&lt;h2&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;Building a failover load balancing cluster on four machines with HAProxy and Keepalived in Debian Squeeze&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;So you&#39;ve got a big-ass VMWare machine with some servers to spare? Lets put them to work creating that redundancy your boss always nags you about whenever there is a split-second of downtime. In this post, I&#39;ll dive into how you can build a basic load-balancing high availability cluster either on VMWare or with separate bare-metal servers.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;I&#39;ve made a few assumptions about network topography and services used based on my own server environment and the services I work with which are mainly Drupal servers and Varnish cache servers. I usually run my Drupal backends on their own servers fronted by a Varnish server on its own box. I run Debian 5 (Lenny) and Debian 6 (Squeeze). &amp;nbsp;Other than that, it&#39;s all pretty basic stuff.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;What I&#39;ll build is a solution that will project one server to the outside but on the inside it will consist of four servers, in essence a small high-availability cluster. The cluster can be extended infinitely in all levels should the need arise.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;h3&gt;
&lt;div style=&quot;font-size: medium; font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/h3&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjWdV6xx66E4vxtUrCAPR0i6olBaNBh6XE7vXfCeoIovfxnQqV1RKp0LAbnf0SJYI_eLsKTEj0kKNnF88DD76RVCObhfZvMCwFqgqS1StfmxuHWkwaegqV28EYqBbrPPOIe0pL0j9HZhTe/s1600/lastbalanserad+miljo%CC%88.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjWdV6xx66E4vxtUrCAPR0i6olBaNBh6XE7vXfCeoIovfxnQqV1RKp0LAbnf0SJYI_eLsKTEj0kKNnF88DD76RVCObhfZvMCwFqgqS1StfmxuHWkwaegqV28EYqBbrPPOIe0pL0j9HZhTe/s1600/lastbalanserad+miljo%CC%88.jpg&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;High availability cluster&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;The pros of this kind of setup are redundancy, load balancing, ease of maintenance and the possibility to do proxying for all kinds of tcp connections, not just http but for basically any service over TCP.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;The cons are that it can take quite a bit of debugging if anything starts behaving funky and, obviously, it requires a few spare servers and IPs.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;Outline&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;There are a few steps we need to go through to get this up and running:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Install HAProxy and Keepalived&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Configure HAProxy and Keepalived&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Configure sysctl&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Configure cache servers/backends&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Start services&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;Verify that the system is up&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Verify failover function&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;The tools&lt;/span&gt;&lt;/h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;To provide redundancy I&#39;ll be using &lt;a href=&quot;http://www.keepalived.org/&quot; target=&quot;_blank&quot;&gt;Keepalived&lt;/a&gt;, a simple and robust linux routing software written in C that provides failover functionality via the virtual routing protocol &lt;a href=&quot;http://en.wikipedia.org/wiki/Virtual_Router_Redundancy_Protocol&quot; target=&quot;_blank&quot;&gt;VRRP&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Keepalived also provides layer 4 load balancing.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Keepalived is responsible for maintaining the shared public IP and determining which server is alive.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;To provide true layer 7 load balancing I will be using HAProxy. &lt;a href=&quot;http://haproxy.1wt.eu/&quot; target=&quot;_blank&quot;&gt;HAProxy&lt;/a&gt; is a fast, free and reliable TCP load balancing, proxying and high availability software that provides us with the parts needed to finish our cluster. HAProxy determines the health of the backends - removing any one that fails - and distributes the load between them. HAProxy also provides sticky sessions through cookies that pin each visitor to it&#39;s own backend.&lt;br /&gt;HAProxy is also light on resources, easily handling thousands of connections on cheap hardware&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;To make it all happen, I&#39;m using four servers. Two will be serving as load balancers and two as cache servers. The load balancers run HAProxy and Keepalived and the cache servers run Varnish and Apache (which you could replace with Nginx or whatever). The reason the cache servers need to run Apache as well as Varnish is because they need to be able to serve a file on their default IP and Varnish doesn&#39;t handle that (yet). Of course, many are running backend and cache server on the same box so in that case, this is not a problem.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;The idea of it all is to have the load balancers sharing one IP in a master/backup setup. Since they share one IP there will only be one server visible to the outside at any one time. Should one of them fail, the other instantly picks up the IP and resumes business. For this to work, we need to use the Keepalived daemon.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;For the load balancing part, we use HAProxy which works in tandem with Keepalived to assure that the backup server takes over if HAProxy should fail. HAProxy provides another layer of failover by monitoring our cache servers and removing them if they fail to respond.&lt;/span&gt;&lt;/div&gt;
&lt;h3&gt;
&lt;div style=&quot;font-size: medium; font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;The servers are:&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-size: medium; font-weight: normal;&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;proxy1&amp;nbsp;&lt;i&gt;haproxy, keepalived, ip 11.22.33.42 (sharing ip 11.22.33.44)&lt;/i&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;proxy2&amp;nbsp;&lt;i&gt;haproxy, keepalived, ip 11.22.33.43 (sharing ip 11.22.33.44)&lt;/i&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;cache1&amp;nbsp;&lt;i&gt;varnish, apache2, ip 11.22.33.45&lt;/i&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;cache2&amp;nbsp;&lt;i&gt;varnish, apache2, ip 11.22.33.46&lt;/i&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div style=&quot;font-size: medium; font-weight: normal;&quot;&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/blogger.g?blogID=5600017894340887470&quot; name=&quot;installha&quot;&gt;&lt;/a&gt;Install HAProxy and Keepalived&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;I won&#39;t cover installation of web servers and caching servers.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;For the load balancers you need to install HAProxy and Keepalived which are available in the usual deb repositiories.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy1: #&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;apt-get install haproxy keepalived&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy2: #&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;apt-get install haproxy keepalived&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;On Squeeze, this will also install ipvsadm and ask you to run dpkg-reconfigure to enable it but this can safely be ignored since Keepalived will load necessary parts from it.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/blogger.g?blogID=5600017894340887470&quot; name=&quot;configureha&quot;&gt;&lt;/a&gt;Configure HAProxy and Keepalived&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;i&gt;UPDATE: Adjusted HAProxy config as per input from Willy Tarreau, resulting in a nice extra 1000 req/s throughput increase&lt;/i&gt;&lt;br /&gt;This is a very basic setup to get the load balancing and failover running&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;/etc/keepalived/keepalived.conf on proxy1:&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;vrrp_script chk_haproxy { &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Requires keepalived-1.1.13&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; script &quot;killall -0 haproxy&quot; &amp;nbsp; &amp;nbsp; # cheaper than pidof&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; interval 2 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# check every 2 seconds&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; weight 2 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# add 2 points of prio if OK&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;vrrp_instance VI_1 {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; interface eth0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; state MASTER&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; virtual_router_id 51&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; priority 101 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# 101 on master, 100 on backup&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; virtual_ipaddress {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 11.22.33.44 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # supply your own spare public ip&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; track_script {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; chk_haproxy&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;/etc/keepalived/keepalived.conf on proxy2:&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;vrrp_script chk_haproxy { &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Requires keepalived-1.1.13&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; script &quot;killall -0 haproxy&quot; &amp;nbsp; &amp;nbsp; # cheaper than pidof&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; interval 2 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# check every 2 seconds&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; weight 2 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# add 2 points of prio if OK&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;vrrp_instance VI_1 {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; interface eth0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; state MASTER&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; virtual_router_id 51&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; priority 100 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# 101 on master, 100 on backup&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; virtual_ipaddress {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 11.22.33.44 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # supply your own spare public ip&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; track_script {&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; chk_haproxy&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;/etc/default/haproxy on proxy1 and proxy2:&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;# Set ENABLED to 1 if you want the init script to start haproxy.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;ENABLED=1&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;# Add extra flags here.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;#EXTRAOPTS=&quot;-de -m 16&quot;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;/etc/haproxy/haproxy.cfg on proxy1 and proxy2:&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;global&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; log 127.0.0.1 &amp;nbsp; local0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; log 127.0.0.1 &amp;nbsp; local1 notice&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; #log loghost &amp;nbsp; &amp;nbsp;local0 info&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; maxconn 4096&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; #debug&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; #quiet&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; user haproxy&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; group haproxy&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;daemon&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;defaults&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; log &amp;nbsp; &amp;nbsp; global&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; mode &amp;nbsp; &amp;nbsp;http&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; option &amp;nbsp;httplog&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; option &amp;nbsp;dontlognull&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; retries 3&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; option&lt;span class=&quot;Apple-tab-span&quot; style=&quot;white-space: pre;&quot;&gt; &lt;/span&gt;redispatch&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; maxconn 2000&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; contimeout &amp;nbsp; &amp;nbsp; &amp;nbsp;5000&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; clitimeout &amp;nbsp; &amp;nbsp; &amp;nbsp;50000&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; srvtimeout &amp;nbsp; &amp;nbsp; &amp;nbsp;50000&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;listen webfarm *:80&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;mode http&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;stats enable&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;stats auth user:pass&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;balance roundrobin&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;cookie SERVERID insert # pin visitor to server&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;option http-server-close # Thanks Willy!&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;option forwardfor&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;option httpchk HEAD /check.txt HTTP/1.0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# change IP to your cacheservers public IP&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;server webA 11.22.33.45:80 cookie A check&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;# change IP to your cacheservers public IP&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;server webB 11.22.33.46:80 cookie B check&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/blogger.g?blogID=5600017894340887470&quot; name=&quot;configuresys&quot;&gt;&lt;/a&gt;Configure sysctl&lt;/span&gt;&lt;/h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;Edit /etc/sysctl.conf on proxy1:&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy1: # echo &quot;&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;net.ipv4.ip_forward = 1&quot; &amp;gt;&amp;gt; /etc/&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;sysctl.conf&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy1: # echo &quot;&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;net.ipv4.ip_nonlocal_bind = 1&quot; &amp;gt;&amp;gt; /etc/&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;sysctl.conf&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy1: # sysctl -p&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
net.ipv4.ip_forward = 1&lt;/div&gt;
&lt;div style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
net.ipv4.ip_nonlocal_bind = 1&lt;br /&gt;
root@proxy1: #&lt;/div&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;Edit /etc/sysctl.conf on proxy2:&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy2: # echo &quot;&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;net.ipv4.ip_forward = 1&quot; &amp;gt;&amp;gt; /etc/&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;sysctl.conf&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy2: # echo &quot;&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;net.ipv4.ip_nonlocal_bind = 1&quot; &amp;gt;&amp;gt; /etc/&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;sysctl.conf&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy2: # sysctl -p&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
net.ipv4.ip_forward = 1&lt;/div&gt;
&lt;div style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
net.ipv4.ip_nonlocal_bind = 1&lt;br /&gt;
root@proxy2: #&lt;/div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/blogger.g?blogID=5600017894340887470&quot; name=&quot;configureback&quot;&gt;&lt;/a&gt;Configure cache servers / backends&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;Make sure that your cache servers respond on port 80 of their IP as assigned in your haproxy config on the load balancers.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;Make sure they serve a file named check.txt on for example 11.22.33.45:80/check.txt . The contents are not important but since they will be serving it every 2 seconds, just put &quot;check ok&quot; inside it or a simple &quot;1&quot; if you&#39;re really anal about optimizations. Which you should be :)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/blogger.g?blogID=5600017894340887470&quot; name=&quot;startservices&quot;&gt;&lt;/a&gt;Start services&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;Start services on proxy1&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;root@proxy1: # service haproxy start&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy1: #&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp;service keepalived start&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;Start services on proxy2&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;root@proxy2: # service haproxy start&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy2: #&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp;service keepalived start&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/blogger.g?blogID=5600017894340887470&quot; name=&quot;#verifysys&quot;&gt;&lt;/a&gt;Verify that the system works&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;Check your network on proxy1&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy1: # ip addr sh eth0&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;br /&gt;link/ether 00:11:22:33:44:55 brd ff:ff:ff:ff:ff:ff&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;br /&gt;inet 11.22.33.43/27 brd 11.22.33.63 scope global eth0&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;br /&gt;inet 11.22.33.44/32 scope global eth0&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;valid_lft forever preferred_lft forever&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;Check your network on proxy2&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy2: # ip addr sh eth0&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;link/ether 00:11:22:33:44:54 brd ff:ff:ff:ff:ff:ff&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;br /&gt;inet 11.22.33.42/27 brd 11.22.33.63 scope global eth0&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;valid_lft forever preferred_lft forever&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;
&lt;/span&gt;
&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;It&#39;s working! Proxy1 is now master and has the correct IP assigned as an alias. It assumes the master role by default since it has a higher priority defined in keepalived.conf&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;To verify that the connection to your backend / cache servers work, you&#39;ll have to edit the hosts file on your local machine, adding an entry for any of your backend domains that points to 11.22.33.44. After flushing your DNS cache, you should now be able to browse your site. If it doesn&#39;t work, check that haproxy.cfg points to the correct cache/backend and that your backend server is up. Also check that your dns entry was activated.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/blogger.g?blogID=5600017894340887470&quot; name=&quot;#verifysys&quot;&gt;&lt;/a&gt;Verify the failover function&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;Watch /var/log/messages on proxy2 while stopping the network on proxy1 and you should see something along the lines of this:&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
root@proxy2: # tail -f /var/log/messages&lt;/div&gt;
&lt;div style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
Sep 28 15:12:28 proxy-02 Keepalived_vrrp: VRRP_Instance(VI_1) Received lower prio advert, forcing new election&lt;/div&gt;
&lt;div style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
Sep 28 15:12:56 proxy-02 Keepalived_vrrp: VRRP_Instance(VI_1) Received higher prio advert&lt;/div&gt;
&lt;div style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
Sep 28 15:12:56 proxy-02 Keepalived_vrrp: VRRP_Instance(VI_1) Entering BACKUP STATE&lt;/div&gt;
&lt;div style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
Sep 28 16:29:45 proxy-02 Keepalived_vrrp: VRRP_Instance(VI_1) Transition to MASTER STATE&lt;/div&gt;
&lt;div style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
Sep 28 16:29:46 proxy-02 Keepalived_vrrp: VRRP_Instance(VI_1) Entering MASTER STATE&lt;/div&gt;
&lt;div style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;Check your network&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div style=&quot;font-family: Times;&quot;&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy2: # ip addr sh eth0&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: Times;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;link/ether 00:11:22:33:44:54 brd ff:ff:ff:ff:ff:ff&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;inet 11.22.33.42/27 brd 11.22.33.63 scope global eth0&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;inet 11.22.33.44/32 scope global eth0&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;valid_lft forever preferred_lft forever&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;i&gt;It&#39;s working. Proxy2 has now taken over the role of master and activated the IP.&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;Now watch the messages log again and reenable networking on proxy1&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;root@proxy2: # tail -f /var/log/messages&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Sep 28 16:29:45 proxy-02 Keepalived_vrrp: VRRP_Instance(VI_1) Transition to MASTER STATE&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Sep 28 16:29:46 proxy-02 Keepalived_vrrp: VRRP_Instance(VI_1) Entering MASTER STATE&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Sep 28 16:29:55 proxy-02 mpt-statusd: detected non-optimal RAID status&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Sep 28 16:32:52 proxy-02 Keepalived_vrrp: VRRP_Instance(VI_1) Received lower prio advert, forcing new election&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Sep 28 16:32:53 proxy-02 Keepalived_vrrp: VRRP_Instance(VI_1) Received higher prio advert&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;Sep 28 16:32:53 proxy-02 Keepalived_vrrp: VRRP_Instance(VI_1) Entering BACKUP STATE&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;
&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;b&gt;Check your network&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;root@proxy2: # ip addr sh eth0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;/span&gt;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;link/ether 00:11:22:33:44:54 brd ff:ff:ff:ff:ff:ff&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;inet 11.22.33.42/27 brd 11.22.33.63 scope global eth0&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;valid_lft forever preferred_lft forever&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;i&gt;It&#39;s working. Proxy1 has now taken over the role of master and activated the IP.&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;h3&gt;
&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;Benchmarking&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;testserver1:~# ab -k -n 10000 -c 1000 http://www.mydomain.com/favicon.ico&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;This is ApacheBench, Version 2.3 &amp;lt;$Revision: 655654 $&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Licensed to The Apache Software Foundation, http://www.apache.org/&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Benchmarking www.mydomain.com (be patient)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Completed 1000 requests&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Completed 2000 requests&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Completed 3000 requests&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Completed 4000 requests&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Completed 5000 requests&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Completed 6000 requests&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Completed 7000 requests&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Completed 8000 requests&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Completed 9000 requests&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Completed 10000 requests&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Finished 10000 requests&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Server Software: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;Apache/2.2.16&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Server Hostname: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;www.mydomain.com&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Server Port: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;80&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Document Path: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;/favicon.ico&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Document Length: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;894 bytes&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Concurrency Level: &amp;nbsp; &amp;nbsp; &amp;nbsp;1000&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Time taken for tests: &amp;nbsp; 1.474 seconds&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Complete requests: &amp;nbsp; &amp;nbsp; &amp;nbsp;10000&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Failed requests: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Write errors: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Keep-Alive requests: &amp;nbsp; &amp;nbsp;10000&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Total transferred: &amp;nbsp; &amp;nbsp; &amp;nbsp;14118199 bytes&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;HTML transferred: &amp;nbsp; &amp;nbsp; &amp;nbsp; 8940000 bytes&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Requests per second: &amp;nbsp; &amp;nbsp;6783.93 [#/sec] (mean)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Time per request: &amp;nbsp; &amp;nbsp; &amp;nbsp; 147.407 [ms] (mean)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Time per request: &amp;nbsp; &amp;nbsp; &amp;nbsp; 0.147 [ms] (mean, across all concurrent requests)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Transfer rate: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;9353.22 [Kbytes/sec] received&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Connection Times (ms)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; min &amp;nbsp;mean[+/-sd] median &amp;nbsp; max&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Connect: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp;1 &amp;nbsp; 5.3 &amp;nbsp; &amp;nbsp; &amp;nbsp;0 &amp;nbsp; &amp;nbsp; &amp;nbsp;30&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Processing: &amp;nbsp; &amp;nbsp;23 &amp;nbsp; 79 &amp;nbsp;88.0 &amp;nbsp; &amp;nbsp; 29 &amp;nbsp; &amp;nbsp; 706&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Waiting: &amp;nbsp; &amp;nbsp; &amp;nbsp; 23 &amp;nbsp; 79 &amp;nbsp;88.0 &amp;nbsp; &amp;nbsp; 29 &amp;nbsp; &amp;nbsp; 706&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Total: &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 23 &amp;nbsp; 80 &amp;nbsp;88.6 &amp;nbsp; &amp;nbsp; 29 &amp;nbsp; &amp;nbsp; 706&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Percentage of the requests served within a certain time (ms)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; 50% &amp;nbsp; &amp;nbsp; 29&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; 66% &amp;nbsp; &amp;nbsp; 93&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; 75% &amp;nbsp; &amp;nbsp;119&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; 80% &amp;nbsp; &amp;nbsp;127&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; 90% &amp;nbsp; &amp;nbsp;204&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; 95% &amp;nbsp; &amp;nbsp;244&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; 98% &amp;nbsp; &amp;nbsp;266&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; 99% &amp;nbsp; &amp;nbsp;295&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp;100% &amp;nbsp; &amp;nbsp;706 (longest request)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;Deploying&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;To put this all to work, all you need to do is to alter your dns records and point them towards your shared proxy IP where you normally would point to your backend / cache server.&lt;/span&gt;&lt;/div&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;Monitoring&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;To get an overview of HAProxy current statistics, log in to your stats page at 11.22.33.44:1936 as configured in haproxy.cfg.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo4exUwtisc3xSIcwlkirlIWXbYiz4PTHiAYv1Sro7md0XsK3W_F-HrAP4d56slgDLHRy1BHUWrByCp5tpUUgf240vfUHKwqJXUTTsWVPbJ9MbNMlr1YhWVHmpItX4toGjcsFPtXo4ccY0/s1600/Statistics+Report+for+HAProxy.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;155&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo4exUwtisc3xSIcwlkirlIWXbYiz4PTHiAYv1Sro7md0XsK3W_F-HrAP4d56slgDLHRy1BHUWrByCp5tpUUgf240vfUHKwqJXUTTsWVPbJ9MbNMlr1YhWVHmpItX4toGjcsFPtXo4ccY0/s400/Statistics+Report+for+HAProxy.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;HAProxy statistics overview&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-weight: normal;&quot;&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;Troubleshooting&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Replace all the example IPs with real addresses&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Run keepalived with the -d flag&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Check your network&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Check that the cache/backend servers listen on the IP:s you assigned in haproxy.conf&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Verify that you can reach the shared IP from the outside&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Tail those logs.. /var/log/daemon.log /var/log/messages&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Read the documentation!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;Low performance? Check that your virtualization network drivers can handle the load. See this blog post -&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;http://www.networkredux.com/blog/view/1346&quot; style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;http://www.networkredux.com/blog/view/1346&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;Gotchas&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;If all else fails and that shared IP won&#39;t respond to your pings from the outside - check with your hosting admin and see if he has configured your vlan correctly. I spent a few hours debugging everything without result and the day after, our provider checked and lo and behold - the vlan was misconfigured. Click-clickety-clack, ten seconds later everything was working as intented.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;Using ACLs in Varnish? Fail much? client.ip will now always be the same as your proxy ip.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;Use req.http.x-forward-for and match them line for line instead. Or write a VMOD.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;Check this blog post for more info: &lt;a href=&quot;http://zcentric.com/2012/03/16/varnish-acl-with-x-forwarded-for-header/&quot;&gt;http://zcentric.com/2012/03/16/varnish-acl-with-x-forwarded-for-header/&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;br /&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3&gt;
&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif; font-size: large;&quot;&gt;Resources&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://haproxy.1wt.eu/&quot; style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot; target=&quot;_blank&quot;&gt;HAProxy homepage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.keepalived.org/&quot; style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot; target=&quot;_blank&quot;&gt;Keepalived homepage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Helvetica Neue, Arial, Helvetica, sans-serif;&quot;&gt;&lt;a href=&quot;http://marc.info/?l=haproxy&amp;amp;w=2&quot; target=&quot;_blank&quot;&gt;HAProxy mailing list archives (searchable)&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://marc.theaimsgroup.com/?l=keepalived-devel&amp;amp;r=1&amp;amp;w=2&quot; style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot; target=&quot;_blank&quot;&gt;Keepalived mailing list archives (searchable)&lt;/a&gt;&lt;span style=&quot;font-family: &#39;Helvetica Neue&#39;, Arial, Helvetica, sans-serif;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/671882345452231659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2012/09/haproxy-and-keepalived-on-debian.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/671882345452231659'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/671882345452231659'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2012/09/haproxy-and-keepalived-on-debian.html' title='HAProxy and Keepalived on Debian Squeeze for failover and loadbalancing'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjWdV6xx66E4vxtUrCAPR0i6olBaNBh6XE7vXfCeoIovfxnQqV1RKp0LAbnf0SJYI_eLsKTEj0kKNnF88DD76RVCObhfZvMCwFqgqS1StfmxuHWkwaegqV28EYqBbrPPOIe0pL0j9HZhTe/s72-c/lastbalanserad+miljo%CC%88.jpg" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-5223603430911350221</id><published>2012-03-28T02:29:00.000-07:00</published><updated>2012-03-28T02:29:55.026-07:00</updated><title type='text'>Rendering fields correctly in Drupal 7</title><content type='html'>&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
While searching for some field api stuff I stumbled on this rather good introduction to the Field API in Drupal 7 and specifically on how to read field contents in a safe manner.&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
If you (as I did) read the below excerpt and feel a little guilty then you should most definitely read the &lt;a href=&quot;http://www.computerminds.co.uk/articles/rendering-drupal-7-fields-right-way&quot; target=&quot;_blank&quot;&gt;full article&lt;/a&gt;.&amp;nbsp; &lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
From &lt;a href=&quot;http://www.computerminds.co.uk/articles/rendering-drupal-7-fields-right-way&quot;&gt;http://www.computerminds.co.uk/articles/rendering-drupal-7-fields-right-way&lt;/a&gt; by S&lt;span class=&quot;username&quot;&gt;tephen Tweeddale:&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot; style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
You may well have seen (or written!) code that looks something like this:&lt;br /&gt;
&lt;div&gt;
&lt;div class=&quot;syntaxhighlighter  plain&quot; id=&quot;highlighter_265382&quot;&gt;
&lt;table border=&quot;0&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;br /&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;div class=&quot;container&quot;&gt;
&lt;div class=&quot;line number1 index0 alt2&quot;&gt;
&lt;code class=&quot;plain plain&quot;&gt;&amp;nbsp;&lt;/code&gt;&lt;/div&gt;
&lt;div class=&quot;line number1 index0 alt2&quot;&gt;
&lt;code class=&quot;plain plain&quot;&gt;// This is WRONG example.&lt;/code&gt;&lt;/div&gt;
&lt;div class=&quot;line number2 index1 alt1&quot;&gt;
&lt;code class=&quot;plain plain&quot;&gt;$block[&#39;content&#39;] = $node-&amp;gt;field_name[&#39;und&#39;][0][&#39;safe_value&#39;];&lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;br /&gt;
Poking around the node object for the value you wanted to print was 
fairly common in Drupal 6, and the &#39;safe_value&#39; sounds like it&#39;s been 
sanitised, right? What&#39;s wrong with that? Oh, Let me count the ways.&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Firstly, the &lt;code&gt;[&#39;und&#39;]&lt;/code&gt; element is part of the field localisation in Drupal 7 (see &lt;a href=&quot;http://hojtsy.hu/blog/2011-jan-31/drupal-7039s-new-multilingual-systems-part-4-node-translation&quot;&gt;this article from Gábor Hojtsy&lt;/a&gt; for more on that); directly accessing that value will cause issues in any kind of multi-lingual environment. Boo.&lt;/li&gt;
&lt;li&gt;By accessing the field value directly you miss out on any theming that might come courtesy of the normal field markup.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;[0][safe_value]&lt;/code&gt; explicitly accesses the first value
 of the field - if you wanted every value from a multi-value field you&#39;d
 need to do some sort of loop.&lt;/li&gt;
&lt;li&gt;Some fields (such as node references) won&#39;t have a safe_value 
element, only a value - which can easily be printed without thought for 
sanitisation. This is dangerous, not because node reference fields 
contain dangerous data (they&#39;re just a nid), but because it&#39;s not a 
helpful habit to get into, especially for new developers. Other fields 
types &#39;value&#39; may well be highly dangerous.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
Thanks, Stephen. I hearby wow never to repeat my sins against Drupal. &lt;i&gt;Honestly.&lt;/i&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/5223603430911350221/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2012/03/rendering-fields-correctly-in-drupal-7.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/5223603430911350221'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/5223603430911350221'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2012/03/rendering-fields-correctly-in-drupal-7.html' title='Rendering fields correctly in Drupal 7'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-8479956793977421110</id><published>2012-02-18T07:32:00.002-08:00</published><updated>2012-02-18T07:32:42.753-08:00</updated><title type='text'>Site performance - analyze and improve</title><content type='html'>&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;i&gt;&lt;span style=&quot;font-size: small;&quot;&gt;Looking
 back at the Drupal site I built two years ago for my current employer 
it&#39;s starting to look a little old and worn. Sure, we&#39;re running 
Varnish, we have purge rules, we have memcached for the backend and 
we&#39;ve shut off basically all cpu hogs. But what about the visitors side -
 apart from getting a speedy response from our cache servers, there has 
to be more we can do? Well - load times, page rendering speed and total 
data size seem like good 
targets for improvement since they also provide (via Firebug, YSlow and 
NewRelic) great metrics.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;b&gt;&lt;span style=&quot;font-size: x-large;&quot;&gt;Record, improve, measure, profit?&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;We
 start initially by collecting metrics on the site usage so we can set 
goals for the improvements. We use a mix-and-match approach to this, 
utilizing tools like Yahoos YSlow, Pingdoms Pagetest, New Relic and 
Firebug. Mind you, we had to disable a few rules in YSlow since they&#39;re 
really not applicable for us - the CDN rules (hey, we don&#39;t have a CDN),
 ETags (we have them but they&#39;re default Apache - YSlow hates them), 
Expires headers (yeah we don&#39;t want to set them 3 years into the future)
 and DNS Lookups (Friggin external services are really DNS-expensive)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;The
 pages we&#39;re measuring typically show one full article, 3 banners 
(flash/jpg/whatever) and up to 150 teasers consisting of an image and up
 to 200 characters text. Insane amount of teasers.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;b&gt;&lt;span style=&quot;font-size: small;&quot;&gt;Initial metrics &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;Total load time: 8sec&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;Waiting for external services: 3-12 sec&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;Data size: 2.5mb &lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;DOM Elements: 1377&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;YSlow score: D (67)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;&lt;b&gt;Changes&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;1) GZIP GZIP GZIP&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;Apparently,
 somewhere in the past we had to turn the mod_deflate off and never 
brought it back online. Bad robot! We turned it back on and are now 
gzipping css, js, html and anything text-based which resulted in the 
total data size dropping to about 2.1 megs. Still a shitload of data 
though.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;2) Lazy-loading of images&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;Instead
 of loading 150+ images from the get-go, we only load what&#39;s visible in 
the visitors browser. Anything else is loaded when it scrolls into view.
 This was the major improvement, bringing us down to about 1.5 megs. 
Still not slim enough!&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;3) Reduction of DOM elements&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;As
 we&#39;ve progressed through the last two years, the site has been extended
 and fixed and extended again - resulting in a patchwork of DIVs and css
 classes. Some parts were done through Semantic Views and other parts 
through their own .tpl files. We went through and made sure all parts 
are rendered from their own .tpl so we have full control over the 
output. Then we got started reducing and simplifying the files, swapping
 out wrapper DIVs and extraneous containers. This brought us down to 
1044 DOM elements and 1.1mb in size&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;4) Minimizing external services&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;We
 used to have a GooglePlus button on the site. It typically took 
anywhere between 3 and 10 seconds to load all of it&#39;s resources. Need I 
say it&#39;s gone? We also used to have the Facebook activity stream with 
Faces enabled. It required between 50 and 70 http requests to load all 
it&#39;s resources and took up to 8 seconds to load. No more. We also used 
to load the ever-ubiquitous JQ&lt;/span&gt;&lt;span style=&quot;font-size: small;&quot;&gt;uery from Googles 
ajax-cdn to be sure we always had the latest version on the site. I 
guess we can live with having it lag a version or two if that&#39;s the 
price we have to pay to have a faster site so we cached it on our own 
servers instead.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;We
 still have a Twitter button and a few Facebook boxes on the page but 
we&#39;ll have to live with them until we develop a better method to load 
them (preferrably they will be loaded when the user hovers over the 
boxes)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;&lt;b&gt;Result&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span style=&quot;font-size: small;&quot;&gt;Final metrics &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;Total load time: 2 sec (-75%)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;Waiting for external services: 2-3 sec&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;Data size: 1.1mb (-56%)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;DOM Elements 1044 (-24%)&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;YSlow score: B (89)&lt;/span&gt;&lt;/div&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;So
 here we are. The new site is now a lot slimmer, nearly ready for Beach 
2012. Stuff that&#39;s left to consider is trimming of the master CSS, 
adding the responsive parts to the CSS and trimming away some of the 
extraneous Drupal CSS classes which it so loves to add. All in all, I 
think the result is quite good but surely there are a some more 
optimizations left to do. Or at least I hope so, this performance 
hunting is addictive!&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;&lt;b&gt;Other possible optimizations&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;A couple of points that could be worth researching are&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-size: small;&quot;&gt;Progressive loading of all content, not just images&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: small;&quot;&gt;Dividing the posts into categories, thereby reducing the number of posts on any page&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: small;&quot;&gt;Minifying *everything*&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: small;&quot;&gt;Writing our own sharing functions that don&#39;t require hefty scripts from external sources&lt;/span&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: small;&quot;&gt;Spreading the downloads over multiple domains to reduce browser blocking&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: small;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;&lt;b&gt;Tools used&amp;nbsp; &lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;font-family: &amp;quot;Helvetica Neue&amp;quot;,Arial,Helvetica,sans-serif;&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;a href=&quot;http://getfirebug.com/&quot; target=&quot;_blank&quot;&gt;FireBug, a Mozilla extension&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;a href=&quot;https://addons.mozilla.org/sv-se/firefox/addon/yslow/&quot; target=&quot;_blank&quot;&gt;Yahoo&#39;s YSlow, another Mozilla extension&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;a href=&quot;http://newrelic.com/&quot; target=&quot;_blank&quot;&gt;New Relic, performance analysis tools for php&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: small;&quot;&gt;Coffee and heavy metal&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/8479956793977421110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2012/02/site-performance-analyze-and-improve.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/8479956793977421110'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/8479956793977421110'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2012/02/site-performance-analyze-and-improve.html' title='Site performance - analyze and improve'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-3327730825666257144</id><published>2012-02-14T06:51:00.001-08:00</published><updated>2012-02-14T06:54:26.819-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C"/><category scheme="http://www.blogger.com/atom/ns#" term="drupal"/><category scheme="http://www.blogger.com/atom/ns#" term="random"/><category scheme="http://www.blogger.com/atom/ns#" term="varnish"/><title type='text'>VCL Random url part</title><content type='html'>Random is random, usually. Unless it&#39;s being fetched every 20th minute and included as a part of a site with heavy traffic. That&#39;s a lesson I learned the hard way by relying on an ad networks RSS aggregator that included one of our RSS feeds on it&#39;s pages. The feed is randomized on our end with a list of nodes that are straight out of Views via some custom theming. The nodes are grouped in threes from a larger set.&lt;br /&gt;
&lt;br /&gt;
What I noticed was that over 24 hours, what should have been an even distribution turned out to be heavily weighted towards one specific set. The ad networks RSS aggregation ran on a schedule and as bad luck would have it, Views liked to display the same set every time the RSS aggregator made a visit. Probably just bad luck but to the customer it looked like one set of nodes were favored over the others.&lt;br /&gt;
&lt;br /&gt;
As I run Varnish for caching I started thinking about if I could do this in another way. I thought about faux round-robin directors and complicated solutions involving dns aliases and htaccess rewrites.&lt;br /&gt;
&lt;br /&gt;
Then I stumbled upon &lt;a href=&quot;http://cd34.com/blog/webserver/using-varnish-to-assist-with-ab-testing/&quot; target=&quot;_blank&quot;&gt;this blogpost&lt;/a&gt; by Chris Davies who is just generally speaking one of the most knowledgeable techies I know of. So enter inline-C for my VCL.&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
sub vcl_recv{&lt;/div&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (req.url == &quot;/randomizeme&quot;) {&lt;br /&gt;
C{&lt;br /&gt;
char buff[5];&lt;br /&gt;
sprintf(buff, &quot;%d&quot;, rand()%4+1);&lt;br /&gt;
VRT_SetHdr(sp, HDR_REQ, &quot;\017X-Distribution:&quot;, buff, vrt_magic_string_end);&lt;br /&gt;
}C&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; set req.url = &quot;/randomizeme/&quot; req.http.X-Distribution;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;
&amp;nbsp;}&lt;/div&gt;
&lt;br /&gt;
It works like this:&lt;br /&gt;
- Varnish picks up the request on url /randomizeme&lt;br /&gt;
- Varnish executes the inline C&lt;br /&gt;
- Varnish sets a special header with the randomized integer (the header works as a variable)&lt;br /&gt;
- Varnish then rewrites the url to /randomizeme/1-4&lt;br /&gt;
- Varnish finally fetches the above url from the backend which is rigged to display different content depending on which &quot;slot&quot; is chosen.&lt;br /&gt;
- Varnish delivers the randomized content to the visitor/aggregator/whatever&lt;br /&gt;
&lt;br /&gt;
A little warning: If you modify the header name &quot;X-Distribution&quot;, note that the &quot;\017&quot; must be updated, it&#39;s octal for the length of the string. I forget if it should include the &quot;:&quot; or not. Trial and error, watch that log for segfaults!</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/3327730825666257144/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2012/02/vcl-random-url-part.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/3327730825666257144'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/3327730825666257144'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2012/02/vcl-random-url-part.html' title='VCL Random url part'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-1174485058755681790</id><published>2011-11-02T08:17:00.001-07:00</published><updated>2011-11-04T04:17:43.963-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="handheld"/><category scheme="http://www.blogger.com/atom/ns#" term="mobila enheter"/><category scheme="http://www.blogger.com/atom/ns#" term="mobile"/><category scheme="http://www.blogger.com/atom/ns#" term="statistics"/><category scheme="http://www.blogger.com/atom/ns#" term="statistik"/><category scheme="http://www.blogger.com/atom/ns#" term="sverige"/><category scheme="http://www.blogger.com/atom/ns#" term="sweden"/><category scheme="http://www.blogger.com/atom/ns#" term="web"/><category scheme="http://www.blogger.com/atom/ns#" term="webb"/><title type='text'>Swedish browser statistics Q4 2011</title><content type='html'>It&#39;s been a while since I did this last but it&#39;s time for another rundown of who uses what in the Swedish (and nordic) marketspace.&lt;br /&gt;&lt;br /&gt;These figures are extracted from a 24-hr statistics collection period and represent around five million pageviews of which roughly 350K were mobile views. Total unique visitors around one million. The sources are mainstream sites that serve mainly swedish content and targets a wide array of audiences.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Desktop browsers:&lt;/span&gt;&lt;br /&gt;&lt;table class=&quot;records pie_view&quot; id=&quot;f_table_graph&quot; style=&quot;height: 261px; width: 472px;&quot;&gt;&lt;tbody id=&quot;f_tbody_0&quot;&gt;&lt;tr&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;&lt;br /&gt;&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;Browser make&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;Now&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;Feb2011&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;Change&lt;/td&gt;&lt;/tr&gt;&lt;tr class=&quot;rank_1 highlight&quot;&gt;&lt;td class=&quot;count&quot;&gt;1.&lt;/td&gt;   &lt;td class=&quot;text&quot; colspan=&quot;1&quot;&gt;&lt;div class=&quot;text_wrapper&quot; id=&quot;f_primary_segment0&quot; title=&quot;Firefox&quot;&gt;&lt;div class=&quot;text_wrapper&quot;&gt;&lt;div class=&quot;ie_fix_wrapper&quot;&gt;Firefox  &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;    &lt;td id=&quot;f_pie_pct_0&quot;&gt;43,42 %&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;(51,92%)&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;-8,5%&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;     &lt;tbody id=&quot;f_tbody_1&quot;&gt;&lt;tr class=&quot;rank_2&quot;&gt; &lt;td class=&quot;count&quot;&gt;2.&lt;/td&gt;   &lt;td class=&quot;text&quot; colspan=&quot;1&quot;&gt;&lt;div class=&quot;text_wrapper&quot; id=&quot;f_primary_segment1&quot; title=&quot;Chrome&quot;&gt;&lt;div class=&quot;text_wrapper&quot;&gt;&lt;div class=&quot;ie_fix_wrapper&quot;&gt;Chrome   &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;    &lt;td id=&quot;f_pie_pct_1&quot;&gt;42,07 %&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;(31,57%)&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;+10,5%&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;     &lt;tbody id=&quot;f_tbody_2&quot;&gt;&lt;tr class=&quot;rank_3 highlight&quot;&gt; &lt;td class=&quot;count&quot;&gt;3.&lt;/td&gt;   &lt;td class=&quot;text&quot; colspan=&quot;1&quot;&gt;&lt;div class=&quot;text_wrapper&quot; id=&quot;f_primary_segment2&quot; title=&quot;Internet Explorer&quot;&gt;&lt;div class=&quot;text_wrapper&quot;&gt;&lt;div class=&quot;ie_fix_wrapper&quot;&gt;Internet Explorer  &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;    &lt;td id=&quot;f_pie_pct_2&quot;&gt;9,25 %&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;(12,12%)&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;-3,13%&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;     &lt;tbody id=&quot;f_tbody_3&quot;&gt;&lt;tr class=&quot;rank_4&quot;&gt; &lt;td class=&quot;count&quot;&gt;4.&lt;/td&gt;   &lt;td class=&quot;text&quot; colspan=&quot;1&quot;&gt;&lt;div class=&quot;text_wrapper&quot; id=&quot;f_primary_segment3&quot; title=&quot;Safari&quot;&gt;&lt;div class=&quot;text_wrapper&quot;&gt;&lt;div class=&quot;ie_fix_wrapper&quot;&gt;Safari  &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;    &lt;td id=&quot;f_pie_pct_3&quot;&gt;3,23 %&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;(2,16%)&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;+1,08%&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;     &lt;tbody id=&quot;f_tbody_4&quot;&gt;&lt;tr class=&quot;rank_5 highlight&quot;&gt; &lt;td class=&quot;count&quot;&gt;5.&lt;/td&gt;   &lt;td class=&quot;text&quot; colspan=&quot;1&quot;&gt;&lt;div class=&quot;text_wrapper&quot; id=&quot;f_primary_segment4&quot; title=&quot;Opera&quot;&gt;&lt;div class=&quot;text_wrapper&quot;&gt;&lt;div class=&quot;ie_fix_wrapper&quot;&gt;Opera   &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;    &lt;td id=&quot;f_pie_pct_4&quot;&gt;1,60 %&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;(1,81%)&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;-0,21%&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;     &lt;tbody id=&quot;f_tbody_5&quot;&gt;&lt;tr class=&quot;rank_6&quot;&gt; &lt;td class=&quot;count&quot;&gt;6.&lt;/td&gt;   &lt;td class=&quot;text&quot; colspan=&quot;1&quot;&gt;&lt;div class=&quot;text_wrapper&quot; id=&quot;f_primary_segment5&quot; title=&quot;Mozilla Compatible Agent&quot;&gt;&lt;div class=&quot;text_wrapper&quot;&gt;&lt;div class=&quot;ie_fix_wrapper&quot;&gt;Mozilla Compatible Agent  &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;    &lt;td id=&quot;f_pie_pct_5&quot;&gt;0,20 %&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;(0,01%)&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;+0,19%&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;     &lt;tbody id=&quot;f_tbody_6&quot;&gt;&lt;tr class=&quot;rank_7 highlight&quot;&gt; &lt;td class=&quot;count&quot;&gt;7.&lt;/td&gt;   &lt;td class=&quot;text&quot; colspan=&quot;1&quot;&gt;&lt;div class=&quot;text_wrapper&quot; id=&quot;f_primary_segment6&quot; title=&quot;RockMelt&quot;&gt;&lt;div class=&quot;text_wrapper&quot;&gt;&lt;div class=&quot;ie_fix_wrapper&quot;&gt;RockMelt   &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;    &lt;td id=&quot;f_pie_pct_6&quot;&gt;0,08 %&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;(0,11%)&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;-0,03%&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;     &lt;tbody id=&quot;f_tbody_7&quot;&gt;&lt;tr class=&quot;rank_8&quot;&gt; &lt;td class=&quot;count&quot;&gt;8.&lt;/td&gt;   &lt;td class=&quot;text&quot; colspan=&quot;1&quot;&gt;&lt;div class=&quot;text_wrapper&quot; id=&quot;f_primary_segment7&quot; title=&quot;BlackBerry9700&quot;&gt;&lt;div class=&quot;text_wrapper&quot;&gt;&lt;div class=&quot;ie_fix_wrapper&quot;&gt;BlackBerry9700  &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;    &lt;td id=&quot;f_pie_pct_7&quot;&gt;0,04 %&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;---&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;+0,04%&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;     &lt;tbody id=&quot;f_tbody_8&quot;&gt;&lt;tr class=&quot;rank_9 highlight&quot;&gt; &lt;td class=&quot;count&quot;&gt;9.&lt;/td&gt;   &lt;td class=&quot;text&quot; colspan=&quot;1&quot;&gt;&lt;div class=&quot;text_wrapper&quot; id=&quot;f_primary_segment8&quot; title=&quot;IE with Chrome Frame&quot;&gt;&lt;div class=&quot;text_wrapper&quot;&gt;&lt;div class=&quot;ie_fix_wrapper&quot;&gt;IE with Chrome Frame  &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;    &lt;td id=&quot;f_pie_pct_8&quot;&gt;0,02 %&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;---&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;+0,02%&lt;/td&gt;     &lt;/tr&gt;&lt;/tbody&gt;     &lt;tbody id=&quot;f_tbody_9&quot;&gt;&lt;tr class=&quot;rank_10&quot;&gt; &lt;td class=&quot;count&quot;&gt;10.&lt;/td&gt;   &lt;td class=&quot;text&quot; colspan=&quot;1&quot;&gt;&lt;div class=&quot;text_wrapper&quot; id=&quot;f_primary_segment9&quot; title=&quot;Mozilla&quot;&gt;&lt;div class=&quot;text_wrapper&quot;&gt;&lt;div class=&quot;ie_fix_wrapper&quot;&gt;Mozilla   &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;    &lt;td id=&quot;f_pie_pct_9&quot;&gt;0,01 %&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;(0,03%)&lt;/td&gt;&lt;td style=&quot;vertical-align: top;&quot;&gt;-0,02%&lt;/td&gt;  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Mobile browsers:&lt;/span&gt;&lt;br /&gt;&lt;table class=&quot;graph &quot; border=&quot;0&quot; cellpadding=&quot;5&quot; cellspacing=&quot;0&quot;&gt;&lt;tbody&gt;&lt;tr class=&quot;alt&quot;&gt;&lt;td class=&quot;itemname2 &quot;&gt;&lt;h4&gt;&lt;img src=&quot;https://static.getclicky.com/media/useragent/iphone.gif&quot; /&gt; iPhone&lt;/h4&gt;&lt;/td&gt;                  &lt;td class=&quot;itemvalue&quot; nowrap=&quot;nowrap&quot;&gt;&lt;h4&gt;396,326&lt;/h4&gt;&lt;/td&gt;         &lt;td class=&quot;small grey pr20&quot;&gt;70.9%&lt;/td&gt;          &lt;td class=&quot;itemgraph&quot;&gt;&lt;img src=&quot;https://static.getclicky.com/media/graph_bar_standard.gif&quot; height=&quot;20&quot; width=&quot;250&quot; /&gt;&lt;/td&gt; &lt;td class=&quot;itemtrend&quot;&gt;&lt;br /&gt;&lt;/td&gt;        &lt;/tr&gt;                                &lt;tr class=&quot;alt&quot;&gt;         &lt;td class=&quot;itemname2 &quot;&gt; &lt;h4&gt;&lt;img src=&quot;https://static.getclicky.com/media/useragent/android.gif&quot; /&gt; Android&lt;/h4&gt;&lt;/td&gt;                  &lt;td class=&quot;itemvalue&quot; nowrap=&quot;nowrap&quot;&gt;&lt;h4&gt;153,449&lt;/h4&gt;&lt;/td&gt;         &lt;td class=&quot;small grey pr20&quot;&gt;27.4%&lt;/td&gt;          &lt;td class=&quot;itemgraph&quot;&gt;&lt;img src=&quot;https://static.getclicky.com/media/graph_bar_standard.gif&quot; height=&quot;20&quot; width=&quot;97&quot; /&gt;&lt;/td&gt; &lt;td class=&quot;itemtrend&quot;&gt;&lt;br /&gt;&lt;/td&gt;        &lt;/tr&gt;                                &lt;tr class=&quot;alt&quot;&gt;         &lt;td class=&quot;itemname2 &quot;&gt; &lt;h4&gt;&lt;img src=&quot;https://static.getclicky.com/media/useragent/symbian.gif&quot; /&gt; Symbian&lt;/h4&gt;&lt;/td&gt;                  &lt;td class=&quot;itemvalue&quot; nowrap=&quot;nowrap&quot;&gt;&lt;h4&gt;8,076&lt;/h4&gt;&lt;/td&gt;         &lt;td class=&quot;small grey pr20&quot;&gt;1.4%&lt;/td&gt;          &lt;td class=&quot;itemgraph&quot;&gt;&lt;img src=&quot;https://static.getclicky.com/media/graph_bar_standard.gif&quot; height=&quot;20&quot; width=&quot;6&quot; /&gt;&lt;/td&gt; &lt;td class=&quot;itemtrend&quot;&gt;&lt;br /&gt;&lt;/td&gt;        &lt;/tr&gt;                                                                                                        &lt;tr class=&quot;alt&quot;&gt;         &lt;td class=&quot;itemname2 &quot;&gt; &lt;h4&gt;&lt;img src=&quot;https://static.getclicky.com/media/useragent/blackberry.gif&quot; /&gt; Blackberry&lt;/h4&gt;&lt;/td&gt;                  &lt;td class=&quot;itemvalue&quot; nowrap=&quot;nowrap&quot;&gt;&lt;h4&gt;992&lt;/h4&gt;&lt;/td&gt;         &lt;td class=&quot;small grey pr20&quot;&gt;0.2%&lt;/td&gt;          &lt;td class=&quot;itemgraph&quot;&gt;&lt;img src=&quot;https://static.getclicky.com/media/graph_bar_standard.gif&quot; height=&quot;20&quot; width=&quot;1&quot; /&gt;&lt;/td&gt; &lt;td class=&quot;itemtrend&quot;&gt;&lt;br /&gt;&lt;/td&gt;        &lt;/tr&gt;                                                                                                                                        &lt;tr class=&quot;alt&quot;&gt;         &lt;td class=&quot;itemname2 &quot;&gt; &lt;h4&gt;&lt;img src=&quot;https://static.getclicky.com/media/useragent/windows.gif&quot; /&gt; Windows phone&lt;/h4&gt;&lt;/td&gt;                  &lt;td class=&quot;itemvalue&quot; nowrap=&quot;nowrap&quot;&gt;&lt;h4&gt;351&lt;/h4&gt;&lt;/td&gt;         &lt;td class=&quot;small grey pr20&quot;&gt;0.1%&lt;/td&gt;          &lt;td class=&quot;itemgraph&quot;&gt;&lt;img src=&quot;https://static.getclicky.com/media/graph_bar_standard.gif&quot; height=&quot;20&quot; width=&quot;1&quot; /&gt;&lt;/td&gt; &lt;td class=&quot;itemtrend&quot;&gt;&lt;br /&gt;&lt;/td&gt;        &lt;/tr&gt;                &lt;tr class=&quot;alt&quot;&gt;         &lt;td class=&quot;itemname2 &quot;&gt; &lt;h4&gt;&lt;img src=&quot;https://static.getclicky.com/media/useragent/windows.gif&quot; /&gt; Windows CE&lt;/h4&gt;&lt;/td&gt;                  &lt;td class=&quot;itemvalue&quot; nowrap=&quot;nowrap&quot;&gt;&lt;h4&gt;21&lt;/h4&gt;&lt;/td&gt;         &lt;td class=&quot;small grey pr20&quot;&gt;0%&lt;/td&gt;          &lt;td class=&quot;itemgraph&quot;&gt;&lt;img src=&quot;https://static.getclicky.com/media/graph_bar_standard.gif&quot; height=&quot;20&quot; width=&quot;1&quot; /&gt;&lt;/td&gt; &lt;td class=&quot;itemtrend&quot;&gt;&lt;br /&gt;&lt;/td&gt;        &lt;/tr&gt;                &lt;tr class=&quot;alt&quot;&gt;         &lt;td class=&quot;itemname2 &quot;&gt; &lt;h4&gt;&lt;img src=&quot;https://static.getclicky.com/media/useragent/mobile.gif&quot; /&gt; Unknown mobile&lt;/h4&gt;&lt;/td&gt;                  &lt;td class=&quot;itemvalue&quot; nowrap=&quot;nowrap&quot;&gt;&lt;h4&gt;17&lt;/h4&gt;&lt;/td&gt;         &lt;td class=&quot;small grey pr20&quot;&gt;0%&lt;/td&gt;          &lt;td class=&quot;itemgraph&quot;&gt;&lt;img src=&quot;https://static.getclicky.com/media/graph_bar_standard.gif&quot; height=&quot;20&quot; width=&quot;1&quot; /&gt;&lt;/td&gt; &lt;td class=&quot;itemtrend&quot;&gt;&lt;br /&gt;&lt;/td&gt;        &lt;/tr&gt;                &lt;tr class=&quot;alt&quot;&gt;         &lt;td class=&quot;itemname2 &quot;&gt; &lt;h4&gt;&lt;img src=&quot;https://static.getclicky.com/media/useragent/webos.gif&quot; /&gt; WebOS&lt;/h4&gt;&lt;/td&gt;                  &lt;td class=&quot;itemvalue&quot; nowrap=&quot;nowrap&quot;&gt;&lt;h4&gt;2&lt;/h4&gt;&lt;/td&gt;         &lt;td class=&quot;small grey pr20&quot;&gt;0%&lt;/td&gt;          &lt;td class=&quot;itemgraph&quot;&gt;&lt;img src=&quot;https://static.getclicky.com/media/graph_bar_standard.gif&quot; height=&quot;20&quot; width=&quot;1&quot; /&gt;&lt;/td&gt; &lt;td class=&quot;itemtrend&quot;&gt;&lt;br /&gt;&lt;/td&gt;        &lt;/tr&gt;        &lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Conclusion:&lt;/span&gt;&lt;br /&gt;IE steadily declining. Firefox and Chrome dominate desktop market. Android dominates mobile market allthough browser brand and versions seems obscured.&lt;br /&gt;&lt;br /&gt;Mobile continues to grow as a platform, now at 14.7% of total visitors. iPad stands for 1.5% of that figure while Android tablets are hard to identify (and GA won&#39;t group very good on screen resolutions) so I&#39;ll leave that figure dangling until I get better data.&lt;br /&gt;&lt;br /&gt;For us CSS and HTML jockeys it sure looks like we get to play with the nice toys a bit more next year since Chrome and Firefox totally dominate the market with a whooping 85.47%. Crossbrowser hell just became a little cooler.</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/1174485058755681790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2011/11/swedish-browser-statistics-q4-2011.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/1174485058755681790'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/1174485058755681790'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2011/11/swedish-browser-statistics-q4-2011.html' title='Swedish browser statistics Q4 2011'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-3747720499714572476</id><published>2011-10-05T05:36:00.000-07:00</published><updated>2011-10-06T07:09:57.349-07:00</updated><title type='text'>Node.JS-based real-time web tracking</title><content type='html'>&lt;span style=&quot;font-size:100%;&quot;&gt;This all started out of a need. A need for a statistics service that did not suck and that could handle our quite intense traffic (we run at 1500 req/sec max). Google Analytics failed miserably, GetClicky failed a little less miserably and other options were quite simply to expensive for our taste.&lt;br /&gt;&lt;br /&gt;Enter Node.JS and a little bit of pre-alpha code known as &lt;a href=&quot;http://hummingbirdstats.com/&quot;&gt;Hummingbird&lt;/a&gt;. I&#39;ll let Hummingbird introduce it self:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;&quot;Hummingbird lets you see how visitors are interacting with your website in real time. And by “real time” we don’t mean it refreshes every 5 minutes—WebSockets enable Hummingbird to update 20 times per second. Hummingbird is built on top of &lt;/span&gt;&lt;a style=&quot;font-style: italic;&quot; href=&quot;http://www.nodejs.org/&quot;&gt;Node.js&lt;/a&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;, a new javascript web toolkit that can handle large amounts of traffic and many concurrent users.&quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Sounds good to me, where do I sign up? Well, as is customary these days, this project is on github and is installed by first cloning the repo and then running &quot;npm install&quot; in the hummingbird subdir. Of course, you need to have a recent node.js core, mongodb and libgeoip-dev 1.4.7+ if you want to get ip-location working (hummingbird has a nice little map display in the demo setup). Unfortunately there is not much documentation written (yet) so be prepared for a lot of debugging and guesswork if you want it to do anything besides the graph / total / map that&#39;s included in the demo.&lt;br /&gt;Note: On Debian Lenny, libgeoip is at 1.4.4 which means you&#39;ll have to load it from lenny-backports to get the correct version (1.4.7+). Instructions for installing from backports can be found here: &lt;a href=&quot;http://backports-master.debian.org/Instructions/&quot;&gt;http://backports-master.debian.org/Instructions/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So how does it work? Well, the core is really a pixeltracker - including a 1x1 pixel from the system in your content will register a view with hummingbird, in effect saving a little bit of data to our mongodb collection. Hummingbird also runs a dashboard (if enabled) that can be viewed via http. The dashboard utilizes Web Sockets for rapid updates and binds the updates to jQuery elements on the dashboard page.&lt;br /&gt;&lt;br /&gt;This is about as far as I have gotten right now. The lack of documentation makes it a bit hard to develop more widgets for the dashboard but that&#39;s nothing a little trial-and-error won&#39;t fix :)&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Update:&lt;br /&gt;&lt;/span&gt;Managed to get another piece of the puzzle working - a custom widget for the dashboard page. I started with the backend connection by combining the code for cart_adds.js and total_views.js to get a starting point for an event-driven counter widget. Followed up by creating a very rudimentary widget endpoint that picks up on whatever is processed on the backend by hooking into the event system. So any tracking that has a specific event attached to it (basically parts of the query string for the tracking pixel) will result in a display on the dashboard that reacts to new hits by incrementing a value or otherwise adjusting the style or layout of the widget. Nothing new really but still a valuable tool for our editors who are constantly chasing those extra page views.&lt;br /&gt;&lt;br /&gt;I&#39;ll update again once I have a better implementation of it all.&lt;br /&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/3747720499714572476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2011/10/adventures-in-nodejs-based-real-time.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/3747720499714572476'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/3747720499714572476'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2011/10/adventures-in-nodejs-based-real-time.html' title='Node.JS-based real-time web tracking'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-1016033876845993712</id><published>2011-08-18T04:18:00.001-07:00</published><updated>2011-08-18T04:47:01.983-07:00</updated><title type='text'>How to ip-migrate web sites using Varnish</title><content type='html'>This is a quick guide on how to migrate a bunch of web sites by using Varnish as a intermediary to allow for low-latency zero downtime migration between ip addresses or domain names.&lt;br /&gt;&lt;br /&gt;Requirements: Varnish 2.x up and running, access to apache config, access to dns config.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;1) Configure Varnish&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt; &lt;/span&gt;&lt;br /&gt;Start out by defining your existing web sites as backends in the varnish config (default.vcl) by adding them in this format to the beginning of your vcl:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;backend website1{&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;    // NO CACHING&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;    // website1.company.com&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;    .host = &quot;10.0.0.1&quot;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;    .port = &quot;80&quot;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;    .connect_timeout = 160s;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;    .first_byte_timeout = 55s;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;    .between_bytes_timeout = 25s;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;backend website2{&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt; backend website3{&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt; ...&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt; }&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;&quot;&gt;  &lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Then add some clever host/backend switching logic to your vcl:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:courier new;font-size:85%;&quot;&gt;sub vcl_recv {&lt;br /&gt;# Find out which backend to use for the request&lt;br /&gt;if (req.http.Host == &quot;website1.company.com&quot;){&lt;br /&gt;  set req.backend = website1;&lt;br /&gt;  return(pass);&lt;br /&gt;}&lt;br /&gt;else if (req.http.Host == &quot;website2.company.com&quot;){&lt;br /&gt;  set req.backend = website2;&lt;br /&gt;  return(pass); &lt;br /&gt;}&lt;br /&gt;else {&lt;br /&gt; # maybe switch to your default backend here if you&#39;re using varnish in production&lt;br /&gt;}&lt;br /&gt;.....&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You&#39;re now ready to start using varnish as your intermediary frontend router. Varnish will PASS any requests to these sites and you are now free to change the IP:s of the sites without the lag of DNS. You remembered to load and use your varnish config too, right?&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;2) Alter DNS for sites&lt;/span&gt;&lt;br /&gt;Update your dns records, all www pointers should be changed to the ip address of your Varnish server.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;3) Migrate!&lt;br /&gt;&lt;/span&gt;When the changes have propagated (and you&#39;ve verified that it works as intended) you are free to change ip:s or whatever you need on your sites, Varnish will maintain the dnsname -&amp;gt; backend connection as long as you remember to update your backend config in vcl. And, changes are instant - allowing fast rollbacks if needed.&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/1016033876845993712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2011/08/how-to-migrate-web-sites-without.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/1016033876845993712'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/1016033876845993712'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2011/08/how-to-migrate-web-sites-without.html' title='How to ip-migrate web sites using Varnish'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-797734886125724852</id><published>2011-08-17T06:49:00.000-07:00</published><updated>2011-08-17T06:50:16.293-07:00</updated><title type='text'>How to use bash to find all used IP:s in your apache configs (following the debian config model)</title><content type='html'>&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;for i in `ls /etc/apache2/sites-enabled/*.vhost`; do echo &quot;Working file:$i&quot;; echo &quot;Servername:&quot;;grep &quot;ServerName&quot; $i | cut -c 16-40; echo &quot;Ipaddress:&quot;;grep &quot;&amp;lt;VirtualHost&quot; $i|cut -c 14-27; done&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/797734886125724852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2011/08/how-to-use-bash-to-find-all-used-ips-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/797734886125724852'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/797734886125724852'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2011/08/how-to-use-bash-to-find-all-used-ips-in.html' title='How to use bash to find all used IP:s in your apache configs (following the debian config model)'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-8477876725419303190</id><published>2011-03-22T07:08:00.000-07:00</published><updated>2011-11-17T11:40:51.637-08:00</updated><title type='text'>Top 5 Varnish commands</title><content type='html'>Here&#39;s a brief list of my top &lt;strike&gt;&lt;/strike&gt;5 varnish commands&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;varnishstat&lt;/b&gt;&lt;br /&gt;
This is what I use to get a birds-eye view of what we have cooking. Provides all the info you need to spot cache misses and errors.&lt;br /&gt;
Usage: &lt;i&gt;varnishstat&lt;/i&gt; for continuous display or &lt;i&gt;varnishstat -i 1&lt;/i&gt; for a quick one-off. More on this command: &lt;a href=&quot;http://www.varnish-cache.org/docs/2.1/reference/varnishstat.html&quot; target=&quot;_blank&quot;&gt;http://www.varnish-cache.org/docs/2.1/reference/varnishstat.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;varnishhist&lt;/b&gt;&lt;br /&gt;
Provides a histogram view of cache hits/misses&lt;br /&gt;
Usage: &lt;i&gt;varnishhist&lt;/i&gt; More on this command: &lt;a href=&quot;http://www.varnish-cache.org/docs/2.1/reference/varnishhist.html&quot; target=&quot;_blank&quot;&gt;http://www.varnish-cache.org/docs/2.1/reference/varnishhist.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;varnishlog&lt;/b&gt;&lt;br /&gt;
Provides detailed information on requests. I use it to debug cache operations by for example issuing the command &lt;i&gt;varnishlog -c -o ReqStart [insert ip here]&lt;/i&gt; which allows me to see what happens when I visit a cache object in my browser.&lt;br /&gt;
Usage: &lt;i&gt;varnishlog -c -o ReqStart 192.168.0.1&lt;/i&gt; More on this command: &lt;a href=&quot;http://www.varnish-cache.org/docs/2.1/reference/varnishlog.html&quot; target=&quot;_blank&quot;&gt;http://www.varnish-cache.org/docs/2.1/reference/varnishlog.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;varnishtop&lt;/b&gt;&lt;br /&gt;
I use this mainly to get lists of things. Like this one that gives me a list of the top urls hitting the backend (pass).&lt;br /&gt;
Usage: &lt;i&gt;varnishtop -b -i TxURL &lt;/i&gt;More on this command: &lt;a href=&quot;http://www.varnish-cache.org/docs/2.1/reference/varnishtop.html&quot; target=&quot;_blank&quot;&gt;http://www.varnish-cache.org/docs/2.1/reference/varnishtop.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;varnishadm&lt;/b&gt;&lt;br /&gt;
Command-line varnish administration. I mainly use this to reload vcl and purge urls.&lt;br /&gt;
Usage: &lt;i&gt;varnishadm -t host:port command&lt;/i&gt;&lt;br /&gt;
Reloading a vcl from the command line can be done like this:&lt;br /&gt;
Load (your changed vcl): &lt;i&gt;varnishadm -t localhost:6082 vcl.load load01 /etc/varnish/default.vcl&lt;/i&gt;&lt;br /&gt;
Use (apply) the vcl: &lt;i&gt;varnishadm -t localhost:6082 vcl.use load01&lt;/i&gt;&lt;br /&gt;
More on this command: &lt;a href=&quot;http://www.varnish-cache.org/docs/2.1/reference/varnishadm.html&quot; target=&quot;_blank&quot;&gt;http://www.varnish-cache.org/docs/2.1/reference/varnishadm.html&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/8477876725419303190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2011/03/top-4-varnish-commands.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/8477876725419303190'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/8477876725419303190'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2011/03/top-4-varnish-commands.html' title='Top 5 Varnish commands'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-6280563138001184131</id><published>2011-03-15T14:29:00.000-07:00</published><updated>2011-03-15T14:29:38.140-07:00</updated><title type='text'>Facebook iframe like box tracking with Clicky (or Google Analytics)</title><content type='html'>This is how to do GetClicky tracking for facebooks fbxml iframe like box and the fbxml like button.&lt;br /&gt;
&lt;br /&gt;
Without going into details about fb app id and such, this is a working method to implement the GetClicky tracking for facebook like boxes and buttons.&lt;br /&gt;
&lt;br /&gt;
Standard fb script:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;div id=&amp;quot;fb-root&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
//&amp;lt;![CDATA[
window.fbAsyncInit = function() {
 FB.init({appId: &#39;157019890979609&#39;, status: true, cookie: true,
 xfbml: true});
});
(function() {
var e = document.createElement(&#39;script&#39;); 
e.async = true;
e.src = document.location.protocol +
&#39;//connect.facebook.net/sv_SE/all.js&#39;;
document.getElementById(&#39;fb-root&#39;).appendChild(e);
}());
//]]&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
The facebook &quot;like&quot; event hook:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;FB.Event.subscribe(&#39;edge.create&#39;, function(href, widget) {
// do something here
});
&lt;/pre&gt;&lt;br /&gt;
The clicky call:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;if(typeof(clicky) != &amp;quot;undefined&amp;quot;){
clicky.log(&#39;page url&#39;,&#39;facebook like clicked&#39;,&#39;click&#39;);
}
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Combined:&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;div id=&amp;quot;fb-root&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;
//&amp;lt;![CDATA[
window.fbAsyncInit = function() {
FB.init({appId: &#39;157019890979609&#39;, status: true, cookie: true,
xfbml: true});
FB.Event.subscribe(&#39;edge.create&#39;, function(href, widget) {
if(typeof(clicky) != &amp;quot;undefined&amp;quot;){
clicky.log(&#39;page url&#39;,&#39;facebook like clicked&#39;,&#39;click&#39;);
}
});
};
(function() {
var e = document.createElement(&#39;script&#39;); 
e.async = true;
e.src = document.location.protocol +
&#39;//connect.facebook.net/sv_SE/all.js&#39;;
document.getElementById(&#39;fb-root&#39;).appendChild(e);
}());
//]]&amp;gt;
&amp;lt;/script&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Of course the same works for Google Analytics, just swap &lt;em&gt;clicky.log&lt;/em&gt; for &lt;em&gt;_gaq.push&lt;/em&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/6280563138001184131/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2011/03/facebook-iframe-like-box-tracking-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/6280563138001184131'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/6280563138001184131'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2011/03/facebook-iframe-like-box-tracking-with.html' title='Facebook iframe like box tracking with Clicky (or Google Analytics)'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-8930481820358275390</id><published>2011-03-14T15:29:00.000-07:00</published><updated>2011-03-16T05:56:40.674-07:00</updated><title type='text'>Custom Drupal RSS Feed with CCK</title><content type='html'>Ever needed to do a quick RSS feed one-off out of your Drupal site? This is how I do it.&lt;br /&gt;
&lt;br /&gt;
Setup: Drupal 6, CCK, Views enabled.&lt;br /&gt;
&lt;br /&gt;
First, create a new content type and name it &lt;em&gt;rssarticle&lt;/em&gt;. Add three text fields named &lt;em&gt;heading, text&lt;/em&gt; and &lt;em&gt;link&lt;/em&gt;. Save the content type.&lt;br /&gt;
&lt;br /&gt;
Now, we&#39;ll use Views as a query builder that will provide the SQL you will run to build the feed. Start out by setting up a &lt;em&gt;Node&lt;/em&gt; View, set Style to &lt;em&gt;unformatted&lt;/em&gt; and Row style to &lt;em&gt;Fields&lt;/em&gt;. Select the fields you want in your feed and move on to add a &lt;em&gt;node type&lt;/em&gt; filter to restrict the view to our newly added &lt;em&gt;rssarticle&lt;/em&gt; content type. Keep the rest of the settings untouched.&lt;br /&gt;
&lt;br /&gt;
Now, hit the Preview button. You should now see some nodes rendered and a Query field that displays the query like so:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;SELECT node.nid AS nid,
   node_data_field_heading.field_heading_value AS 
   node_data_field_heading_field_heading_value,
   node.type AS node_type,
   node.vid AS node_vid,
   node_data_field_heading.field_link_value AS 
   node_data_field_heading_field_link_value,
   node_data_field_heading.field_text_value AS 
   node_data_field_heading_field_text_value
 FROM node node 
 LEFT JOIN content_type_rssarticle node_data_field_heading ON 
   node.vid = node_data_field_heading.vid
 WHERE node.type in (&#39;rssarticle&#39;)
&lt;/pre&gt;&lt;br /&gt;
Copy that SQL query and fire up your favorite php editor. Create a new php file by the name of &lt;em&gt;mycustomfeed.php&lt;/em&gt;. Start by adding the following lines.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;?php
// Load necessary Drupal parts
require_once &#39;./includes/bootstrap.inc&#39;;
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// XML header
echo(&#39;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&amp;gt;&#39;);

// Get nodes from db
$results = db_query(&quot;&quot;);

// Loop over the result
while ($result = db_fetch_object($results)) {
 print $result-&amp;gt;nid;
}
?&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Now this won&#39;t do much on it&#39;s own, we need the SQL you just copied to go in here too. Complete the code with this, placing it within the &lt;em&gt;db_query(&quot;&quot;)&lt;/em&gt; statement.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;?php
// Load necessary Drupal parts
require_once &#39;./includes/bootstrap.inc&#39;;
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// XML header
echo(&#39;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&amp;gt;&#39;);

// Get nodes from db
$results = db_query(&quot;SELECT node.nid AS nid, 
node_data_field_heading.field_heading_value AS 
node_data_field_heading_field_heading_value, node.type AS 
node_type, node.vid AS node_vid, 
node_data_field_heading.field_link_value AS 
node_data_field_heading_field_link_value, 
node_data_field_heading.field_text_value AS 
node_data_field_heading_field_text_value FROM node node 
LEFT JOIN content_type_rssarticle node_data_field_heading 
ON node.vid = node_data_field_heading.vid WHERE 
node.type in (&#39;rssarticle&#39;)&quot;);

// Loop over the result
while ($result = db_fetch_object($results)) {
 print $result-&amp;gt;nid . &quot;\n&quot;;
}
?&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Upload the file to your Drupal root and run either from a browser or from the command line.&lt;br /&gt;
&lt;br /&gt;
It should output an xml header and list of NIDs. Check error logs for any warnings or sql errors and correct your code accordingly.&lt;br /&gt;
&lt;br /&gt;
Now that we have the query working it&#39;s time to finish the job, adding the xml parts required for a valid RSS 2.0 feed as well as adding a &lt;em&gt;LIMIT&lt;/em&gt; clause and performing some ISO date conversion magic.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;?php
// Load necessary Drupal parts
require_once &#39;./includes/bootstrap.inc&#39;;
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// XML header
echo(&#39;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&amp;gt;&#39;);
?&amp;gt;

&amp;lt;rss version=&quot;2.0&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot;&amp;gt;
  &amp;lt;channel&amp;gt;
    &amp;lt;title&amp;gt;My Custom Feed&amp;lt;/title&amp;gt;
    &amp;lt;description&amp;gt;This is My Custom Feed&amp;lt;/description&amp;gt;
    &amp;lt;link&amp;gt;http://www.domain.com/mycustomfeed&amp;lt;/link&amp;gt;

&amp;lt;?php

// Get nodes from db
$results = db_query(&quot;SELECT node.nid AS nid,
node_data_field_heading.field_heading_value AS 
node_data_field_heading_field_heading_value, 
node.type AS node_type, node.vid AS node_vid, 
node_data_field_heading.field_link_value AS 
node_data_field_heading_field_link_value, 
node_data_field_heading.field_text_value AS 
node_data_field_heading_field_text_value,
node.changed AS node_changed FROM node node 
LEFT JOIN content_type_rssarticle node_data_field_heading 
ON node.vid = node_data_field_heading.vid
WHERE node.type in (&#39;rssarticle&#39;) LIMIT 0,10&quot;);
// Execute query and loop over the result
while ($result = db_fetch_object($results)) {
?&amp;gt;
&amp;lt;item&amp;gt;
&amp;lt;title&amp;gt;
&amp;lt;?php echo $result-&amp;gt;node_data_field_heading_field_heading_value?&amp;gt;
&amp;lt;/title&amp;gt;
&amp;lt;description&amp;gt;
&amp;lt;?php echo $result-&amp;gt;node_data_field_heading_field_text_value?&amp;gt;
&amp;lt;/description&amp;gt;
&amp;lt;link&amp;gt;
&amp;lt;?php echo $result-&amp;gt;node_data_field_heading_field_link_value?&amp;gt;
&amp;lt;/link&amp;gt;
&amp;lt;author&amp;gt;noreply@domain.com (Corporate Inc)&amp;lt;/author&amp;gt;
&amp;lt;dc:creator&amp;gt;Head.Honcho&amp;lt;/dc:creator&amp;gt;
&amp;lt;category&amp;gt;CustomCategory&amp;lt;/category&amp;gt;
&amp;lt;guid isPermaLink=&quot;false&quot;&amp;gt;&amp;lt;?php echo $node-&amp;gt;nid?&amp;gt;&amp;lt;/guid&amp;gt;
&amp;lt;pubDate&amp;gt;
&amp;lt;?php echo date(&#39;D, d M Y H:i:s T&#39;,$result-&amp;gt;node_changed)?&amp;gt;
&amp;lt;/pubDate&amp;gt;
&amp;lt;/item&amp;gt;
&amp;lt;?php } // End while loop ?&amp;gt;
&amp;lt;/channel&amp;gt;
&amp;lt;/rss&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
For more on custom rss from drupal, check out my &lt;a href=&quot;http://christophercato.blogspot.com/2011/03/drupal-rss-2-with-imagecache-images-in.html&quot;&gt;post on rss with imagecache images and media enclosures&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/8930481820358275390/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2011/03/custom-drupal-rss-feed-with-cck.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/8930481820358275390'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/8930481820358275390'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2011/03/custom-drupal-rss-feed-with-cck.html' title='Custom Drupal RSS Feed with CCK'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-2470432928441311871</id><published>2011-03-03T07:35:00.000-08:00</published><updated>2011-03-03T09:45:41.018-08:00</updated><title type='text'>Drupal RSS 2 with imagecache images in media enclosures</title><content type='html'>I got a new project to do. It involved publishing news clips to various sites via valid rss 2.0. The feed includes a headline, a link, a short text and an image. But, the image has to go in an enclosure like the following&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;enclosure url=&quot;http://domain.com/file.jpg&quot; 
length=&quot;3737&quot; 
type=&quot;image/jpeg&quot;/&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
The way I chose to do this was by setting up a view to handle the listings and then doing a custom template based on the dead simple Basic. I removed all trim and just added the outline of a valid rss 2.0 feed structure by creating my page.tpl.php, node-view-viewname.tpl.php and views-view.tpl.php where node-view-viewname is the template file that will print the actual item. Easy.&lt;br /&gt;
&lt;br /&gt;
Now here comes a problem... To make up for the never-ending creativity of our dear editors, we use ImageCache. Without it we would be lost in a world of image sizes and formats. If you are at all familiar with ImageCache you know that it&#39;s lazy and only generates an image if a request for an image fires a 404 error. This is fine for most purposes but since rss media enclosures require certain metadata about the file and it doesn&#39;t exist yet we need to force ImageCache to generate the image before we can fill the enclosure tag with the correct values.&lt;br /&gt;
We can do this in template.php by adding the following function:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;/*
* This function pregenerates ImageCache images
* to give access to the file metadata
* @param $vars
*/
function basic_attach_ic_metadata(&amp;amp;$vars) {
$presetname = &quot;100x100&quot;;
$filepath = $vars[&#39;field_bild&#39;][0][&#39;filepath&#39;];
$preset = imagecache_preset_by_name($presetname);
$dst = imagecache_create_path($presetname, $filepath);
if (!file_exists($dst)) {
imagecache_build_derivative($preset[&#39;actions&#39;], $filepath, $dst);
}
$vars[&#39;genimage&#39;] = $dst;
}&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;
Which in it&#39;s turn gets called from template.php like so:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;?php function basic_preprocess_node(&amp;amp;$vars, $hook) {
  basic_attach_ic_metadata(&amp;amp;$vars);
...
}&amp;gt;
&lt;/pre&gt;Now, when the node is prepared for display the variable $genimage will be set with the path to a generated image. This now available for your node template to consume and we can print the enclosure tag.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;prettyprint&quot;&gt;&amp;lt;enclosure url=&quot;http://domain.com/&amp;lt;?php echo $genimage;?&amp;gt;&quot;
length=&quot;&amp;lt;?php echo filesize($genimage);?&amp;gt;&quot; 
type=&quot;image/jpeg&quot;/&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
All done!</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/2470432928441311871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2011/03/drupal-rss-2-with-imagecache-images-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/2470432928441311871'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/2470432928441311871'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2011/03/drupal-rss-2-with-imagecache-images-in.html' title='Drupal RSS 2 with imagecache images in media enclosures'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5600017894340887470.post-8747608293733719883</id><published>2011-03-01T12:49:00.000-08:00</published><updated>2011-03-02T05:49:46.196-08:00</updated><title type='text'>External ads in Drupal</title><content type='html'>Allrighty. So someone is twisting your arm and trying to make you add blocks of ad network script tags on your perfect Drupal site? Polluting your DOM? No way, not on my shift! Here&#39;s how to keep it safe.&lt;br /&gt;
&lt;br /&gt;
First you need a basic understanding of a few concepts. I&#39;ll use Taxonomy, CCK, Views and some funky template preprocess magic all bound together by our beloved page.tpl.php. The external ads are presumably a bunch of script tags.&lt;br /&gt;
&lt;br /&gt;
Start out by creating a .php or .html file that hold each ad, place these somewhere within your drupal folder in a folder, why not name it &quot;ads&quot;. Any cache-busting techniques should be done with php. Note the full URL:s.&lt;br /&gt;
&lt;br /&gt;
Now for some Drupal hands-on: Create a Vocabulary that will hold the tags that will tell Drupal which nodes get what ads. Name it &quot;Customers&quot;. It should be a flat vocabulary.&lt;br /&gt;
&lt;br /&gt;
Next, create a content-type that will serve as the holder for the dreaded external ads. Name it &quot;Customer&quot;. Add as many text fields as the total of your ad slots. The text fields will only hold URLs and should be plain text only. Save when done. (You can easily add more custom fields here that can be used for your nodes)&lt;br /&gt;
&lt;br /&gt;
Move on to Taxonomy-&amp;gt;Vocabularies. Configure the previously added vocab so that it is selected for your &quot;regular&quot; content-type so you can relate it with its Customer. Now, add as many terms to the vocabulary as you have customer sections, i.e. companya, companyb, companyc.&lt;br /&gt;
&lt;br /&gt;
Create a Customer node. Populate the fields with the URL:s from the first step. Fill the title field with one of your terms from Customers, for example &quot;companya&quot;. Note: This needs to be unique.&lt;br /&gt;
&lt;br /&gt;
Now, edit one of your &quot;regular&quot; nodes. Add the term &quot;companya&quot; to the node and save it.&lt;br /&gt;
&lt;br /&gt;
Set up a view to load your Customer data by creating a new View, naming it &quot;customerdata&quot;.  The View should be Unformatted and row style should be Node. Add Node:Title as an argument, accepting the default 404/hide view settings. Add a filter on node type and set it to Customer. Save it.&lt;br /&gt;
&lt;br /&gt;
The time has come for us to bring it all together and display the ads. This is when your template.php hacking skills come into play. Fire up an editor and open template.php for the theme you&#39;ll be using. You now need to create a function that will load the data from the Customer node and attach it to the node before rendering.&lt;br /&gt;
You also need to make sure this gets called when the page is constructed. You might need it on the page level or the node level, it depends.&lt;br /&gt;
&lt;br /&gt;
template.php:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/850944.js?file=gistfile1.php&quot;&gt;&lt;/script&gt;&lt;br /&gt;
&lt;br /&gt;
The last part is your page.tpl.php. To print your now safer external ads, construct something along the lines of&lt;br /&gt;
&lt;pre&gt;echo &quot;iframe src=&quot; . $ad1 . &quot;/iframe&quot;;&lt;/pre&gt;&lt;br /&gt;
The same can be repeated for any custom field. The process is the same, add it to the Customer content-type, fill out the Customer node, tag your node(s) with the appropriate term and output it in your page.tpl.php.&lt;br /&gt;
&lt;br /&gt;
Upload template.php and page.tpl.php, flush your caches and load one of your tagged nodes. You should now see the ad being displayed. If not, check the html source for your iframe tag or flush your cache.&lt;br /&gt;
&lt;br /&gt;
This example is just a basic example and can be improved upon endlessly. A few of those being Rules integration, error checking and Views caching.</content><link rel='replies' type='application/atom+xml' href='https://christophercato.blogspot.com/feeds/8747608293733719883/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://christophercato.blogspot.com/2011/03/external-ads-in-drupal.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/8747608293733719883'/><link rel='self' type='application/atom+xml' href='https://www.blogger.com/feeds/5600017894340887470/posts/default/8747608293733719883'/><link rel='alternate' type='text/html' href='https://christophercato.blogspot.com/2011/03/external-ads-in-drupal.html' title='External ads in Drupal'/><author><name>Christopher Cato</name><uri>http://www.blogger.com/profile/01740225109829923234</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>