<?xml version="1.0" encoding="UTF-8"?><feed xmlns:a="http://www.w3.org/2005/Atom"><title>Epiccastle Blog</title><subtitle>Epiccastle.io Updates</subtitle><link href="https://epiccastle.io/blog/feed.xml" rel="self"/><link href="https://epiccastle.io/blog/"/><id>https://epiccastle.io/blog/</id><updated>2026-06-18T10:14:10.278986448+08:00</updated><author><name>Crispin Wellington</name></author><entry><title>Announcing ClojureSSH</title><link href="https://epiccastle.io/blog/announcing-clojuressh"/><id>https://epiccastle.io/blog/announcing-clojuressh</id><updated>2026-06-12T22:39:15+08:00</updated><published>2026-06-12T22:39:15+08:00</published><author><name>Crispin Wellington</name></author><content type="html"><![CDATA[<img alt="Crispin Wellington" class="blog-splash" src="https://epiccastle.io/blog/announcing-clojuressh/splash-20.jpg" style="width:50%" /><h1 id="clojuressh:-unified-ssh-support-for-clojure-and-babashka">clojuressh: Unified SSH Support for Clojure and Babashka</h1><p>A while back I wrote about <a href="https://epiccastle.io/blog/a-plan-for-spire/">my plans for Spire</a> saying that the codebase needed to be broken into smaller, more focused libraries. The first of those was <a href="https://github.com/epiccastle/bbssh"><code>bbssh</code></a>. The second is <a href="https://github.com/epiccastle/clojuressh"><code>clojuressh</code></a>. It is a Clojure library wrapping JSch, extracted and cleaned up from the SSH support that&apos;s been inside Spire for years, and made API compatible with bbssh.</p><p><code>clojuressh</code> gives you SSH from Clojure without requiring a local <code>ssh</code> binary. It covers:</p><ul><li>Remote command execution</li><li>SCP file transfer</li><li>Port forwarding</li><li>Proxy support</li><li>SSH agent integration</li><li>SSH authentication support</li><li>Session and channel management</li><li>Host key and known hosts handling</li><li>Key pair operations (load, generate, decrypt, write)</li><li>SSH config file parsing</li><li>Terminal utilities (raw mode, terminal dimensions, readline)</li><li>Custom user-info callbacks for interactive prompts</li><li>Integration with babashka.process</li></ul><h2 id="api-compatibility-with-bbssh">API Compatibility with bbssh</h2><p><code>clojuressh</code> was designed to share its API with <a href="https://github.com/epiccastle/bbssh">bbssh</a>. The namespaces and function signatures are identical across both. The version numbers match for compatibility. So clojuressh 0.7.0 is the first release and matches the API of bbssh 0.7.0. This version sync will continue with dual releases going forwards.</p><h2 id="using-it-in-babashka-instead-of-bbssh">Using it in Babashka Instead of bbssh</h2><p>One interesting facet of <code>clojuressh</code> is that it can be used directly as a dependency inside babashka. In this case it acts as a shim to the bbssh pod. This means you can add it as a dep in your <code>deps.edn</code> and use it the same way in both Clojure and Babashka. There is no need for reader conditionals or pod-loading boilerplate.</p><pre><code class="language-clojure">;; deps.edn - works for both `clj` and `bb`
{:paths [&quot;src&quot;]
 :deps {org.clojure/clojure {:mvn/version &quot;1.12.5&quot;}
        io.epiccastle/clojuressh {:mvn/version &quot;0.7.0&quot;}}}
</code></pre><pre><code class="language-clojure">(ns myapp.core
  (:require [clojuressh.core :as ssh]
            [clojuressh.session :as session])
            [clojuressh.terminal :as terminal]))

(defn -main []
  (terminal/get-width) ;; print JNA warning early on JDK 22+
  (let [s (ssh/ssh &quot;my-host&quot;)]
    (-&gt; (ssh/exec s &quot;uname -a&quot; {:out :string})
        deref
        :out
        println)
    (session/disconnect s)))
</code></pre><p>Run with Clojure:</p><pre><code class="language-shell">clj -M -m myapp.core
</code></pre><p>Run with babashka:</p><pre><code class="language-shell">bb --config deps.edn -m myapp.core
</code></pre><h2 id="differences-from-clj-ssh">Differences from clj-ssh</h2><p>If you are just writing code for clojure and don&apos;t care about Babashka why not just use clj-ssh? Here&apos;s a few things <code>clojuressh</code> does differently:</p><p><strong>SCP.</strong> I originally used clj-ssh in Spire but ran into limitations with its SCP implementation. The SCP code in <code>clojuressh</code> comes from Spire where it has had a lot of real-world use. clj-ssh fails to preserve timestamps or file permissions on files that are copied. <code>clojuressh</code> also supports a <code>progress-fn</code> that can be passed a callback and used to monitor the progress of the copy making it easy to implement things like user feedback.</p><p><strong>Default user interactions.</strong> clojuressh integrates with your existing keychain. In the case of presented keys that need decrypting or passwords that need entering, clojuressh falls back to behaviour just like ssh, prompting the user. The same is true for unknown host keys, asking the user if you want to trust the unknown host key and then adding it to known hosts.</p><p><strong>SSH config file parsing.</strong> <code>clojuressh.config-repository</code> can read <code>~/.ssh/config</code>, picking up your host aliases, port overrides, and identity file settings.</p><p><strong>Terminal management.</strong> The <code>clojuressh.terminal</code> namespace handles raw mode, terminal size, and readline which can be useful if you&apos;re building anything interactive.</p><p><strong>Inter-operation with babashka.process.</strong> <code>clojuressh.core/exec</code> supports process threading with <code>-&gt;</code> to and from <code>babashka.process</code> processes. This means you can stream stdout from a local shell command to a remote command and back to a local process again with a single <code>-&gt;</code>:</p><pre><code class="language-clojure">(-&gt; (babashka.process/process &quot;echo this is local&quot;)
    (clojuressh.core/exec &quot;md5sum&quot; {:session session})
    (babashka.process/process
        &quot;bash -c \&quot;echo &apos;our sum: $(cat)&apos;\&quot;&quot;
        {:out :string})
    deref
    :out)
;; =&gt; &quot;our sum: 4088b54321c3a731eda432ab09fa9f63 -\n&quot;
</code></pre><blockquote><p><strong>Note on JDK 22+:</strong> <code>clojuressh</code> uses JNA for terminal handling. On JDK 22 and newer the JVM will print a warning the first time a native library loads. This isn&apos;t an error. The README covers how to silence it with <code>--enable-native-access=ALL-UNNAMED</code> or to print it early. It&apos;s confusing because it usually pops up just after clojuressh prompts for the user password.</p></blockquote><h2 id="get-your-hands-on-it">Get your hands on it</h2><p>Use the following coordinates:</p><pre><code class="language-clojure">;; tools.deps
io.epiccastle/clojuressh {:mvn/version &quot;0.7.0&quot;}

;; Leiningen
[io.epiccastle/clojuressh &quot;0.7.0&quot;]
</code></pre><p>Find the github project <a href="https://github.com/epiccastle/clojuressh">here</a> or read the documentation <a href="https://epiccastle.io/clojuressh/0.7.0">here</a>.</p>]]></content></entry><entry><title>Uniting C and Clojure in Bbssh</title><link href="https://epiccastle.io/blog/uniting-c-and-clojure-in-bbssh"/><id>https://epiccastle.io/blog/uniting-c-and-clojure-in-bbssh</id><updated>2026-05-04T22:03:50+08:00</updated><published>2026-05-04T22:03:50+08:00</published><author><name>Crispin Wellington</name></author><content type="html"><![CDATA[<img alt="Crispin Wellington" class="blog-splash" src="https://epiccastle.io/blog/uniting-c-and-clojure-in-bbssh/splash-20.jpg" style="width:50%" /><p>Bbssh is a Babashka pod that provides an SSH implementation to your Babashka code. It&apos;s compiled with GraalVM&apos;s native image into a single executable. Part of Bbssh is written in C. In the past, I integrated C code using JNI. I bundled the JNI shared library into the native image, and at runtime it was extracted to the file-system. The Java library path was updated to include that location, and the library was then loaded.</p><p>There are some down sides to this approach: it&apos;s cumbersome, it&apos;s not supported with a musl linked static image on Linux, the shared library has to be specially crafted for JNI to call it and the JNI calls are somewhat slower than what could be achieved with direct linking.</p><p>There is a new way to achieve this hybrid Java/C project. The GraalVM has a layer called the substrate that now allows direct linking to C code. Your C code can be statically or dynamically linked in with your executable. The coupling is efficient and fast. However it only works with native images.</p><p>I built a C library that can be linked directly into a GraalVM native image, but can also be loaded through JNI when running on a JVM. Thus I can continue to do development work with the JNI method and then build the release version with the substrate linking. This article is going to lay out how I achieved this. I am going to be simplifying things to clarify the important parts while also providing links to the full code for deeper investigation.</p><p>I found <a href="https://yyhh.org/blog/2021/02/writing-c-code-in-javaclojure-graalvm-specific-programming/">HuaHai&apos;s post here</a> to be very helpful and should serve you as a useful reference. I did not use the method of copying the libs during static initialisation as he did, instead opting to alter the search paths of the compiler and linker themselves to find the associated files. I found that to be simpler (although this method was impossible in the case of Windows and I had to fall back to copying which I will discuss later).</p><h4 id="the-c-library">The C library</h4><p>I create a basic C library with no JNI. Composed of a number function like this in a file <code>bbssh.c</code>:</p><pre><code class="language-C">int is_stdout_a_tty() {
  return isatty(STDOUT_FILENO);
}
</code></pre><p>And there is a matching header line in <code>bbssh.h</code>:</p><pre><code class="language-C">int is_stdout_a_tty();
</code></pre><p>For all the functions present in the library I have to write a java file containing the substrate binding. I called my class <code>BbsshUtils</code> and the important part looks like this:</p><pre><code class="language-java">@CContext(BbsshUtils.Directives.class)
public final class BbsshUtils {
    public static final class Directives implements CContext.Directives {
        @Override
        public List&lt;String&gt; getHeaderFiles() {
            return Collections.singletonList(&quot;\&quot;bbssh.h\&quot;&quot;);
        }

        @Override
        public List&lt;String&gt; getLibraries() {
            return Arrays.asList(&quot;bbssh&quot;);
        }
    }
    @CFunction(&quot;is_stdout_a_tty&quot;)
    public static native int is_stdout_a_tty();
}
</code></pre><p>The <code>@CContext</code> annotation tells native-image which static class contains the information needed. It specifies the header file (or files), in this case <code>bbssh.h</code>. And it specifies the library to link with, in this case it is <code>bbssh</code>, so would link with bbssh.a, bbssh.lib, libbbssh.so, libbbssh.dylib depending on the method of linking and the platform.</p><p>The main body of the class contains methods annotated by <code>@CFunction</code>. This tells native-image which C function the method calls.</p><p>Sometimes the interface between Java and C required some extra convenience processing on the Java side. In these cases I named the direct native java method something slightly different to the C function, and then made another method with that name that did the various type conversions and processing. For example, to pass a Java string into a function requiring a C style char pointer I did the following:</p><pre><code class="language-java">    @CFunction(&quot;ssh_auth_socket_read&quot;)
    public static native int cssh_auth_socket_read(int fd, CCharPointer buffer, int count);

    public static int ssh_auth_socket_read(int fd, byte[] buf, int count)
    {
        return cssh_auth_socket_read
            (
             fd,
             org.graalvm.nativeimage.c.type.CTypeConversion.toCBytes(buf).get(),
             count
             );
    }
</code></pre><h4 id="compiling">Compiling</h4><p>Now I can compile my C library. For static linking I want a static library file. This is done the same way on mac and Linux. You will need to adjust the GraalVM include folders for your situation and platform.</p><pre><code class="language-shell">cc -I/home/crispin/graalvm-jdk-24.0.2+11.1/include -I/home/crispin/graalvm-jdk-24.0.2+11.1/include/linux -c src/c/bbssh.c -o libbbssh.a
</code></pre><p>On windows this is a little different. We must make a .lib archive. It goes something like this:</p><pre><code class="language-powershell">cl /c src\c\bbssh.c
lib /out:bbssh.lib bbssh.obj
</code></pre><p>So on Linux and mac we have a <code>libbbssh.a</code> file. On windows we have a <code>bbssh.lib</code> file. These are what will be statically linked into the native-image.</p><h4 id="native-image">native-image</h4><p>To statically link this custom library file in the native image build you pass the <code>--native-compiler-options</code> flag to <code>native-image</code>, and it will include any flags you give it into the build and link steps. You will need to give it an extra <code>-I</code> flag for header includes and a <code>-L</code> flag to point to the location of the library file you just built. These are just directory locations. Remember the actual name of the header file and the name of the library file are specified in the Java binding source files under the <code>@CContext</code> annotation.</p><p>In short, you will pass in some extra arguments like:</p><pre><code class="language-shell">native-image \
--native-compiler-options=-I/path/to/project/src/c \
--native-compiler-options=-L/path/to/project/build \
... many more args ...
</code></pre><p>Bbssh has so many different arrangements for these parameters for different platforms and static vs dynamically linked builds that I broke the varying parameters out into the <a href="https://github.com/epiccastle/bbssh/blob/main/deps.edn#L23">deps.edn</a> inside the :aliases section, and launch the relevant native-image build code from my <a href="https://github.com/epiccastle/bbssh/blob/main/build.clj">build.clj</a> with a <code>clojure -M:alias-name</code></p><h4 id="windows-difficulties">Windows difficulties</h4><p>On windows you can pass in the location of extra include files to the underlying windows C compiler and linker with:</p><pre><code class="language-shell">--native-compiler-options=/IC:\path\to\project\src\c
</code></pre><p>But the <strong>Microsoft linker simply cannot</strong> be made to look in more places for library files for linking. You can pass in a <code>/L</code> argument, and this is passed through by GraalVM&apos;s native-image, but the windows compiler does not pass it through to the linker. This appears to be a problem with Window&apos;s build tools themselves.</p><p>To work around this you have to copy the library file you built into the libs folder that GraalVM is using in the build before running native image. It&apos;s an ugly hack but it works. You will need a copy directive like the following in powershell:</p><pre><code class="language-powershell">copy build\bbssh.lib C:\Users\myuser\project\graalvm\graalvm-jdk-24.0.2+11.1\lib\static\windows-amd64\
</code></pre><p>The lib will now be found and the <code>.exe</code> will be generated successfully.</p><h4 id="supporting-jni-for-java-based-development">Supporting JNI for Java based development</h4><p>When developing day to day, it&apos;s faster to build the C code as a shared library and call it through Java&apos;s JNI. We can keep the static native‑image build for production and use the JNI version during development.</p><p>At this point it&apos;s pretty simple. As well as building the <code>build/libbbssh.a</code> file, we also build a <code>build/libbbssh.so</code> file from the same source. We will need the JNI binding file here (<code>src/c/jni/BbsshUtils.c</code> for us) to facilitate this build. You can find out about making this file from documentation on JNI.</p><p>Here are the two build commands side by side on Linux:</p><pre><code class="language-bash"># build static lib
cc -I/home/crispin/graalvm-jdk-24.0.2+11.1/include -I/home/crispin/graalvm-jdk-24.0.2+11.1/include/linux -c src/c/bbssh.c -o build/libbbssh.a

# build JNI shared library
cc -I/home/crispin/graalvm-jdk-24.0.2+11.1/include -I/home/crispin/graalvm-jdk-24.0.2+11.1/include/linux -shared -Isrc/c src/c/jni/BbsshUtils.c src/c/bbssh.c -fPIC -o build/libbbssh.so
</code></pre><p>In your mainline code you can detect at runtime if you are using the Substrate VM and load the shared object if you are not:</p><pre><code class="language-clojure">(defn native-image? []
  (and (= &quot;Substrate VM&quot; (System/getProperty &quot;java.vm.name&quot;))
       (= &quot;runtime&quot; (System/getProperty &quot;org.graalvm.nativeimage.imagecode&quot;))))

(defn -main [&amp; args]
  ;; parse args and setup

  ;; load a shared library with JNI in development
  (when-not (native-image?)
    (clojure.lang.RT/loadLibrary &quot;bbssh&quot;))

  ;; now run mainline
)
</code></pre><p>So in summary you will have <strong>two</strong> <code>BbsshUtils.java</code> binding files, one for JNI, and one for Substrate VM. In you code you will simply require BbsshUtils and call the functions there in. You need to make sure that the paths are setup so that development will see one, and native builds will see the other. I just did this with <code>:extra-paths</code> in my <code>deps.edn</code>.</p><pre><code class="language-clojure">(BbsshUtils/is-stdout-a-tty)
</code></pre><p>For completeness, here is the <a href="https://github.com/epiccastle/bbssh/blob/main/src/c/jni/BbsshUtils.java">JNI binding file</a> and here is the <a href="https://github.com/epiccastle/bbssh/blob/main/src/c/native/BbsshUtils.java">Substrate VM binding file</a> for you to compare.</p><p>May your images be native and your builds be small.</p>]]></content></entry><entry><title>A Plan for Spire</title><link href="https://epiccastle.io/blog/a-plan-for-spire"/><id>https://epiccastle.io/blog/a-plan-for-spire</id><updated>2022-08-30T23:08:15+08:00</updated><published>2022-08-30T23:08:15+08:00</published><author><name>Crispin Wellington</name></author><content type="html"><![CDATA[<img alt="Crispin Wellington" class="blog-splash" src="https://epiccastle.io/blog/a-plan-for-spire/splash-20.jpg" style="width:50%" /><p>The Spire code base is in a bit of a state. It was never the cleanest code but the addition of babashka pod support has increased its complexity a lot. There are multiple code paths, duplicated (but slightly different) namespaces, clojure code inside strings and namespace inspecting macros that test your ability to reason.</p><p>After the podification it got to the point that I couldn&apos;t bear to work on it anymore. I felt burnt out. Adding things or fixing bugs became a daunting prospect. I did not know how to make it right.</p><p>This break from the project gave me some perspective. Slowly I realised what needed to be done. This post is to layout the future direction of spire development.</p><p>I plan for one more release of spire as it presently stands to set free the latest bug-fixes and improvements. Then I will undertake a large development effort to rebuild it from the ground up. At the end of this work it should work much as it does now. Perhaps it will do even more. But it will certainly be a much more stable foundation on which to build more features and it will be composed of parts that can be reused in different places and contexts.</p><h4 id="decomplect-the-parts">Decomplect the Parts</h4><p>The code base complects all of the things into one mess. It&apos;s nice that it&apos;s one binary but we can keep that and also have the separate components that can be used to make other nice things. Not everyone who wants SSH wants idempotent scripts. Not everyone wanting idempotent scripts wants them executed over SSH. Some people want its functionality in the JVM, some in babashka. Perhaps even in future it might run on a JavaScript platform.</p><h4 id="just-the-ssh-bits.">Just the SSH bits.</h4><p>I think the SSH support inside spire is very complete. I initially used clj-ssh but found bugs and unimplemented features. I found scp support in particular was buggy. These things all work in spire but you cannot use them outside of it. The SSH functionality should be available on its own.</p><p>So the first step is to break out the low level SSH support into a library. Because of how different writing a pod and writing a clojure library are, there will be two projects. These two libraries will strive to be as similar in API design as I can make them.</p><h5 id="bbssh">bbssh</h5><p>This will be a babashka pod providing SSH functionality. It will <em>only</em> provide SSH functionality. I will try and expose as much of JSch in pod form as I can. I have begun this work. It is <a href="https://github.com/epiccastle/bbssh">underway here</a>.</p><h5 id="clojuressh">clojuressh</h5><p>This will be a clojure library exposing JSch functionality in a clojure friendly way. It will be uploaded to clojars to be used from your <code>deps.edn</code> or <code>project.clj</code>.</p><h4 id="just-the-idempotent-scripts">Just the Idempotent scripts</h4><p>Similarly, not everyone who wants to run idempotent system scripts wants to do it over SSH. So this part of spire will be broken out into a library. This library will construct bash scripts that perform idempotent operations. How you consume them is optional. Potentially a whole bunch of them could be appended together into a big static uberscript that will do basic provisioning! Spire will become a consumer of this library.</p><h4 id="spire-becomes-a-cljc-library">Spire becomes a cljc library</h4><p>Spire can then become a pure clojure library. By using cljc reader tags the differences between the babashka version and the clojure version can be elegantly expressed. Babashka will evaluate <code>:bb</code> tagged code if it comes before a <code>:clj</code> tag. The spire code will become clean and elegant!</p><h4 id="falling-behind-babashka">Falling behind babashka</h4><p>Spire&apos;s execution environment has fallen significantly behind babashka&apos;s. I would like spire to support the consumption of pods and clojure libraries. This is already present in babashka. Implementing this in spire is just duplicate work. And so it is likely I will eventually retire the spire binary. Spire will then not contain sci, or evaluate any clojure code. It will be a library.</p><p>To provide an upgrade path the spire binary will be replaced by a small shim script that will launch babashka. Using some pre-execution scripts the babashka execution environment could be made to <code>require</code> the namespaces that spire has by default. The hope is that spire scripts should continue to work without much need of change by running inside babashka.</p><p>That&apos;s the plan. Now for the hard work of doing it...</p>]]></content></entry><entry><title>Hot loading WASM</title><link href="https://epiccastle.io/blog/hot-loading-wasm"/><id>https://epiccastle.io/blog/hot-loading-wasm</id><updated>2022-03-21T16:04:07+08:00</updated><published>2022-03-21T16:04:07+08:00</published><author><name>Crispin Wellington</name></author><content type="html"><![CDATA[<img alt="Crispin Wellington" class="blog-splash" src="https://epiccastle.io/blog/hot-loading-wasm/splash-20.jpg" style="width:50%" /><h3 id="hot-loading-c-wasm-with-heap-preservation">Hot loading C wasm with heap preservation</h3><p>Wasm, or WebAssembly, is a very fast stack machine that happens to be buried in your browser. You can compile all kinds of low level code to wasm and have it execute at break-neck speed. But we like Clojure and clojurians love hot loading their code for maximal development cycles. Here is how I set up a hot loading wasm environment using clang, shadow-cljs and babashka. I also managed to preserve the WebAssembly heap between loads to really enhance that Clojure experience.</p><h4 id="clang">Clang</h4><p>I&apos;m using clang to compile my C. You could use any wasm language. The <code>makefile</code> I use to build it looks in part like:</p><pre><code class="language-makefile">CLANG_DIR = $(HOME)/clang+llvm-13.0.1-x86_64-linux-gnu-ubuntu-18.04
CLANG = $(CLANG_DIR)/bin/clang
LLC = $(CLANG_DIR)/bin/llc
LD = $(CLANG_DIR)/bin/wasm-ld

C_SRC := $(wildcard src/c/*.c)
OBJ_SRC := $(patsubst %.c, %.o, $(C_SRC))

%.o: %.c # delete competing implicit rule

%.ll: %.c
    $(CLANG) \
        --target=wasm32	\
        -emit-llvm \
        -c \
        -S \
        -std=c99 \
        -o $@ \
        -nostdlib \
        $&lt;

%.o: %.ll
    $(LLC) \
        -march=wasm32 \
        -filetype=obj \
        $&lt;

resources/public/wasm/mymodule.wasm: $(OBJ_SRC)
    $(LD) \
        --no-entry \
        --strip-all \
        --import-memory \
        --export=__heap_base \
        -o $@ \
        $^

</code></pre><p><code>-nostdlib</code> tells the compiler that we wont be linking with any libc (so no printf!). <code>--import-memory</code> tells the linker that we will be passing our memory into the module rather than letting the module create it for us. <code>--export=__heap_base</code> is needed so the module will report where the heap begins in memory when it is loaded.</p><p>With no other explicit <code>--export</code> arguments we need a way to choose what functions to export from our module. This is done directly in our C code with the <code>export_name</code> clang attribute like this:</p><pre><code class="language-cpp">__attribute__((export_name(&quot;calc&quot;)))
int calc(int a, int b)
{
  return a*b;
}
</code></pre><p>And now we can compile the wasm code with</p><pre><code class="language-shell">$ make resources/public/wasm/mymodule.wasm
</code></pre><h4 id="memory">Memory</h4><p>I need to construct the WebAssembly Memory object myself as this will be reused between instances. I will pass this Memory object into the module instantiation later. Let&apos;s make some heap:</p><pre><code class="language-clojure">(ns myproject.wasm.heap)

(def page-size (* 64 1024))
(def initial-pages 16) ;; 1 MiB
(def maximum-pages (* 16 32)) ;; 32 MiB

;; a heap that gets reused between reloaded wasm code
(defonce memory
  (js/WebAssembly.Memory.
   (clj-&gt;js {:initial initial-pages
             :maximum maximum-pages})))

;; all the different views into the wasm heap
(defonce heap-uint8 (js/Uint8Array. (.-buffer memory)))
(defonce heap-uint16 (js/Uint16Array. (.-buffer memory)))
(defonce heap-uint32 (js/Uint32Array. (.-buffer memory)))
(defonce heap-int8 (js/Int8Array. (.-buffer memory)))
(defonce heap-int16 (js/Int16Array. (.-buffer memory)))
(defonce heap-int32 (js/Int32Array. (.-buffer memory)))
</code></pre><p>Now we can use this when we load our wasm byte code. We pass the memory object in to the <code>instantiateStreaming</code> call:</p><h4 id="loader">Loader</h4><pre><code class="language-clojure">(ns myproject.wasm.loader
  (:require [myproject.wasm.heap :as heap]
            [cljs.core.async :refer [go]]
            [cljs.core.async.interop :refer [&lt;p!]]))

;; load and reload compiled wasm modules keeping memory between them
(defonce module (atom {}))

(defn load-streaming [{:keys [name url]}]
  (go
    (let [result
          (&lt;p!
           (js/WebAssembly.instantiateStreaming
            (js/fetch url)
            (clj-&gt;js {:env {:memory heap/memory}})))
          instance (.-instance result)
          exports (.-exports instance)
          heap-base (.-value (aget exports &quot;__heap_base&quot;))]
      (swap! module assoc name
             {:module (.-module result)
              :instance (.-instance result)
              :exports exports})
      (heap/init-memory-map! heap-base)
      (js/console.log (str &quot;wasm &quot; name &quot; reloaded from &quot; url &quot; with heap-base &quot; heap-base)))))
</code></pre><p>Here <code>heap/memory</code> is passed to the <code>WebAssembly.instantiateStreaming</code> call.</p><p><strong>Note:</strong> For this instantiate call to work your web server must return the Content-Type of the wasm file as <code>application/wasm</code>.</p><p>When the call succeeds we store the resulting instance in the <code>module</code> atom and then we initialise our heap with the <code>__heap_base</code> value. More about that in a minute.</p><p>Now if we call <code>(myproject.wasm.loader/load-streaming {:name :mymodule :url &quot;wasm/mymodule.wasm&quot;})</code> then the wasm module will load and the instance objects will be registered inside the <code>module</code> atom. And if we call it again, then it will reload the new wasm code, but keep the heap memory.</p><h4 id="heap-allocator">Heap allocator</h4><p>Unfortunately, having no libc we cannot use dynamic memory allocation (eg. malloc/free) in our C code. However most of the C code I am writing is low level array buffer manipulations. Most of the general code lies on the ClojureScript side and the C code is merely for some heavy buffer processing. If I could partition the heap on the ClojureScript side I could just treat those allocations as buffers on the C side. Then reloading should preserve the state of that allocated memory. What I need is a ClojureScript heap allocator!</p><p>Now the glibc version of malloc does all kinds of wonderful things. My aim is not to out do it but to write a slow and inefficient imitation. My heap allocator is a simple first best fit allocator. It searches for the first free block of suitable size and allocates from that.</p><p>The allocator serves out 4-byte aligned sections of memory and it can coalesce chunks during free to reduce memory reallocation issues. If it runs out of memory, it just fails. It does not try to grow the heap.</p><p>In order to allocate out the right memory we have to be aware of where the heap is. The wasm stack starts just below the heap and grows downwards, and we certainly don&apos;t want to overwrite the stack, or have the stack overwrite our data. The stack by default is 64KB unless it&apos;s changed with the clang options. The location of the heap is exported from the WASM module in <code>__heap_base</code>.  We use this <code>__heap_base</code> value to initialise the memory map correctly in the <code>init-memory-map!</code> function.</p><p>The full allocator is a little large, <a href="https://gist.github.com/retrogradeorbit/3e2837e713b474b4ba98b9ff9fc9557d">so you can see it here</a>.</p><h4 id="babashka-watcher">Babashka watcher</h4><p>The last thing I need is something to trigger the C compile and hot load when a C file is saved. To do this I wrote the following babashka script:</p><pre><code class="language-clojure">(require &apos;[babashka.pods :as pods])
(pods/load-pod &apos;org.babashka/fswatcher &quot;0.0.2&quot;)

(require &apos;[pod.babashka.fswatcher :as fw]
         &apos;[babashka.process :as p]
         &apos;[clojure.string :as string])

(def path &quot;src/c&quot;)
(def event-types #{:write})
(def path-extensions #{&quot;c&quot; &quot;h&quot;})
(def build-command &quot;make resources/public/wasm/mymodule.wasm&quot;)
(def reload-hook-command &quot;touch src/cljs/myproject/wasm/reloader.cljs&quot;)

(defn file-extension [s]
  (last (string/split s #&quot;\.&quot;)))

(def watcher
  (fw/watch path
   (fn [{:keys [type path]}]
     (when (and (event-types type)
                (path-extensions (file-extension path)))
       (println &quot;compiling...&quot;)
       (if (-&gt; (p/process build-command {:inherit true})
               deref
               :exit
               zero?
               not)
         (println &quot;failed!&quot;)
         (do
           (println &quot;done.&quot;)
           @(p/process reload-hook-command)))))))

(.join (Thread/currentThread))
</code></pre><p>Whenever any <code>.c</code> or <code>.h</code> source file is written to, the build process is triggered to make a fresh <code>.wasm</code> file. If the build succeeds then the source file <code>reloader.cljs</code> is touched and this triggers shadow-cljs to reload the file. This little <code>reloader.cljs</code> stub looks like this:</p><pre><code class="language-clojure">(ns myproject.wasm.reloader)

(myproject.wasm.loader/load-streaming
 {:name :mymodule
  :url &quot;wasm/mymodule.wasm&quot;})
</code></pre><p>Touch that and shadow-cljs pops up its little icon on your web page, reloads the name-space and makes the new <code>load-streaming</code> call to load in the fresh wasm code.</p><h4 id="calling-c-and-passing-buffers">Calling C and passing buffers</h4><p>Because our module instance lives in the <code>loader/module</code> atom, we can make a C call like this:</p><pre><code class="language-clojure">(-&gt; @loader/module :mymodule :exports (.calc 10 20))
</code></pre><p>We could make this more convenient with a little more work, but it shows the idea.</p><p>C pointers are represented as integer offsets into memory on the ClojureScript side, and they must be passed accordingly. However, on the ClojureScript side we will want to access the buffers via an array object. In other words, we need to use the array objects on the JS side, and integer offsets when calling and returning from C. I get around this inconvenience by returning both values from my malloc call.</p><pre><code class="language-clojure">(heap/malloc 2048)
;; =&gt; {:buffer #object[Uint8Array 0,0,0...],
;;     :address 70656}
</code></pre><p>Lets make some C functions to see if we can investigate the heap. We add the following to our C code.</p><pre><code class="language-cpp">__attribute__((export_name(&quot;get_byte&quot;)))
uint8 get_byte(uint8 *buffer, int i)
{
  return buffer[i];
}

__attribute__((export_name(&quot;set_byte&quot;)))
void set_byte(uint8 *buffer, int i, uint8 v)
{
  buffer[i]=v;
}
</code></pre><p>We save the file and the code is compiled and hot loaded into the browser. Our browser environment now has two new functions in the wasm module. Lets allocate some memory and see...</p><pre><code class="language-clojure">(def b (heap/malloc 1024))

;; get the first memory location from the cljs and then C
(aget (:buffer b) 0) ;; =&gt; 0
(-&gt; @module :mymodule :exports (.get_byte (:address buff) 0)) ;; =&gt; 0

;; set it to 50
(aset (:buffer b) 0 50)

;; check
(aget (:buffer b) 0) ;; =&gt; 50
(-&gt; @module :mymodule :exports (.get_byte (:address buff) 0)) ;; =&gt; 50

;; go and edit the C file. Save it and wait for it to be hot loaded.
;; still the same memory
(aget (:buffer b) 0) ;; =&gt; 50
(-&gt; @module :mymodule :exports (.get_byte (:address buff) 0)) ;; =&gt; 50

;; set on C side, read on cljs
(-&gt; @module :mymodule :exports (.set_byte (:address buff) 0 100)) ;; =&gt; nil
(aget (:buffer b) 0) ;; =&gt; 100

;; set on cljs, read on C
(aset (:buffer b) 0 150) ;; =&gt; 150
(-&gt; @module :mymodule :exports (.get_byte (:address buff) 0)) ;; =&gt; 150

;; release the memory
(heap/free b)
</code></pre><h4 id="conclusion,-limitations-and-future-work">Conclusion, Limitations and Future Work</h4><p>So how does it behave? Very well! Clang is a fast compiler and the new code is available in the browser almost instantly. For most C work the reloading behaviour and limitations are sufficient to work with the code changes without a browser refresh. Some things one has to be more careful of, however. If you change the layout of the heap, or change how the code interprets the memory packing of the heap, all bets are off! For example, adding a new field to a struct is going to generate new code that sees your existing heap data structures in incorrect ways. Luckily in these cases we just reload the browser to clean the wasm memory and allocate fresh again.</p><p>In the future it would be interesting to hook up our ClojureScript malloc and free as imports into the module. This way we could call malloc and free inside our C code as we saw fit and have the wasm use the ClojureScript allocator to do so. In addition the allocator could itself be improved in many ways. It could try and grow the heap if it cannot allocate. It could be faster. The glibc allocator does other tricks like keeping recently freed small blocks around to reallocate immediately for a malloc of the same size.</p><p>The complete set of files for this can be <a href="https://gist.github.com/retrogradeorbit/3e2837e713b474b4ba98b9ff9fc9557d">found here</a>.</p>]]></content></entry><entry><title>Combining doseq and loadLibrary Considered Harmful</title><link href="https://epiccastle.io/blog/combining-doseq-and-loadlibrary-considered-harmful"/><id>https://epiccastle.io/blog/combining-doseq-and-loadlibrary-considered-harmful</id><updated>2020-06-09T14:12:15+08:00</updated><published>2020-06-09T14:12:15+08:00</published><author><name>Crispin Wellington</name></author><content type="html"><![CDATA[<img alt="Crispin Wellington" class="blog-splash" src="https://epiccastle.io/blog/combining-doseq-and-loadlibrary-considered-harmful/splash-20.jpg" style="width:50%" /><h3 id="update">Update</h3><p>&quot;load/recur&quot; is <em>not</em> a solution. It just fails far less often. Extensive testing shows it failing about 4% of the time (as opposed to 50% of the time with doseq). The problem is not related to doseq... but lies deeper. It is possibly a timing issue. Another blog post will be forthcoming when the root cause is found.</p><h3 id="combining-doseq-and-loadlibrary-considered-harmful">Combining doseq and loadLibrary Considered Harmful</h3><p>Loading multiple C libraries with loadLibrary inside a <code>doseq</code> will lead to lots of strange crashes and issues.</p><h3 id="qt-and-javacpp">Qt and javacpp</h3><p>I have been building a <a href="https://github.com/retrogradeorbit/mullion">test stack using clojure, javacpp and Qt</a> to build a clojure GUI and compile it into a single binary with GraalVM. All was going well until I started to experience strange problems as the code grew. Strangely, the compiled Graal native image continued to function perfectly, but various problems started to occur when running under the JVM. What was most concerning is sometimes it would work fine, and sometimes it would not.</p><p>When running under the JVM I would get one of the following problems when running the program.</p><ul><li>Program prints <code>QWidget: Must construct a QApplication before a QWidget</code> and exits.</li><li>Program prints <code>QPixmap: Must construct a QGuiApplication before a QPixmap</code> and exits.</li><li>Program prints <code>QApplication::exec: Please instantiate the QApplication object first</code> and exits.</li><li>Program prints <code>QGuiApplication::font(): no QGuiApplication instance and no application font set.</code> multiple times and then exits.</li><li>The program runs fine, but then crashes when closing with a <code>SIGSEGV</code></li><li>The program segfaults and crashes with <code>A fatal error has been detected by the Java Runtime Environment:SIGSEGV</code> and one of the following:<ul><li><code># C  [libQt5Widgets.so.5+0x19c075]  QWidget::show()+0x15</code>, or...</li><li><code># C  0x0000000000000000</code></li></ul></li></ul><p>Or... it runs fine! The <a href="http://catb.org/jargon/html/M/mandelbug.html">mandelbug</a> nature of this makes it very strange indeed.</p><h3 id="introducing-delays-works-around-the-problem">Introducing Delays Works Around the Problem</h3><p>The error messages mentioning constructing one thing before another start to pique my curiosity. Why is that error appearing when I quite clearly create the QApplication first? What if I add a <code>(Thread/sleep 1000)</code> after the creation of the QApplication?</p><p>Funnily enough, that stops the errors and crashes and the program now works reliably. Then after a while I just try sleeps in different locations. I move the sleep higher and higher up the code and it continues to work. I move it <em>before</em> the creation of QApplication, and it works! And then I move it before the loading of the Qt libraries, and it no longer works!</p><p>It seems to be related to the way I am loading libraries. Maybe when the routine to load the libraries returns, the libraries aren&apos;t actually fully loaded? Maybe they are being loaded in another thread? Clojure, after all, is a highly parallel language.</p><h3 id="the-problematic-loader">The Problematic Loader</h3><p>Here is the loader as it was:</p><pre><code class="language-clojure">(defn load-libs []
  (doseq [name library-load-list]
    (clojure.lang.RT/loadLibrary name)))
</code></pre><p>Seems innocuous enough. But what if <code>doseq</code> is actually multi-threaded and loading from multiple threads is causing issues? Lets try replacing it with something single threaded.</p><h3 id="the-replacement-loader">The Replacement Loader</h3><p>I remove the debug sleeps and replaced the loader implementation with this:</p><pre><code class="language-clojure">(defn load-libs []
  (loop [[name &amp; remain] library-load-list]
    (when name
      (clojure.lang.RT/loadLibrary name)
      (recur remain))))
</code></pre><p>And the problem instantly disappears. Launch after launch the program works perfectly.</p><p>In this working implementation, each <code>loadLibrary</code> call is issued and the program waits for the call to complete before loading the next shared library.</p><h3 id="the-culprit?">The Culprit?</h3><p>Looking at the source of <code>doseq</code> <a href="https://github.com/clojure/clojure/blob/clojure-1.10.1/src/clj/clojure/core.clj#L3216">here</a> we see that doseq is not inherently multi-threaded, but it does contain code to support chunked sequences. I don&apos;t have time to unravel exactly what <code>doseq</code> is doing here that is causing the crisis, but let it be known: <strong>keep your loadLibrary calling code single threaded</strong></p><h3 id="addendum">Addendum</h3><p>I never did get around to writing up the true cause of this issue. But it was not doseq at all. Or clojure. Or the JVM. It turned out to be Qt. For some unknown reason compiling Qt from source on a Debian based machine (I was using Ubuntu) led to a faulty set of binaries being created. When I switched to compiling it on CentOS it generated a set of binaries that behaved correctly. I did not have the stamina to uncover why this is so. Since then I have given up using Qt. It is huge. It is complex. I do not trust it!</p>]]></content></entry><entry><title>Faster GraalVM Clojure Compilation Times</title><link href="https://epiccastle.io/blog/faster-graalvm-clojure-compilation-times"/><id>https://epiccastle.io/blog/faster-graalvm-clojure-compilation-times</id><updated>2020-05-26T00:46:05+08:00</updated><published>2020-05-26T00:46:05+08:00</published><author><name>Crispin Wellington</name></author><content type="html"><![CDATA[<img alt="Crispin Wellington" class="blog-splash" src="https://epiccastle.io/blog/faster-graalvm-clojure-compilation-times/splash-20.jpg" style="width:50%" /><h3 id="slash-graalvm-clojure-compilation-time-with-this-one-weird-trick">Slash GraalVM Clojure Compilation Time With This One Weird Trick</h3><p>Are you building a clojure project and compiling it to a native binary with GraalVM? As the project has grown, has the GraalVM compilation time gotten longer and longer? Here is the story of how I discovered <a href="https://twitter.com/borkdude">@borkdude</a>&apos;s trick to getting GraalVM native image times in under 5 minutes.</p><h4 id="the-story">The Story</h4><p>As I&apos;ve been building <a href="https://epiccastle.io/spire/">spire</a>, compilation times have gradually been increasing. Then in order to bring a bunch of increased functionality I added a large number of Java class bindings to my sci environment. I check the code in and go to bed. When I wake I discover my <a href="https://circleci.com/gh/epiccastle/spire/1055">Circle CI builds</a> have been killed in the night for taking too long. The build was underway for an hour when the CI system killed the build!</p><p>So I try compiling on my local linux workstation to see what is going on. After an eternity the build crashes with:</p><pre><code class="language-shell">[build/spire:2202]     analysis: 12,784,610.52 ms,  6.22 GB
Fatal error:java.lang.OutOfMemoryError: GC overhead limit exceeded
Error: Image build request failed with exit status 1
com.oracle.svm.driver.NativeImage$NativeImageError: Image build request failed with exit status 1
    at com.oracle.svm.driver.NativeImage.showError(NativeImage.java:1527)
    at com.oracle.svm.driver.NativeImage.build(NativeImage.java:1289)
    at com.oracle.svm.driver.NativeImage.performBuild(NativeImage.java:1250)
    at com.oracle.svm.driver.NativeImage.main(NativeImage.java:1209)
    at com.oracle.svm.driver.NativeImage$JDK9Plus.main(NativeImage.java:1707)

</code></pre><p><strong>12,784,610ms</strong> spent in analysis. That is over <strong>three and a half hours</strong>!</p><p>As I just added a bunch of new class bindings and reflection config for them all, I assume that must be the culprit. I remove 75% of them. And build again. I time this run. It succeeds, but it isn&apos;t pretty.</p><pre><code class="language-shell">[build/spire:11341]    classlist:   5,953.42 ms,  0.94 GB
[build/spire:11341]        (cap):     800.78 ms,  0.94 GB
[build/spire:11341]        setup:   2,536.63 ms,  0.94 GB
[build/spire:11341]   (typeflow): 1,544,374.55 ms,  6.51 GB
[build/spire:11341]    (objects): 5,164,930.94 ms,  6.51 GB
[build/spire:11341]   (features):   4,320.62 ms,  6.51 GB
[build/spire:11341]     analysis: 6,724,448.94 ms,  6.51 GB
[build/spire:11341]     (clinit):   1,898.20 ms,  6.51 GB
[build/spire:11341]     universe:  47,567.23 ms,  6.51 GB
[build/spire:11341]      (parse):  12,451.68 ms,  4.17 GB
[build/spire:11341]     (inline):   9,098.24 ms,  3.94 GB
[build/spire:11341]    (compile):  75,592.43 ms,  3.59 GB
[build/spire:11341]      compile: 102,870.54 ms,  3.59 GB
[build/spire:11341]        image:  14,383.80 ms,  3.61 GB
[build/spire:11341]        write:   1,725.39 ms,  3.61 GB
[build/spire:11341]      [total]: 6,899,951.34 ms,  3.61 GB
cp build/spire spire

real	115m59.386s
user	839m24.587s
sys	1m56.493s

</code></pre><p>Wow! Analysis is now down to only 1 hour and 50 minutes! Good times!</p><p>So this leads me to wonder how Michiel (<a href="https://twitter.com/borkdude">@borkdude</a>) is building his babashka images on Circle CI without hitting the wall. I go over to have a look at his <a href="https://circleci.com/gh/borkdude/babashka/9392">Circle CI builds</a>. They are building his images in <strong>less that 5 minutes</strong>.... whaaaaaaat?</p><h4 id="that-one-weird-trick">That One Weird Trick</h4><p>This leads me to a bunch of comparisons between the compilation and building of babashka with that of spire. I rule out reflection as the source of the problem. I rule out GraalVM options. And then I discover <a href="https://github.com/borkdude/babashka/blob/c3f9480efe08827dfa4ac0fb21f7376d80287ce6/project.clj#L53">the magical incantation</a>.</p><p>I had this setting on my GraalVM build, but I did not have it on when clojure was doing AOT compilation for the uberjar. Before we turn it on lets look into what it does.</p><h4 id="direct-linking">Direct Linking</h4><p>Clojure&apos;s direct linking can be activated by passing <code>-Dclojure.compiler.direct-linking=true</code> to the compiler. This feature is <a href="https://clojure.org/reference/compilation#directlinking">documented here</a>. From this discussion we read:</p><blockquote><p>&quot;Normally, invoking a function will cause a var to be dereferenced to find the function instance implementing it, then invoking that function... <em>Direct linking</em> can be used to replace this indirection with a direct static invocation of the function instead. This will result in faster var invocation. Additionally, the compiler can remove unused vars from class initialization and direct linking will make many more vars unused. Typically this results in smaller class sizes and faster startup times.&quot;</p></blockquote><p>And faster Graal compilation times to boot! This option will produce JVM byte code that will be much more like what a standard Java program will produce. Java is a statically typed language after all, and Java programs are not dereferencing vars every time they are invoked. The Graal compiler, being built primarily to compile Java programmes, is obviously having a very hard time with the dynamic nature of clojure&apos;s compiled byte code.</p><p>But do we lose anything if we compile our code with direct linking? According to the docs:</p><blockquote><p>&quot;One consequence of direct linking is that var redefinitions will not be seen by code that has been compiled with direct linking (because direct linking avoids dereferencing the var). Vars marked as ^:dynamic will never be direct linked. If you wish to mark a var as supporting redefinition (but not dynamic), mark it with ^:redef to avoid direct linking.&quot;</p></blockquote><p>As Michiel pointed out to me, things like a general use of <code>with-redefs</code> won&apos;t work with direct linking. But if we do want to do something dynamic like <code>with-redefs</code> in our code, we can individually mark those vars with <code>^:redef</code> meta data to allow them to work. Also, things like <code>with-redefs</code> is more commonly used in writing tests, so we can keep the option off in our test code and save direct linking for our uberjar builds.</p><h4 id="the-fixed-build">The Fixed Build</h4><p>Now taking the original problematic build that crashed after three and a half hours, I switch that setting on in my uberjar compilation and rebuild. Here&apos;s the result:</p><pre><code class="language-shell">[build/spire:22871]    classlist:   4,379.73 ms,  0.96 GB
[build/spire:22871]        (cap):     739.03 ms,  0.96 GB
[build/spire:22871]        setup:   2,268.45 ms,  0.96 GB
[build/spire:22871]   (typeflow):  50,731.79 ms,  5.92 GB
[build/spire:22871]    (objects): 116,840.36 ms,  5.92 GB
[build/spire:22871]   (features):   2,682.61 ms,  5.92 GB
[build/spire:22871]     analysis: 173,423.16 ms,  5.92 GB
[build/spire:22871]     (clinit):   1,193.08 ms,  5.92 GB
[build/spire:22871]     universe:   3,049.85 ms,  5.92 GB
[build/spire:22871]      (parse):   7,224.44 ms,  5.79 GB
[build/spire:22871]     (inline):  13,408.30 ms,  4.19 GB
[build/spire:22871]    (compile):  77,773.85 ms,  4.16 GB
[build/spire:22871]      compile: 104,068.58 ms,  4.16 GB
[build/spire:22871]        image:  13,542.17 ms,  4.16 GB
[build/spire:22871]        write:   1,792.26 ms,  4.22 GB
[build/spire:22871]      [total]: 302,882.67 ms,  4.22 GB
cp build/spire spire

real	5m32.050s
user	33m7.865s
sys	0m12.756s

</code></pre><p>Analysis is down from 3½ hours... to a little under <strong>3 minutes</strong>. And amazing improvement!</p><h4 id="summary">Summary</h4><p>Add <code>-Dclojure.compiler.direct-linking=true</code> to your clojure compilation JVM options when building your uberjar and when compiling with GraalVM.</p><p>In lein:</p><pre><code class="language-clojure">(defproject foo &quot;0.1.0-SNAPSHOT&quot;

  ;; missing lines

  :profiles {:uberjar {:aot :all
                       :jvm-opts [&quot;-Dclojure.compiler.direct-linking=true&quot;]}
)
</code></pre><p>And in GraalVM native-image:</p><pre><code class="language-shell">graalvm-ce-java11-20.1.0-dev/bin/native-image \
    ...
    -J-Dclojure.compiler.direct-linking=true \
    ...
</code></pre>]]></content></entry><entry><title>Generating XML With Bootleg</title><link href="https://epiccastle.io/blog/generating-xml-with-bootleg"/><id>https://epiccastle.io/blog/generating-xml-with-bootleg</id><updated>2020-02-02T17:32:05+08:00</updated><published>2020-02-02T17:32:05+08:00</published><author><name>Crispin Wellington</name></author><content type="html"><![CDATA[<img alt="Crispin Wellington" class="blog-splash" src="https://epiccastle.io/blog/generating-xml-with-bootleg/splash-20.png" style="width:50%" /><h3 id="outputting-xml-with-bootleg">Outputting XML with Bootleg</h3><p>The latest release of <a href="https://github.com/retrogradeorbit/bootleg">bootleg</a> (0.1.7) contains some new XML output functionality. I added this to bootleg to facilitate the generation of an RSS news feed form the epiccastle blog page that you are reading right now. Here is how I generate this RSS.</p><h4 id="background">Background</h4><p>In this blog I have post metadata stored in some short yaml files. I can gather all the relevant filenames in with the <code>glob</code> function:</p><pre><code class="language-clojure">(for [filename (glob &quot;*/vars.yml&quot;)]
  ...)
</code></pre><p>And then I can read these vars in with the <code>yaml</code> function:</p><pre><code class="language-clojure">(let [vars (yaml filename)]
  ...)
</code></pre><p>I build all these yaml structures into a single hash map keyed by the post number.</p><pre><code class="language-clojure">(let [posts
      (-&gt;&gt; (for [filename (glob &quot;*/vars.yml&quot;)]
             (let [post-num (-&gt; filename
                                (string/split #&quot;/&quot;)
                                first
                                parse-string)
                   vars (yaml filename)]
               [post-num vars]))
           (into {}))]
  ...)
</code></pre><h4 id="generating-the-rss">Generating the RSS</h4><p>I can now use this datastructure to generate an rss xml file. I do this by passing some hiccup to <code>(convert-to hiccup-data :xml)</code></p><pre><code class="language-clojure">(spit &quot;feed.xml&quot;
    (-&gt; [:rss {:version &quot;2.0&quot;}
          [:channel
            [:title &quot;Epiccastle Blog&quot;]
            [:description &quot;Epiccastle.io Updates&quot;]
            [:link &quot;https://epiccastle.io/blog/&quot;]
            [:lastBuildDate now-string]
            [:pubDate now-string]
            [:ttl &quot;1440&quot;]
            (for [[n {:keys [snake-title
                             title
                             rss-date]
                      :as post-data}] (reverse (sort posts))]
              [:item
               [:title title]
               [:description (-&gt; post-data
                                 render-post
                                 as-html
                                 escape-html)]
               [:link (str &quot;https://epiccastle.io/blog/&quot; snake-title)]
               [:gid snake-title]
               [:pubDate rss-date]])]]
          (convert-to :xml)))
</code></pre><h4 id="other-helpful-functions">Other helpful functions</h4><p>I needed to escape the html markup to embed it in the xml description tag with this function:</p><pre><code class="language-clojure">(defn escape-html
  &quot;Change special characters into HTML character entities.&quot;
  [text]
  (-&gt; text
      (string/replace &quot;&amp;&quot; &quot;&amp;amp;&quot;)
      (string/replace &quot;&lt;&quot; &quot;&amp;lt;&quot;)
      (string/replace &quot;&gt;&quot; &quot;&amp;gt;&quot;)
      (string/replace &quot;\&quot;&quot; &quot;&amp;quot;&quot;)))
</code></pre><p>And my <code>now-string</code> variable I generate with the following simple code at the top of my file:</p><pre><code class="language-clojure">(import [java.time OffsetDateTime]
        [java.time.format DateTimeFormatter])

(defn string-&gt;datetime [s]
  (OffsetDateTime/parse s DateTimeFormatter/RFC_1123_DATE_TIME))

(defn datetime-&gt;string [dt]
  (.format dt DateTimeFormatter/RFC_1123_DATE_TIME))

(def now (OffsetDateTime/now))
(def now-string (datetime-&gt;string now))

</code></pre><p>You can see the actual source for this process <a href="https://github.com/epiccastle/epiccastle.io/blob/bce74a8baa757828e510dc463b8b054bf7b4f377/epiccastle.io/blog/index.clj">here</a>.</p>]]></content></entry><entry><title>Tiny Enlive Transformer Implements update-in</title><link href="https://epiccastle.io/blog/tiny-enlive-transformer-implements-update-in"/><id>https://epiccastle.io/blog/tiny-enlive-transformer-implements-update-in</id><updated>2020-01-23T15:58:40+08:00</updated><published>2020-01-23T15:58:40+08:00</published><author><name>Crispin Wellington</name></author><content type="html"><![CDATA[<img alt="Crispin Wellington" class="blog-splash" src="https://epiccastle.io/blog/tiny-enlive-transformer-implements-update-in/splash-20.png" style="width:50%" /><h3 id="modifying-markdown-document-links">Modifying Markdown Document Links</h3><p>I have some markdown in a project on github. And it contains relative links. These relative link take you to other markdown files in the github repo. When you click the links on github the browser navigates to <code>doc/tutorial.md</code> and shows it in the github styling. All good.</p><p>Now I wan&apos;t to render these markdown documents onto my own server, with my own styling, for the project&apos;s home page. This site is comprised of static files generated with <a href="https://github.com/retrogradeorbit/bootleg">bootleg</a>. All the links in the documents look like: <code>doc/tutorial.md</code>. But I need them to look like this: <code>tutorial.html</code>. I need an a-tag-url-modifier. One takes in the <code>*.md</code> href string, and transforms it to the equivalent <code>*.html</code> string.</p><p>What would be even more useful is a transformer that can modify <em>any</em> part of the element, like clojure&apos;s <code>assoc-in</code> or an <code>update-in</code>.</p><p>It&apos;s very simple. Here is the implementation of an update-in transformer from my bootleg file:</p><pre><code class="language-clojure">(defn el-update-in [path func &amp; func-args]
  (fn [el]
    (apply update-in el path func func-args)))
</code></pre><p>I could append a html file extension to all the <code>&lt;a&gt;</code> tags with:</p><pre><code class="language-clojure">[:section
 [:div.container
  (-&gt; (markdown &quot;body.md&quot;)
      (enlive/at [:a] (el-update-in [:attrs :href] str &quot;.html&quot;)))]]
</code></pre><p>The <code>el-update-in</code> function returns the transformer. The transformer operates on a hickory element. These elements have the keys <code>:type</code>, <code>:tag</code>, <code>:attrs</code> and <code>:content</code>. Here I run the <code>str</code> function on the contents of the path <code>[:attrs :href]</code>. You could access any attr this way, like <code>[:attrs :class]</code> or even run on sub elements, with something like <code>[:content 0]</code>!</p><p>Here is my solution to my path transformation problem.</p><pre><code class="language-clojure">[:section
 [:div.container
  (-&gt; (markdown &quot;body.md&quot;)
      (enlive/at
       [:a] (el-update-in [:attrs :href] #(-&gt; %
                                              (string/split #&quot;/&quot; -1)
                                              last
                                              (string/split #&quot;\.&quot; -1)
                                              butlast
                                              (-&gt;&gt; (string/join &quot;.&quot;))
                                              (str &quot;.html&quot;)))))]]
</code></pre><p>I split the string up by <code>/</code> and take the last segment. Then hackishly remove the file extension. Then add the html extension. This turns <code>doc/tutorial.md</code> to <code>tutorial.html</code>.</p>]]></content></entry><entry><title>Setting Up Acmetool With Route53 Hooks</title><link href="https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks"/><id>https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks</id><updated>2019-11-06T16:20:00Z</updated><published>2019-11-06T16:20:00Z</published><author><name>Crispin Wellington</name></author><content type="html"><![CDATA[<img alt="Crispin Wellington" class="blog-splash" src="https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks/splash-20.png" style="width:50%" /><h3 id="let&apos;s-encrypt">Let&apos;s Encrypt</h3><p>Let&apos;s Encrypt is a non-profit certificate authority that can issue you SSL certificates for free. These certificates can be used to secure any type of TLS connection. Most commonly they are used to secure HTTPS web sites, but they can also be used to secure email, usenet news, file servers, chat servers or any other type of internet connection.</p><p>SSL Certificates come with three types of validation: Domain, Organization and Extended. Let&apos;s Encrypt only offers Domain Validation Certificates, but these certificates are all you need to enable high strength encryption on these connections and to allow clients to know that they are connecting to the correct domain, thus thwarting Man-in-the-middle attacks. In order to validate that you do indeed own the domain, Let&apos;s Encrypt uses a completely automatic process implemented via a protocol called ACME.</p><h3 id="acme-protocol">ACME Protocol</h3><img class="right" alt="Wile E Coyote with acme ordering catalogue" src="acme-catalog.png"/><p>AMCE is a basic challenge/response system. You send a request for your domain to the ACME service running on Let&apos;s Encrypt&apos;s servers and it gives you a token. Then the servers look for that token via in that domain via some method and will issue you a certificate if the token is found. You can then use that certificate.</p><p>These certificates are only valid for <strong>three months</strong> and so you will need some automatic method to renegotiate a new certificate as the old one gets close to expiry.</p><p>After trying many different tools to perform the ACME negotiation I have found that the best tool for the job is <a href="https://github.com/hlandau/acme">acmetool</a>. Even before it was easily installable as a package and bundled in the main linux distributions it was well worth manually compiling it. <em>acmetool</em> gives a better experience than the other clients and I have found it to be rock solid and reliable.</p><h3 id="problems-with-web-server-based-verification">Problems with Web Server Based Verification</h3><p>Now, there are a number of ways to place that ACME token for the Let&apos;s Encrypt servers to verify. Commonly they are placed on your local webserver itself in a pre-decided directory. This is easy, but suffers from some fairly singificant problems:</p><ul><li><p><strong>A webserver needs to be running.</strong> If a webserver is not running for any reason then the certificates cannot be gathered or renewed. Some ACME software includes a bundled webserver that can be started as needed for this purpose. But this is still not ideal, as you end up with two sets of ACME configurations. One for servers running a webserver. And one for servers that aren&apos;t.</p></li><li><p><strong>The webserver must (at least) serve the directory over http.</strong> This complicates any http to https redirection rules you have setup in your webserver configuration.</p></li><li><p>In an idempotent provisioning environment <strong>the webserver will initially need to be started without a certificate present at all</strong> leading to a chicken and egg orchestration problem. On a server like nginx, if an SSL certificate is mentioned in the configutation but is not found on the filesystem, the server refuses to start. Thus you need either two seperate configurations, one without a certificate (before the first certificate is issued) and one with the Let&apos;s Encrypt certificate. Or you need a dummy, self-signed certificate just to prevent nginx from blowing up before the Let&apos;s Encrypt certificate is ready.</p></li><li><p><strong>The webserver needs to be running on a live IP, on a standard port and accessible from the Internet.</strong> The Let&apos;s Enrypt servers need to be able to reach your webserver. This means that you cannot use this method for any servers behind a corporate firewall or running on a non standard port.</p></li></ul><h3 id="advantages-of-dns-based-verification">Advantages of DNS Based Verification</h3><p>An alternative way to verify the Let&apos;s Encrypt challenge token is to serve it to the Internet in a DNS record. Although a little more intricate in its setup, I have found through experience that this method has many distinct advantages and <strong>is the method I personally recommend to my clients</strong>. Some of it&apos;s advantages are:</p><ul><li><p><strong>Can be used in exactly the same way on all servers, with or without a webserver present.</strong> This greatly simplifies orchestration code and the amount of information an engineer needs to load into their brain before working on the system or troubleshooting issues.</p></li><li><p><strong>It is <em>out-of-band</em> of any other service and will continue to operate even if the other service has problems.</strong> If nginx experiences trouble, or something else binds to port 80 (in the self contained webserver example), or a firewall rule is changed blocking access, the certificate process will be unaffected.</p></li><li><p><strong>Can generate certificates on machines on private IPs and behind corporate firewalls.</strong> DNS verification allows you to secure <em>all</em> your services with TLS including all your intranet and VPC services. This helps prevent the soft underbelly syndrome. Data is better protected even when it is travelling on the internal private company networks.</p></li></ul><p>Now lets get started...</p><h3 id="install-acmetool-and-packages">Install acmetool and packages</h3><p>If you are using Ubuntu 18.04 or above, then <code>acmetool</code> is already included in the system packages. Install this and we will also need <code>python3</code> and <code>python3-boto3</code> for our DNS hook script:</p><pre><code class="language-language-shell-session">$ apt-get install acmetool python3 python3-boto3
</code></pre><h3 id="configuring-acmetool">Configuring acmetool</h3><p>Make a folder to store the custom DNS hook script in. <em>Make sure this is outside of the acmetool state directory</em>.</p><pre><code class="language-language-shell-session">$ mkdir -p /usr/lib/acme/hooks
</code></pre><p>Setup the <code>acme-conf.yml</code> file to look like the following. This file is found at <code>/var/lib/acme/conf/responses/acme-conf.yml</code></p><h5 id="/var/lib/acme/conf/responses/acme-conf.yml">/var/lib/acme/conf/responses/acme-conf.yml</h5><pre><code class="language-language-yaml"># This is a example of a response file, used with --response-file.
# It automatically answers prompts for unattended operation.
# grep for UniqueID in the source code for prompt names.
#  https://github.com/hlandau/acme/search?q=UniqueID
# Pass --response-file to all invocations, not just quickstart.
# If you don&apos;t pass --response-file, it will be looked for at &quot;(state-dir)/conf/responses&quot;.
# You will typically want to use --response-file with --stdio or --batch.
# For dialogs not requiring a response, but merely acknowledgement, specify true.
# This file is YAML. Note that JSON is a subset of YAML.
&quot;acme-enter-email&quot;: &quot;youremail@yourdomain.com&quot;
&quot;acme-agreement:https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf&quot;: true
#&quot;acmetool-quickstart-choose-server&quot;: https://acme-staging.api.letsencrypt.org/directory
&quot;acmetool-quickstart-choose-server&quot;: https://acme-v01.api.letsencrypt.org/directory
&quot;acmetool-quickstart-choose-method&quot;: hooks
# This is only used if &quot;acmetool-quickstart-choose-method&quot; is &quot;webroot&quot;.
&quot;acmetool-quickstart-webroot-path&quot;: &quot;/var/run/acme/acme-challenge&quot;
&quot;acmetool-quickstart-complete&quot;: true
&quot;acmetool-quickstart-install-cronjob&quot;: true
&quot;acmetool-quickstart-install-haproxy-script&quot;: false
&quot;acmetool-quickstart-install-redirector-systemd&quot;: false
&quot;acmetool-quickstart-key-type&quot;: rsa
&quot;acmetool-quickstart-rsa-key-size&quot;: 4096
&quot;acmetool-quickstart-ecdsa-curve&quot;: nistp256
</code></pre><p>Setup the <code>target</code> file to look like the following. This file is found at <code>/var/lib/acme/conf/target</code></p><h5 id="/var/lib/acme/conf/target">/var/lib/acme/conf/target</h5><pre><code class="language-language-yaml">request:
  provider: https://acme-v01.api.letsencrypt.org/directory
  key:
    type: rsa
</code></pre><p>Now we are ready to install the main Route53 DNS hook script.</p><h5 id="/usr/lib/acme/hooks/route53">/usr/lib/acme/hooks/route53</h5><pre><code class="language-language-python">#!/usr/bin/env python3
&quot;&quot;&quot;
Based on from: https://gist.github.com/ramirovjr/181979298149c5e74887f30fe09dcc71
modified to support acmetool by crispin@epiccastle.io
requires environment variable ACME_HOSTED_ZONE to contain route53 Zone ID
&quot;&quot;&quot;
import os
import sys
import boto3
from time import sleep

def setup_dns(domain, txt_challenge, hosted_zone_id):
    session = boto3.Session()
    client = session.client(&quot;route53&quot;)

    resp = client.change_resource_record_sets(
        HostedZoneId=hosted_zone_id,
        ChangeBatch={
            &apos;Changes&apos;: [{
                &apos;Action&apos;: &apos;UPSERT&apos;,
                &apos;ResourceRecordSet&apos;: {
                    &apos;Name&apos;: &apos;_acme-challenge.{0}&apos;.format(domain),
                    &apos;Type&apos;: &apos;TXT&apos;,
                    &apos;TTL&apos;: 60,
                    &apos;ResourceRecords&apos;: [{
                        &apos;Value&apos;: &apos;&quot;{0}&quot;&apos;.format(txt_challenge)}]}}]})

    # wait 30 seconds for DNS update
    sleep(30)

def delete_dns(domain, txt_challenge, hosted_zone_id):
    session = boto3.Session()
    client = session.client(&quot;route53&quot;)

    resp = client.change_resource_record_sets(
        HostedZoneId=hosted_zone_id,
        ChangeBatch={
            &apos;Changes&apos;: [{
                &apos;Action&apos;: &apos;DELETE&apos;,
                &apos;ResourceRecordSet&apos;: {
                    &apos;Name&apos;: &apos;_acme-challenge.{0}&apos;.format(domain),
                    &apos;Type&apos;: &apos;TXT&apos;,
                    &apos;TTL&apos;: 60,
                    &apos;ResourceRecords&apos;: [{
                        &apos;Value&apos;: &apos;&quot;{0}&quot;&apos;.format(txt_challenge)}]}}]})

if __name__ == &quot;__main__&quot;:
    assert len(sys.argv) &gt; 3, &quot;not enough command line arguments passed in&quot;

    hook = sys.argv[1]
    domain = sys.argv[2]
    txt_challenge = sys.argv[4]

    if &apos;ACME_HOSTED_ZONE&apos; not in os.environ:
        raise Exception(&quot;Environment variable ACME_HOSTED_ZONE not defined&quot;)

    hosted_zone_id = os.environ[&apos;ACME_HOSTED_ZONE&apos;]

    if hook == &quot;challenge-dns-start&quot;:
        setup_dns(domain, txt_challenge, hosted_zone_id)
    elif hook == &quot;challenge-dns-stop&quot;:
        delete_dns(domain, txt_challenge, hosted_zone_id)
</code></pre><p>Now, in order to run this script needs the following environment variables set:</p><ul><li><strong>ACME_HOOKS_DIR</strong> The location of our hooks directory <code>/usr/lib/acme/hooks/</code></li><li><strong>ACME_HOSTED_ZONE</strong> The Route53 Zone ID of the domain hosting the DNS records</li><li><strong>AWS_ACCESS_KEY_ID</strong> An AWS IAM access key ID that will be used to alter the DNS records</li><li><strong>AWS_SECRET_ACCESS_KEY</strong> The IAM secret key for that identity.</li></ul><p>Finally run the quickstart acmetool command in batch mode to initialise the acmetool state directory:</p><pre><code class="language-language-shell-session">$ acmetool --batch quickstart
</code></pre><p>Now that is all setup, let&apos;s go through setting up the IAM identity in AWS and finding out our Zone ID</p><h3 id="setting-up-an-iam-identity-to-alter-route53-records">Setting up an IAM identity to alter Route53 records</h3><p><img alt="IAM Add User" src="https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks/iam-add-user.png" /></p><p>Login to your AWS web console, and navigate to the IAM dashboard. Click on <code>Users</code> and then click on the <code>Add user</code> button:</p><hr /><p><img alt="IAM Add User 1" src="https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks/iam-add-user-1.png" /></p><p>On the next screen enter a name for the identity. Here I have entered <code>acme</code> but any name will do so long as it is valid and not already used. Under Access type select the checkbox next to <strong>Programmatic access</strong>. Then click the <code>Next</code> button.</p><hr /><p><img alt="IAM Add User 2" src="https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks/iam-add-user-2.png" /></p><p>On the second screen click on <strong>Attach existing policies directly</strong>. Then in the Filter policies search box enter <code>Route53DomainsFull</code> to filter the policy list down to find the correct policy. Then mark the checkbox near the <strong>AmazonRoute53DomainsFullAccess</strong> policy and click the <strong>Next</strong> button.</p><hr /><p><img alt="IAM Add User 3" src="https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks/iam-add-user-3.png" /></p><p>Adding a tag is optional but it can help others discover what the IAM identity is used for, so here I have added a tag <code>description</code> with a value of <code>used by acmetool to set lets encrypt challenge string in Route53 DNS records</code>. Click <strong>Next</strong> to move on.</p><hr /><p><img alt="IAM Add User 4" src="https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks/iam-add-user-4.png" /></p><p>Review the user&apos;s details. They should look like the following. If everything is correct click the <strong>Create user</strong> button.</p><hr /><p><img alt="IAM Add User 5" src="https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks/iam-add-user-5.png" /></p><p>The final screen will give you the new user&apos;s access key ID and secret. But to show the secret you will need to click the <strong>Show</strong> link. So go ahead and do that now.</p><hr /><p><img alt="IAM Add User 5 Show Credentials" src="https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks/iam-add-user-5-show.png" /></p><p>This is the only time the key ID and the secret key will be available to you. So you need to save both these values now for later. You can place them into your ansible vault, hashicorp vault, chef databag, or whatever devops secret encryption storage you are using.</p><p><strong>Note:</strong> I left the key ID and secret unblurred in these screenshots so you can see what form they have so as to reduce any confusion. But these are not actually valid IAM access credentials that you can use to hack my account! I am not that silly!</p><h3 id="finding-your-route53-domain-zone-id">Finding your Route53 domain Zone ID</h3><p><img alt="IAM Route53 Dashboard" src="https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks/route53-dashboard.png" /></p><p>Navigate to the Route53 dashboard webpage. Click <strong>Hosted zones</strong> on the left panel or the central dashboard area.</p><hr /><p><img alt="IAM Route53 ZoneID" src="https://epiccastle.io/blog/setting-up-acmetool-with-route53-hooks/route53-zoneid.png" /></p><p>On the hosted zones page you will see a list of the Hosted Zone IDs down the right hand side. There is one Zone ID for each Zone. Each Zone ID begins with the letter Z and is 13 or 14 characters long. You will need to record the Zone ID for the zone that your Let&apos;s Encrypt certificate&apos;s domain will be in.</p><h3 id="setup-cron-running-of-acmetool-renewal">Setup Cron Running Of acmetool Renewal</h3><p><code>acmetool</code> will need to be run regularly in order to update any certificates that are coming up for renewal. Let&apos;s Encrypt currently issues 90 day certificates. acmetool will try to renew certificates automatically once they are 30 days from expiry, or two thirds through their validity period. Put the following in <code>/etc/cron.d/acmetool</code>:</p><h5 id="/usr/lib/acme/hooks/route53-2">/usr/lib/acme/hooks/route53</h5><pre><code class="language-language-shell">SHELL=/bin/sh
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
MAILTO=root
ACME_HOOKS_DIR=&quot;/usr/lib/acme/hooks/&quot;
ACME_HOSTED_ZONE=&quot;&lt;&lt; zone id here &gt;&gt;&quot;
AWS_ACCESS_KEY_ID=&quot;&lt;&lt; aws access key id here &gt;&gt;&quot;
AWS_SECRET_ACCESS_KEY=&quot;&lt;&lt; aws secret access key here &gt;&gt;&quot;
23 0 * * * root /usr/bin/acmetool --batch reconcile
</code></pre><p>Replace the values inside the double angled brackets with your values</p><p><strong>Note:</strong> acmetool will exit with an error message with nonzero exit status if it cannot renew a certificate. Ensure your system is configured so that you get notifications of failing cronjobs.</p><h3 id="gather-the-certificates">Gather the certificates</h3><p>Now we are ready to gather the certificates we need. Export the environment variables into the shell, and then run <code>acmetool want</code> to gather the certificates. Replace my.domain.com with the fully qualified domain name you want the certificate for.</p><pre><code class="language-language-shell-session">$ export ACME_HOOKS_DIR=&quot;/usr/lib/acme/hooks/&quot;
$ export ACME_HOSTED_ZONE=&quot;&lt;&lt; zone id here &gt;&gt;&quot;
$ export AWS_ACCESS_KEY_ID=&quot;&lt;&lt; aws access key id here &gt;&gt;&quot;
$ export AWS_SECRET_ACCESS_KEY=&quot;&lt;&lt; aws secret access key here &gt;&gt;&quot;
$ acmetool --batch want my.domain.com
</code></pre><p>Now, if nothing went wrong, you should find your certificate(s) and private key at <code>/var/lib/acme/live/domain.name</code></p><pre><code class="language-language-shell-session">$ ls /var/lib/acme/live/my.domain.com/
cert  chain  fullchain  privkey  url
</code></pre><h3 id="troubleshooting">Troubleshooting</h3><p>If something fails, even inside the cron job, you can examine what last went wrong with additional information with the following:</p><pre><code class="language-language-shell-session">$ acmetool --xlog.severity=debug
</code></pre><p>This will show you all the steps that acmetool took to try to verify your domain and the results of those steps.</p><h3 id="example-setup-for-nginx">Example Setup For Nginx</h3><p>Here is a quick example section from an nginx sites-enabled config file showing the use of that certificate. Use this as a reference for ither servers or applications.</p><pre><code class="language-language-nginx"># HTTP Server
server {
    listen 80;
    server_name  my.domain.com;

    # redirect http traffic to https
    location / {
      return 301 https://$host$request_uri;
    }
}

# HTTPS Server
server {
   listen 443 ssl;
   server_name my.domain.com;

   # our lets encrypt certificate chain and private key
   ssl_certificate      /var/lib/acme/live/my.domain.com/fullchain;
   ssl_certificate_key  /var/lib/acme/live/my.domain.com/privkey;

   ssl_session_cache    shared:SSL:1m;
   ssl_session_timeout  5m;

   # disable weak and vulnerable ciphers
   ssl_ciphers &quot;ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES&quot;;
   ssl_prefer_server_ciphers  on;

   # you may want some custome diffie hellman parameters to be extra secure
   ssl_dhparam /etc/nginx/dhparams.pem;

   # logging
   access_log /var/log/nginx/my.domain.com_access.log main;
   error_log /var/log/nginx/my.domain.com_error.log;

   # our documents location
   root /var/www/my.domain.com/public;
}
</code></pre><p>This should get you up and running with Route53 and acmetool. I hope you had success!</p>]]></content></entry></feed>