git » kxd » commit bc74d7e

Update documentation to markdown and pod

author Alberto Bertogli
2019-08-10 09:17:00 UTC
committer Alberto Bertogli
2019-08-31 16:26:53 UTC
parent 0150a9390cd549f552aa893bfe4af3f2adeba5fc

Update documentation to markdown and pod

This patch updates the documentation to use markdown (for text files)
and pod (for man files). They're easier to manage and the tooling chain
required is easier.

.gitignore +1 -0
.mkdocs.yml +9 -0
README +0 -92
README.md +90 -0
doc/index.md +1 -0
doc/man/.gitignore +0 -1
doc/man/Makefile +0 -11
doc/man/generate.sh +27 -0
doc/man/kxc-cryptsetup.1 +180 -0
doc/man/kxc-cryptsetup.1.pod +60 -0
doc/man/kxc-cryptsetup.rst +0 -69
doc/man/kxc.1 +178 -0
doc/man/kxc.1.pod +54 -0
doc/man/kxc.rst +0 -59
doc/man/kxd.1 +231 -0
doc/man/kxd.1.pod +131 -0
doc/man/kxd.rst +0 -111
doc/quick_start.md +112 -0
doc/quick_start.rst +0 -115

diff --git a/.gitignore b/.gitignore
index c4db43c..b68d062 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 out/
 *.swp
+.*
 
 # Just in case, we ignore all .pem so noone commits them by accident.
 *.pem
diff --git a/.mkdocs.yml b/.mkdocs.yml
new file mode 100644
index 0000000..f32cc20
--- /dev/null
+++ b/.mkdocs.yml
@@ -0,0 +1,9 @@
+site_name: kxd
+docs_dir: doc
+theme: readthedocs
+
+markdown_extensions:
+  - codehilite:
+      guess_lang: false
+  - attr_list
+
diff --git a/README b/README
deleted file mode 100644
index b707742..0000000
--- a/README
+++ /dev/null
@@ -1,92 +0,0 @@
-
-kxd - Key exchange daemon
-=========================
-
-kxd is a key exchange daemon, which serves blobs of data (keys) over https.
-
-It can be used to get keys remotely instead of using local storage.
-The main use case is to get keys to open dm-crypt devices automatically,
-without having to store them on the local machine.
-
-
-Quick start
------------
-
-The document at doc/quick_start.rst contains a step by step guide of a typical
-server and client setups.
-
-
-Server configuration
---------------------
-
-The server configuration is stored in a root directory (/etc/kxd/data), and
-within there, with per-key directories (e.g. /etc/kxd/data/host1/key1), each
-containing the following files:
-
- - key: Contains the key to give to the client.
- - allowed_clients: Contains one or more PEM-encoded client certificates that
-   will be allowed to request the key.
-   If not present, then no clients will be allowed to access this key.
- - allowed_hosts: Contains one or more host names (one per line).
-   If not present, then all hosts will be allowed to access that key (as long
-   as they are authorized with a valid client certificate).
- - email_to: Contains one or more email destinations to notify (one per line).
-   If not present, then no notifications will be sent upon key accesses.
-
-
-Client configuration
---------------------
-
-The basic command line client (kxc) will take the client key and certificate,
-the expected server certificate, and a URL to the server (like
-kxd://server/host1/key1), and it will print on standard output the returned
-key (the contents of the corresponding key file).
-
-There are scripts to tie this with cryptsetup's infrastructure to make the
-opening of encrypted devices automatic; see cryptsetup/ for the details.
-
-
-Security
---------
-
-All traffic between the server and the clients goes over SSL, using the
-provided server certificate.
-
-The clients are authenticated and authorized based on their SSL client
-certificates matching the ones associated with the key in the server
-configuration, not using a root of trust (for now).
-
-Likewise, the clients will authenticate the server based on a certificate
-given on the command line, and will only accept keys from it.
-
-
-Note the server will return reasonably detailed information on errors, for
-example it will tell when a key is not found vs. when the client is not
-allowed. While this leaks some information about existence of keys, it makes
-troubleshooting much easier.
-
-The server itself makes no effort to protect the data internally; for example,
-there is no on-disk encryption, and memory is not locked. We work under the
-assumption that the server's host is secure and trusted.
-
-
-Dependencies
-------------
-
-There are no runtime dependencies for the kxd and kxc binaries.
-
-Building requires Go 1.11.
-
-The configuration helper scripts (create-kxd-config, kxc-add-key, etc.)
-depend on: bash, openssl (the binary), and core utilities (mkdir, dd, etc.).
-
-Testing needs Python 2.7, and openssl (the binary).
-
-
-Bugs and contact
-----------------
-
-Please report bugs to albertito@blitiri.com.ar.
-
-The latest version can be found at http://blitiri.com.ar/p/kxd/.
-
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5b32001
--- /dev/null
+++ b/README.md
@@ -0,0 +1,90 @@
+
+# Key exchange daemon
+
+[kxd](https://blitiri.com.ar/p/kxd) is a key exchange daemon, and
+corresponding client, which serves blobs of data (keys) over https.
+
+It can be used to get keys remotely instead of using local storage.
+The main use case is to get keys to open dm-crypt devices automatically,
+without having to store them on the local machine.
+
+[![Travis-CI build status](https://travis-ci.org/albertito/kxd.svg?branch=master)](https://travis-ci.org/albertito/kxd)
+
+
+## Quick start
+
+Please see the [quick start](https://blitiri.com.ar/p/kxd/docs/quick_start)
+document for a step by step guide of a typical server and client setups.
+
+
+## Server configuration
+
+The server configuration is stored in a root directory (`/etc/kxd/data`), and
+within there, with per-key directories (e.g. `/etc/kxd/data/host1/key1`), each
+containing the following files:
+
+- `key`: Contains the key to give to the client.
+- `allowed_clients`: Contains one or more PEM-encoded client certificates
+  that will be allowed to request the key.  If not present, then no clients
+  will be allowed to access this key.
+- `allowed_hosts`: Contains one or more host names (one per line).  If not
+  present, then all hosts will be allowed to access that key (as long as they
+  are authorized with a valid client certificate).
+- `email_to`: Contains one or more email destinations to notify (one per
+  line).  If not present, then no notifications will be sent upon key
+  accesses.
+
+
+## Client configuration
+
+The basic command line client (*kxc*) will take the client key and
+certificate, the expected server certificate, and a URL to the server (like
+`kxd://server/host1/key1`), and it will print on standard output the returned
+key (the contents of the corresponding key file).
+
+There are scripts to tie this with cryptsetup's infrastructure to make the
+opening of encrypted devices automatic; see `cryptsetup/` for the details.
+
+
+## Security
+
+All traffic between the server and the clients goes over SSL, using the
+provided server certificate.
+
+The clients are authenticated and authorized based on their SSL client
+certificates matching the ones associated with the key in the server
+configuration, not using a root of trust (for now).
+
+Likewise, the clients will authenticate the server based on a certificate
+given on the command line, and will only accept keys from it.
+
+Note the server will return reasonably detailed information on errors, for
+example it will tell when a key is not found vs. when the client is not
+allowed. While this leaks some information about existence of keys, it makes
+troubleshooting much easier.
+
+The server itself makes no effort to protect the data internally; for example,
+there is no on-disk encryption, and memory is not locked. We work under the
+assumption that the server's host is secure and trusted.
+
+
+## Dependencies
+
+There are no runtime dependencies for the kxd and kxc binaries.
+
+Building requires Go 1.11.
+
+The configuration helper scripts (`create-kxd-config`, `kxc-add-key`, etc.)
+depend on: `bash`, `openssl` (the binary), and core utilities (`mkdir`, `dd`,
+etc.).
+
+Testing needs Python 2.7, and openssl (the binary).
+
+
+## Bugs and contact
+
+Please report bugs to albertito@blitiri.com.ar.
+
+The latest version can be found at
+[https://blitiri.com.ar/p/kxd/](https://blitiri.com.ar/p/kxd/)
+
diff --git a/doc/index.md b/doc/index.md
new file mode 120000
index 0000000..32d46ee
--- /dev/null
+++ b/doc/index.md
@@ -0,0 +1 @@
+../README.md
\ No newline at end of file
diff --git a/doc/man/.gitignore b/doc/man/.gitignore
deleted file mode 100644
index f7e585b..0000000
--- a/doc/man/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.1
diff --git a/doc/man/Makefile b/doc/man/Makefile
deleted file mode 100644
index 22c9bec..0000000
--- a/doc/man/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-
-default: manpages
-
-%.1: %.rst
-	rst2man < $^ > $@
-
-manpages: kxd.1 kxc.1 kxc-cryptsetup.1
-
-clean:
-	rm -f kxd.1 kxc.1 kxc-cryptsetup.1
-
diff --git a/doc/man/generate.sh b/doc/man/generate.sh
new file mode 100755
index 0000000..2f29a58
--- /dev/null
+++ b/doc/man/generate.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+#
+# Convert pod files to manual pages, using pod2man.
+# 
+# Assumes files are named like:
+#   <name>.<section>.pod
+
+set -e
+
+for IN in *.pod; do
+	OUT=$( basename $IN .pod )
+	SECTION=${OUT##*.}
+	NAME=${OUT%.*}
+
+	# If it has not changed in git, set the mtime to the last commit that
+	# touched the file.
+	CHANGED=$( git status --porcelain -- "$IN" | wc -l )
+	if [ $CHANGED -eq 0 ]; then
+		GIT_MTIME=$( git log --pretty=%at -n1 -- "$IN" )
+		touch -d "@$GIT_MTIME" "$IN"
+	fi
+
+	podchecker $IN
+	pod2man --section=$SECTION --name=$NAME \
+		--release "" --center "" \
+		$IN $OUT
+done
diff --git a/doc/man/kxc-cryptsetup.1 b/doc/man/kxc-cryptsetup.1
new file mode 100644
index 0000000..8b7fbb1
--- /dev/null
+++ b/doc/man/kxc-cryptsetup.1
@@ -0,0 +1,180 @@
+.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is >0, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{\
+.    if \nF \{\
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{\
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "kxc-cryptsetup 1"
+.TH kxc-cryptsetup 1 "2019-08-10" "" ""
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+kxc\-cryptsetup \- Cryptsetup helper to kxc
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+\&\fBkxc-cryptsetup\fR \fI\s-1NAME\s0\fR
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\&\fBkxc\fR\|(1) is a client for \fBkxd\fR\|(1), a key exchange daemon.
+.PP
+kxc-cryptsetup is a convenience wrapper for invoking kxc while taking the
+options from the files in \fI/etc/kxc/\fR.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+Its only command-line argument is a descriptive name, which will be used to
+find the configuration files.
+.SH "FILES"
+.IX Header "FILES"
+For a given \fI\s-1NAME\s0\fR that is passed as the only command-line argument, the
+following files are needed:
+.IP "\fI/etc/kxc/NAME.key.pem\fR" 8
+.IX Item "/etc/kxc/NAME.key.pem"
+Private key to use.
+.IP "\fI/etc/kxc/NAME.cert.pem\fR" 8
+.IX Item "/etc/kxc/NAME.cert.pem"
+Certificate to use. Must match the given key.
+.IP "\fI/etc/kxc/NAME.server_cert.pem\fR" 8
+.IX Item "/etc/kxc/NAME.server_cert.pem"
+Server certificate, used to validate the server.
+.IP "\fI/etc/kxc/NAME.url\fR" 8
+.IX Item "/etc/kxc/NAME.url"
+Contains the \s-1URL\s0 to the key; usually in the form of \f(CW\*(C`kxd://server/name\*(C'\fR.
+.SH "CONTACT"
+.IX Header "CONTACT"
+Main website <https://blitiri.com.ar/p/kxd>.
+.PP
+If you have any questions, comments or patches please send them to
+\&\f(CW\*(C`albertito@blitiri.com.ar\*(C'\fR.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fBkxc\fR\|(1), \fBkxd\fR\|(1), \fBcrypttab\fR\|(5), \fBcryptsetup\fR\|(8).
diff --git a/doc/man/kxc-cryptsetup.1.pod b/doc/man/kxc-cryptsetup.1.pod
new file mode 100644
index 0000000..550837a
--- /dev/null
+++ b/doc/man/kxc-cryptsetup.1.pod
@@ -0,0 +1,60 @@
+=head1 NAME
+
+kxc-cryptsetup - Cryptsetup helper to kxc
+
+=head1 SYNOPSIS
+
+B<kxc-cryptsetup> I<NAME>
+
+
+=head1 DESCRIPTION
+
+L<kxc(1)> is a client for L<kxd(1)>, a key exchange daemon.
+
+kxc-cryptsetup is a convenience wrapper for invoking kxc while taking the
+options from the files in F</etc/kxc/>.
+
+
+=head1 OPTIONS
+
+Its only command-line argument is a descriptive name, which will be used to
+find the configuration files.
+
+
+=head1 FILES
+
+For a given I<NAME> that is passed as the only command-line argument, the
+following files are needed:
+
+=over 8
+
+=item F</etc/kxc/NAME.key.pem>
+
+Private key to use.
+
+=item F</etc/kxc/NAME.cert.pem>
+
+Certificate to use. Must match the given key.
+
+=item F</etc/kxc/NAME.server_cert.pem>
+
+Server certificate, used to validate the server.
+
+=item F</etc/kxc/NAME.url>
+
+Contains the URL to the key; usually in the form of C<kxd://server/name>.
+
+=back
+
+
+=head1 CONTACT
+
+L<Main website|https://blitiri.com.ar/p/kxd>.
+
+If you have any questions, comments or patches please send them to
+C<albertito@blitiri.com.ar>.
+
+
+=head1 SEE ALSO
+
+L<kxc(1)>, L<kxd(1)>, L<crypttab(5)>, L<cryptsetup(8)>.
diff --git a/doc/man/kxc-cryptsetup.rst b/doc/man/kxc-cryptsetup.rst
deleted file mode 100644
index a6769b0..0000000
--- a/doc/man/kxc-cryptsetup.rst
+++ /dev/null
@@ -1,69 +0,0 @@
-
-================
- kxc-cryptsetup
-================
-
-------------------------
-Cryptsetup helper to kxc
-------------------------
-
-:Author: Alberto Bertogli <albertito@blitiri.com.ar>
-:Manual section: 1
-
-
-SYNOPSIS
-========
-
-kxc-cryptsetup <NAME>
-
-
-DESCRIPTION
-===========
-
-``kxc(1)`` is a client for kxd, a key exchange daemon.
-
-kxc-cryptsetup is a convenience wrapper for invoking kxc while taking the
-options from the files in ``/etc/kxc/``.
-
-It can be used as a cryptsetup keyscript, to automatically get keys to open
-encrypted devices with kxc.
-
-
-OPTIONS
-=======
-
-Its only command-line argument is a descriptive name, which will be used to
-find the configuration files.
-
-
-FILES
-=====
-
-For a given *NAME* that is passed as the only command-line argument, the
-following files are needed:
-
-/etc/kxc/NAME.key.pem
-  Private key to use.
-
-/etc/kxc/NAME.cert.pem
-  Certificate to use. Must match the given key.
-
-/etc/kxc/NAME.server_cert.pem
-  Server certificate, used to validate the server.
-
-/etc/kxc/NAME.url
-  Contains the URL to the key; usually in the form of ``kxd://server/name``.
-
-
-SEE ALSO
-========
-
-``kxc(1)``, ``kxd(1)``, ``crypttab(5)``, ``cryptsetup(8)``.
-
-
-BUGS
-====
-
-If you want to report bugs, or have any questions or comments, just let me
-know. For more information, you can go to http://blitiri.com.ar/p/kxd.
-
diff --git a/doc/man/kxc.1 b/doc/man/kxc.1
new file mode 100644
index 0000000..cc4c402
--- /dev/null
+++ b/doc/man/kxc.1
@@ -0,0 +1,178 @@
+.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is >0, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{\
+.    if \nF \{\
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{\
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "kxc 1"
+.TH kxc 1 "2019-08-10" "" ""
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+kxc \- Key exchange client
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+\&\fBkxc\fR [\fIoptions\fR...]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+kxc is a client for \fBkxd\fR\|(1), a key exchange daemon.
+.PP
+It will take a client key and certificate, the expected server certificate,
+and a \s-1URL\s0 to the server (like \f(CW\*(C`kxd://server/host1/key1\*(C'\fR), and it will print
+on standard output the returned key (the contents of the corresponding key
+file on the server).
+.PP
+There are scripts to tie this with cryptsetup's infrastructure to make the
+opening of encrypted devices automatic; see \fBkxc\-cryptsetup\fR\|(1) for the
+details.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+.IP "\fB\-\-client_key\fR=\fIfile\fR" 8
+.IX Item "--client_key=file"
+File containing the client private key (in \s-1PAM\s0 format).
+.IP "\fB\-\-client_cert\fR=\fIfile\fR" 8
+.IX Item "--client_cert=file"
+File containing the client certificate that corresponds to the given key (in
+\&\s-1PAM\s0 format).
+.IP "\fB\-\-server_cert\fR=\fIfile\fR" 8
+.IX Item "--server_cert=file"
+File containing valid server certificate (in \s-1PAM\s0 format).
+.SH "CONTACT"
+.IX Header "CONTACT"
+Main website <https://blitiri.com.ar/p/kxd>.
+.PP
+If you have any questions, comments or patches please send them to
+\&\f(CW\*(C`albertito@blitiri.com.ar\*(C'\fR.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fBkxc\-cryptsetup\fR\|(1), \fBkxd\fR\|(1).
diff --git a/doc/man/kxc.1.pod b/doc/man/kxc.1.pod
new file mode 100644
index 0000000..25becde
--- /dev/null
+++ b/doc/man/kxc.1.pod
@@ -0,0 +1,54 @@
+=head1 NAME
+
+kxc - Key exchange client
+
+=head1 SYNOPSIS
+
+B<kxc> [I<options>...]
+
+
+=head1 DESCRIPTION
+
+kxc is a client for L<kxd(1)>, a key exchange daemon.
+
+It will take a client key and certificate, the expected server certificate,
+and a URL to the server (like C<kxd://server/host1/key1>), and it will print
+on standard output the returned key (the contents of the corresponding key
+file on the server).
+
+There are scripts to tie this with cryptsetup's infrastructure to make the
+opening of encrypted devices automatic; see L<kxc-cryptsetup(1)> for the
+details.
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--client_key>=I<file>
+
+File containing the client private key (in PAM format).
+
+=item B<--client_cert>=I<file>
+
+File containing the client certificate that corresponds to the given key (in
+PAM format).
+
+=item B<--server_cert>=I<file>
+
+File containing valid server certificate (in PAM format).
+
+=back
+
+
+=head1 CONTACT
+
+L<Main website|https://blitiri.com.ar/p/kxd>.
+
+If you have any questions, comments or patches please send them to
+C<albertito@blitiri.com.ar>.
+
+
+=head1 SEE ALSO
+
+L<kxc-cryptsetup(1)>, L<kxd(1)>.
diff --git a/doc/man/kxc.rst b/doc/man/kxc.rst
deleted file mode 100644
index 54b25f2..0000000
--- a/doc/man/kxc.rst
+++ /dev/null
@@ -1,59 +0,0 @@
-
-=====
- kxc
-=====
-
--------------------
-Key exchange client
--------------------
-:Author: Alberto Bertogli <albertito@blitiri.com.ar>
-:Manual section: 1
-
-
-SYNOPSIS
-========
-
-kxc --client_cert=<file> --client_key=<file> --server_cert=<file> <URL>
-
-
-DESCRIPTION
-===========
-
-kxc is a client for kxd, a key exchange daemon.
-
-It will take a client key and certificate, the expected server certificate,
-and a URL to the server (like ``kxd://server/host1/key1``), and it will print
-on standard output the returned key (the contents of the corresponding key
-file on the server).
-
-There are scripts to tie this with cryptsetup's infrastructure to make the
-opening of encrypted devices automatic; see ``kxc-cryptsetup(1)`` for the
-details.
-
-
-OPTIONS
-=======
-
---client_key=<file>
-  File containing the client private key (in PAM format).
-
---client_cert=<file>
-  File containing the client certificate that corresponds to the given key (in
-  PAM format).
-
---server_cert=<file>
-  File containing valid server certificate(s).
-
-
-SEE ALSO
-========
-
-``kxc-cryptsetup(1)``, ``kxd(1)``.
-
-
-BUGS
-====
-
-If you want to report bugs, or have any questions or comments, just let me
-know. For more information, you can go to http://blitiri.com.ar/p/kxd.
-
diff --git a/doc/man/kxd.1 b/doc/man/kxd.1
new file mode 100644
index 0000000..dcde8f2
--- /dev/null
+++ b/doc/man/kxd.1
@@ -0,0 +1,231 @@
+.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings.  \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
+.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+.    ds -- \(*W-
+.    ds PI pi
+.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
+.    ds L" ""
+.    ds R" ""
+.    ds C` ""
+.    ds C' ""
+'br\}
+.el\{\
+.    ds -- \|\(em\|
+.    ds PI \(*p
+.    ds L" ``
+.    ds R" ''
+.    ds C`
+.    ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\"
+.\" If the F register is >0, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD.  Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{\
+.    if \nF \{\
+.        de IX
+.        tm Index:\\$1\t\\n%\t"\\$2"
+..
+.        if !\nF==2 \{\
+.            nr % 0
+.            nr F 2
+.        \}
+.    \}
+.\}
+.rr rF
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
+.    \" fudge factors for nroff and troff
+.if n \{\
+.    ds #H 0
+.    ds #V .8m
+.    ds #F .3m
+.    ds #[ \f1
+.    ds #] \fP
+.\}
+.if t \{\
+.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+.    ds #V .6m
+.    ds #F 0
+.    ds #[ \&
+.    ds #] \&
+.\}
+.    \" simple accents for nroff and troff
+.if n \{\
+.    ds ' \&
+.    ds ` \&
+.    ds ^ \&
+.    ds , \&
+.    ds ~ ~
+.    ds /
+.\}
+.if t \{\
+.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+.    \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+.    \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+.    \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+.    ds : e
+.    ds 8 ss
+.    ds o a
+.    ds d- d\h'-1'\(ga
+.    ds D- D\h'-1'\(hy
+.    ds th \o'bp'
+.    ds Th \o'LP'
+.    ds ae ae
+.    ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "kxd 1"
+.TH kxd 1 "2019-08-10" "" ""
+.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+kxd \- Key exchange daemon
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+\&\fBkxd\fR [\fIoptions\fR...]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+kxd is a key exchange daemon, which serves blobs of data (keys) over https.
+.PP
+It can be used to get keys remotely instead of using local storage.
+The main use case is to get keys to open dm-crypt devices automatically,
+without having to store them on the local machine.
+.SH "SETUP"
+.IX Header "SETUP"
+The server configuration is stored in a root directory (\fI/etc/kxd/data/\fR by
+default), and within there, with per-key directories (e.g.
+\&\fI/etc/kxd/data/host1/key1/\fR), each containing the following files:
+.IP "\fIkey\fR" 8
+.IX Item "key"
+Contains the key to give to the client.
+.IP "\fIallowed_clients\fR" 8
+.IX Item "allowed_clients"
+Contains one or more PEM-encoded client certificates that will be allowed to
+request the key. If not present, then no clients will be allowed to access
+this key.
+.IP "\fIallowed_hosts\fR" 8
+.IX Item "allowed_hosts"
+Contains one or more host names (one per line). If not present, then all hosts
+will be allowed to access that key (as long as they are authorized with a
+valid client certificate).
+.IP "\fIemail_to\fR" 8
+.IX Item "email_to"
+Contains one or more email destinations to notify (one per line).  If not
+present, then no notifications will be sent upon key accesses.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+.IP "\fB\-\-key\fR=\fIfile\fR" 8
+.IX Item "--key=file"
+Private key to use (in \s-1PAM\s0 format). Defaults to \fI/etc/kxd/key.pem\fR.
+.IP "\fB\-\-cert\fR=\fIfile\fR" 8
+.IX Item "--cert=file"
+Certificate to use (in \s-1PAM\s0 format); must match the given key. Defaults to
+\&\fI/etc/kxd/cert.pem\fR.
+.IP "\fB\-\-data_dir\fR=\fIdirectory\fR" 8
+.IX Item "--data_dir=directory"
+Data directory, where the key and configuration live (see the \s-1SETUP\s0 section
+above). Defaults to \fI/etc/kxd/data\fR.
+.IP "\fB\-\-ip_addr\fR=\fIip-address\fR" 8
+.IX Item "--ip_addr=ip-address"
+\&\s-1IP\s0 address to listen on. Defaults to all.
+.IP "\fB\-\-logfile\fR=\fIfile\fR" 8
+.IX Item "--logfile=file"
+File to write logs to, use \*(L"\-\*(R" for stdout. By default, the daemon will log to
+syslog.
+.IP "\fB\-\-port\fR=\fIport\fR" 8
+.IX Item "--port=port"
+Port to listen on. The default port is 19840.
+.IP "\fB\-\-email_from\fR=\fIemail-address\fR" 8
+.IX Item "--email_from=email-address"
+Email address to send email from.
+.IP "\fB\-\-smtp_addr\fR=\fIhost:port\fR" 8
+.IX Item "--smtp_addr=host:port"
+Address of the \s-1SMTP\s0 server to use to send emails. If none is given, then
+emails will not be sent.
+.IP "\fB\-\-hook\fR=\fIfile\fR" 8
+.IX Item "--hook=file"
+Script to run before authorizing keys. Skipped if it doesn't exist. Defaults
+to \fI/etc/kxd/hook\fR.
+.SH "FILES"
+.IX Header "FILES"
+.IP "\fI/etc/kxd/key.pem\fR" 8
+.IX Item "/etc/kxd/key.pem"
+Private key to use (in \s-1PAM\s0 format).
+.IP "\fI/etc/kxd/cert.pem\fR" 8
+.IX Item "/etc/kxd/cert.pem"
+Certificate to use (in \s-1PAM\s0 format); must match the given key.
+.IP "\fI/etc/kxd/hook\fR" 8
+.IX Item "/etc/kxd/hook"
+Script to run before authorizing keys. Skipped if it doesn't exist.
+.IP "\fI/etc/kxd/data/\fR" 8
+.IX Item "/etc/kxd/data/"
+Data directory, where the keys and their configuration live.
+.SH "CONTACT"
+.IX Header "CONTACT"
+Main website <https://blitiri.com.ar/p/kxd>.
+.PP
+If you have any questions, comments or patches please send them to
+\&\f(CW\*(C`albertito@blitiri.com.ar\*(C'\fR.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fBkxc\fR\|(1), \fBkxc\-cryptsetup\fR\|(1).
diff --git a/doc/man/kxd.1.pod b/doc/man/kxd.1.pod
new file mode 100644
index 0000000..07eda6e
--- /dev/null
+++ b/doc/man/kxd.1.pod
@@ -0,0 +1,131 @@
+=head1 NAME
+
+kxd - Key exchange daemon
+
+=head1 SYNOPSIS
+
+B<kxd> [I<options>...]
+
+
+=head1 DESCRIPTION
+
+kxd is a key exchange daemon, which serves blobs of data (keys) over https.
+
+It can be used to get keys remotely instead of using local storage.
+The main use case is to get keys to open dm-crypt devices automatically,
+without having to store them on the local machine.
+
+=head1 SETUP
+
+The server configuration is stored in a root directory (F</etc/kxd/data/> by
+default), and within there, with per-key directories (e.g.
+F</etc/kxd/data/host1/key1/>), each containing the following files:
+
+=over 8
+
+=item F<key>
+
+Contains the key to give to the client.
+
+=item F<allowed_clients>
+
+Contains one or more PEM-encoded client certificates that will be allowed to
+request the key. If not present, then no clients will be allowed to access
+this key.
+
+=item F<allowed_hosts>
+
+Contains one or more host names (one per line). If not present, then all hosts
+will be allowed to access that key (as long as they are authorized with a
+valid client certificate).
+
+=item F<email_to>
+
+Contains one or more email destinations to notify (one per line).  If not
+present, then no notifications will be sent upon key accesses.
+
+=back
+
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--key>=I<file>
+
+Private key to use (in PAM format). Defaults to F</etc/kxd/key.pem>.
+
+=item B<--cert>=I<file>
+
+Certificate to use (in PAM format); must match the given key. Defaults to
+F</etc/kxd/cert.pem>.
+
+=item B<--data_dir>=I<directory>
+
+Data directory, where the key and configuration live (see the SETUP section
+above). Defaults to F</etc/kxd/data>.
+
+=item B<--ip_addr>=I<ip-address>
+
+IP address to listen on. Defaults to all.
+
+=item B<--logfile>=I<file>
+
+File to write logs to, use "-" for stdout. By default, the daemon will log to
+syslog.
+
+=item B<--port>=I<port>
+
+Port to listen on. The default port is 19840.
+
+=item B<--email_from>=I<email-address>
+
+Email address to send email from.
+
+=item B<--smtp_addr>=I<host:port>
+
+Address of the SMTP server to use to send emails. If none is given, then
+emails will not be sent.
+
+=item B<--hook>=I<file>
+
+Script to run before authorizing keys. Skipped if it doesn't exist. Defaults
+to F</etc/kxd/hook>.
+
+=back
+
+
+=head1 FILES
+
+=over 8
+
+=item F</etc/kxd/key.pem>
+
+Private key to use (in PAM format).
+
+=item F</etc/kxd/cert.pem>
+
+Certificate to use (in PAM format); must match the given key.
+
+=item F</etc/kxd/hook>
+
+Script to run before authorizing keys. Skipped if it doesn't exist.
+
+=item F</etc/kxd/data/>
+
+Data directory, where the keys and their configuration live.
+
+=back
+
+
+=head1 CONTACT
+
+L<Main website|https://blitiri.com.ar/p/kxd>.
+
+If you have any questions, comments or patches please send them to
+C<albertito@blitiri.com.ar>.
+
+
+=head1 SEE ALSO
+
+L<kxc(1)>, L<kxc-cryptsetup(1)>.
diff --git a/doc/man/kxd.rst b/doc/man/kxd.rst
deleted file mode 100644
index 9525b86..0000000
--- a/doc/man/kxd.rst
+++ /dev/null
@@ -1,111 +0,0 @@
-
-=====
- kxd
-=====
-
--------------------
-Key exchange daemon
--------------------
-
-:Author: Alberto Bertogli <albertito@blitiri.com.ar>
-:Manual section: 1
-
-
-SYNOPSIS
-========
-
-kxd [--key=<file>] [--cert=<file>] [--data_dir=<directory>]
-[--email_from=<email-address>] [--ip_addr=<ip-address>] [--logfile=<file>]
-[--port=<port>] [--smtp_addr=<host:port>]
-
-
-DESCRIPTION
-===========
-
-kxd is a key exchange daemon, which serves blobs of data (keys) over https.
-
-It can be used to get keys remotely instead of using local storage.
-The main use case is to get keys to open dm-crypt devices automatically,
-without having to store them on the local machine.
-
-
-SETUP
-=====
-
-The server configuration is stored in a root directory (``/etc/kxd/data/`` by
-default), and within there, with per-key directories (e.g.
-``/etc/kxd/data/host1/key1/``), each containing the following files:
-
-  - ``key``: Contains the key to give to the client.
-  - ``allowed_clients``: Contains one or more PEM-encoded client certificates
-    that will be allowed to request the key.
-    If not present, then no clients will be allowed to access this key.
-  - ``allowed_hosts``: Contains one or more host names (one per line).
-    If not present, then all hosts will be allowed to access that key (as long
-    as they are authorized with a valid client certificate).
-  - ``email_to``: Contains one or more email destinations to notify (one per
-    line).  If not present, then no notifications will be sent upon key
-    accesses.
-
-
-OPTIONS
-=======
-
---key=<file>
-  Private key to use.
-  Defaults to /etc/kxd/key.pem.
-
---cert=<file>
-  Certificate to use; must match the given key.
-  Defaults to /etc/kxd/cert.pem.
-
---data_dir=<directory>
-  Data directory, where the key and configuration live (see the SETUP section
-  above).
-  Defaults to /etc/kxd/data.
-
---email_from=<email-address>
-  Email address to send email from.
-
---ip_addr=<ip-address>
-  IP address to listen on.
-  Defaults to 0.0.0.0, which means all.
-
---logfile=<file>
-  File to write logs to, use '-' for stdout.
-  By default, the daemon will log to syslog.
-
---port=<port>
-  Port to listen on.
-  The default port is 19840.
-
---smtp_addr=<host:port>
-  Address of the SMTP server to use to send emails.
-  If none is given, then emails will not be sent.
-
-
-FILES
-=====
-
-/etc/kxd/key.pem
-  Private key to use for SSL.
-
-/etc/kxd/cert.pem
-  Certificate to use for SSL. Must match the given private key.
-
-/etc/kxd/data/
-  Directory where the keys and their configuration are stored.
-
-
-SEE ALSO
-========
-
-``kxc(1)``, ``kxc-cryptsetup(1)``.
-
-
-BUGS
-====
-
-If you want to report bugs, or have any questions or comments, just let me
-know. For more information, you can go to http://blitiri.com.ar/p/kxd.
-
diff --git a/doc/quick_start.md b/doc/quick_start.md
new file mode 100644
index 0000000..353094e
--- /dev/null
+++ b/doc/quick_start.md
@@ -0,0 +1,112 @@
+
+# Quick start
+
+In this guide we show how to set up a [key exchange daemon][kxd] and client
+on a typical scenario where the keys are used to open a device encrypted with
+[dm-crypt] \(the standard Linux disk encryption).
+
+These steps have been checked on a Debian install, other distributions should
+be similar but may differ on some of the details (specially on the
+[Configuring crypttab] section).
+
+- `server` is the hostname of the server.
+- `client` is the hostname of the client.
+- `sda2` is the encrypted drive.
+
+
+## Server setup
+
+Install [kxd] on the server, via your distribution packages (e.g. `apt install
+kxd`), or directly from source.
+
+Then, run `create-kxd-config`, which will create the configuration
+directories, and generate a [self-signed] key/cert pair for the server (valid
+for 10 years).
+Everything is in `/etc/kxd/`.
+
+
+## Client setup
+
+Install [kxc][kxd] on the client machine, via your distribution packages (e.g.
+`apt install kxc`), or directly from source.
+
+Then, run `kxc-add-key server sda2`, which will create the configuration
+directories, generate the client key/cert pair (valid for 10 years), and also
+create an entry for an `client/sda2` key to be fetched from the server.
+Everything is in `/etc/kxc/`.
+
+Finally, copy the server public certificate over, using
+`scp server:/etc/kxd/cert.pem /etc/kxc/sda2.server_cert.pem` (or something
+equivalent).
+
+
+## Adding the key to the server
+
+On the server, run `kxd-add-client-key client sda2` to generate the basic
+configuration for that client's key, including the key itself (generated
+randomly).
+
+Then, copy the client public certificate over, using
+`scp client:/etc/kxc/cert.pem /etc/kxd/data/client/sda2/allowed_clients`
+(or something equivalent).
+
+That allows the client to fetch the key.
+
+
+## Updating the drive's key
+
+On the client, run `kxc-cryptsetup sda2 | wc -c` to double-check that the
+output length is as expected (you could also compare it by running sha256 or
+something equivalent).
+
+Assuming that goes well, all you need is to add that key to your drives' key
+ring so it can be decrypted with it:
+
+```shell
+# Note we copy to /dev/shm which should not be written to disk.
+kxc-cryptsetup sda2 > /dev/shm/key
+
+cryptsetup luksAddKey /dev/sda2 /dev/shm/key
+
+rm /dev/shm/key
+```
+
+Note this *adds* a new key, but your existing ones are still valid. Always
+have more than one key, so if something goes wrong with kxd, you can still
+unlock the drive manually.
+
+
+## Configuring crypttab
+
+In order to get kxc to be run automatically to fetch the key, we need to edit
+`/etc/crypttab` and tell it to use a keyscript:
+
+```
+sda2_crypt UUID=blah-blah-blah sda2 luks,keyscript=/usr/bin/kxc-cryptsetup
+                               ^^^^      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+```
+
+Note the `sda2` field corresponds to the name we've been passing around in
+previous sections. The `keyscript=/usr/bin/kxc-cryptsetup` option is our way
+of telling the cryptsetup infrastructure to use our script to fetch the key
+for this target.
+
+
+You can test that this works by using:
+
+```shell
+cryptdisks_stop sda2_crypt
+cryptdisks_start sda2_crypt
+```
+
+The second command should issue a request to your server to get the key.
+
+Consider running `update-initramfs -u` if your device is the root device, or
+it is needed very early in the boot process.
+
+
+[kxd]: https://blitiri.com.ar/p/kxd
+[kxc]: https://blitiri.com.ar/p/kxd
+[dm-crypt]: https://en.wikipedia.org/wiki/dm-crypt
+[self-signed]: https://en.wikipedia.org/wiki/Self-signed_certificate
+
diff --git a/doc/quick_start.rst b/doc/quick_start.rst
deleted file mode 100644
index 3f32ec6..0000000
--- a/doc/quick_start.rst
+++ /dev/null
@@ -1,115 +0,0 @@
-
-===================================
- Key Exchange Daemon - Quick start
-===================================
-
-In this guide we show how to set up a `key exchange daemon`_ and client
-on a typical scenario where the keys are used to open a device encrypted with
-dm-crypt_ (the standard Linux disk encryption).
-
-These steps have been checked on a Debian install, other distributions should
-be similar but may differ on some of the details (specially on the
-"`Configuring crypttab`_" section).
-
-- ``server`` is the hostname of the server.
-- ``client`` is the hostname of the client.
-- ``sda2`` is the encrypted drive.
-
-
-Initial server setup
-====================
-
-First of all, install kxd_ on the server, usually via your distribution
-packages, or directly from source.
-
-Then, run ``create-kxd-config``, which will create the configuration
-directories, and generate a self-signed_ key/cert pair for the server (valid
-for 10 years).
-Everything is in ``/etc/kxd/``.
-
-
-Initial client setup
-====================
-
-Install kxc_ on the client machine, usually via your distribution packages, or
-directly from source.
-
-
-Then, run ``kxc-add-key server sda2``, which will create the configuration
-directories, generate the client key/cert pair (valid for 10 years), and also
-create an entry for an ``client/sda2`` key to be fetched from the server.
-Everything is in ``/etc/kxc/``.
-
-Finally, copy the server public certificate over, using
-``scp server:/etc/kxd/cert.pem /etc/kxc/sda2.server_cert.pem`` (or something
-equivalent).
-
-
-Adding the key to the server
-============================
-
-On the server, run ``kxd-add-client-key client sda2`` to generate the basic
-configuration for that client's key, including the key itself (generated
-randomly).
-
-Then, copy the client public certificate over, using
-``scp client:/etc/kxc/cert.pem /etc/kxd/data/client/sda2/allowed_clients``
-(or something equivalent).
-
-That allows the client to fetch the key.
-
-
-Updating the drive's key
-========================
-
-On the client, run ``kxc-cryptsetup sda2 | wc -c`` to double-check that the
-output length is as expected (you could also compare it by running sha256 or
-something equivalent).
-
-Assuming that goes well, all you need is to add that key to your drives' key
-ring so it can be decrypted with it::
-
-  # Note we copy to /dev/shm which should not be written to disk.
-  kxc-cryptsetup sda2 > /dev/shm/key
-
-  cryptsetup luksAddKey /dev/sda2 /dev/shm/key
-
-  rm /dev/shm/key
-
-Note this *adds* a new key, but your existing ones are still valid. Always
-have more than one key, so if something goes wrong with kxd, you can still
-unlock the drive manually.
-
-
-Configuring crypttab
-====================
-
-In order to get kxc to be run automatically to fetch the key, we need to edit
-``/etc/crypttab`` and tell it to use a keyscript::
-
-  sda2_crypt UUID=blah-blah-blah sda2 luks,keyscript=/usr/bin/kxc-cryptsetup
-                                 ^^^^      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Note the ``sda2`` field corresponds to the name we've been passing around in
-previous sections. The ``keyscript=/usr/bin/kxc-cryptsetup`` option is our way
-of telling the cryptsetup infrastructure to use our script to fetch the key
-for this target.
-
-
-You can test that this works by using::
-
-  cryptdisks_stop sda2_crypt
-  cryptdisks_start sda2_crypt
-
-The second command should issue a request to your server to get the key.
-
-Consider running ``update-initramfs -u`` if your device is the root device, or
-it is needed very early in the boot process.
-
-
-.. _key exchange daemon: http://blitiri.com.ar/p/kxd
-.. _kxd: http://blitiri.com.ar/p/kxd
-.. _kxc: http://blitiri.com.ar/p/kxd
-.. _dm-crypt: https://en.wikipedia.org/wiki/dm-crypt
-.. _self-signed: https://en.wikipedia.org/wiki/Self-signed_certificate
-