<h1 id="title">Emacs daemon as a runit service</h1>
<div id="dates">
<span>Posted: <time id="post-date">2018-06-09</time></span>
</div>
<p><span class="bold caps">Updated:</span> See <a href="/blog/emacs-daemon-runit-user-service/">this entry</a> on an Emacs daemon "user service" with runit!</p>
<p id="post-excerpt">
So, you want to run an Emacs daemon as a runit service - and you also want to connect to it in your desktop session. Thanks to the new <code>--fg-daemon</code> option in Emacs 26.x you now can! I'm going to describe how to set up the service, as well as <code>sudo</code> rules for managing it without requiring a password each time. Read on for the exciting details!
</p>
<div id="toc"></div>
<h4>Requirements</h4>
<p>Before you get too excited, there's a few prerequisites you'll need for this to be possible:</p>
<ul>
<li>Emacs 26+: As I've already mentioned, the <code>--fg-daemon</code> option was just added in Emacs 26 so you'll need that version.</li>
<li>Runit: It doesn't have to be your PID1 (but maybe it should be?), but you of course need it running, doing its thing.</li>
</ul>
I'll also go into detail about how to configure <code>sudo</code> as well as hotkeys for OpenBox.
<h4>The Service</h4>
<p>The service "run" file is below:</p>
<pre><code>#!/bin/sh
export HOME=/home/hristos
cd $HOME
exec chpst -u hristos:hristos /usr/bin/emacs --fg-daemon=hristos-emacsd 2>&1</code></pre>
<p>Nothing too crazy for a runit service here. I export my user's home directory as <code>$HOME</code>, this way Emacs can find my <code>~/.emacs.d/</code> directory. I'm also naming the server's socket -- this way I can just pass that name to <code>emacsclient</code> when I want to attatch:</p>
<pre><code>$ emacsclient --socket-name=hristos-emacsd -c -n</code></pre>
<p>This is nicer than having to give the path to the server's socket; easier for a human to reason about.</p>
<h4>Optional Logging</h4>
<p>This is optional, but I prefer to add logging to all runit services. Doing this is standard fare for a runit service; Create a direcory called "log" in the root of your "emacs-daemon" service directory, and within that put a file called "run" with the below contents:</p>
<pre><code>#!/bin/sh
exec logger -t emacs-daemon</code></pre>
<p>Make sure you have something like <code>rsyslog</code> installed, and then you'll be able to find your "emacs-daemon" service logs in <code>/var/log/syslog</code> or wherever your logs go. You can of course look at this output in the <code>*Messages*</code> buffer, but what the hay am I right?</p>
<h4>Run It</h4>
<p>Now's the time to enable the service so that it can be used:</p>
<pre><code># ln -s /path/to/emacs-daemon /var/service/</code></pre>
<p>Alter the paths to match where your things actually are, and then that's it. The Emacs daemon is now running.</p>
<h4>Connecting</h4>
<p>As I showed above, you can now connect with a simple invocation of <code>emacsclient</code>, but some aliases would be a lot better. For fish, I use this function:</p>
<pre><code>function emacs
command emacsclient --socket-name=hristos-emacsd -c -n $argv ; or \
zenity --error --no-wrap --text 'Failed to connect to the Emacs daemon!' ^/dev/null
end</code></pre>
<p>Now, anytime I invoke <code>emacs</code> from the command line, I'll attach to the daemon. If it isn't running (and if you have zenity installed), then a message will pop up saying it was unable to connect. And for you OpenBox users out there, add the following in your <code>rc.xml</code>:</p>
<pre><code> <keybind key="W-e">
<action name="Execute">
<startupnotify>
<enabled>true</enabled>
<name>Emacs</name>
</startupnotify>
<command>fish -c "emacs"</command>
</action>
</keybind></code></pre>
<p>Now you can open Emacs, and connect to your daemon with a simple press of "Meta+E"!</p>
<h4>Sudo Rules</h4>
<p>Although it's actually simple to close the daemon from within Emacs itself, thus prompting runit to relaunch a new process, it's still great to be able to use <code>sv</code> to manage the service if need be. Even better, you can use sudo rules to allow you to do this without needing a password. Put the following in <code>/etc/sudoers.d/emacs-daemon</code>:</p>
<pre><code>Cmnd_Alias EMACSD_CMDS=/usr/bin/sv check emacs-daemon,/usr/bin/sv start emacs-daemon,/usr/bin/sv stop emacs-daemon,/usr/bin/sv restart emacs-daemon
hristos ALL=(ALL) NOPASSWD: EMACSD_CMDS</code></pre>
<p>Of course replace user names and commands as needed, but that's all you need.</p>
<h4>Conclusion</h4>
<p>For a long time I managed an Emacs daemon outside of runit (or any other service manager) and it was fine; One can run <code>emacsclient</code> with the <code>--alternative-editor=''</code> option and that will start the daemon if it's not already running. But having it start with your system, and having simple system-level controls for it is pretty useful and worthwhile considering the small amounts of effort required to implement.</p>