<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mixu&#039;s tech blog &#187; How-to</title>
	<atom:link href="http://blog.mixu.net/category/how-to/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mixu.net</link>
	<description>When I read what I write I learn what I think</description>
	<lastBuildDate>Tue, 31 Jan 2012 23:14:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>How to: thinkpad_acpi and fan control on Arch</title>
		<link>http://blog.mixu.net/2012/01/19/how-to-thinkpad_acpi-and-fan-control-on-arch/</link>
		<comments>http://blog.mixu.net/2012/01/19/how-to-thinkpad_acpi-and-fan-control-on-arch/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 08:04:45 +0000</pubDate>
		<dc:creator>Mikito Takada</dc:creator>
				<category><![CDATA[How-to]]></category>

		<guid isPermaLink="false">http://blog.mixu.net/?p=2201</guid>
		<description><![CDATA[From the &#8220;this might help some random person&#8221; department &#8211; setting up manual Thinkpad fan control in Arch Linux. 1. Edit /etc/rc.conf. Add thinkpad_acpi to MODULES=() in the hardware section. 2. Create a new file enabling fan control as /etc/modprobe.d/thinkfan.conf: options thinkpad_acpi fan_control=1 3. Reload the thinkpad_acpi module: sudo modprobe -r thinkpad_acpi &#38;&#38; sudo modprobe [...]]]></description>
			<content:encoded><![CDATA[<p>From the &#8220;this might help some random person&#8221; department &#8211; setting up manual Thinkpad fan control in Arch Linux.</p>
<p>1. Edit /etc/rc.conf. Add thinkpad_acpi to MODULES=() in the hardware section.</p>
<p>2. Create a new file enabling fan control as /etc/modprobe.d/thinkfan.conf:</p>
<pre>options thinkpad_acpi fan_control=1</pre>
<p>3. Reload the thinkpad_acpi module:</p>
<pre>sudo modprobe -r thinkpad_acpi &amp;&amp; sudo modprobe thinkpad_acpi</pre>
<p>To view the current fan speed:</p>
<pre>[~]$ cat /proc/acpi/ibm/fan
status: enabled
speed: 2887
level: 4
commands: level ( is 0-7, auto, disengaged, full-speed)
commands: enable, disable
commands: watchdog ( is 0 (off), 1-120 (seconds))</pre>
<p>To control fan speed:</p>
<pre># echo level 0 | sudo tee /proc/acpi/ibm/fan (fan off)
# echo level 2 | sudo tee /proc/acpi/ibm/fan (low speed)
# echo level 4 | sudo tee /proc/acpi/ibm/fan (medium speed)
# echo level 7 | sudo tee /proc/acpi/ibm/fan (maximum speed)
# echo level auto | sudo tee /proc/acpi/ibm/fan (automatic - default)</pre>
<p>For easy control from the command line:</p>
<pre>function fan() {
  sensors
  echo level $@ | sudo tee /proc/acpi/ibm/fan
}</pre>
<p>Now you can run <code>fan 2</code> to set the fan level to 2 and so on.</p>
<p>To view fan speed, install lm_sensors <a href="https://wiki.archlinux.org/index.php/Lm_sensors">following the instructions on the Arch wiki</a>. Example output:</p>
<pre>[~]$ sensors
acpitz-virtual-0
Adapter: Virtual device
temp1:        +37.0°C  (crit = +99.0°C)

thinkpad-isa-0000
Adapter: ISA adapter
fan1:        2904 RPM

coretemp-isa-0000
Adapter: ISA adapter
Physical id 0:  +39.0°C  (high = +86.0°C, crit = +100.0°C)
Core 0:         +37.0°C  (high = +86.0°C, crit = +100.0°C)
Core 1:         +37.0°C  (high = +86.0°C, crit = +100.0°C)
Core 2:         +35.0°C  (high = +86.0°C, crit = +100.0°C)
Core 3:         +39.0°C  (high = +86.0°C, crit = +100.0°C)</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.mixu.net/2012/01/19/how-to-thinkpad_acpi-and-fan-control-on-arch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Arch Linux setup</title>
		<link>http://blog.mixu.net/2011/11/10/my-arch-linux-setup/</link>
		<comments>http://blog.mixu.net/2011/11/10/my-arch-linux-setup/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 04:22:41 +0000</pubDate>
		<dc:creator>Mikito Takada</dc:creator>
				<category><![CDATA[How-to]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.mixu.net/?p=2033</guid>
		<description><![CDATA[This is mostly just a reminder for myself &#8211; but I always learn new things when I read how other people set up their system. Leave a comment if you have a tip &#8211; that&#8217;s how I learned about wicd-gtk . Oh, and install my window manager (tiling, written in C++ and node.js, configurable using Javascript). [...]]]></description>
			<content:encoded><![CDATA[<p>This is mostly just a reminder for myself &#8211; but I always learn new things when I read how other people set up their system. Leave a comment if you have a tip &#8211; that&#8217;s how I learned about wicd-gtk <img src='http://blog.mixu.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Oh, and install <a href="https://github.com/mixu/nwm">my window manager</a> (tiling, written in C++ and node.js, configurable using Javascript).</p>
<p><strong>First steps</strong></p>
<ul>
<li>do the basic arch setup first (or <a href="https://wiki.archlinux.org/index.php/Installing_Arch_Linux_in_VMware">VMware</a>, or Virtualbox)</li>
</ul>
<p><strong>Update the system (and install/setup sudo)</strong></p>
<pre>dhcpcd eth0 #if you did not add "interface=eth0" in rc.conf during setup
pacman -Syu</pre>
<p>Fixes:</p>
<p><a href="http://www.archlinux.org/news/initscripts-update-manual-intervention-required/">http://www.archlinux.org/news/initscripts-update-manual-intervention-required/</a></p>
<pre>rm /etc/profile.d/locale.sh</pre>
<p><a href="http://www.archlinux.org/news/filesystem-upgrade-manual-intervention-required/">http://www.archlinux.org/news/filesystem-upgrade-manual-intervention-required/</a></p>
<pre>pacman -S filesystem --force</pre>
<pre>pacman -S sudo
vim /etc/sudoers # add yourself to sudoers
sudo vim /etc/pacman.conf # set SigLevel = Never TrustAll
sudo shutdown-r now</pre>
<p>Install X11:</p>
<pre>pacman -S xorg-server xorg-xinit xorg-utils xorg-server-utils xterm</pre>
<p>If virtualized in VirtualBox, make copy-paste work first:</p>
<pre>pacman -S virtualbox-archlinux-additions</pre>
<p><a href="https://wiki.archlinux.org/index.php/Arch_Linux_VirtualBox_Guest#Arch_Linux_guests">Details</a></p>
<p><strong> Create a new user</strong></p>
<pre>pacman -S zsh
useradd -m -g users -G audio,lp,optical,storage,video,games,power,scanner -s /bin/zsh USERNAME
su USERNAME
passwd</pre>
<p><strong>Add x11</strong></p>
<pre>pacman -S xorg-server xorg-xinit xorg-utils xorg-server-utils</pre>
<p><strong>Copy ssh keys over from old machine</strong><br />
<strong>Useful packages</strong></p>
<pre>pacman -S base-devel sudo python2 git libev mlocate mercurial nitrogen \
sakura wicd-gtk pcmanfm gnome-icon-theme htop unzip \
openssl chromium flashplugin bash-completion xterm \
epdfview mysql ruby tilda tmux wget redis xcursor-vanilla-dmz \
xarchiver gzip bzip2 zip unzip unrar p7zip \
meld ttf-ubuntu-font-family mpg123 alsa-utils redis mysql ruby libxslt</pre>
<ul>
<li>base-devel and python2 for compiling node</li>
<li>libev for nwm</li>
<li>mlocate for locate command</li>
<li>nitrogen is better than feh for multiple screens</li>
<li>sakura is a nice terminal</li>
<li>wicd-gtk is a simple wifi network gui</li>
<li>pcmanfm gnome-icon-theme are for pcmanfm, a Nautilus alternative</li>
</ul>
<p>Remember to visudo and remove the password requirement from wheel. And add dbus and wicd to /etc/rc.conf just like pacman tells you to.<br />
<strong>Configuring X11</strong></p>
<p>Add ~/.Xresources:</p>
<pre>Xcursor.theme: vanilla-dmz
Xcursor.size:  16       !  32, 48 or 64 may also be good values</pre>
<p><strong>Configuring git</strong></p>
<pre>git config --global color.ui true</pre>
<p><strong>Configuring sakura</strong></p>
<p>I want to use ctrl + Page_Up / Page_Down to switch tabs, so edit ~/.config/sakura/sakura.conf:</p>
<pre>switch_tab_accelerator=4 # since <a>GDK_CONTROL_MASK</a> is 1 &lt;&lt; 2, e.g. 4.
prev_tab_key=Page_Down
next_tab_key=Page_Up</pre>
<p><strong>Some basic niceties: whatprovides, service and chkconfig</strong></p>
<pre>pacman -S pkgtools</pre>
<ul>
<li>pkgtools provides the pkgfile tool. It works like yum whatprovides (e.g. allows you to search for a particular command or dependency in all the pacman packages)</li>
<li>&#8220;sudo pkgfile -u&#8221; to update the db</li>
<li>&#8220;pgkfile zipinfo&#8221; to search for zipinfo</li>
</ul>
<p>Arch don&#8217;t have a service and chkconfig, but we can make the new things curve a bit less steep by adding some functions to .bashrc:</p>
<pre>function service() {
  sudo /etc/rc.d/$1 $2
}

alias chkconfig='cat /etc/rc.conf | grep DAEMONS &amp;&amp; echo "cat + grep /etc/rc.conf"'</pre>
<p>This makes service an alias for /etc/rc.d/ and prints out the enabled services from /etc/rc.conf. While we&#8217;re editing .bashrc, might as well add:</p>
<pre>PS1="[\W]\$ " # my preferred bash prompt (e.g. only the current dirname).
ulimit -s 16400 # higher stack limit
# ssh-agent
SSH_ENV="$HOME/.ssh/environment"
function start_agent {
     echo "Initialising new SSH agent..."
     /usr/bin/ssh-agent | sed 's/^echo/#echo/' &gt; "${SSH_ENV}"
     echo succeeded
     chmod 600 "${SSH_ENV}"
     . "${SSH_ENV}" &gt; /dev/null
     /usr/bin/ssh-add;
}
# Source SSH settings, if applicable
if [ -f "${SSH_ENV}" ]; then
     . "${SSH_ENV}" &gt; /dev/null
     #ps ${SSH_AGENT_PID} doesn't work under cywgin
     ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ &gt; /dev/null || {
         start_agent;
     }
else
     start_agent;
fi</pre>
<p><strong>Installing Node and NPM</strong></p>
<p>You can just do:</p>
<pre>pacman -S nodejs</pre>
<p>If you&#8217;re OK with that version, which seems to track the Node releases pretty well.</p>
<p>Arch uses python3 as python. You need to change python to python2 (thanks <a href="http://www.robsearles.com/2011/02/11/nodejs-v0-4-0-on-arch-linux/">Rob Searles</a>!)</p>
<pre># node.js fix for arch (use python2) 
mkdir /tmp/bin
ln -s /usr/bin/python2 /tmp/bin/python
export PATH=/tmp/bin:$PATH</pre>
<p>You can then do a regular node install:</p>
<p>git clone git://github.com/joyent/node.git</p>
<p>git checkout v0.4.12</p>
<p>./configure</p>
<p>make</p>
<p>sudo make install</p>
<p>Remember to install npm as well:</p>
<pre>curl http://npmjs.org/install.sh | sudo sh</pre>
<p><strong>Installing my window manager and personal config</strong></p>
<pre>git clone git://github.com/mixu/nwm.git
cd nwm
node-waf clean || true &amp;&amp; node-waf configure build
sudo npm link # add a global npm symlink to this repository - so nwm-user can find it (man npm link)
cd ..
git clone git://github.com/mixu/nwm-user.git
cd nwm-user
npm link nwm # now make a symlink to the nwm installation</pre>
<p>Add it to ~/.xinitrc (change paths!!):</p>
<pre>exec /usr/local/bin/node ~/mnt/nwm-user/nwm-user.js 2&gt;~/nwm.err.log 1&gt;~/nwm.log</pre>
<p>And while we&#8217;re at it, lets add some other stuff:</p>
<pre>VBoxClient-all &amp;
export PATH=/tmp/bin:$PATH # for node-waf, too lazy to work on a better solution
xset +fp /usr/share/fonts/local
xset fp rehash</pre>
<p>Run &#8220;startx&#8221; to start X11 with nwm.</p>
<p><strong>Installing my mp3 player</strong></p>
<p>First, we need to configure alsa (included by default):</p>
<pre>pacman -S mpg123 alsa-utils</pre>
<p>Run:</p>
<pre>alsamixer</pre>
<p>and turn on Master and PCM channels (by pressing m) as they are muted by default.</p>
<pre>sudo alsactl store</pre>
<p>Then continue:</p>
<pre>git clone git://github.com/mixu/nplay.git</pre>
<p>Run nplay with</p>
<pre>node nplay.js</pre>
<p>TODO: fix directory in source code and change backend from mpg321 to mpg123.</p>
<p><strong>Switching the keyboard language in X11</strong></p>
<p>I sometimes need to write emails in Finnish, so here is how to switch the layout:</p>
<pre><code>setxkbmap -layout fi # revert back </code><span class="Apple-style-span" style="font-family: monospace;">setxkbmap -layout us</span><span class="Apple-style-span" style="font-family: monospace;"> </span></pre>
<p>Install yaourt</p>
<p>Install dependencies</p>
<p>yaourt libpng12 gtk2-theme-dust</p>
<p>&nbsp;</p>
<p><strong>Install Sublime Text 2</strong></p>
<p>Sublime Text needs libpng12, which you have to install from AUR:</p>
<pre>wget http://aur.archlinux.org/packages/li/libpng12/libpng12.tar.gz
tar -xzvf libpng12.tar.gz
cd libpng12
makepkg
pacman -U ./libpng12-1.2.46-2-x86_64.pkg.tar.xz</pre>
<p>Then download and run Sublime Text 2.</p>
<p>Also, you might want to ger http://aur.archlinux.org/packages/gt/gtk2-theme-dust/gtk2-theme-dust.tar.gz.</p>
<p><strong>Configuring Sublime Text 2</strong></p>
<pre>locate Packages # returns ~/.config/sublime-text-2/Packages
cd ~/.config/sublime-text-2/Packages
git clone https://github.com/buymeasoda/soda-theme/ "Theme - Soda"
cd User
wget http://blog.mixu.net/files/2010/05/my_themes.zip # Install my themes
unzip my_themes
rm my_themes.zip</pre>
<p><strong>Base File settings</strong></p>
<pre>{
  // FONTS and COLORS
  "color_scheme": "Packages/User/Mixu Espresso.tmTheme",
  "font_size": 11,
  "tab_size": 2,
  // WHITESPACE
    // Set to true to insert spaces when tab is pressed
    "translate_tabs_to_spaces": true,
    "trim_automatic_white_space": true,
    "trim_trailing_white_space_on_save": true,
    // Set to false to disable detection of tabs vs. spaces on load
    "detect_indentation": false,
  "shift_tab_unindent": true,
  // Set to false to disable highlighting any line with a caret
  "highlight_line": true,
  // Set to "none" to turn off drawing white space, "selection" to draw only the
  // white space within the selection, and "all" to draw all white space
  "draw_white_space": "selection",
  // Set to true to ensure the last line of the file ends in a newline
  // character when saving
  "ensure_newline_at_eof_on_save": true,
  "fold_buttons": false
}</pre>
<p><strong>Global Settings</strong></p>
<pre>{
  "theme": "Soda Light.sublime-theme"
}</pre>
<p><strong>Other tweaks</strong></p>
<p>I put these in my usual &#8220;startup&#8221; command, nwm-setup.sh and run it manually:</p>
<pre>xrandr --output VBOX0 --auto --left-of VBOX1 # Virtualbox displays
chromium &amp; # start chromium
export PS1="[\W]\$ "
xsetroot -cursor_name left_ptr # Set pointer
nitrogen --restore &amp; # Restore desktop background using nitrogen</pre>
<p><strong>Other dependencies</strong></p>
<pre>pacman -S redis mysql ruby libxslt</pre>
<p>Setting up ree:</p>
<pre>cd
bash &lt; &lt;(curl -s https://rvm.beginrescueend.com/install/rvm)
echo '[[ -s "$HOME/.rvm/scripts/rvm" ]] &amp;&amp; . "$HOME/.rvm/scripts/rvm" # Load RVM function' &gt;&gt; ~/.bashrc
source .bashrc
rvm install ree-1.8.7-2011.03</pre>
<p>Installing REE will fail. <a href=" http://stackoverflow.com/questions/6134456/error-while-installing-ruby-1-8-7-on-fedora-15">You need to</a>run the installer from /home/m/.rvm/src/ree-1.8.7-2011.03/installer manually:</p>
<pre>./installer -no-tcmalloc</pre>
<p>Then continue on:</p>
<pre>rvm ree-1.8.7-2011.03 --default</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.mixu.net/2011/11/10/my-arch-linux-setup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementing Facebook login (part 3)</title>
		<link>http://blog.mixu.net/2011/01/09/implementing-facebook-login-part-3/</link>
		<comments>http://blog.mixu.net/2011/01/09/implementing-facebook-login-part-3/#comments</comments>
		<pubDate>Sun, 09 Jan 2011 12:51:11 +0000</pubDate>
		<dc:creator>Mikito Takada</dc:creator>
				<category><![CDATA[How-to]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.mixu.net/?p=1472</guid>
		<description><![CDATA[Damn Facebook documentation! I finally managed to piece together a better picture &#8211; after first getting all that info in the previous posts (part 1, part 2) &#8211; about how registration and login can be handled. Basically, you can&#8217;t use the registration tool unless you really want to replace your registration dialog with Facebook&#8217;s own [...]]]></description>
			<content:encoded><![CDATA[<p>Damn Facebook documentation! I finally managed to piece together a better picture &#8211; after first getting all that info in the previous posts (<a href="http://blog.mixu.net/2010/12/27/implementing-facebook-login-single-sign-on-part-1/">part 1</a>, <a href="http://blog.mixu.net/2011/01/03/implementing-facebook-login-part-2/">part 2</a>) &#8211; about how registration and login can be handled.</p>
<p>Basically, you can&#8217;t use the registration tool unless you really want to replace your registration dialog with Facebook&#8217;s own version. You can&#8217;t redirect to it conditionally, e.g. if the user has Facebook and clicks the login button, since the login will already trigger the Facebook authorization process.</p>
<p>So unless you want two logins (Facebook login link and regular login form) and two registration links (regular registration page and Facebook register page), you can&#8217;t use the registration tool. My ideal implementation would just have a single link for everything related to Facebook, but present the full registration form if the user clicks it and has not yet registered with my site&#8230; no luck.</p>
<p>Hence, I will do this the traditional way:</p>
<ul>
<li>Use the Javascript SDK to render the Facebook Login link and popup.</li>
<li>Ask for additional permissions on the Login.</li>
<li>When the authorization returns, process the user login / registration.</li>
<li>If the user wants to register using Facebook, then they will still need to fill in additional fields in a separate field after authorizing the information we can read from Facebook.</li>
</ul>
<h2>Preparations</h2>
<p><strong>Get an app_id and a secret from Facebook. </strong><a href="http://developers.facebook.com/setup/">Register your website/app here</a> to get an app_id and secret.</p>
<p><strong>Add the Facebook namespace.</strong> Your HTML tag should contain the additional xmlns:fb -attribute so that the Facebook custom tags work with IE:</p>
<div id="wpshdo_1" class="wp-synhighlighter-outer"><div id="wpshdt_1" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_1"></a><a id="wpshat_1" class="wp-synhighlighter-title" href="#codesyntax_1"  onClick="javascript:wpsh_toggleBlock(1)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_1" onClick="javascript:wpsh_code(1)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_1" onClick="javascript:wpsh_print(1)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_1" class="wp-synhighlighter-inner" style="display: block;"><div class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>html xmlns<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;http://www.w3.org/1999/xhtml&quot;</span> xmlns<span style="color: #339933;">:</span>fb<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;http://www.facebook.com/2008/fbml&quot;</span><span style="color: #339933;">&gt;</span></div></div></div>
<p>I did not know you could add XML namespaces to your documents and actually have custom tags which work in all current browsers, but since Facebook does it, it must have been tested well.</p>
<h2>Rendering the Facebook login link and popup</h2>
<div id="wpshdo_2" class="wp-synhighlighter-outer"><div id="wpshdt_2" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_2"></a><a id="wpshat_2" class="wp-synhighlighter-title" href="#codesyntax_2"  onClick="javascript:wpsh_toggleBlock(2)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_2" onClick="javascript:wpsh_code(2)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_2" onClick="javascript:wpsh_print(2)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_2" class="wp-synhighlighter-inner" style="display: block;"><div class="php" style="font-family:monospace;">&lt;div id=&quot;fb-root&quot;&gt;&lt;/div&gt;<br />
&lt;script&gt;<br />
&nbsp; &nbsp; window.fbAsyncInit = function() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; FB.init({<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; appId &nbsp; : '<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$facebook</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAppId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>',<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; session : <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <a href="http://www.php.net/json_encode"><span style="color: #990000;">json_encode</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$session</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>, // don't refetch the session when PHP already has it<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; status &nbsp;: true, // check login status<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cookie &nbsp;: true, // enable cookies to allow the server to access the session<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xfbml &nbsp; : true // parse XFBML<br />
&nbsp; &nbsp; });<br />
&nbsp; &nbsp; // whenever the user logs in, we tell our login service<br />
&nbsp; &nbsp; FB.Event.subscribe('auth.login', function() {<br />
&nbsp; &nbsp; &nbsp; &nbsp;window.location = &quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> URL<span style="color: #339933;">::</span><span style="color: #004000;">site</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/user/fb_login'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;;<br />
&nbsp; &nbsp; });<br />
&nbsp; };<br />
<br />
&nbsp; (function() {<br />
&nbsp; &nbsp; var e = document.createElement('script');<br />
&nbsp; &nbsp; e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';<br />
&nbsp; &nbsp; e.async = true;<br />
&nbsp; &nbsp; document.getElementById('fb-root').appendChild(e);<br />
&nbsp; }());<br />
&lt;/script&gt;</div></div></div>
<h2>Asking for additional permissions</h2>
<p>You have to do this by adding the perms attribute to the fb:login-button tag. The links in the docs are broken, but <a href="http://developers.facebook.com/docs/reference/plugins/login">here is the page documenting the login button</a> and the <a href="http://developers.facebook.com/docs/authentication/permissions/">extended permissions you can ask for are listed here</a>.</p>
<p>We&#8217;ll just ask for the email address:</p>
<div id="wpshdo_3" class="wp-synhighlighter-outer"><div id="wpshdt_3" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_3"></a><a id="wpshat_3" class="wp-synhighlighter-title" href="#codesyntax_3"  onClick="javascript:wpsh_toggleBlock(3)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_3" onClick="javascript:wpsh_code(3)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_3" onClick="javascript:wpsh_print(3)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_3" class="wp-synhighlighter-inner" style="display: block;"><div class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>fb<span style="color: #339933;">:</span>login<span style="color: #339933;">-</span>button perms<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;email&quot;</span> size<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;large&quot;</span><span style="color: #339933;">&gt;&lt;/</span>fb<span style="color: #339933;">:</span>login<span style="color: #339933;">-</span>button<span style="color: #339933;">&gt;</span></div></div></div>
<h2>Processing the resulting login or registration</h2>
<p>As you can see above, we subscribe to the auth.login event using Javascript and specify that on completion, the user will be redirected to /user/fb_login/.</p>
<p>On that page, we need to:</p>
<ol>
<li>Check whether a user account exists with the returned Facebook user id.</li>
<li>If no user is found with the FB uid, retrieve the user&#8217;s email via the Graph API and check whether a user exists with that email. If so, we will merge the user.</li>
<li>If no user is found with the FB email, create a new account.</li>
<li>If creating a new user fails, then accept defeat and show the regular registration page.</li>
</ol>
<p>A complete implementation of this available from Bitbucket &#8211; soon! I&#8217;m releasing it as part of my Useradmin module for Kohana 3.</p>
<h2>Logging out</h2>
<p>We need to handle logging out sensibly. I prefer that the user explicitly clicks a login button if they do not currently have a session with our application. Automatic relogin is confusing, particularly when logging out usually redirects to the login page.</p>
<p>So we need to handle the case where the person is connected (logged in to Facebook and authorized with us) by displaying a custom login button.</p>
<p>You can find the Facebook logo from the branding site. Of course, a Google search for facebook logo won&#8217;t find it, so <a href="http://www.facebook.com/brandpermissions/logos.php">click here to get the image</a> that you are allowed to use for this purpose.</p>
<div id="wpshdo_4" class="wp-synhighlighter-outer"><div id="wpshdt_4" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_4"></a><a id="wpshat_4" class="wp-synhighlighter-title" href="#codesyntax_4"  onClick="javascript:wpsh_toggleBlock(4)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_4" onClick="javascript:wpsh_code(4)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_4" onClick="javascript:wpsh_print(4)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_4" class="wp-synhighlighter-inner" style="display: block;"><div class="javascript" style="font-family:monospace;">window.<span style="color: #660066;">fbAsyncInit</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; FB.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; appId &nbsp; <span style="color: #339933;">:</span> <span style="color: #3366CC;">'&lt;?php echo Kohana::config('</span>facebook<span style="color: #3366CC;">')-&gt;app_id; ?&gt;'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">status</span> &nbsp;<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// check login status</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cookie &nbsp;<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// enable cookies to allow the server to access the session</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xfbml &nbsp; <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span> <span style="color: #006600; font-style: italic;">// parse XFBML</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// whenever the user logs in, we tell our login service</span><br />
&nbsp; &nbsp; FB.<span style="color: #660066;">Event</span>.<span style="color: #660066;">subscribe</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'auth.login'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;window.<span style="color: #660066;">location</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;&lt;?php echo URL::site('/user/fb_login') ?&gt;&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// if the user is already logged in, redirect them to the login action</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// they cannot reach the login page if they are already logged in</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// since login() redirects to profile if the user is logged in</span><br />
&nbsp; &nbsp;FB.<span style="color: #660066;">getLoginStatus</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>response.<span style="color: #000066;">status</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'connected'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'fb-login-li'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;a href=&quot;&lt;?php echo URL::site('</span><span style="color: #339933;">/</span>user<span style="color: #339933;">/</span>fb_login<span style="color: #3366CC;">') ?&gt;&quot;&gt;&lt;img src=&quot;/img/fb-login.png&quot;&gt;&lt;/a&gt;'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'fb-login-li'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">innerHTML</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;fb:login-button perms=&quot;email&quot; size=&quot;large&quot;&gt;&lt;?php echo __('</span>Login <span style="color: #339933;">/</span> Register <span style="color: #000066; font-weight: bold;">with</span> Facebook<span style="color: #3366CC;">')?&gt;&lt;/fb:login-button&gt;'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; FB.<span style="color: #660066;">XFBML</span>.<span style="color: #660066;">parse</span><span style="color: #009900;">&#40;</span>document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'fb-login-li'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></div></div>
<h2>Appendix: all fb:login-button attributes</h2>
<p>The Facebook documentation does not list the fb:login-button attributes, which is infuriating. I found a forum post (<a href="http://forum.developers.facebook.net/viewtopic.php?id=72137">here</a>), which documents the optional attributes of fb:login-button:</p>
<ul>
<li><strong>condition</strong>; string Indicates whether the button is visible or hidden.</li>
<li><strong>size</strong>; string Specifies the size of the button. Specify icon to display a favicon only, or small, medium, large, or xlarge. (Default value is medium.)</li>
<li><strong>autologoutlink</strong>; bool If true and the user is already connected and has a session, then the button image changes to indicate the user can log out. Clicking the button logs the user out of Facebook and all connected sessions. (Default value is false.)</li>
<li><strong>background</strong>; string Specifies the button image to use that is anti-aliased to match the background of your site &#8212; whether it&#8217;s pure white, light, or dark. Specify white, dark, or light. (Default value is light.) Note: You don&#8217;t specify this attribute if you are using v=&#8221;2&#8243;.</li>
<li><strong>length</strong>; string Specifies which text label to use on a button with size specified as small, medium, large, or xlarge. Specify short for the text label Connect only or long for the text label Connect with Facebook. If you are rendering the login button text by including it within the fb:login-button tags, you don&#8217;t specify a length at all. (Default value is short.)</li>
<li><strong>onlogin</strong>;     string JavaScript code to execute when the user gains a Facebook session (that is, after logging into Facebook and authorizing the site).</li>
<li><strong>v</strong>;     string Specify &#8220;2&#8243; to use the latest Facebook Connect login buttons, (examples available in the Facebook Connect wizard). Don&#8217;t use the attribute if you need to use the original Facebook Connect login buttons.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.mixu.net/2011/01/09/implementing-facebook-login-part-3/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Nginx, php-fpm and node.js install on Centos 5.5</title>
		<link>http://blog.mixu.net/2011/01/04/nginx-php-fpm-and-node-js-install-on-centos-5-5/</link>
		<comments>http://blog.mixu.net/2011/01/04/nginx-php-fpm-and-node-js-install-on-centos-5-5/#comments</comments>
		<pubDate>Tue, 04 Jan 2011 18:04:47 +0000</pubDate>
		<dc:creator>Mikito Takada</dc:creator>
				<category><![CDATA[How-to]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.mixu.net/?p=1527</guid>
		<description><![CDATA[After some time with node.js I recently decided to move to nginx + php-fpm + node.js for my future servers. Here we will be installing: Nginx as a fast HTTP server with reverse proxy to node.js php-fpm for running PHP scripts. The php-fpm (PHP FastCGI sapi) is built into the PHP core but only since [...]]]></description>
			<content:encoded><![CDATA[<p>After some time with node.js I recently decided to move to nginx + php-fpm + node.js for my future servers. Here we will be installing:</p>
<ul>
<li>Nginx as a fast HTTP server with reverse proxy to node.js</li>
<li>php-fpm for running PHP scripts. The php-fpm (PHP FastCGI sapi) is built into the PHP core but only since 5.3.3, so we need a recent version of PHP.</li>
<li>node.js for handling comet and high-concurrency/persistent connections.</li>
<li>Monit is used to restart node.js in case of errors.</li>
</ul>
<p>For all the packages other than node.js (obviously, since it&#8217;s new/actively changing), you can get the most recent version without to patching/compiling anything anymore.</p>
<p>Start by updating your packages and uninstalling httpd if you had it installed:</p>
<pre>yum update</pre>
<pre>yum remove httpd</pre>
<h2>Add repositories for nginx and PHP-fpm</h2>
<p>Just add the EPEL and Remi repos:</p>
<div id="wpshdo_5" class="wp-synhighlighter-outer"><div id="wpshdt_5" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_5"></a><a id="wpshat_5" class="wp-synhighlighter-title" href="#codesyntax_5"  onClick="javascript:wpsh_toggleBlock(5)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_5" onClick="javascript:wpsh_code(5)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_5" onClick="javascript:wpsh_print(5)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_5" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;">rpm <span style="color: #660033;">-Uvh</span> http:<span style="color: #000000; font-weight: bold;">//</span>download.fedora.redhat.com<span style="color: #000000; font-weight: bold;">/</span>pub<span style="color: #000000; font-weight: bold;">/</span>epel<span style="color: #000000; font-weight: bold;">/</span>5<span style="color: #000000; font-weight: bold;">/</span>i386<span style="color: #000000; font-weight: bold;">/</span>epel-release-5-4.noarch.rpm<br />
rpm <span style="color: #660033;">-Uvh</span> http:<span style="color: #000000; font-weight: bold;">//</span>rpms.famillecollet.com<span style="color: #000000; font-weight: bold;">/</span>enterprise<span style="color: #000000; font-weight: bold;">/</span>remi-release-5.rpm</div></div></div>
<h2>Install nginx and PHP-fpm</h2>
<div>Remi has the php-fpm package (php 5.3.4); EPEL has nginx:</div>
<div id="wpshdo_6" class="wp-synhighlighter-outer"><div id="wpshdt_6" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_6"></a><a id="wpshat_6" class="wp-synhighlighter-title" href="#codesyntax_6"  onClick="javascript:wpsh_toggleBlock(6)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_6" onClick="javascript:wpsh_code(6)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_6" onClick="javascript:wpsh_print(6)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_6" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;">yum <span style="color: #660033;">--enablerepo</span>=remi <span style="color: #c20cb9; font-weight: bold;">install</span> php-fpm nginx</div></div></div>
<div>Some other common packages:</div>
<div id="wpshdo_7" class="wp-synhighlighter-outer"><div id="wpshdt_7" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_7"></a><a id="wpshat_7" class="wp-synhighlighter-title" href="#codesyntax_7"  onClick="javascript:wpsh_toggleBlock(7)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_7" onClick="javascript:wpsh_code(7)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_7" onClick="javascript:wpsh_print(7)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_7" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;">yum <span style="color: #660033;">--enablerepo</span>=remi <span style="color: #c20cb9; font-weight: bold;">install</span> mysql mysql-server php-mysql php-common php-gd php-mbstring php-mcrypt php-xml php-gd php-bcmath</div></div></div>
<p>PHPunit and PHPdocumentor:<br />
<div id="wpshdo_8" class="wp-synhighlighter-outer"><div id="wpshdt_8" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_8"></a><a id="wpshat_8" class="wp-synhighlighter-title" href="#codesyntax_8"  onClick="javascript:wpsh_toggleBlock(8)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_8" onClick="javascript:wpsh_code(8)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_8" onClick="javascript:wpsh_print(8)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_8" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;">yum <span style="color: #660033;">--enablerepo</span>=remi <span style="color: #c20cb9; font-weight: bold;">install</span> php-channel-phpunit php-pear-PhpDocumentor php-phpunit-PHPUnit</div></div></div></p>
<h2>Create a test application</h2>
<pre>mkdir /var/www/</pre>
<p>In /var/www/index.php:</p>
<div id="wpshdo_9" class="wp-synhighlighter-outer"><div id="wpshdt_9" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_9"></a><a id="wpshat_9" class="wp-synhighlighter-title" href="#codesyntax_9"  onClick="javascript:wpsh_toggleBlock(9)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_9" onClick="javascript:wpsh_code(9)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_9" onClick="javascript:wpsh_print(9)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_9" class="wp-synhighlighter-inner" style="display: block;"><div class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
&nbsp; <a href="http://www.php.net/phpinfo"><span style="color: #990000;">phpinfo</span></a><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div></div>
<h2>Configure nginx</h2>
<div>In /etc/nginx/nginx.conf:</div>
<div id="wpshdo_10" class="wp-synhighlighter-outer"><div id="wpshdt_10" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_10"></a><a id="wpshat_10" class="wp-synhighlighter-title" href="#codesyntax_10"  onClick="javascript:wpsh_toggleBlock(10)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_10" onClick="javascript:wpsh_code(10)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_10" onClick="javascript:wpsh_print(10)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_10" class="wp-synhighlighter-inner" style="display: block;"><div class="php" style="font-family:monospace;">server <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;listen &nbsp; &nbsp; &nbsp; <span style="color: #cc66cc;">80</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;server_name &nbsp;_<span style="color: #339933;">;</span><br />
&nbsp; &nbsp;access_log &nbsp;logs<span style="color: #339933;">/</span>host<span style="color: #339933;">.</span>access<span style="color: #339933;">.</span><a href="http://www.php.net/log"><span style="color: #990000;">log</span></a> &nbsp;main<span style="color: #339933;">;</span><br />
&nbsp; &nbsp;root &nbsp; <span style="color: #339933;">/</span><span style="color: #000000; font-weight: bold;">var</span><span style="color: #339933;">/</span>www<span style="color: #339933;">;</span><br />
&nbsp; &nbsp;index &nbsp;index<span style="color: #339933;">.</span>php index<span style="color: #339933;">.</span>html index<span style="color: #339933;">.</span>htm<span style="color: #339933;">;</span><br />
&nbsp; &nbsp;location ~ \<span style="color: #339933;">.</span>php$ <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;"># Security: must set cgi.fixpathinfo to 0 in php.ini!<br />
</span> &nbsp; &nbsp; &nbsp;fastcgi_split_path_info ^<span style="color: #009900;">&#40;</span><span style="color: #339933;">.+</span>\<span style="color: #339933;">.</span>php<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">/.+</span><span style="color: #009900;">&#41;</span>$<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; fastcgi_pass 127<span style="color: #339933;">.</span>0<span style="color: #339933;">.</span>0<span style="color: #339933;">.</span>1<span style="color: #339933;">:</span><span style="color: #cc66cc;">9000</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; fastcgi_index index<span style="color: #339933;">.</span>php<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; fastcgi_param SCRIPT_FILENAME &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$document_root</span><span style="color: #000088;">$fastcgi_script_name</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; fastcgi_param PATH_INFO <span style="color: #000088;">$fastcgi_path_info</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">include</span> <span style="color: #339933;">/</span>etc<span style="color: #339933;">/</span>nginx<span style="color: #339933;">/</span>fastcgi_params<span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div></div>
<p><strong>Default fastcgi_params</strong></p>
<p>I start the php location by including /etc/nginx/fastcgi_params. This is because I want to use those as defaults, then override them individually afterwards. It is also recommended to have one root directive per server.</p>
<p><strong>PHP path</strong></p>
<p>I  use fastcgi_split_path_info which became available in 0.7.31 to pass PATH_INFO.</p>
<p><strong>Security settings</strong></p>
<p>IMPORTANT: Change cgi.fix_pathinfo to 0 in php.ini to prevent a <a href="http://cnedelcu.blogspot.com/2010/05/nginx-php-via-fastcgi-important.html">security issue</a> which arises with the default PHP configuration when PHP incorrectly tries to guess which file you want for URLS specifying nonexistent files. Setting cgi.fix_pathinfo=0 causes PHP to only try the literal path given. Alternatively check that the file exists: if (!-f $request_filename) { return 404; }</p>
<p>See also: <a href="http://wiki.nginx.org/Pitfalls">Nginx pitfalls</a>.</p>
<h2>Start/restart and test</h2>
<pre>service php-fpm start</pre>
<pre>service nginx restart</pre>
<p>Test by going to your server root, it should show you your phpinfo().</p>
<h2>Prepare to install node.js</h2>
<p>Excellent post: <a href="http://wavded.tumblr.com/post/475957278/hosting-nodejs-apps-on-centos-5">http://wavded.tumblr.com/post/475957278/hosting-nodejs-apps-on-centos-5</a></p>
<p>Add a user for node.js:<br />
<div id="wpshdo_11" class="wp-synhighlighter-outer"><div id="wpshdt_11" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_11"></a><a id="wpshat_11" class="wp-synhighlighter-title" href="#codesyntax_11"  onClick="javascript:wpsh_toggleBlock(11)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_11" onClick="javascript:wpsh_code(11)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_11" onClick="javascript:wpsh_print(11)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_11" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;">groupadd <span style="color: #660033;">-r</span> node<br />
useradd <span style="color: #660033;">-r</span> <span style="color: #660033;">--shell</span> <span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">bash</span> <span style="color: #660033;">--comment</span> <span style="color: #ff0000;">'User for running node.js'</span> <span style="color: #660033;">-g</span> node  --home <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>node node</div></div></div><br />
I prefer using /var/lib/node rather than /home/node because this is more in line with how other server daemon users are defined (e.g. nginx, mysql). -r is for &#8211;system, &#8211;comment is for &#8211;gecos.</p>
<h2>Install node.js</h2>
<div id="wpshdo_12" class="wp-synhighlighter-outer"><div id="wpshdt_12" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_12"></a><a id="wpshat_12" class="wp-synhighlighter-title" href="#codesyntax_12"  onClick="javascript:wpsh_toggleBlock(12)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_12" onClick="javascript:wpsh_code(12)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_12" onClick="javascript:wpsh_print(12)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_12" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;">yum <span style="color: #c20cb9; font-weight: bold;">install</span> gcc-c++ openssl-devel<br />
<span style="color: #c20cb9; font-weight: bold;">wget</span> <span style="color: #660033;">--no-check-certificate</span> https:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>ry<span style="color: #000000; font-weight: bold;">/</span>node<span style="color: #000000; font-weight: bold;">/</span>tarball<span style="color: #000000; font-weight: bold;">/</span>v0.3.3<br />
<span style="color: #c20cb9; font-weight: bold;">tar</span> -xzvf ry-node-v0.3.3-0-g57544ba.tar.gz<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> ry-node-v0.3.3-0-g57544bac1<br />
.<span style="color: #000000; font-weight: bold;">/</span>configure<br />
<span style="color: #c20cb9; font-weight: bold;">make</span><br />
<span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span><br />
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>node</div></div></div>
<h2>Create a test application</h2>
<div>For node.js apps, I prefer to keep the www and node trees separate. Also note that I am running unstable 0.3.3 not 0.2.x, so the example is slightly different. Create the example file /var/node/hello_world/example.js:</div>
<div>
<div id="wpshdo_13" class="wp-synhighlighter-outer"><div id="wpshdt_13" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_13"></a><a id="wpshat_13" class="wp-synhighlighter-title" href="#codesyntax_13"  onClick="javascript:wpsh_toggleBlock(13)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_13" onClick="javascript:wpsh_code(13)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_13" onClick="javascript:wpsh_print(13)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_13" class="wp-synhighlighter-inner" style="display: block;"><div class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> sys <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;sys&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp;http <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;http&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
http.<span style="color: #660066;">createServer</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>request<span style="color: #339933;">,</span> response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; response.<span style="color: #660066;">writeHead</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">200</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;Content-Type&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;text/plain&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; response.<span style="color: #660066;">end</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Hello World<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span>8000<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
sys.<span style="color: #660066;">puts</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Server running at 127.0.0.1:8000&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div></div>
</div>
<h2>Configure nginx for node.js (subdirectory approach)</h2>
<div>In /etc/nginx/nginx.conf (after the server definition has started):</div>
<div>
<div id="wpshdo_14" class="wp-synhighlighter-outer"><div id="wpshdt_14" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_14"></a><a id="wpshat_14" class="wp-synhighlighter-title" href="#codesyntax_14"  onClick="javascript:wpsh_toggleBlock(14)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_14" onClick="javascript:wpsh_code(14)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_14" onClick="javascript:wpsh_print(14)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_14" class="wp-synhighlighter-inner" style="display: block;"><div class="javascript" style="font-family:monospace;">location <span style="color: #339933;">/</span>node <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;proxy_set_header X<span style="color: #339933;">-</span>Real<span style="color: #339933;">-</span>IP $remote_addr<span style="color: #339933;">;</span><br />
&nbsp; &nbsp;proxy_set_header X<span style="color: #339933;">-</span>Forwarded<span style="color: #339933;">-</span><span style="color: #000066; font-weight: bold;">For</span> $proxy_add_x_forwarded_for<span style="color: #339933;">;</span><br />
&nbsp; &nbsp;proxy_set_header Host $http_host<span style="color: #339933;">;</span><br />
&nbsp; &nbsp;proxy_set_header X<span style="color: #339933;">-</span>NginX<span style="color: #339933;">-</span>Proxy <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;proxy_pass http<span style="color: #339933;">:</span><span style="color: #006600; font-style: italic;">//127.0.0.1:8000/;</span><br />
&nbsp; &nbsp;proxy_redirect off<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div></div></span></pre>
</div>
<h2>Install monit</h2>
<pre>yum install monit</pre>
<h2>Create monit script</h2>
<p>/etc/monit.d/hello_world content:</p>
<p><div id="wpshdo_15" class="wp-synhighlighter-outer"><div id="wpshdt_15" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_15"></a><a id="wpshat_15" class="wp-synhighlighter-title" href="#codesyntax_15"  onClick="javascript:wpsh_toggleBlock(15)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_15" onClick="javascript:wpsh_code(15)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_15" onClick="javascript:wpsh_print(15)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_15" class="wp-synhighlighter-inner" style="display: block;"><div class="php" style="font-family:monospace;">check host hello_world with address 127<span style="color: #339933;">.</span>0<span style="color: #339933;">.</span>0<span style="color: #339933;">.</span>1<br />
&nbsp; &nbsp; start program <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;/usr/local/bin/node /var/node/hello_world/example.js&quot;</span> <span style="color: #b1b100;">as</span> uid node and gid node<br />
&nbsp; &nbsp; stop program &nbsp;<span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;/usr/bin/pkill -f 'node /var/node/hello_world/example.js'&quot;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> failed port <span style="color: #cc66cc;">8000</span> protocol HTTP<br />
&nbsp; &nbsp; &nbsp; &nbsp; request <span style="color: #339933;">/</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; with timeout <span style="color: #cc66cc;">10</span> seconds<br />
&nbsp; &nbsp; &nbsp; &nbsp; then restart</div></div></div>
<h2>Start/restart and test</h2>
<pre>service monit start</pre>
<pre>service nginx restart</pre>
<p>Test by going to /node on your server.</p>
<p>Also, run ps -Af to verify that node is running with the uid node.</p>
<h2>The reboot test</h2>
<p>Finally, test everything by restarting your server. A friendly reminder:</p>
<p>chkconfig nginx on</p>
<p>chkconfig monit on</p>
<p>chkconfig php-fpm on</p>
<p>chkconfig mysqld on</p>
<p>chkconfig &#8211;list</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mixu.net/2011/01/04/nginx-php-fpm-and-node-js-install-on-centos-5-5/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Implementing Facebook login / single sign-on (part 1)</title>
		<link>http://blog.mixu.net/2010/12/27/implementing-facebook-login-single-sign-on-part-1/</link>
		<comments>http://blog.mixu.net/2010/12/27/implementing-facebook-login-single-sign-on-part-1/#comments</comments>
		<pubDate>Mon, 27 Dec 2010 16:59:22 +0000</pubDate>
		<dc:creator>Mikito Takada</dc:creator>
				<category><![CDATA[How-to]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.mixu.net/?p=1393</guid>
		<description><![CDATA[I am implementing Facebook single sign on for my applications. In this first part of my Facebook authentication tutorial, I discuss the basics of the Facebook authentication process (see also: part 2, part 3). Getting started: some terminology If you are like me and haven&#8217;t implemented Facebook integration before, the terminology and various API&#8217;s can [...]]]></description>
			<content:encoded><![CDATA[<p>I am implementing Facebook single sign on for my applications. In this first part of my Facebook authentication tutorial, I discuss the basics of the Facebook authentication process (see also: <a href="http://blog.mixu.net/2011/01/03/implementing-facebook-login-part-2/">part 2</a>, <a href="http://blog.mixu.net/2011/01/09/implementing-facebook-login-part-3/">part 3</a>).</p>
<h2>Getting started: some terminology</h2>
<p>If you are like me and haven&#8217;t implemented Facebook integration before, the terminology and various API&#8217;s can be confusing. And the Facebook developer documentation is a combination of too-much-information and not-enough-explanation.</p>
<p>First, the Facebook documentation talks about different kinds of applications, which are:</p>
<ul>
<li><strong>Facebook canvas applications</strong>: Applications-within-Facebook, or what users think of as &#8220;Facebook apps&#8221;.
<ul>
<li>FBML / FBJS apps (built using FB-specific markup)</li>
<li>Iframe canvas apps (built using Javascript and the FB JS API)</li>
</ul>
</li>
<li><strong>Facebook desktop applications</strong> (rare; basically anything that cannot run within a browser, like a desktop client for Facebook)</li>
<li><strong>Facebook web applications</strong> (websites with Facebook-integration such as single sign-on and custom Facebook elements within them such as CNN and Digg)</li>
</ul>
<p>And there are multiple developer tools that Facebook offers:</p>
<ul>
<li><strong>Facebook Connect</strong> &#8211; no such thing exists anymore (e.g. <a href="http://mashable.com/2010/04/21/facebook-kills-facebook-connect/">http://mashable.com/2010/04/21/facebook-kills-facebook-connect/</a>). The new API is called the Graph API, and talking about Facebook Connect is inaccurate..</li>
<li><strong>APIs</strong> (always used, either on the server side or on the client&#8217;s web browser via Javascript)
<ul>
<li><strong>Graph API</strong>: The new version of Facebook&#8217;s API. The Graph API is much more than just authentication: it is the mechanism which powers Facebook applications and allows you to read and write date to Facebook.</li>
<li><strong>Old REST API</strong>: The early version of Facebook&#8217;s Graph API; Facebook does not recommend you use it because they are in the process of deprecating it.</li>
<li><strong>FQL</strong> (Facebook Query Language): A SQL-like language for querying the Graph API. Supposedly makes using the API easier for apps.</li>
</ul>
</li>
<li><strong>Markup </strong>
<ul>
<li><strong>FBML</strong> (Facebook Markup Language): A HTML-like language for building Facebook applications. FBML is rendered on the Facebook server. Facebook does not recommend that you use it; instead suggesting that you use the Graph API via their Javascript SDK with XFBML.</li>
<li><strong>XFBML</strong>: FBML-within-(X)HTML pages rendered using Facebook&#8217;s Javascript SDK.</li>
</ul>
</li>
<li><strong>SDKs </strong>
<ul>
<li>Language-specific libraries for querying the API. Other than the Javascript SDK, it&#8217;s all server-side and based on HTTP requests.</li>
<li>Note that the Javascript SDK allows you to render XFBML embedded on a (X)HTML page! This was confusing because I had done something with FBML before, and didn&#8217;t see where exactly the transformation from fb:login-button to HTML was occurring&#8230;</li>
</ul>
</li>
<li><strong>Other stuff from Facebook: </strong>
<ul>
<li><strong>Open Graph Protocol</strong>: A convention of meta and other tags which allows you to add metadata to Like button clicks, integrating them with Facebook (e.g. a like on a profile).</li>
<li><strong>Social plugins</strong>: Ready-made Facebook widgets you can embed using an iframe.</li>
</ul>
</li>
</ul>
<h2>How does Facebook authentication work?</h2>
<p>Conceptually, it works like this (picture of user represents page shown to user):</p>
<p><a href="http://blog.mixu.net/files/2010/12/facebook.png"><img class="alignnone size-full wp-image-1446" title="facebook" src="http://blog.mixu.net/files/2010/12/facebook.png" alt="" width="471" height="581" /></a></p>
<p>There most important authentication methods are:</p>
<ol>
<li><strong>Javascript single sign-on</strong>: The Javascript single sign-on is simplest, because it provides a function (FB.login) which handles everything from the details of OAuth 2.0 requests to rendering the actual login button. When using the Javascript API, the user id and access token are stored in a cookie (e.g. fbs_app_id) which you can access both server-side and via Javascript in the client.</li>
<li><strong>web application authentication (using server side SDK&#8217;s)</strong>: When you do web application authentication, you need redirect the user to Facebook in your app. When the user allows access for your app, Facebook redirects them back and sends the access token and user ID as part of the GET request to your authentication-complete redirection page. Then you can access the user&#8217;s information using the returned token.</li>
</ol>
<h2>Next part</h2>
<p><a href="http://blog.mixu.net/2011/01/03/implementing-facebook-login-part-2/">In part 2 of my Facebook login tutorial</a> I address database design considerations and look at how Facebook login can be integrated with your existing user management.</p>
<p><a href="http://blog.mixu.net/2011/01/09/implementing-facebook-login-part-3/">In part 3 of my Facebook login tutorial</a> I go into implementation specifics using the Javascript SDK.</p>
<p><strong>References</strong></p>
<ul>
<li><a href="http://developers.facebook.com/docs/">http://developers.facebook.com/docs/</a></li>
<li><a href="http://developers.facebook.com/docs/guides/performance">http://developers.facebook.com/docs/guides/performance</a> (good illustration on the difference between FBML and IFrame applications)</li>
<li><a href="http://stackoverflow.com/questions/1175047/facebook-app-vs-facebook-connect-site">http://stackoverflow.com/questions/1175047/facebook-app-vs-facebook-connect-site</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.mixu.net/2010/12/27/implementing-facebook-login-single-sign-on-part-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How to deploy web applications using Mercurial</title>
		<link>http://blog.mixu.net/2010/12/01/how-to-deploy-web-applications-using-mercurial/</link>
		<comments>http://blog.mixu.net/2010/12/01/how-to-deploy-web-applications-using-mercurial/#comments</comments>
		<pubDate>Wed, 01 Dec 2010 08:49:50 +0000</pubDate>
		<dc:creator>Mikito Takada</dc:creator>
				<category><![CDATA[How-to]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.mixu.net/?p=1351</guid>
		<description><![CDATA[Does deploying changes to your site take too long? Are you tired of manually sorting out the update? Here is how to deploy your projects using Mercurial. Why? Ease of updating. Mercurial keeps track of the changes and only sends the necessary changes -  you don&#8217;t need to worry about transferring files. Make it possible to [...]]]></description>
			<content:encoded><![CDATA[<p>Does deploying changes to your site take too long? Are you tired of manually sorting out the update? Here is how to deploy your projects using Mercurial.</p>
<p><strong>Why?</strong></p>
<ul>
<li>Ease of updating. Mercurial keeps track of the changes and only sends the necessary changes -  you don&#8217;t need to worry about transferring files.</li>
<li>Make it possible to roll back changes on the deployed site. You can use hg to roll back from a bad update if necessary.</li>
<li>Once set up, it&#8217;s beautiful. &#8220;hg deploy&#8221;. How can you not like that?</li>
</ul>
<p>How is this different from <a href="http://blog.mixu.net/2010/10/04/setting-up-private-ssh-based-mercurial-repo-hosting-on-centos/">the other guide you wrote about setting up private repo hosting</a>?</p>
<ul>
<li>While the differences aren&#8217;t that big, this setup is better for <em>deployment </em>rather than <em>code distribution via repositories</em>:
<ul>
<li>Minimal dependencies. This approach only uses the hg-ssh script from the Mercurial core contrib.</li>
<li>Manual configuration. You can set different directories for each repository which allows you to work with your existing webroot setup. However, you will need to manually add new repositories, since hg-ssh does not support adding new repositories remotely.</li>
</ul>
</li>
</ul>
<p>If you want a private version of Bitbucket (without any additional features, of course), e.g.  to be able to remotely init/clone new repositories, <a href="http://blog.mixu.net/2010/10/04/setting-up-private-ssh-based-mercurial-repo-hosting-on-centos/">check out my other tutorial about setting up private repo hosting</a>.</p>
<h2>1. Make sure that the .hg directories are never served to the public</h2>
<p>To prevent .hg directories from being accessible to other people, you can take a number of (optional, but recommended) precautions:</p>
<p><strong>Move the web root of your project to a different folder</strong></p>
<p>You can probably alter your project  repository so that you have an explicit webroot folder in which you only have the files that should be accessible to the public (bootstrap + js/css resources). This makes it less likely that you accidentally serve your .hg directory. You move the files within hg do this using hg move:</p>
<div id="wpshdo_16" class="wp-synhighlighter-outer"><div id="wpshdt_16" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_16"></a><a id="wpshat_16" class="wp-synhighlighter-title" href="#codesyntax_16"  onClick="javascript:wpsh_toggleBlock(16)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_16" onClick="javascript:wpsh_code(16)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_16" onClick="javascript:wpsh_print(16)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_16" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> webroot<br />
hg move . webroot</div></div></div>
<p>Or you can use hg addremove &#8211;similarity=100 after moving the files manually. It will detect identical files as moved.</p>
<p>After this, you may need to update your apache config to serve from the webroot (e.g. adjust the DocumentRoot directive for the site / virtual host).</p>
<p><strong>Set up Apache not to serve .hg directories</strong></p>
<p>You can also prevent Apache from serving directories with .hg in them by adding the following to your httpd.conf:</p>
<div id="wpshdo_17" class="wp-synhighlighter-outer"><div id="wpshdt_17" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_17"></a><a id="wpshat_17" class="wp-synhighlighter-title" href="#codesyntax_17"  onClick="javascript:wpsh_toggleBlock(17)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_17" onClick="javascript:wpsh_code(17)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_17" onClick="javascript:wpsh_print(17)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_17" class="wp-synhighlighter-inner" style="display: block;"><div class="apache" style="font-family:monospace;">&lt;<span style="color: #000000; font-weight:bold;">DirectoryMatch</span> \.hg&gt;<br />
&nbsp; &nbsp;<span style="color: #00007f;">Order</span> <span style="color: #00007f;">allow</span>,<span style="color: #00007f;">deny</span><br />
&nbsp; &nbsp;<span style="color: #00007f;">Deny</span> from <span style="color: #0000ff;">all</span><br />
&lt;/<span style="color: #000000; font-weight:bold;">DirectoryMatch</span>&gt;</div></div></div>
<p>Restart Apache if you change httpd.conf.</p>
<h2>2. Setup the server</h2>
<p><strong>Create the user</strong></p>
<div id="wpshdo_18" class="wp-synhighlighter-outer"><div id="wpshdt_18" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_18"></a><a id="wpshat_18" class="wp-synhighlighter-title" href="#codesyntax_18"  onClick="javascript:wpsh_toggleBlock(18)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_18" onClick="javascript:wpsh_code(18)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_18" onClick="javascript:wpsh_print(18)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_18" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># make a system user (-r) with a home directory (-m)</span><br />
useradd <span style="color: #660033;">-r</span> <span style="color: #660033;">-m</span> hg<br />
<span style="color: #666666; font-style: italic;"># lock the user account</span><br />
usermod <span style="color: #660033;">-L</span> hg</div></div></div></span></pre>
<div>
<p><strong>Setup ssh<br />
</strong> <div id="wpshdo_19" class="wp-synhighlighter-outer"><div id="wpshdt_19" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_19"></a><a id="wpshat_19" class="wp-synhighlighter-title" href="#codesyntax_19"  onClick="javascript:wpsh_toggleBlock(19)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_19" onClick="javascript:wpsh_code(19)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_19" onClick="javascript:wpsh_print(19)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_19" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#install mercurial if not previously installed</span><br />
yum <span style="color: #c20cb9; font-weight: bold;">install</span> mercurial<br />
<span style="color: #c20cb9; font-weight: bold;">su</span> hg<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>hg<span style="color: #000000; font-weight: bold;">/</span><br />
<span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>www.selenic.com<span style="color: #000000; font-weight: bold;">/</span>repo<span style="color: #000000; font-weight: bold;">/</span>hg-stable<span style="color: #000000; font-weight: bold;">/</span>raw-file<span style="color: #000000; font-weight: bold;">/</span>tip<span style="color: #000000; font-weight: bold;">/</span>contrib<span style="color: #000000; font-weight: bold;">/</span>hg-ssh<br />
<span style="color: #c20cb9; font-weight: bold;">chmod</span> u+x ~hg<span style="color: #000000; font-weight: bold;">/</span>hg-ssh<br />
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>hg<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span><br />
<span style="color: #c20cb9; font-weight: bold;">nano</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>hg<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span>authorized_keys<br />
<span style="color: #666666; font-style: italic;"># remember to chmod the ssh config</span><br />
<span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #660033;">-R</span> 0700 <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>hg<span style="color: #000000; font-weight: bold;">/</span>.ssh<span style="color: #000000; font-weight: bold;">/</span></div></div></div>
<p>Copy the public key: ssh-rsa &#8230;(key data)== to /home/hg/.ssh/authorized_keys, one line for each authorized key.</p>
<p>Add the following in front of each authorized key in /home/hg/.ssh/authorized_keys:</p>
<pre><div id="wpshdo_20" class="wp-synhighlighter-outer"><div id="wpshdt_20" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_20"></a><a id="wpshat_20" class="wp-synhighlighter-title" href="#codesyntax_20"  onClick="javascript:wpsh_toggleBlock(20)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_20" onClick="javascript:wpsh_code(20)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_20" onClick="javascript:wpsh_print(20)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_20" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">command</span>=<span style="color: #ff0000;">&quot;~hg/hg-ssh /path/to/repository&quot;</span>,no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa ...==</div></div></div></pre>
<p>If necessary, enable public key auth in /etc/ssh/sshd_config and add hg to the AllowUsers directive. Restart sshd if you change sshd_config.</p>
<h2>3. Init the repo</h2>
<p><strong>New repo on the remote server</strong></p>
<p>Just run hg init in the new repo folder, then hg clone it on your computer from the remote server:</p>
<pre>hg clone -v --debug ssh://hg@server:port/path/to/repo</pre>
<p>The -v and &#8211;debug make the clone show more information about what is going on.</p>
<p><strong>From existing sources</strong></p>
<p>Unfortunately hg-ssh does not support the hg init/hg clone command remotely. If you have an existing repo, you have to copy it first to the repository directory on the server. Since there are many files to move, I recommend gzipping the whole directory before moving it, then unzipping on the server. Do a hg log and hg status to see that everything transferred correctly.</p>
<p><strong>Adding more repos</strong></p>
<p>To add more repositories, simply add another repository path (separated by a space) immediately after the first repo path in .ssh/authorized_keys, and either init a new repo or copy an existing repo.</p>
<h2>4. Push updates</h2>
<p>After you have the same repository on both the server and locally, you can start pushing  stuff to the server:</p>
<pre><div id="wpshdo_21" class="wp-synhighlighter-outer"><div id="wpshdt_21" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_21"></a><a id="wpshat_21" class="wp-synhighlighter-title" href="#codesyntax_21"  onClick="javascript:wpsh_toggleBlock(21)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_21" onClick="javascript:wpsh_code(21)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_21" onClick="javascript:wpsh_print(21)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_21" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;">hg push <span style="color: #c20cb9; font-weight: bold;">ssh</span>:<span style="color: #000000; font-weight: bold;">//</span>hg<span style="color: #000000; font-weight: bold;">@</span>server:port<span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>relative<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">dir</span></div></div></div></pre>
<p>If your repo path is not relative to the home dir, you need an extra slash in front of the push:</p>
<pre><div id="wpshdo_22" class="wp-synhighlighter-outer"><div id="wpshdt_22" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_22"></a><a id="wpshat_22" class="wp-synhighlighter-title" href="#codesyntax_22"  onClick="javascript:wpsh_toggleBlock(22)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_22" onClick="javascript:wpsh_code(22)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_22" onClick="javascript:wpsh_print(22)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_22" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;">hg push <span style="color: #c20cb9; font-weight: bold;">ssh</span>:<span style="color: #000000; font-weight: bold;">//</span>hg<span style="color: #000000; font-weight: bold;">@</span>server:port<span style="color: #000000; font-weight: bold;">//</span>path<span style="color: #000000; font-weight: bold;">/</span>relative<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>base<span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">dir</span></div></div></div></pre>
<p>If you run into problems, try connecting via ssh &#8211; <a href="http://blog.mixu.net/2010/10/04/setting-up-private-ssh-based-mercurial-repo-hosting-on-centos/">see my previous post for some tips on this</a>.</p>
<h2>5. Automate hg update</h2>
<p>You should automate hg update so that each push causes the repository to be updated automatically to the pushed version. You can automate hg update on the remote repo by adding the following to the remote .hg/hgrc:</p>
<div id="wpshdo_23" class="wp-synhighlighter-outer"><div id="wpshdt_23" class="wp-synhighlighter-expanded"><table border="0" width="100%"><tr><td align="left" width="80%"><a name="#codesyntax_23"></a><a id="wpshat_23" class="wp-synhighlighter-title" href="#codesyntax_23"  onClick="javascript:wpsh_toggleBlock(23)" title="Click to show/hide code block">Source code</a></td><td align="right"><a href="#codesyntax_23" onClick="javascript:wpsh_code(23)" title="Show code only"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/code.png" /></a>&nbsp;<a href="#codesyntax_23" onClick="javascript:wpsh_print(23)" title="Print code"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/printer.png" /></a>&nbsp;<a href="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/About.html" target="_blank" title="Show plugin information"><img border="0" style="border: 0 none" src="http://blog.mixu.net/wp-content/plugins/wp-synhighlight/themes/default/images/info.gif" /></a>&nbsp;</td></tr></table></div><div id="wpshdi_23" class="wp-synhighlighter-inner" style="display: block;"><div class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>hooks<span style="color: #7a0874; font-weight: bold;">&#93;</span><br />
changegroup = hg update <span style="color: #000000; font-weight: bold;">&gt;&amp;</span><span style="color: #000000;">2</span></div></div></div>
<p>Note that output has to be redirected to stderr (or /dev/null), because stdout is used for the data stream -which is why there is the &gt;&amp;2 at the end of the command.</p>
<p>If you get errors in updating automatically, check the permissions. In particular, make sure that .hg/ is owned by hg and that the content is readable by apache.</p>
<h2>6. Set up default push or create an alias</h2>
<p>If you only push to one location, then you can set up the default locations for pull and push in the local  .hg/hgrc:</p>
<pre>[paths]
default = ssh://hg@servername/reponame
default-push = ssh//:hg@servername/reponame</pre>
<p>This allows you to simply use &#8220;hg push&#8221; to deploy.</p>
<p>If you need more than one push location, create an alias in the local  .hg/hgrc:</p>
<pre>[alias]
deploy = push -v --debug ssh://hg@server:port/path/to/repo</pre>
<p>This allows you use &#8220;hg deploy&#8221; as an alias for deploying.</p>
<h2>What about configuration files?</h2>
<p>One simple solution is to use &#8220;hg forget&#8221; to forget them once you have deployed the configuration files. This means that hg will not track the configuration files, but will not delete them either.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.mixu.net/2010/12/01/how-to-deploy-web-applications-using-mercurial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to get Google Docs to full screen view (get rid of the stuff on top of the page)</title>
		<link>http://blog.mixu.net/2010/11/22/how-to-get-google-docs-to-full-screen-view-get-rid-of-the-stuff-on-top-of-the-page/</link>
		<comments>http://blog.mixu.net/2010/11/22/how-to-get-google-docs-to-full-screen-view-get-rid-of-the-stuff-on-top-of-the-page/#comments</comments>
		<pubDate>Mon, 22 Nov 2010 10:33:40 +0000</pubDate>
		<dc:creator>Mikito Takada</dc:creator>
				<category><![CDATA[How-to]]></category>

		<guid isPermaLink="false">http://blog.mixu.net/?p=1339</guid>
		<description><![CDATA[I find that I am using Google Docs a lot more these days. A major annoyance is that the Google logo and other useless tools take up space from the page, so I came up with the following simple bookmarklet: GDocs toggle Just grab the link with your mouse, and drag it to your bookmarks [...]]]></description>
			<content:encoded><![CDATA[<p>I find that I am using Google Docs a lot more these days. <strong>A major annoyance</strong> is that the Google logo and other useless tools take up space from the page, so I came up with the following simple bookmarklet:</p>
<p><a href="javascript:(function(){var elem = document.getElementById(&quot;docs-chrome&quot;);if (elem.style) {elem.style.display = ('' == elem.style.display)? 'none' : '';}})()">GDocs toggle</a></p>
<p>Just grab the link with your mouse, and drag it to your bookmarks bar. Click on it when you have a Google Docs page open, and it will hide / show the extra stuff on top of the page.</p>
<p><strong>Note: You may  have to resize your window once so that the text area expands, press F11 to do this quickly.</strong></p>
<p>I don&#8217;t understand why this isn&#8217;t included as a default feature &#8211; it used to be supported in Google Docs as a menu option.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mixu.net/2010/11/22/how-to-get-google-docs-to-full-screen-view-get-rid-of-the-stuff-on-top-of-the-page/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting up SPF, SenderID and DKIM on Centos 5.3 using sendmail</title>
		<link>http://blog.mixu.net/2009/11/03/setting-up-spf-senderid-and-dkim-on-centos-5-3-using-sendmail/</link>
		<comments>http://blog.mixu.net/2009/11/03/setting-up-spf-senderid-and-dkim-on-centos-5-3-using-sendmail/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 10:52:51 +0000</pubDate>
		<dc:creator>Mikito Takada</dc:creator>
				<category><![CDATA[How-to]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.mixu.net/?p=510</guid>
		<description><![CDATA[The biggest four email providers Gmail, AOL, Hotmail and Yahoo (in this order according to Comscore) all implement some form of anti-spam techniques. The main technologies are reverse DNS checking, SPF, SenderID, Domainkeys and DKIM. I will discuss all of these here and provide my tips on setting up SPF, SenderID and DKIM. Please keep in mind [...]]]></description>
			<content:encoded><![CDATA[<p>The biggest four email providers Gmail, AOL, Hotmail and Yahoo (in this order <a href="http://www.informationweek.com/news/internet/google/showArticle.jhtml?articleID=219400298">according to Comscore</a>) all implement some form of anti-spam techniques.</p>
<p>The main technologies are reverse DNS checking, SPF, SenderID, Domainkeys and DKIM. I will discuss all of these here and provide my tips on setting up SPF, SenderID and DKIM. Please keep in mind that I am not an expert on email servers &#8211; but I hope this helps someone! It took me about half a day to figure this all out, so it is probably worth doing to improve your email delivery rates.</p>
<p><a href="http://zohrob.com/posts/entrepreneurs-guide-to-email-delivery-part-2.html">This blog entry from Dave Zohrom provides a nice discussion of sending email to a general audience</a> (part 2 of a 3-post series).</p>
<h2>Introduction</h2>
<p><strong>SPF or Sender Policy Framework</strong></p>
<p>SPF is easy to setup. It uses DNS TXT records to allow the email providers to check which servers are authorized to send email for a particular domain. The SPF project has done a great<strong> </strong>job at making this simple to setup. Just <a href="http://www.openspf.org/">go to their homepage</a> and use the setup wizard to generate the appropriate TXT records (the text field underneath &#8220;Deploying SPF&#8221;). Then change the values in your DNS records.</p>
<p>One thing to note is that if you have multiple servers and send email from a server with a different hostname (e.g. &#8220;mail.example.com&#8221;), you need to setup a record for that server as well. See <a href="http://www.openspf.org/FAQ/Common_mistakes">the common mistakes page on the SPF site</a>. Also, if you have hostnames that are not supposed to send mail, you ought to indicate this as well.</p>
<p>Another thing is that if you are using Google Apps for Your Domain to send email, then you will need to have to add &#8220;include:aspmx.googlemail.com&#8221; to also allow mail from Google to validate. See <a href="http://www.google.com/support/a/bin/answer.py?hl=en&amp;answer=33786">this answer for more</a>.</p>
<p><strong>SenderID from Microsoft</strong></p>
<p>SenderID is a variant of SPF, which for most practical cases is the same as SPF. Just setup SPF and this should produce a validation pass for SenderID as well. The semantics of the validation are a bit different,  but this does not seem to be a major practical problem. See testing tips below to make sure that this is also true in your case.</p>
<p><strong>DomainKeys</strong></p>
<p>DomainKeys is an older version of DKIM (DomainKeys Identified Mail) developed by Yahoo. Despite having very similar names, these ARE NOT the same!</p>
<p>Both DomainKeys and DKIM store public key information in DNS records and sign the message headers of every email sent. The recipient can then verify the signature.</p>
<p>DomainKeys was deprecated in 2007, but some email providers may still be using it. However, <a href="http://blog.deliverability.com/2009/09/franck-martin-on-the-future-of-dkim-and-domainbased-reputation-.html">these are a shrinking minority </a>and Yahoo does support the newer DKIM. <span style="background-color: #ffffff;">Because of this I did not add DomainKeys support but opted only to use DKIM.</span></p>
<p><span style="background-color: #ffffff;">You can add it to sendmail or Postfix using the dk-milter project code, but the unofficial RPM release <a href="http://www.topdog-software.com/oss/dk-milter/">is not maintained anymore</a>, which means you will need to install it from source (<a href="http://sourceforge.net/projects/dk-milter/">available via SourceForge</a>).</span></p>
<p><span style="background-color: #ffffff;"><strong>DKIM, or DomainKeys Identified Mail</strong></span></p>
<p><span style="background-color: #ffffff;">DKIM on the other hand seems to be gaining momentum. It is used by Gmail, Yahoo and AOL and many others, and also works by publishing public keys via DNS TXT records and by signing the emails at the email server.</span></p>
<p><span style="background-color: #ffffff;">To setup DKIM, you need an additional filter which takes the completed email and adds the DKIM signature to the email prior to sending it out.</span></p>
<p><span style="background-color: #ffffff;">Postfix and sendmail support &#8220;<a href="http://en.wikipedia.org/wiki/Milter">milters</a>&#8220;, which is apparently short for &#8220;mail filter&#8221;. There is a DKIM-milter package available for Centos at the EPEL repositories (see <a href="http://wiki.centos.org/AdditionalResources/Repositories">Centos page for 3rd party repos</a>).</span></p>
<h2><span style="background-color: #ffffff;">Setting up DKIM-milter with sendmail</span></h2>
<p><strong>Updated: Linked tutorial is DEAD. Here are the steps:</strong></p>
<p><strong>Step 1. Generate a private key</strong></p>
<p>openssl genrsa -out default.private 1024</p>
<p>A “default.private” key file will be generated. It will be moved to a specific location later.</p>
<p><strong>Step 2. Generate a public key for this private key</strong></p>
<p>openssl rsa -in default.private -pubout -out default.public -outform PEM</p>
<p>A file with filename “default.public” will be generated with content like</p>
<p>&#8212;&#8211;BEGIN PUBLIC KEY&#8212;&#8211;</p>
<p>&#8230;</p>
<p>&#8212;&#8211;END PUBLIC KEY&#8212;-</p>
<p>It will be used to create a DNS TXT record. See next step.</p>
<p><strong>Step 3. Create a DNS record of type TXT</strong></p>
<p>Modify DNS records and add a record of type TXT:</p>
<p>TXT record name</p>
<p>default._domainkey</p>
<p>TXT record value</p>
<p>v=DKIM1; g=*; k=rsa; p=&lt;content of default.public&gt;</p>
<p>Note that the prefix “—–BEGIN PUBLIC KEY—–” and suffix “—–END PUBLIC KEY—-” should not be put in the TXT record value.</p>
<p>This DNS record will be retrieved by mail receivers who want to verify emails with DKIM signatures. The record name “default._domainkey” tells verifier that the “selector” of this signature is “default”, therefore if you are changing selector name to something else, make sure you change all of them consistently.</p>
<p><strong>Step 4. Install dkim-milter in Fedora</strong></p>
<p>Run the following as root to install the dkim-milter pacakge.</p>
<p>yum install dkim-milter</p>
<p><strong>Step 5. Enable dkim-milter to run on start-up</strong></p>
<p>Make sure dkim-milter service will run on start-up by running this command:</p>
<p>chkconfig &#8211;level 3 dkim-milter on</p>
<p>Note that your server may use a different “runlevel”. You can check “/etc/inittab” to see which run level you are on.</p>
<p><strong>Step 6. Move private key to appropriate location</strong></p>
<p>As root, copy the private key to the location specified by the “keylist” (refer to next step) and make sure it is readable by dkim-milter:</p>
<p>mkdir /etc/dkim-milter/</p>
<p>mv default.private /etc/dkim-milter/default</p>
<p>chown dkim-milter.dkim-milter /etc/dkim-milter/default</p>
<p>Make sure the filename of private key file matches the “selector” name specified in the DNS record.</p>
<p><strong>Step 7. Add an entry to the keylist for dkim-milter to read</strong></p>
<p>Add the following line to /etc/mail/dkim-milter/keys/keylist. Replace &lt;domain.com&gt; with your domain name.</p>
<p>*:&lt;domain.com&gt;:/etc/dkim-milter/default</p>
<p><span style="background-color: #ffffff;"><strong>Step 8. Configure dkim-milter</strong></span></p>
<p><span style="background-color: #ffffff;">Open configuration file /etc/mail/dkim-milter/dkim-filter.conf and use the following configuration:</span></p>
<pre>Canonicalization simple
Domain example.com
KeyFile /some/path/to/whatever-your-keyfile-was
Selector name-of-the-selector
SignatureAlgorithm rsa-sha256
Socket inet:8891@localhost
Syslog Yes
Userid dkim-milter</pre>
<p>NOTE: you will be configuring dkim-milter to use the loopback interface instead of a socket file. I was unable to get dkim-milter to work via the socket file with sendmail. If you get it working, let me know.</p>
<p>You may also want to setup the following:</p>
<pre>SubDomains Yes
SyslogSuccess Yes
X-Header Yes</pre>
<p><span style="background-color: #ffffff;">The X-Header and Syslog options are useful for debugging. See the config file, each option should be documented there.</span></p>
<p><strong>Step 9. Change the default init.d script to use the loopback interface</strong></p>
<p><span style="background-color: #ffffff;">The default init script uses a socket, this needs to be changed. Open /etc/init.d/dkim-milter and change/comment the line:</span></p>
<pre>SOCKET=local:/var/run/${name}/${name}.sock</pre>
<p>to:</p>
<pre>SOCKET=inet:8891@localhost</pre>
<p><span style="background-color: #ffffff;"><strong>Step 10. Configure sendmail to use dkim-milter</strong></span></p>
<p>First a few reminders about sendmail configuration, remember that:</p>
<p>1. Sendmail comments DO NOT USE # as the comment, instead &#8220;dnl&#8221;  (<a href="http://www.sendmail.org/m4/intro_m4.html">delete through newline</a>) at beginning of the line is used to comment lines out.<br />
2. Sendmail configuration is built from the *.mc script files using the M4 macro processor.<br />
3. You need to install the sendmail-cf package for dependencies and install the m4 macro processor separately.<br />
4. In the configuration, the opening quote is a grave accent ` and the closing quote is a straight quote &#8216;.</p>
<p>To configure sendmail, open the &#8220;/etc/mail/submit.mc&#8221; file (which contains the settings for message sending; in older sendmail versions this config was in sendmail.mc).</p>
<p><strong>10.1 Edit submit.mc by adding the following entry to it:</strong></p>
<pre>INPUT_MAIL_FILTER(`dk-filter', `S=inet:8891@localhost')dnl</pre>
<p>(for example just before &#8220;FEATURE(`msp&#8217;, `[127.0.0.1]&#8216;)dnl&#8221;). Make sure that there are no <span style="background-color: #ffffff; font-family: Calibri; font-size: 15px;">define(`confINPUT_MAIL_FILTERS&#8217;, `&#8230;&#8217;)dnl lines after this; if there are, you will need to add dkim-milter manually to the INPUT_MAIL_FILTERS list.</span></p>
<p><strong>10.2 Build and install a new submit.cf:</strong></p>
<pre>m4 /etc/mail/submit.mc &gt; submit.cf</pre>
<p>Tip: use m4 -d /etc/mail/submit.mc to debug first.</p>
<p><strong>10.3 Restart sendmail</strong></p>
<pre>service sendmail restart</pre>
<h2>Testing tips</h2>
<p><strong>Some possible errors:</strong></p>
<ol>
<li><span style="background-color: #ffffff;">Errors getting the sendmail configuration generated: Check whether the dependencies (m4 and sendmail-cf) are installed and paths are correct.</span></li>
<li><span style="background-color: #ffffff;">Errors starting sendmail: Make sure you replaced the correct files (submit.mc to submit.cf and sendmail.mc to sendmail.cf) and if you modified sendmail.mc in addition to submit.mc, make sure you have regenerated both.</span></li>
<li><span style="background-color: #ffffff;">Errors starting dkim-milter: check the permissions on the key file</span></li>
<li><span style="background-color: #ffffff;">Sendmail seems to ignore the dkim-milter, no X-dkim-milter header is in the mail even after you enabled the X-Header option in dkim-filter.conf: </span>
<ol>
<li><span style="background-color: #ffffff;">Check /var/log/maillog.</span></li>
<li><span style="background-color: #ffffff;">Sendmail seems to default to ignoring the milter if it cannot connect to it. This was the problem I ran into when using sockets; after switching to the loopback interface everything started working.</span></li>
<li><span style="background-color: #ffffff;">Also, check whether your mail is sent from a recipient for whom mail is supposed to be signed! If you haven&#8217;t setup your hostname, then this may lead to email not being signed (eg. hostname -F hostname plus /etc/hosts plus /etc/sysconfig/network).  See, for example <a href="http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch21_:_Configuring_Linux_Mail_Servers#_Toc109364456">this tutorial for configuring sendmail</a>.</span></li>
<li><span style="background-color: #ffffff;">Also, check if you need to configure masquerading for Sendmail, see <a href="http://www.sendmail.org/m4/masquerading_relaying.html">http://www.sendmail.org/m4/masquerading_relaying.html</a></span></li>
</ol>
</li>
</ol>
<p><strong>Sending email from the console using only sendmail</strong></p>
<p style="margin: 0in; font-family: Calibri; font-size: 11.0pt;">Create a file with the following content:</p>
<pre>To: "Recipient name" &lt;john.doe@example.com&gt;
<span style="background-color: #ffffff;">From: "Sender name" &lt;admin@example.com&gt;
Reply-To: admin@example.com
Subject: Hello world
This is the content of the message, end it with a line containing only a period as sendmail expects this.
.</span></pre>
<p>Then cat the file and pipe to sendmail -t:</p>
<pre>cat message.txt |sendmail -t</pre>
<p><strong>Checking all of the technologies mentioned above</strong></p>
<p>Port25.com offers a free service which check SPF, SenderID, DomainKeys and DKIM: <span style="background-color: #ffffff;"><a href="http://port25.com/domainkeys/">http://port25.com/domainkeys/</a></span></p>
<p><span style="background-color: #ffffff;">Quote: </span></p>
<ul>
<li><em>If you wish to receive the results at the address in the &#8220;mail_from,&#8221; the sample message should be sent to </em><a style="text-decoration: underline; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 9pt; color: #56759b;" href="mailto:check-auth@verifier.port25.com"><em>check-auth@verifier.port25.com</em></a><em>. </em></li>
<li><em>If you wish to receive the results at the address in the &#8220;from&#8221; header, the sample message should be sent to </em><a style="text-decoration: underline; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 9pt; color: #56759b;" href="mailto:check-auth2@verifier.port25.com"><em>check-auth2@verifier.port25.com</em></a><em>.</em></li>
</ul>
<p><em>A reply email will be sent back to you with an analysis of the message&#8217;s authentication status. The report will perform the following checks: SPF, SenderID, DomainKeys, DKIM and SpamAssassin.</em></p>
<p><strong>Additional resources:</strong></p>
<p><a href="http://allaboutlamp.com/2009/09/setup-dkim-for-postfix-in-fedora-using-dkim-milter/">How to Setup DKIM for Postfix in Fedora using dkim-milter</a></p>
<p><a href="http://allaboutlamp.com/2009/09/how-to-prevent-web-server-emails-from-being-marked-as-spam/">How to Prevent Web Server Emails from being Marked as SPAM</a></p>
<p><a href="http://domainkeys.sourceforge.net/"> DomainKey Implementor&#8217;s Tools and Library for email servers &amp; clients</a></p>
<p><a href="http://www.elandsys.com/resources/sendmail/dkim.html">Sendmail DKIM</a></p>
<p><a href="http://palma-seo.com/setting-dkim-spf-domainkeys-dns-bind">Setting up DKIM, SPF, Domainkeys DNS, Regular DNS on CentOS 5.3 at Pacificrack.com</a></p>
<p><a href="http://blog.nataprawira.com/tech/2009/08/15/how-to-manually-install-dkim-filter-with-sendmail/">How to manually install DKIM-Filter with Sendmail</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mixu.net/2009/11/03/setting-up-spf-senderid-and-dkim-on-centos-5-3-using-sendmail/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Picking the right nonfiction book</title>
		<link>http://blog.mixu.net/2009/11/02/picking-the-right-nonfiction-book/</link>
		<comments>http://blog.mixu.net/2009/11/02/picking-the-right-nonfiction-book/#comments</comments>
		<pubDate>Mon, 02 Nov 2009 01:29:43 +0000</pubDate>
		<dc:creator>Mikito Takada</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[How-to]]></category>

		<guid isPermaLink="false">http://blog.mixu.net/?p=485</guid>
		<description><![CDATA[When it comes to reading, I&#8217;m spoiled! I notice I am getting more and more picky when it comes to ordering books from Amazon, which makes finding books that seem worth reading much harder to find. Over the years I&#8217;ve read quite a pile of books particularly related to programming, general business, entrepreneurship and software [...]]]></description>
			<content:encoded><![CDATA[<p>When it comes to reading, I&#8217;m spoiled! I notice I am getting more and more picky when it comes to ordering books from Amazon, which makes finding books that seem worth reading much harder to find.</p>
<p>Over the years I&#8217;ve read quite a pile of books particularly related to programming, general business, entrepreneurship and software engineering. Now that I am reading up on new topics such as organizational development, lean methods and statistical research methods I am having real trouble finding books I would consider reading just based on the table of contents and Amazon reviews. This is probably a good thing, since the most efficient way to get information is to only read good books.</p>
<p>Here are a couple of guidelines for picking good non-fiction books:</p>
<ol>
<li><strong>Number of reviews.</strong> If there is only a small number of reviews, there is a risk that those reviews are written by the author or his/her friends. A book with more reviews is more credible, as is a book which has had more editions.</li>
<li><strong>Distribution of reviews. </strong>If the reviews are split between 5-star and 1-star reviews, the 5-star reviews are most likely fake. This is an absolutely disgusting practice, but unfortunately common.</li>
<li><strong>Credentials of the authors.</strong> If the authors are practitioners and not scientists, make sure they do not work for a consultancy. I have unfortunately 1-2 books that I did not check adequately and ended up getting a useless brochure book.</li>
<li><strong>The table of contents.</strong>
<ol>
<li><strong>What is the starting point of the discussion? </strong>This defines the prerequisite knowledge that you are expected to have. Reading a book which is for beginners is incredible boring, while reading an advanced book as a beginner is frustrating.Evaluate whether you have the prerequisite knowledge and could read the first few chapters without getting bored to tears. Remember that most popular business books are written for an audience that reads just a few books per year &#8211; this pretty much makes them too repetitive if you read more than that.</li>
<li><strong>What is the emphasis of the book? </strong>Is it oriented towards: a) practice or b) checklists, c) proper theory or d) undergraduate students textbook? (See below for more)</li>
<li><strong>How many pages are dedicated towards each topic? </strong>Don&#8217;t expect anything good from a book that has a 200 pages and cover 200 topics: that&#8217;s just one tiny page per topic.Good books don&#8217;t cover everything with the same small amount of pages, because everything is not equally important in real life.</li>
</ol>
</li>
<li><strong>The actual content of the reviews.</strong> Don&#8217;t bother with 5- or 4-star reviews, they will just tell you the book is good. Read the 1-star and 3-star reviews.See if the 1-star reviews seem to be justified or are just a result of the reviewer being an idiot (e.g. &#8220;Haven&#8217;t received book from Amazon&#8221; or &#8220;This book is too difficult&#8221; -reviews).3-star reviews are usually the best, since the author did like some aspects but did not like others. Pay attention to reviews that say that a book is too basic or simple. If this is said more than once, you probably don&#8217;t want to read that book &#8211; American writing in particular is already very verbose and too many books are written where a five-page article would do, hence reviews which state that the book is too simple should be taken very seriously.</li>
<li><strong>Number of and affiliation of authors. </strong>If all the authors are from the same institution or organization, the book is probably of lower quality. A huge warning sign is a &#8220;collection&#8221; book that has multiple chapters on different topics by the same authors, all from the same decade. This indicates that the authors have not bothered to contact the people who are at the top of their respective fields; articles which are all from the same decade are likely to be just a random set of articles which were written for the book rather than the result of good editorial work.</li>
<li><strong>Order of topics. </strong>Scientific collection books usually order the chapters so that the better and more widely applicable material is at the front of the book, and the more specialized and less interesting material is at the end. It is safe to assume that if the chapter that seems decent for your purpose is at the end of the book, you are better off finding a more specialized book.</li>
</ol>
<p><strong>Four classes of books:</strong></p>
<p>I would put books in four broad categories, two of which are useful and two are useless:</p>
<ol>
<li>Practical books</li>
<li>Academic books</li>
<li>Ego-booster books</li>
<li>Motivational books</li>
</ol>
<p><strong>Practical books: experience-based vs checklist books</strong></p>
<p>Practical books are in my opinion divisible into two categories: advice from practitioners and advice from people who like to write checklists. That is, you have books that are based on the experiences of a practitioner, and then you have books that are written by people who have not actually done that much but wanted to write a book and ended up writing a checklist &#8211; a list of things that might be of use without really emphasizing what is important.</p>
<p>Try to get a feel of the book from the preview (if you can&#8217;t, don&#8217;t buy it!), search for a couple of phrases that interest you. Does the author know what they are doing, or are they just collecting information from other people? Sometimes a &#8220;checklist book&#8221; is not bad &#8211; when you just need the basics and can&#8217;t be bothered to collect all the information. However, usually the experience-based book is better.</p>
<p><strong>Academic books: theory vs textbook</strong></p>
<p>When it comes to academic books, the two main types are proper theory books and textbooks. The more I have seen and read textbooks, the less I like them. Generally speaking they try to cover everything and end up saying nothing.</p>
<p>If you care about the topic, don&#8217;t get a textbook. Instead, get a proper collection of influential articles if it exists (ex. Oxford Handbook of X). You will perhaps not be fully prepared for everything you read, but you will learn something useful. Unlike after reading a textbook, where you just have fuzzy awareness of the fact that &#8220;all kinds of things happen&#8221; in a particular field.</p>
<p><strong>Ego-booster books: academic and practical</strong></p>
<p>There is also another category of books which are basically books written for the author&#8217;s ego. Some books are not written to be read, they are written either to impress others or to act as marketing tools.</p>
<p>The academic substitute for having a nice car sometimes seems to be writing an obtuse treatise which is downright hostile towards the reader, while consultancies in particular are guilty of writing books in which the answer to every question is &#8220;hire our consultancy&#8221;. The academic ego book is harder to spot, so pay attention when previewing the book.</p>
<p><strong>Motivational books: feeling good doesn&#8217;t make it so</strong></p>
<p>Finally, there is a category of fiction books which pretend to be non-fiction books. The motivational books may be a fun read at times, and are usually the most popular books in their category.</p>
<p>However, they are fiction for your entertainment. Feeling good is nice, but that does not change the fact that there are people who are knowledgeable, talented and well-connected doing whatever the book is about, and that feeling good does not make you knowledgeable, talented or well-connected.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mixu.net/2009/11/02/picking-the-right-nonfiction-book/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to setup a LAN DNS server using MaraDNS under Windows 7</title>
		<link>http://blog.mixu.net/2009/10/14/how-to-setup-a-lan-dns-server-using-maradns-under-windows-7/</link>
		<comments>http://blog.mixu.net/2009/10/14/how-to-setup-a-lan-dns-server-using-maradns-under-windows-7/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 10:39:59 +0000</pubDate>
		<dc:creator>Mikito Takada</dc:creator>
				<category><![CDATA[How-to]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.mixu.net/?p=472</guid>
		<description><![CDATA[Are you tired of using 192.168.0.x to refer to the computers within your LAN? Setting up a DNS server and getting domain names for your local computers is surprisingly easy &#8211; even on Windows. 0. Preliminary setup: make sure each computer gets a constant IP address Before setting up the DNS server, you need to [...]]]></description>
			<content:encoded><![CDATA[<p>Are you tired of using 192.168.0.x to refer to the computers within your LAN? Setting up a DNS server and getting domain names for your local computers is surprisingly easy &#8211; even on Windows.</p>
<p><strong>0. Preliminary setup: make sure each computer gets a constant IP address</strong></p>
<p><em>Before setting up the DNS server, you need to ensure that each computer or virtual machine gets a fixed IP address. Otherwise the IP address of the computer may change on each reboot.</em></p>
<p>This should be done on your router, which is usually located either at 192.168.0.1 or 192.168.1.1 (check your current local IP address by running the Command Prompt and &#8220;ipconfig&#8221;, which shows your current IP address). Check your router manual on instructions how to log in, most routers have a HTTP-based configuration system which can be accessed when connected to the router.</p>
<p>In my case (I have a Asus RT-N11), the address was 192.168.1.1. Make sure that the computers you want to setup IPs for are connected, then find the &#8220;Status&#8221; or &#8220;DHCP Leases&#8221; listing on the router web interface. This listing will contain the MAC addresses for each host. Here is mine:</p>
<pre>Host Name       MAC Address       IP Address      Lease
--------------------------------------------------------------
HOST1        00-11-22-33-F0-AC 192.168.1.5     60016 secs.
HOST2        00-11-33-44-F2-2C 192.168.1.6     85074 secs.</pre>
<p>A <a href="http://en.wikipedia.org/wiki/MAC_address">MAC address </a>is a unique identifier given to each network adapter. It allows you to setup fixed IPs.</p>
<p>Find the router functionality which allows you to &#8220;Assign IP Addresses Manually&#8221;. This should enable you to specify a MAC address and a corresponding fixed IP address. Do this for each of the network adapters you wish to have a fixed IP address. On the Asus RT-N11 this was under &#8220;IP Config&#8221; -&gt; &#8220;DHCP Server&#8221;.</p>
<p>Add a MAC address &lt;-&gt; IP address pair for each computer.</p>
<p><strong>1. Get MaraDNS </strong></p>
<p>MaraDNS is a free, lightweight and relatively easy-to-configure DNS server for Windows and Linux. <a href="http://www.maradns.org/download.html">Download it from here </a>and unzip it to some folder.</p>
<p><strong>2. Configure MaraDNS</strong></p>
<p>Open &#8220;secret.txt&#8221; and change the value to something else (random characters).</p>
<p>The MaraDNS configuration is in the &#8220;mararc&#8221; file in the same directory. <a href="http://en.wikipedia.org/wiki/Name_server">DNS servers </a>have two sets of functionality. They can function as a &#8220;Authoritative name server&#8221; or a &#8220;Recursive/caching name server&#8221;.</p>
<p>Authoritative name servers specify IP addresses for domain names. Recursive name servers store information from authoritative name servers and pass on queries in a recursive manner.</p>
<p>We will be configuring both authoritative and recursive functionality in MaraDNS.</p>
<p><strong>2.1 Authoritative configuration</strong></p>
<p>We will configure the server to provide authoritative names of the LAN domain names. Pick any domain, I chose &#8220;local.com&#8221; (note though that you will not be able to access the actual &#8220;local.com&#8221; website if you pick an existing domain name).</p>
<p>Add configuration lines to &#8220;mararc&#8221; like these:</p>
<pre>csv2 = {}
csv2["local.com."] = "db.lan.txt"</pre>
<p>Where <em>local.com </em>is the domain name you picked, and <em>db.lan.txt</em> is the name of the second configuration file which we will be creating next (change it if you want to name the second configuration file).</p>
<p>Create a new file named &#8220;db.lan.txt&#8221; in the same directory as MaraDNS.</p>
<p>For each of the computers you want to resolve to a name, add a line to &#8220;db.lan.txt&#8221;. For example, for two machines, one &#8220;dev.local.com&#8221; and the other &#8220;blog.local.com&#8221;, add the following lines:</p>
<pre>dev.%       192.168.1.4 ~
blog.%        192.168.1.6 ~</pre>
<p>Done!</p>
<p><strong>2.2 Recursive configuration</strong></p>
<p>We will setup MaraDNS to ask your default name servers for all other domains so that you can resolve all other domain names to their correct IP addresses.</p>
<p>Find out your ISP&#8217;s DNS server addresses. These are likely to be listed either on the Router status page, or by checking the details on your network adapter.</p>
<p>Now add your ISP&#8217;s DNS servers as upstream servers in &#8220;mararc&#8221;:</p>
<pre>upstream_servers = {}
upstream_servers["."] = "xxx.xxx.xxx.xxx, yyy.yyy.yyy.yyy"</pre>
<p>Where <em>xxx.xxx.xxx.xxx</em> and <em>yyy.yyy.yyy.yyy </em>are your ISP&#8217;s DNS servers.</p>
<p>Done!</p>
<p><strong>3. Run MaraDNS and test it using askmara.exe</strong></p>
<p>Double-click &#8220;runmara.bat&#8221; , and leave the server running.</p>
<p>Open a command prompt, navigate to the MaraDNS directory and try running:</p>
<pre>askmara.exe Agoogle.com.</pre>
<p>and</p>
<pre>askmara.exe Ablog.local.com.</pre>
<p>You should get replies like this:</p>
<pre># Querying the server with the IP 127.0.0.1
# Question: Agoogle.com.
google.com. +300 a 74.125.67.100
google.com. +300 a 74.125.53.100
google.com. +300 a 74.125.45.100
# NS replies:
# AR replies:</pre>
<p>and:</p>
<pre># Querying the server with the IP 127.0.0.1
# Question: Ablog.local.com.
blog.local.com. +86400 a 192.168.1.6
# NS replies:
#local.com. +86400 ns synth-ip-7f000001.local.com.
# AR replies:
#synth-ip-7f000001.local.com. +86400 a 127.0.0.1</pre>
<p>If you get problems with the first query, you messed up the recursive DNS settings (are your ISP DNS server addresses correct?), and if you get an error with the second query, you messed up the authoritative settings.</p>
<p><strong>4. Change MaraDNS to reply to queries from your LAN</strong></p>
<p>Shutdown the MaraDNS window, and change the first two lines of &#8220;mararc&#8221; to something like:</p>
<pre>ipv4_bind_addresses = "192.168.1.2
recursive_acl = "192.168.1.0/24"</pre>
<p>Where 192.168.1.2 is the IP address of the computer on which the server will be running and the &#8220;192.168.1&#8243; part of recursive_acl is the same as on your network (might be 192.168.0.0/24).</p>
<p>Start MaraDNS again, and leave it running.</p>
<p><strong>5. Setup your router to hand out your new DNS server</strong></p>
<p>Open your router&#8217;s web interface and find the DHCP server settings. There should be an option to set up a DNS server. Write the IP address of the computer on which the DNS server will be running.</p>
<p>For each of your computers, disconnect the network (e.g. by disabling and enabling it in Windows, or by using &#8220;ifconfig eth0 down&#8221;/&#8221;ifconfig eth0 up&#8221; on Linux).</p>
<p>That&#8217;s it, you should now be able to refer to your LAN computers by their domain names.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mixu.net/2009/10/14/how-to-setup-a-lan-dns-server-using-maradns-under-windows-7/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>

