<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://dikant.de/feed.xml" rel="self" type="application/atom+xml" /><link href="https://dikant.de/" rel="alternate" type="text/html" /><updated>2025-07-03T16:16:47+02:00</updated><id>https://dikant.de/feed.xml</id><title type="html">No pain no gain</title><subtitle>Personal blog of Peter Dikant
</subtitle><entry><title type="html">Disqus Comments disabled</title><link href="https://dikant.de/2018/05/01/disqus-disabled/" rel="alternate" type="text/html" title="Disqus Comments disabled" /><published>2018-05-01T18:00:00+02:00</published><updated>2018-05-01T18:00:00+02:00</updated><id>https://dikant.de/2018/05/01/disqus-disabled</id><content type="html" xml:base="https://dikant.de/2018/05/01/disqus-disabled/"><![CDATA[<p>The upcoming General Data Protection Regulation of the European Community has some dire consequences for web site admins. Due to the uncertain legal status of the Disqus comment system I use on this site, I have decided to disable comments for now. I hope this will be only a temporary measure and I can reenable them sometime in the future.</p>

<h3 id="update-may-13-disqus-reenabled">Update May, 13: Disqus reenabled</h3>

<p>Disqus has been updated to conform to the GDPR regulations so that it could be reenabled on this site.</p>]]></content><author><name>Peter</name></author><category term="Site" /><category term="Site" /><summary type="html"><![CDATA[The upcoming General Data Protection Regulation of the European Community has some dire consequences for web site admins. Due to the uncertain legal status of the Disqus comment system I use on this site, I have decided to disable comments for now. I hope this will be only a temporary measure and I can reenable them sometime in the future. Update May, 13: Disqus reenabled Disqus has been updated to conform to the GDPR regulations so that it could be reenabled on this site.]]></summary></entry><entry><title type="html">Automatic Raspberry Pi Recorder for Behringer XR18</title><link href="https://dikant.de/2018/02/28/raspberry-xr18-recorder/" rel="alternate" type="text/html" title="Automatic Raspberry Pi Recorder for Behringer XR18" /><published>2018-02-28T20:55:15+01:00</published><updated>2018-02-28T20:55:15+01:00</updated><id>https://dikant.de/2018/02/28/raspberry-xr18-recorder</id><content type="html" xml:base="https://dikant.de/2018/02/28/raspberry-xr18-recorder/"><![CDATA[<p>Recently I have switched from a <a href="http://www.musictri.be/Categories/Behringer/Mixers/Digital/X32/p/P0ASF" target="_blank">Behringer X32</a> mixer to the smaller <a href="http://www.musictri.be/Categories/Behringer/Mixers/Digital/XR18/p/P0BI8" target="_blank">XR18</a> as I am a big fan of the small stage box type form factor and I can usually get by with using 16 channels.</p>

<p>One thing that I found missing compared to the X32 is the ability to record 2 channels directly to a usb stick. Therefore I thought about possible ways to work around this missing feature. In the end I settled on a <a href="https://www.raspberrypi.org/" target="_blank">Raspberry Pi 3</a> which is running the audio player distribution <a href="http://moodeaudio.org/" target="_blank">moode audio</a> and is connected via USB to the XR18. With a small bash script it is possible to create an automatic recorder that will record mp3 files whenever audio is playing on the XR18.</p>

<!--more-->

<p>Let’s start with some pointers on setting up the XR18 for <em>moode audio</em> and recording. Make sure to send the <em>Main LR</em> bus on USB1 and USB2. So go to <em>In/Out</em>, select <em>USB Sends</em> and select <em>Main LR</em> for USB1 and USB2. You can choose any mode you like but I prefer <em>Pre EQ</em>. My Main LR EQ is always trimmed for the room. So I don’t want to have this EQ on the recording. The <em>Pre EQ</em> setting will achieve just that and has the added benefit that changes to the master volume will also not be reflected on the recording. The screen will look like this:</p>

<p><img src="/wp-content/uploads/2018/02/usbsends.png" alt="USB send configuration" /></p>

<p>USB return channels 1 and 2 also need to be mapped to XR18 channels. I usually map them to <em>Aux L/R</em> and <em>FX4 L/R</em>. I only need 3 send FX, so my FX4 is configured as an insert effect and therefore does not need return channels. By mapping the USB return to <em>FX4 L/R</em>, I free up the Aux Stereo Channel for other uses. This is what my <em>USB Returns</em> mapping looks like:</p>

<p><img src="/wp-content/uploads/2018/02/usbreturns.png" alt="USB return configuration" /></p>

<p>In <em>moode audio</em> you just need to enable USB audio output and you will be able to play audio through your XR18 without any other configuration changes.</p>

<p>Now we are all set for working on the recording side. The following steps can be done on a plain Raspbian distribution or on <em>moode audio</em> or most probably any other Debian based Rapsberry Pi distribution.</p>

<p>First we need to install required software packages. So log in to your Raspberry via SSH and run this command:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo </span>apt-get <span class="nb">install </span>sox libsox-fmt-mp3</code></pre></figure>

<p>Now create a new shell script named <code class="language-plaintext highlighter-rouge">recorder.sh</code> in <code class="language-plaintext highlighter-rouge">/home/pi</code> with the following contents:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c">#!/bin/bash</span>

<span class="k">while</span> <span class="o">[</span> 1 <span class="o">]</span>
<span class="k">do
  </span><span class="nv">FILENAME</span><span class="o">=</span>/media/FILES/XR18/<span class="si">$(</span><span class="nb">date</span> +<span class="s2">"%Y%m%d_%H%M"</span><span class="si">)</span>.mp3
  <span class="nv">AUDIODEV</span><span class="o">=</span><span class="s2">"hw:X18XR18,0"</span> rec <span class="nt">-q</span> <span class="nt">--buffer</span> 262144 <span class="nt">-c</span> 2 <span class="nt">-C</span> 256 <span class="nv">$FILENAME</span> silence 1 0.1 2% 1 3:00 2% gain <span class="nt">-9</span>
  <span class="o">[</span> <span class="nv">$?</span> <span class="nt">-eq</span> 0 <span class="o">]</span> <span class="o">||</span> <span class="nb">exit</span> <span class="nv">$?</span>
  
  <span class="c"># Remove file if nothing has been recorded</span>
  <span class="nv">FILESIZE</span><span class="o">=</span><span class="si">$(</span><span class="nb">du</span> <span class="nt">-sb</span> <span class="nv">$FILENAME</span> | <span class="nb">cut</span> <span class="nt">-f</span> 1<span class="si">)</span>
  <span class="k">if</span> <span class="o">[</span> <span class="nv">$SIZE</span> <span class="nt">-lt</span> 2048 <span class="o">]</span><span class="p">;</span> <span class="k">then
    </span><span class="nb">rm</span> <span class="nv">$FILENAME</span>
  <span class="k">fi
  
  </span><span class="nb">sleep </span>30
<span class="k">done</span></code></pre></figure>

<p>Please change the path in <code class="language-plaintext highlighter-rouge">FILENAME</code> to the location where you want the recordings to be stored. I am using a USB stick named <em>FILES</em> that is automatically mounted during bootup by moode audio under the path <code class="language-plaintext highlighter-rouge">/media/FILES</code>. On this stick the recordings should be stored in the directory <code class="language-plaintext highlighter-rouge">XR18</code>.</p>

<p>The XR18 will identify itself to the operating system with the string <code class="language-plaintext highlighter-rouge">X18XR18</code>. If you are using another device, you need to identify the string that the other device reports by running <code class="language-plaintext highlighter-rouge">aplay -l</code>. The X32 for example can be accessed by the name <code class="language-plaintext highlighter-rouge">XUSB</code>.</p>

<p>The recording is done in an endless loop with the current timestamp as the filename by running the <code class="language-plaintext highlighter-rouge">rec</code> utility. It is configured to start recording once a signal with at least 2% volume is present and it will automatically stop 3 minutes after the signal level has dropped below 2%. Additionally the gain is reduced by 9dB to prevent possible clipping when running the XR18 output hot. Recording format is mp3 with a bitrate of 256kBit.</p>

<p>Should the <code class="language-plaintext highlighter-rouge">rec</code> utility exit with an error code (for example if the XR18 is not found), then the script will terminate. In all other cases it will delete the created file if it has not recorded anything (detected by checking the file size), sleep for 30 seconds and then start the recording again.</p>

<p>Make the script executable by running:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">chmod </span>a+x recorder.sh</code></pre></figure>

<p>Now you only need to run this script automatically after booting up the Raspberry PI. Do this by appending the following line to the file <code class="language-plaintext highlighter-rouge">/etc/rc.local</code> before <code class="language-plaintext highlighter-rouge">exit 0</code>:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">/home/pi/recorder.sh &amp;</code></pre></figure>

<p>From now on, you just need to connect your Raspberry Pi via USB to the XR18 and it will both serve as an audio player and a recorder that will start recording whenever a signal is detected on the Main LR output of the XR18.</p>

<h3 id="update-march-5-multitrack-recording">Update March, 5: Multitrack Recording</h3>

<p>It is also possible to use the <code class="language-plaintext highlighter-rouge">rec</code> utility for multitrack recording. It is possible to record all 18 inputs of the XR18 in a single multichannel WAV file. But there are some caveats you need to be aware of:</p>

<ul>
  <li>Silence detection does not work in multitrack mode. So you need a way to start and stop the recording manually.</li>
  <li>Multitrack files tend to get very big, so your recording target (USB stick) needs to be formatted with a file system, that supports large files. I had no problems with exFAT formatted USB sticks.</li>
  <li>Your USB stick should be able to consistently write at least 2MB per second. I had some good results with a <em>SanDisk Ultra Fit 64GB USB3 stick</em>.</li>
</ul>

<p>Here is the command line to record 18 tracks 24bit WAV files:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">AUDIODEV</span><span class="o">=</span><span class="s2">"hw:X18XR18,0"</span> rec <span class="nt">-q</span> <span class="nt">--buffer</span> 262144 <span class="nt">-c</span> 18 <span class="nt">-b</span> 24 /path/to/file.wav</code></pre></figure>

<h3 id="update-may-12-2-track-wav-recording">Update May, 12: 2-Track WAV Recording</h3>

<p>I have now switched to recording wav files as my USB sticks have more than enough free space so that I don’t need compression during recording. The <code class="language-plaintext highlighter-rouge">rec</code> parameters look like this:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">AUDIODEV</span><span class="o">=</span><span class="s2">"hw:X18XR18,0"</span> rec <span class="nt">-q</span> <span class="nt">--buffer</span> 1048576 <span class="nt">-b</span> 16 <span class="nt">-c</span> 2 <span class="k">${</span><span class="nv">FILENAME</span><span class="k">}</span> silence 1 0.1 0.1% 1 3:00 0.1%</code></pre></figure>

<h3 id="update-june-2-fixing-soundcard-order">Update June, 2: Fixing soundcard order</h3>

<p>With the latest Moode release 4.1 the XR18 sometimes is detected as device 0 and sometimes as device 1. This leads to problems when trying to use Moode. The sound will not play. You can see the order your cards have been initializes with:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">pi@moode:~ <span class="nb">cat</span> /proc/asound/cards
 0 <span class="o">[</span>ALSA           <span class="o">]</span>: bcm2835_alsa - bcm2835 ALSA
                      bcm2835 ALSA
 1 <span class="o">[</span>X18XR18        <span class="o">]</span>: USB-Audio - X18/XR18
                      BEHRINGER X18/XR18 at usb-3f980000.usb-1.3, high speed</code></pre></figure>

<p>Moode expects the USB device to be device 1. To make sure the XR18 is device 1 you need to create a file <code class="language-plaintext highlighter-rouge">/etc/modprobe.d/alsa.conf</code> with the following contents:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">options snd-usb-audio <span class="nv">index</span><span class="o">=</span>1</code></pre></figure>

<p>Besides the XR18, I have also connected a X-TOUCH-MINI controller which is also recognized as an USB audio device, so I need to make sure the XR18 is device 1 and the X-TOUCH device 2. This is done with the following line:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">options snd-usb-audio <span class="nv">index</span><span class="o">=</span>1,2 <span class="nv">vid</span><span class="o">=</span>0x1397,0x1397 <span class="nv">pid</span><span class="o">=</span>0x00d4,0x00b3</code></pre></figure>]]></content><author><name>Peter</name></author><category term="XR18" /><category term="Music" /><category term="XR18" /><category term="RaspberryPi" /><category term="Music" /><summary type="html"><![CDATA[Recently I have switched from a Behringer X32 mixer to the smaller XR18 as I am a big fan of the small stage box type form factor and I can usually get by with using 16 channels. One thing that I found missing compared to the X32 is the ability to record 2 channels directly to a usb stick. Therefore I thought about possible ways to work around this missing feature. In the end I settled on a Raspberry Pi 3 which is running the audio player distribution moode audio and is connected via USB to the XR18. With a small bash script it is possible to create an automatic recorder that will record mp3 files whenever audio is playing on the XR18.]]></summary></entry><entry><title type="html">DIY MIDI Footswitch Controller</title><link href="https://dikant.de/2015/01/18/diy-midi-footswitch-controller/" rel="alternate" type="text/html" title="DIY MIDI Footswitch Controller" /><published>2015-01-18T19:42:15+01:00</published><updated>2015-01-18T19:42:15+01:00</updated><id>https://dikant.de/2015/01/18/diy-midi-footswitch-controller</id><content type="html" xml:base="https://dikant.de/2015/01/18/diy-midi-footswitch-controller/"><![CDATA[<p>I am using a <a href="http://www.behringer.com/EN/Products/X32.aspx" target="_blank">Behringer X32</a> digital mixing desk both when mixing other bands and mixing my own band while performing at the same time on stage. In the latter case I always struggle to turn the vocal reverb on and off in time when a song starts or ends. When I was using an analog mixing console, I had the option to attach a footswitch to toggle this effect on and off. On the X32 this is not possible but it is possible to remote control the desk via MIDI commands. So I decided to build a footswitch controller that will send MIDI commands to the X32.</p>

<!--more-->

<p>The controller is based on a cheap Arduino Nano board that can be ordered on Ebay for around 3 Euro. All parts can be bought for less than 10 Euro in total. Here is a complete list of all necessary parts (assuming that you want to connect an existing footswitch):</p>

<ul>
  <li>Arduino Nano</li>
  <li>5-pin DIN jack</li>
  <li>6.3mm Instrument cable jack</li>
  <li>LED in your color of choice</li>
  <li>2 220 Ohm resistors</li>
  <li>Some wires</li>
  <li>small case</li>
</ul>

<p>Wiring is pretty easy. Here is a complete view of the breadboard layout:</p>

<p><a href="http://www.dikant.de/wp-content/uploads/2015/01/midi-footswtich-1.jpg"><img src="http://www.dikant.de/wp-content/uploads/2015/01/midi-footswtich-1.jpg" alt="Breadboard Layout" width="1024" height="680" class="alignnone size-full wp-image-337" srcset="http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-1.jpg 1024w, http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-1-300x199.jpg 300w, http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-1-452x300.jpg 452w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>

<p>To connect the footswitch, wire the tip of the 6.3mm jack to pin D2 on the Arduino. Connect the ring to pin GND.</p>

<p>Connecting the MIDI jack is done by soldering a 220 Ohm resistor to pin 4 and then connecting the other pin of the resistor to pin 5V on the Arduino. Pin 2 on the jack needs to be connected to GND and pin 5 to TX1. Here is a picture of the wiring on the MIDI jack:</p>

<p><a href="http://www.dikant.de/wp-content/uploads/2015/01/midi-footswtich-3.jpg"><img src="http://www.dikant.de/wp-content/uploads/2015/01/midi-footswtich-3.jpg" alt="MIDI jack cabling" width="1024" height="682" class="alignnone size-full wp-image-339" srcset="http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-3.jpg 1024w, http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-3-300x200.jpg 300w, http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-3-450x300.jpg 450w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>

<p>The LED is optional but I wanted a visual indicator when I have mute enganged on the X32. Solder a 220 Ohm resistor to the longer pin of the LED and connect it to D12 on the Arduino. Now connect the other pin of the LED to GND. Here is the wiring on the breadboard:</p>

<p><a href="http://www.dikant.de/wp-content/uploads/2015/01/midi-footswtich-2.jpg"><img src="http://www.dikant.de/wp-content/uploads/2015/01/midi-footswtich-2.jpg" alt="LED wiring" width="1024" height="683" class="alignnone size-full wp-image-338" srcset="http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-2.jpg 1024w, http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-2-300x200.jpg 300w, http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-2-450x300.jpg 450w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>

<p>Finally a view of all pins used on the Arduino:</p>

<p><a href="http://www.dikant.de/wp-content/uploads/2015/01/midi-footswtich-4.jpg"><img src="http://www.dikant.de/wp-content/uploads/2015/01/midi-footswtich-4.jpg" alt="Arduino wiring" width="1024" height="683" class="alignnone size-full wp-image-340" srcset="http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-4.jpg 1024w, http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-4-300x200.jpg 300w, http://dikant.de/wp-content/uploads/2015/01/midi-footswtich-4-450x300.jpg 450w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>

<p>The hardware part is now complete. All you need to do is upload the following program to the Arduino board:</p>

<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="c1">// pin to use for indicator LED</span>
<span class="kt">int</span> <span class="n">ledPin</span> <span class="o">=</span> <span class="mi">12</span><span class="p">;</span>
<span class="c1">// pin that is connected to the footswitch</span>
<span class="kt">int</span> <span class="n">buttonPin</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>

<span class="kt">int</span> <span class="n">buttonState</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">buttonLastState</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">buttonInitState</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

<span class="kt">int</span> <span class="n">muteStatus</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

<span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">pinMode</span><span class="p">(</span><span class="n">ledPin</span><span class="p">,</span> <span class="n">OUTPUT</span><span class="p">);</span>
  <span class="n">pinMode</span><span class="p">(</span><span class="n">buttonPin</span><span class="p">,</span> <span class="n">INPUT_PULLUP</span><span class="p">);</span>
  
  <span class="c1">// Setup serial port for MIDI communication</span>
  <span class="n">Serial</span><span class="p">.</span><span class="n">begin</span><span class="p">(</span><span class="mi">31250</span><span class="p">);</span>
  
  <span class="c1">// read current button state, a press is detected whenever</span>
  <span class="c1">// state changes to anything else than the init state</span>
  <span class="n">buttonInitState</span> <span class="o">=</span> <span class="n">digitalRead</span><span class="p">(</span><span class="n">buttonPin</span><span class="p">);</span>
  <span class="c1">// we only want to do something on state changes</span>
  <span class="n">buttonLastState</span> <span class="o">=</span> <span class="n">buttonInitState</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">buttonState</span> <span class="o">=</span> <span class="n">digitalRead</span><span class="p">(</span><span class="n">buttonPin</span><span class="p">);</span>
  
  <span class="c1">// has the state changed?</span>
  <span class="k">if</span> <span class="p">(</span><span class="n">buttonState</span> <span class="o">!=</span> <span class="n">buttonLastState</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">buttonLastState</span> <span class="o">=</span> <span class="n">buttonState</span><span class="p">;</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">buttonState</span> <span class="o">!=</span> <span class="n">buttonInitState</span><span class="p">)</span> <span class="p">{</span>
      <span class="c1">// button is in pressed state, trigger action</span>
      <span class="k">if</span> <span class="p">(</span><span class="n">muteStatus</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
        <span class="c1">// mute and light up LED</span>
        <span class="n">digitalWrite</span><span class="p">(</span><span class="n">ledPin</span><span class="p">,</span> <span class="n">HIGH</span><span class="p">);</span>
        <span class="c1">// send CC 85 on channel 2 with value 0 to mute</span>
        <span class="c1">// mute group 6 on a Behringer X32</span>
        <span class="n">midiCc</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">85</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
        <span class="n">muteStatus</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
      <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="c1">// unmute and turn off LED</span>
        <span class="n">digitalWrite</span><span class="p">(</span><span class="n">ledPin</span><span class="p">,</span> <span class="n">LOW</span><span class="p">);</span>
        <span class="n">midiCc</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">85</span><span class="p">,</span> <span class="mi">127</span><span class="p">);</span>
        <span class="n">muteStatus</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
      <span class="p">}</span>
    <span class="p">}</span>
    <span class="c1">// workaround to prevent fluttering of button state</span>
    <span class="n">delay</span><span class="p">(</span><span class="mi">10</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>

<span class="kt">void</span> <span class="nf">midiCc</span><span class="p">(</span><span class="kt">int</span> <span class="n">channel</span><span class="p">,</span> <span class="kt">int</span> <span class="n">command</span><span class="p">,</span> <span class="kt">int</span> <span class="n">value</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">Serial</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="mi">175</span> <span class="o">+</span> <span class="n">channel</span><span class="p">);</span>
  <span class="n">Serial</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">command</span><span class="p">);</span>
  <span class="n">Serial</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">value</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>

<p>This solution should work with any regular footswitch. Polarity doesn’t matter as the initial state will be detected during startup. I am sending MIDI CC messages to mute and unmute mute group 6 of the X32 in this example, but you can replace that part with any MIDI command you like.</p>]]></content><author><name>Peter</name></author><category term="Arduino" /><category term="Music" /><category term="Arduino" /><category term="MIDI" /><category term="Music" /><summary type="html"><![CDATA[I am using a Behringer X32 digital mixing desk both when mixing other bands and mixing my own band while performing at the same time on stage. In the latter case I always struggle to turn the vocal reverb on and off in time when a song starts or ends. When I was using an analog mixing console, I had the option to attach a footswitch to toggle this effect on and off. On the X32 this is not possible but it is possible to remote control the desk via MIDI commands. So I decided to build a footswitch controller that will send MIDI commands to the X32.]]></summary></entry><entry><title type="html">Enabling iPhone push emails on your Ubuntu mail server</title><link href="https://dikant.de/2013/10/04/enabling-iphone-push-emails-on-your-ubuntu-mail-server/" rel="alternate" type="text/html" title="Enabling iPhone push emails on your Ubuntu mail server" /><published>2013-10-04T18:47:44+02:00</published><updated>2013-10-04T18:47:44+02:00</updated><id>https://dikant.de/2013/10/04/enabling-iphone-push-emails-on-your-ubuntu-mail-server</id><content type="html" xml:base="https://dikant.de/2013/10/04/enabling-iphone-push-emails-on-your-ubuntu-mail-server/"><![CDATA[<p>The iPhone does not support the IMAP Idle protocol to receive push notifications for new emails. Fortunately the open source project <a href="http://z-push.sourceforge.net" target="_blank">Z-Push</a> implements the ActiveSync protocol which can be also used by iOS to receive push email notifications.</p>

<p>If you followed my other articles on how to install a mail server on Ubuntu, you have a running Dovecot server. You also need a running Apache server with PHP5. The server has to respond to https requests. If your server meets these requirements, adding Z-Push to this setup is easy.</p>

<!--more-->

<p>Download the latest Z-Push version from <a href="http://z-push.sourceforge.net/soswp/index.php?pages_id=39&#038;t=Download" target="_blank">here</a>. At the time of writing the most recent version is 2.1.0.</p>

<p>Now install necessary Ubuntu packages:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">aptitude <span class="nb">install </span>php5-cli php5-imap php-soap</code></pre></figure>

<p>Unpack Z-Push and move the folder into your https directory:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">tar</span> <span class="nt">-xvzf</span> z-push-2.1.0-1750.tar.gz
<span class="nb">mv </span>z-push-2.1.0-1750 /var/www/vhosts/YOUR_DOMAIN/httpsdocs/z-push
<span class="nb">chown</span> <span class="nt">-R</span> www-data.www-data /var/www/vhosts/YOUR_DOMAIN/httpsdocs/z-push</code></pre></figure>

<p>Z-Push needs two additional working directories:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">mkdir</span> /var/lib/z-push /var/log/z-push
<span class="nb">chown </span>www-data.www-data /var/lib/z-push /var/log/z-push</code></pre></figure>

<p>Now it’s time to modify the Z-Push configuration file <code class="language-plaintext highlighter-rouge">config.php</code>. You only need to set the timezone and the backend provider. Anything else can be left on default.</p>

<figure class="highlight"><pre><code class="language-php" data-lang="php"><span class="nb">define</span><span class="p">(</span><span class="s1">'TIMEZONE'</span><span class="p">,</span> <span class="s1">'Europe/Berlin'</span><span class="p">);</span>
<span class="nb">define</span><span class="p">(</span><span class="s1">'BACKEND_PROVIDER'</span><span class="p">,</span> <span class="s1">'BackendIMAP'</span><span class="p">);</span></code></pre></figure>

<p>The last step is to set an alias address to the z-push folder in the Apache virtual host configuration:</p>

<figure class="highlight"><pre><code class="language-apache" data-lang="apache"><span class="nc">Alias</span> /Microsoft-Server-ActiveSync /var/www/vhosts/YOUR_DOMAIN/httpsdocs/z-push/index.php</code></pre></figure>

<p>You can test if the server is setup properly by opening the url <code class="language-plaintext highlighter-rouge">https://YOUR_DOMAIN/Microsoft-Server-ActiveSync</code> in the browser. You will be prompted for username and password. After you enter your login credentials, the server will answer <code class="language-plaintext highlighter-rouge">GET not supported</code>. If you get this message, you are all setup.</p>

<p>On the iPhone you now have to create a new Exchange mail account and you are done.</p>]]></content><author><name>Peter</name></author><category term="Apache" /><category term="Mail" /><category term="dovecot" /><category term="iphone" /><category term="push" /><summary type="html"><![CDATA[The iPhone does not support the IMAP Idle protocol to receive push notifications for new emails. Fortunately the open source project Z-Push implements the ActiveSync protocol which can be also used by iOS to receive push email notifications. If you followed my other articles on how to install a mail server on Ubuntu, you have a running Dovecot server. You also need a running Apache server with PHP5. The server has to respond to https requests. If your server meets these requirements, adding Z-Push to this setup is easy.]]></summary></entry><entry><title type="html">Secure Offsite Backups for Synology NAS</title><link href="https://dikant.de/2013/06/25/secure-offsite-backups-for-synology-nas/" rel="alternate" type="text/html" title="Secure Offsite Backups for Synology NAS" /><published>2013-06-25T22:23:23+02:00</published><updated>2013-06-25T22:23:23+02:00</updated><id>https://dikant.de/2013/06/25/secure-offsite-backups-for-synology-nas</id><content type="html" xml:base="https://dikant.de/2013/06/25/secure-offsite-backups-for-synology-nas/"><![CDATA[<p>I have a solid backup strategy in place where my <a href="http://www.synology.com/products/product.php?product_name=DS213j" target="_blank">2-bay Synology NAS</a> is the central data store. The HDDs in the NAS are setup in a JBOD configuration. I don’t need a RAID so this way I am more flexible in which data is stored where.</p>

<p>One HDD is dedicated as a backup drive. Every computer is backed up via Time Machine on this drive. The other HDD is used for network shares. Important documents, pictures, whatever are stored on a dedicated documents share on that HDD. This share is also backed up daily onto the backup drive.</p>

<p>Once per week I connect a USB drive to the NAS and create a backup of the backup drive.</p>

<!--more-->

<p>With this strategy I feel quite confident that hardware failures or human failures will not cause any data loss. The only scenario missing so far is fire / theft / water damage. Anything that will affect all HDDs in my household at the same time.</p>

<p>This is where offsite backups come into place. The Synology NAS has different options for creating offsite backups. You can use <a href="http://aws.amazon.com/s3/" target="_blank">Amazon S3</a>, <a href="http://aws.amazon.com/glacier/" target="_blank">Amazon Glacier</a>, <a href="http://www.strato.de/online-speicher/" target="_blank">Strato HiDrive</a> or any server running a rsync daemon. All of these options have the problem that backups are not being encrypted before they are sent to the destination. I don’t want to store my data in unencrypted form anywhere on the internet.</p>

<p>Luckily it is possible to create encrypted shared folders on the NAS. Synology uses <a href="http://ecryptfs.org/" target="_blank">ecryptfs</a> to encrypt files stored on this folder. So I am using an encrypted folder on the backup drive to store the unencrypted documents folder from the first HDD. The files are encrypted using a passphrase. Make sure that you use a secure und sufficiently long passphrase. Also make sure that you do not loose this passphrase. Without the passphrase you will not be able to decrypt your files.</p>

<p>When backing up the encrypted folder only the already encrypted files are sent to the destination server. Filenames and folder names are also encrypted so that the data is completely secure as long as the passphrase is long enough.</p>

<p>I already have a virtual server hosted by a <a href="http://www.hosteurope.de/" target="_blank">reliable company</a> which has enough diskspace and gets backed up daily. So I decided to store my offsite backup on this server. This is done via rsync. Unfortunately Synology does not support rsync over SSH so you need to setup an rsync daemon. The following steps describe how to setup this daemon in a secure way on Ubuntu Linux.</p>

<p>First you need to install rsync:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo </span>aptitude <span class="nb">install </span>rsync</code></pre></figure>

<p>Now create the configuration file <code class="language-plaintext highlighter-rouge">/etc/rsyncd.conf</code> with the following contents:</p>

<figure class="highlight"><pre><code class="language-conf" data-lang="conf"><span class="n">max</span> <span class="n">connections</span> = <span class="m">2</span>
<span class="n">log</span> <span class="n">file</span> = /<span class="n">var</span>/<span class="n">log</span>/<span class="n">rsync</span>.<span class="n">log</span>
<span class="n">timeout</span> = <span class="m">300</span>

[<span class="n">SHARE_NAME</span>]
<span class="n">path</span> = <span class="n">SHARE_PATH</span>
<span class="n">read</span> <span class="n">only</span> = <span class="n">no</span>
<span class="n">list</span> = <span class="n">yes</span>
<span class="n">uid</span> = <span class="n">SHARE_USER</span>
<span class="n">gid</span> = <span class="n">SHARE_GROUP</span>
<span class="n">auth</span> <span class="n">users</span> = <span class="n">LOGIN_NAME</span>
<span class="n">secrets</span> <span class="n">file</span> = /<span class="n">etc</span>/<span class="n">rsyncd</span>.<span class="n">secrets</span>
<span class="n">use</span> <span class="n">chroot</span> = <span class="n">yes</span></code></pre></figure>

<p>Replace <code class="language-plaintext highlighter-rouge">SHARE_NAME</code> with any symbolic name you like. You need to specify the share name when setting up the remote backup on the Synology NAS. The <code class="language-plaintext highlighter-rouge">SHARE_PATH</code> should point to a directory on the server where you want to store the backup. Uid and Gid should point to a user account that has write privileges to the destination directory. <code class="language-plaintext highlighter-rouge">LOGIN_NAME</code> is only used for authenticating against the rsync daemon. You don’t need to specify a system user.</p>

<p>The login credentials are specified in the file <code class="language-plaintext highlighter-rouge">/etc/rsyncd.secrets</code>. Create this file and add the <code class="language-plaintext highlighter-rouge">LOGIN_NAME</code> specified in <code class="language-plaintext highlighter-rouge">/etc/rsyncd.conf</code>:</p>

<figure class="highlight"><pre><code class="language-conf" data-lang="conf"><span class="n">LOGIN_NAME</span>:<span class="n">PASSWORD</span></code></pre></figure>

<p>Again, use a long and secure password.</p>

<p>Please note that rsync uses unencrypted file transfers. Never use the rsync daemon to transfer unencrypted private files over the internet.</p>

<p>Now you need to activate the rsync daemon. First set <code class="language-plaintext highlighter-rouge">RSYNC_ENABLE=true</code> in <code class="language-plaintext highlighter-rouge">/etc/default/rsync</code>. Now you can start the daemon:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo</span> /etc/init.d/rsync start</code></pre></figure>

<p>I recommend preventing brute force attacks on the rsync daemon via fail2ban. Please see my article <a href="http://www.dikant.de/2009/06/19/securing-ssh-server-with-fail2ban/" title="Securing SSH server with fail2ban">Securing SSH server with fail2ban</a> on how to setup fail2ban. You can use the following ruleset to catch all login attempts:</p>

<figure class="highlight"><pre><code class="language-conf" data-lang="conf"><span class="n">failregex</span> = <span class="n">unknown</span> <span class="n">module</span>.*\(&lt;<span class="n">HOST</span>&gt;\)
            <span class="n">auth</span> <span class="n">failed</span> <span class="n">on</span> <span class="n">module</span>.*\(&lt;<span class="n">HOST</span>&gt;\)</code></pre></figure>

<p>Every IP address with 4 failed login attempts within 10 minutes will be blocked for a couple of hours. Together with a secure password this will effectively prevent break in attempts.</p>

<p>The rsync log files can become quite large. You therefore need to setup a logrotate job. Create the file <code class="language-plaintext highlighter-rouge">/etc/logrotate.d/rsync</code> with following contents:</p>

<figure class="highlight"><pre><code class="language-conf" data-lang="conf">/<span class="n">var</span>/<span class="n">log</span>/<span class="n">rsync</span>.<span class="n">log</span> {
    <span class="n">daily</span>
    <span class="n">rotate</span> <span class="m">4</span>
    <span class="n">compress</span>
    <span class="n">notifempty</span>
    <span class="n">missingok</span>
}</code></pre></figure>

<p>Everything is now setup on the server side. You only need to create the backup job on the Synology NAS and don’t forget to select the encrypted folder as the source folder.</p>]]></content><author><name>Peter</name></author><category term="Linux" /><category term="Security" /><category term="backup" /><category term="nas" /><category term="rsync" /><category term="synology" /><summary type="html"><![CDATA[I have a solid backup strategy in place where my 2-bay Synology NAS is the central data store. The HDDs in the NAS are setup in a JBOD configuration. I don’t need a RAID so this way I am more flexible in which data is stored where. One HDD is dedicated as a backup drive. Every computer is backed up via Time Machine on this drive. The other HDD is used for network shares. Important documents, pictures, whatever are stored on a dedicated documents share on that HDD. This share is also backed up daily onto the backup drive. Once per week I connect a USB drive to the NAS and create a backup of the backup drive.]]></summary></entry><entry><title type="html">Optimizing scanned documents with ImageMagick</title><link href="https://dikant.de/2013/05/01/optimizing-scanned-documents-with-imagemagick/" rel="alternate" type="text/html" title="Optimizing scanned documents with ImageMagick" /><published>2013-05-01T21:35:06+02:00</published><updated>2013-05-01T21:35:06+02:00</updated><id>https://dikant.de/2013/05/01/optimizing-scanned-documents-with-imagemagick</id><content type="html" xml:base="https://dikant.de/2013/05/01/optimizing-scanned-documents-with-imagemagick/"><![CDATA[<p>I am in the process of scanning in all my paper receipts and correspondence. I use a small standalone document scanner that creates jpg images on an SD card. These documents are then converted into searchable PDF files.</p>

<p>The problem is that the images have not enough contrast to be easily readable on screen. Text is usually grey instead of black and you always see a grayish paper background.</p>

<p>Here comes ImageMagick to the rescue. You can easily stretch the color distribution so that light gray becomes white and dark gray becomes black. I use the following command line to modify all images in a folder before converting them to the PDF format:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="k">for </span>img <span class="k">in</span> <span class="k">*</span>.jpg<span class="p">;</span> <span class="k">do </span>mogrify <span class="nt">-normalize</span> <span class="nt">-level</span> 10%,90% <span class="nt">-sharpen</span> 0x1 <span class="nv">$img</span><span class="p">;</span> <span class="k">done</span></code></pre></figure>

<p>The level values fit my requirements. You should try different values if you don’t like the result.</p>

<p>Please note that pictures will look worse after the above step. Text documents will improve but the colors might change a bit.</p>]]></content><author><name>Peter</name></author><category term="Linux" /><category term="Mac" /><category term="ImageMagick" /><category term="Linux" /><category term="Mac" /><summary type="html"><![CDATA[I am in the process of scanning in all my paper receipts and correspondence. I use a small standalone document scanner that creates jpg images on an SD card. These documents are then converted into searchable PDF files. The problem is that the images have not enough contrast to be easily readable on screen. Text is usually grey instead of black and you always see a grayish paper background. Here comes ImageMagick to the rescue. You can easily stretch the color distribution so that light gray becomes white and dark gray becomes black. I use the following command line to modify all images in a folder before converting them to the PDF format: for img in *.jpg; do mogrify -normalize -level 10%,90% -sharpen 0x1 $img; done The level values fit my requirements. You should try different values if you don’t like the result. Please note that pictures will look worse after the above step. Text documents will improve but the colors might change a bit.]]></summary></entry><entry><title type="html">Running OLA without network</title><link href="https://dikant.de/2013/02/24/running-ola-without-network/" rel="alternate" type="text/html" title="Running OLA without network" /><published>2013-02-24T19:09:23+01:00</published><updated>2013-02-24T19:09:23+01:00</updated><id>https://dikant.de/2013/02/24/running-ola-without-network</id><content type="html" xml:base="https://dikant.de/2013/02/24/running-ola-without-network/"><![CDATA[<p>Recently I bought a <a href="http://www.raspberrypi.org" target="_blank">Raspberry Pi</a>. My plan was to use this tiny computer as a lighting controller for my band on stage. I have installed the <a href="http://www.opendmx.net" target="_blank">Open Lighting Architecture</a> (OLA) daemon to talk to a cheap FT232 based DMX interface I bought from ebay and developed a simple lighting controller software in python which uses the OLA ClientWrapper API to talk to the DMX interface.</p>

<!--more-->

<p>To make the DMX interface work, I needed to update the Raspberry kernel as the preinstalled kernel had some issues with the DMX interface. Kernel updates are easy using the rpi-update script from Hexxeh: <a href="https://github.com/Hexxeh/rpi-update" target="_blank">https://github.com/Hexxeh/rpi-update</a></p>

<p>Once everything was working, I tried to run the Raspberry Pi standalone without a network. This is the scenario on stage. Only the Raspberry Pi connected to the light fixtures via DMX. In this scenario OLA refused to start because it was searching for a network interface and ignoring the loopback interface.</p>

<p>A simple workaround is to configure a static ip address for eth0. But then you can no longer use DHCP when connecting to your normal network.</p>

<p>To keep DHCP capabilities and provide a backup network interface when the Raspberry Pi is not connected to a real network, I added a new virtual network interface with a static ip address.</p>

<p>Edit the file <code class="language-plaintext highlighter-rouge">/etc/network/interfaces</code> and add the following lines:</p>

<figure class="highlight"><pre><code class="language-config" data-lang="config"><span class="n">auto</span> <span class="n">eth0</span>:<span class="m">0</span>
<span class="n">iface</span> <span class="n">eth0</span>:<span class="m">0</span> <span class="n">inet</span> <span class="n">static</span>
<span class="n">address</span> <span class="m">10</span>.<span class="m">1</span>.<span class="m">1</span>.<span class="m">100</span>
<span class="n">gateway</span> <span class="m">10</span>.<span class="m">1</span>.<span class="m">1</span>.<span class="m">1</span>
<span class="n">netmask</span> <span class="m">255</span>.<span class="m">255</span>.<span class="m">255</span>.<span class="m">0</span>
<span class="n">broadcast</span> <span class="m">10</span>.<span class="m">1</span>.<span class="m">1</span>.<span class="m">255</span></code></pre></figure>

<p>The above configuration will create a new virtual interface <code class="language-plaintext highlighter-rouge">eth0:0</code> with a static ip address. Make sure that this address is not conflicting with your network.</p>

<p>Now OLA will start without issues even if it is not connected to a network. On stage, I just plug in the Raspberry Pi and once it is booted I can playback scenes via a small USB keypad. No display and no network needed.</p>]]></content><author><name>Peter</name></author><category term="RaspberryPi" /><category term="dmx" /><category term="ola" /><category term="raspberry pi" /><summary type="html"><![CDATA[Recently I bought a Raspberry Pi. My plan was to use this tiny computer as a lighting controller for my band on stage. I have installed the Open Lighting Architecture (OLA) daemon to talk to a cheap FT232 based DMX interface I bought from ebay and developed a simple lighting controller software in python which uses the OLA ClientWrapper API to talk to the DMX interface.]]></summary></entry><entry><title type="html">Setting up server side mail filtering</title><link href="https://dikant.de/2012/05/21/setting-up-server-side-mail-filtering/" rel="alternate" type="text/html" title="Setting up server side mail filtering" /><published>2012-05-21T21:52:37+02:00</published><updated>2012-05-21T21:52:37+02:00</updated><id>https://dikant.de/2012/05/21/setting-up-server-side-mail-filtering</id><content type="html" xml:base="https://dikant.de/2012/05/21/setting-up-server-side-mail-filtering/"><![CDATA[<p>This is a follow up to my former article “<a href="http://www.dikant.de/2007/08/11/setting-up-a-spamsafe-postfix-server/" title="Setting up a spamsafe Postfix server">Setting up a spamsafe Postfix server</a>“. I will describe how to extend that installation to use Sieve for server side mail filtering in Dovecot. This article is based on an Ubuntu 10.04 installation but should work with other Linux distributions.</p>

<!--more-->

<p>Filtering is done in the final mail delivery stage. Normally Postfix will write the messages directly into the Maildir of the user. We need to change the Postfix setting to use the Dovecot delivery agent. Edit the file <code class="language-plaintext highlighter-rouge">/etc/postfix/main.cf</code> and add the following line:</p>

<figure class="highlight"><pre><code class="language-config" data-lang="config"><span class="n">mailbox_command</span> = /<span class="n">usr</span>/<span class="n">lib</span>/<span class="n">dovecot</span>/<span class="n">deliver</span></code></pre></figure>

<p>After a restart, Postfix will forward received messages to Dovecot for delivery:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo</span> /etc/init.d/postfix reload</code></pre></figure>

<p>The deliver tool uses the configuration file <code class="language-plaintext highlighter-rouge">/etc/dovecot/dovecot.conf</code>. Make sure that this file is globally readable:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo chmod </span>644 /etc/dovecot/dovecot.conf</code></pre></figure>

<p>Now we need to edit the file <code class="language-plaintext highlighter-rouge">/etc/dovecot/dovecot.conf</code> and enable sieve and managesieve functionality. First enable the <code class="language-plaintext highlighter-rouge">managesieve</code> protocol. Search the line with the <code class="language-plaintext highlighter-rouge">protocols</code> entry and add <code class="language-plaintext highlighter-rouge">managesieve</code> as a new protocol:</p>

<figure class="highlight"><pre><code class="language-config" data-lang="config"><span class="n">protocols</span> = <span class="n">imap</span> <span class="n">imaps</span> <span class="n">pop3</span> <span class="n">pop3s</span> <span class="n">managesieve</span></code></pre></figure>

<p>Now make sure that the section <code class="language-plaintext highlighter-rouge">lda</code> is enabled and contains the following settings:</p>

<figure class="highlight"><pre><code class="language-config" data-lang="config"><span class="n">protocol</span> <span class="n">lda</span> {
  <span class="n">postmaster_address</span> = <span class="n">postmaster</span>@<span class="n">yourdomain</span>.<span class="n">com</span>
  <span class="n">mail_plugins</span> = <span class="n">sieve</span>
}</code></pre></figure>

<p>Set the path to your sieve scripts in the <code class="language-plaintext highlighter-rouge">plugin</code> section:</p>

<figure class="highlight"><pre><code class="language-config" data-lang="config"><span class="n">sieve</span>=~/.<span class="n">dovecot</span>.<span class="n">sieve</span>
<span class="n">sieve_dir</span>=~/<span class="n">sieve</span></code></pre></figure>

<p>You can now restart Dovecot:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo</span> /etc/init.d/dovecot restart</code></pre></figure>

<p>Server side mail filterin should now be working. You can test it by setting up some rules. I would recommend to use a webmail client like <a href="http://roundcube.net" target="_blank">Roundcube</a> to do this. Roundcube has a very nice client plugin for the managesieve protocol.</p>]]></content><author><name>Peter</name></author><category term="Linux" /><category term="Postfix" /><category term="dovecot" /><category term="postifx" /><category term="sieve" /><summary type="html"><![CDATA[This is a follow up to my former article “Setting up a spamsafe Postfix server“. I will describe how to extend that installation to use Sieve for server side mail filtering in Dovecot. This article is based on an Ubuntu 10.04 installation but should work with other Linux distributions.]]></summary></entry><entry><title type="html">Standalone nginx &amp;amp; PHP Guide for Ubuntu 10.04</title><link href="https://dikant.de/2012/04/25/standalone-nginx-php-guide-for-ubuntu-10-04/" rel="alternate" type="text/html" title="Standalone nginx &amp;amp; PHP Guide for Ubuntu 10.04" /><published>2012-04-25T21:55:24+02:00</published><updated>2012-04-25T21:55:24+02:00</updated><id>https://dikant.de/2012/04/25/standalone-nginx-php-guide-for-ubuntu-10-04</id><content type="html" xml:base="https://dikant.de/2012/04/25/standalone-nginx-php-guide-for-ubuntu-10-04/"><![CDATA[<p>The last 1 or 2 years I have been running nginx as reverse proxy in front of Apache2. Now with the release of nginx version 1.2.0 I decided to revamp my installation and use nginx as a standalone server again. This guide explains my installation which uses <a href="http://wiki.nginx.org/Main" target="_blank">nginx</a>, PHP via FastCGI connector and SSL running on Ubuntu 10.04.</p>

<p>I want to use the current version of nginx, so I use the PPA repository where current nginx builds can be found:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo </span>apt-get <span class="nb">install </span>python-software-properties
<span class="nb">sudo </span>add-apt-repository ppa:nginx/stable
<span class="nb">sudo </span>apt-get update
<span class="nb">sudo </span>apt-get <span class="nb">install </span>nginx</code></pre></figure>

<!--more-->

<p>Currently this will install nginx version 1.2.0. Now install the packages required for php:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo </span>apt-get <span class="nb">install </span>php5-cgi</code></pre></figure>

<p>Now we need to create a start/stop script to start our cgi process. Create a file <code class="language-plaintext highlighter-rouge">/etc/init.d/php-fastcgi</code> with the following contents:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c">#!/bin/sh</span>

<span class="nv">USER</span><span class="o">=</span>www-data
<span class="nv">CHILDREN</span><span class="o">=</span>3
<span class="nv">MAX_REQUESTS</span><span class="o">=</span>1000
<span class="nv">RETVAL</span><span class="o">=</span>0

start<span class="o">()</span> <span class="o">{</span>
    <span class="nb">echo</span> <span class="nt">-n</span> <span class="s2">"Starting PHP FastCGI: "</span>
    start-stop-daemon <span class="nt">--quiet</span> <span class="nt">--start</span> <span class="nt">--background</span> <span class="nt">--chuid</span> <span class="s2">"</span><span class="nv">$USER</span><span class="s2">"</span> <span class="nt">--exec</span> /usr/bin/env <span class="nt">--</span> - <span class="nv">USER</span><span class="o">=</span><span class="nv">$USER</span> <span class="nv">PATH</span><span class="o">=</span>/usr/bin <span class="nv">PHP_FCGI_CHILDREN</span><span class="o">=</span><span class="nv">$CHILDREN</span> <span class="nv">PHP_FCGI_MAX_REQUESTS</span><span class="o">=</span><span class="nv">$MAX_REQUESTS</span> /usr/bin/php-cgi <span class="nt">-b</span> 127.0.0.1:9000
    <span class="nv">RETVAL</span><span class="o">=</span><span class="nv">$?</span>
    <span class="nb">echo</span> <span class="s2">"OK"</span>
<span class="o">}</span>

stop<span class="o">()</span> <span class="o">{</span>
    <span class="nb">echo</span> <span class="nt">-n</span> <span class="s2">"Stopping PHP FastCGI: "</span>
    killall <span class="nt">-q</span> <span class="nt">-w</span> <span class="nt">-u</span> <span class="nv">$USER</span> /usr/bin/php-cgi
    <span class="nv">RETVAL</span><span class="o">=</span><span class="nv">$?</span>
    <span class="nb">echo</span> <span class="s2">"OK"</span>
<span class="o">}</span>

<span class="k">case</span> <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> <span class="k">in
    </span>start<span class="p">)</span>
        start
    <span class="p">;;</span>
    stop<span class="p">)</span>
        stop
    <span class="p">;;</span>
    restart<span class="p">)</span>
        stop
        start
    <span class="p">;;</span>
    <span class="k">*</span><span class="p">)</span>
        <span class="nb">echo</span> <span class="s2">"Usage: php-fastcgi {start|stop|restart}"</span>
        <span class="nb">exit </span>1
    <span class="p">;;</span>
<span class="k">esac</span>

<span class="nb">exit</span> <span class="nv">$RETVAL</span></code></pre></figure>

<p>This script will start 3 PHP worker processes which will server up to 1000 requests each. Make the script executable:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo chmod </span>a+x /etc/init.d/php-fastcgi</code></pre></figure>

<p>Now you can try to start the php daemon:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo</span> /etc/init.d/php-fastcgi start</code></pre></figure>

<p>You should see the daemons in the process list. If everything is running so far, enable autostart for the service:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo </span>update-rc.d php-fastcgi defaults</code></pre></figure>

<p>The next step is to create a self signed SSL certificate:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash">openssl req <span class="nt">-new</span> <span class="nt">-x509</span> <span class="nt">-days</span> 4312 <span class="nt">-nodes</span> <span class="nt">-keyout</span> /etc/nginx/web.pem <span class="nt">-out</span> /etc/nginx/web.pem</code></pre></figure>

<p>When filling out the certificate details, make sure that you enter your domain name in the field “Common Name”. The above command will create a self signed certificate file.</p>

<p>The last step is to create virtual host configurations for nginx. Here is an example which can act as a boilerplate to setting up a new vhost which will listen on http and https. Let’s say we want to create a vhost for a domain <code class="language-plaintext highlighter-rouge">mydomain.com</code> where the files are located at <code class="language-plaintext highlighter-rouge">/srv/www/vhosts/mydomain.com/httpdocs</code>. Create a new file <code class="language-plaintext highlighter-rouge">/etc/nginx/sites-available/mydomain.com</code> with the following contents:</p>

<figure class="highlight"><pre><code class="language-nginx" data-lang="nginx"><span class="k">server</span> <span class="p">{</span>
    <span class="kn">listen</span> <span class="mi">80</span><span class="p">;</span>
    <span class="kn">listen</span> <span class="mi">443</span> <span class="s">ssl</span><span class="p">;</span>
    <span class="kn">server_name</span> <span class="s">mydomain.com</span> <span class="s">www.mydomain.com</span><span class="p">;</span>
 
    <span class="kn">ssl_certificate</span> <span class="n">/etc/nginx/web.pem</span><span class="p">;</span>
    <span class="kn">ssl_certificate_key</span> <span class="n">/etc/nginx/web.pem</span><span class="p">;</span>
  
    <span class="kn">access_log</span> <span class="n">/srv/www/vhosts/mydomain.com/logs/access.log</span> <span class="s">combined</span><span class="p">;</span>
    <span class="kn">error_log</span> <span class="n">/srv/www/vhosts/mydomain.com/logs/error.log</span><span class="p">;</span>

    <span class="kn">root</span> <span class="n">/srv/www/vhosts/mydomain.com/httpdocs</span><span class="p">;</span>

    <span class="kn">index</span> <span class="s">index.php</span><span class="p">;</span>

    <span class="kn">location</span> <span class="n">/</span> <span class="p">{</span>
        <span class="kn">try_files</span> <span class="nv">$uri</span> <span class="nv">$uri</span><span class="n">/</span> <span class="n">/index.php</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="kn">location</span> <span class="p">~</span> <span class="sr">\.php</span> <span class="p">{</span>
        <span class="kn">try_files</span> <span class="nv">$uri</span> <span class="p">=</span> <span class="mi">404</span><span class="p">;</span>
        <span class="kn">include</span> <span class="n">/etc/nginx/fastcgi_params</span><span class="p">;</span>
        <span class="kn">fastcgi_param</span> <span class="s">SCRIPT_FILENAME</span> <span class="nv">$document_root$fastcgi_script_name</span><span class="p">;</span>
        <span class="kn">fastcgi_pass</span> <span class="nf">127.0.0.1</span><span class="p">:</span><span class="mi">9000</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span></code></pre></figure>

<p>If you want to redirect all non-ssl traffic to the https port, add the following lines inside the server block:</p>

<figure class="highlight"><pre><code class="language-nginx" data-lang="nginx"><span class="k">if</span> <span class="s">(</span><span class="nv">$ssl_protocol</span> <span class="p">=</span> <span class="s">"")</span> <span class="p">{</span>
   <span class="kn">rewrite</span> <span class="s">^</span> <span class="s">https://</span><span class="nv">$server_name$request_uri</span><span class="s">?</span> <span class="s">permanent</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>

<p>To activate the vhost, create a symbolic link in the directory <code class="language-plaintext highlighter-rouge">/etc/nginx/sites-enabled/</code>:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">ln</span> <span class="nt">-s</span> /etc/nginx/sites-available/mydomain.com /etc/nginx/sites-enabled/mydomain.com</code></pre></figure>

<p>And now reload the nginx configuration:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo</span> /etc/init.d/nginx reload</code></pre></figure>

<p>Everything should be working by now.</p>]]></content><author><name>Peter</name></author><category term="nginx" /><category term="PHP" /><category term="nginx" /><category term="PHP" /><category term="ssl{% endhighlight %}" /><summary type="html"><![CDATA[The last 1 or 2 years I have been running nginx as reverse proxy in front of Apache2. Now with the release of nginx version 1.2.0 I decided to revamp my installation and use nginx as a standalone server again. This guide explains my installation which uses nginx, PHP via FastCGI connector and SSL running on Ubuntu 10.04. I want to use the current version of nginx, so I use the PPA repository where current nginx builds can be found: sudo apt-get install python-software-properties sudo add-apt-repository ppa:nginx/stable sudo apt-get update sudo apt-get install nginx]]></summary></entry><entry><title type="html">Quickie: Change Time Machine interval</title><link href="https://dikant.de/2012/01/28/quickie-change-time-machine-interval/" rel="alternate" type="text/html" title="Quickie: Change Time Machine interval" /><published>2012-01-28T15:25:42+01:00</published><updated>2012-01-28T15:25:42+01:00</updated><id>https://dikant.de/2012/01/28/quickie-change-time-machine-interval</id><content type="html" xml:base="https://dikant.de/2012/01/28/quickie-change-time-machine-interval/"><![CDATA[<p>Here is a quick shell snippet to change the time machine backup interval on OSX. The time interval is specified in seconds. If you want to change it to 4 hours open terminal and enter:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo </span>defaults write /System/Library/LaunchDaemons/com.apple.backupd-auto.plist StartInterval <span class="nt">-int</span> 14400</code></pre></figure>

<p>You can restore the default interval with:</p>

<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">sudo </span>defaults write /System/Library/LaunchDaemons/com.apple.backupd-auto.plist StartInterval <span class="nt">-int</span> 3600</code></pre></figure>]]></content><author><name>Peter</name></author><category term="Apple" /><category term="Mac" /><category term="apple" /><category term="backup" /><category term="interval" /><category term="shell" /><category term="TimeMachine" /><summary type="html"><![CDATA[Here is a quick shell snippet to change the time machine backup interval on OSX. The time interval is specified in seconds. If you want to change it to 4 hours open terminal and enter: sudo defaults write /System/Library/LaunchDaemons/com.apple.backupd-auto.plist StartInterval -int 14400 You can restore the default interval with: sudo defaults write /System/Library/LaunchDaemons/com.apple.backupd-auto.plist StartInterval -int 3600]]></summary></entry></feed>