diff --git a/pkgs/certifix-client/certifix-client.fnl b/pkgs/certifix-client/certifix-client.fnl
new file mode 100644
index 00000000..81cea76f
--- /dev/null
+++ b/pkgs/certifix-client/certifix-client.fnl
@@ -0,0 +1,80 @@
+(local { : view } (require :fennel))
+(local { : assoc : split } (require :anoia))
+
+(local ctx (require :openssl.ssl.context))
+(local csr (require :openssl.x509.csr))
+(local pkey (require :openssl.pkey))
+(local xn (require :openssl.x509.name))
+
+(local http (require :fetch))
+
+(macro ncall [f]
+  `(case ,f
+     ok# ok#
+     (nil err#) (error err#)))
+
+
+(fn x509-name [subj]
+  (let [n (xn.new)]
+    (each [_ c (ipairs (split "," subj))]
+      (let [(k v) (string.match c "(.-)=(.+)")]
+        (n:add k v)))
+    n))
+
+(fn parse-args [args]
+  (case args
+    ["--secret" secret & rest]
+    (assoc (parse-args rest)
+           :secret (with-open [f (ncall (io.open secret :r))] (f:read "l")))
+
+    ["--subject" subject & rest]
+    (assoc (parse-args rest) :subject subject)
+
+    ["--key-out" pathname & rest]
+    (assoc (parse-args rest) :key-out pathname)
+
+    ["--certificate-out" pathname & rest]
+    (assoc (parse-args rest) :certificate-out pathname)
+
+    [server] { : server }
+    _ {}))
+
+
+(local options (parse-args arg))
+
+(fn private-key []
+  (pkey.new { :type :rsa :bits 1024 }))
+
+(fn signing-request [pk]
+  (doto (csr.new)
+    (: :setVersion 3)
+    (: :setSubject (x509-name options.subject))
+    (: :setPublicKey pk)
+    (: :addAttribute :challengePassword [options.secret])
+    (: :sign pk)))
+
+
+(fn http-post [url body]
+  (match
+      (http.request "POST" url
+                    "" 0
+                    "application/x-pem-file"
+                    body)
+    s s
+    (nil code msg) (error (.. "Error " code " POST " url ": " msg))))
+
+
+(fn run []
+  (let [pk (private-key)
+        csr (signing-request pk)
+    ;; key-out (or options.key-out-handle io.stdout)
+    ;; cert-out (or options.cert-out-handle io.stdout)
+        cert (http-post options.server (csr:toPEM))]
+    (with-open [f (ncall (io.open options.key-out :w))]
+      (f:write (pk:toPEM :private)))
+    (with-open [f (ncall (io.open options.certificate-out :w))]
+      (f:write cert))
+    (print "done")))
+
+
+{ : run }
diff --git a/pkgs/certifix-client/default.nix b/pkgs/certifix-client/default.nix
new file mode 100644
index 00000000..5876cf06
--- /dev/null
+++ b/pkgs/certifix-client/default.nix
@@ -0,0 +1,36 @@
+{
+  fetchurl,
+  writeFennel,
+  fennel,
+  fennelrepl,
+  runCommand,
+  lua,
+  anoia,
+  lualinux,
+  fetch-freebsd,
+  openssl,
+  luaossl',
+  stdenv
+}:
+let name = "certifix-client";
+in stdenv.mkDerivation {
+  inherit name;
+  src = ./.;
+
+  buildInputs = [fetch-freebsd openssl lua];
+
+  buildPhase = "";
+  installPhase = ''
+    mkdir -p $out/bin
+    cp -p ${writeFennel name {
+      packages = [
+        fetch-freebsd
+        fennel
+        anoia
+        lualinux
+        luaossl'
+      ] ;
+      mainFunction = "run";
+    } ./${name}.fnl } $out/bin/${name}
+  '';
+}
diff --git a/pkgs/certifix-client/main.fnl b/pkgs/certifix-client/main.fnl
new file mode 100644
index 00000000..0ac152de
--- /dev/null
+++ b/pkgs/certifix-client/main.fnl
@@ -0,0 +1,9 @@
+(local { : view } (require :fennel))
+(local ctx (require openssl.ssl.ctx))
+
+(fn run []
+  (print "hey"))
+
+
+
+{ : run }
diff --git a/pkgs/default.nix b/pkgs/default.nix
index 81e17d08..975ba7fe 100644
--- a/pkgs/default.nix
+++ b/pkgs/default.nix
@@ -60,6 +60,7 @@ in {
   # please keep the rest of this list alphabetised :-)
 
   anoia = callPackage ./anoia { };
+  certifix-client = callPackage ./certifix-client { };
   devout = callPackage ./devout { };
   fetch-freebsd = callPackage ./fetch-freebsd { };
   fennel = callPackage ./fennel { };