diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,18 @@
+keysafe (0.20161022) unstable; urgency=medium
+
+  * Add keywords to desktop file.
+    Thanks, Sean Whitton
+  * Fix use of .IP macro in manpage.
+    Thanks, Sean Whitton
+  * Fix some mispellings.
+    Thanks, Sean Whitton
+  * Makefile: Propagate LDFLAGS, CFLAGS, and CPPFLAGS through ghc.
+  * Makefile: Allow setting BUILDER=./Setup to build w/o cabal or stack.
+  * Makefile: Allow setting BUILDEROPTIONS=-j1 to avoid concurrent
+    build, which should make build reproducible.
+
+ -- Joey Hess <id@joeyh.name>  Sat, 22 Oct 2016 19:01:24 -0400
+
 keysafe (0.20161007) unstable; urgency=medium
 
   * Check if --store-local directory is writable.
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -1,21 +1,47 @@
+# The install target will add this before all paths it writes to.
 PREFIX?=
-# Can be stack or cabal
+
+# Can be "stack" or "cabal", or "./Setup" to build and use Setup.hs 
 BUILDER?=stack
 
+# Options to pass to the BUILDER.
+# Using -j1 may result in a reproducible build.
+BUILDEROPTIONS?=
+
+# Propigate flags through ghc to linker and compiler.
+ghc_options=$(shell \
+	for w in $(LDFLAGS); do \
+	       printf -- "-optl%s\n" "$$w"; \
+	done; \
+	for w in $(CFLAGS); do \
+	       printf -- "-optc%s\n" "$$w"; \
+	done; \
+	for w in $(CPPFLAGS); do \
+	       printf -- "-optc-Wp,%s\n" "$$w"; \
+	done; \
+	)
+
 build:
 	rm -f keysafe
 	$(MAKE) keysafe
 
 keysafe:
-	$(BUILDER) build
+	if [ "$(BUILDER)" = ./Setup ]; then ghc --make Setup; fi
 	if [ "$(BUILDER)" = stack ]; then \
+		$(BUILDER) build --ghc-options="$(ghc_options)" $(BUILDEROPTIONS); \
+	else \
+		$(BUILDER) configure --ghc-options="$(ghc_options)"; \
+		$(BUILDER) build $(BUILDEROPTIONS); \
+	fi
+	if [ "$(BUILDER)" = stack ]; then \
 		ln -sf $$(find .stack-work/ -name keysafe -type f | grep build/keysafe/keysafe | tail -n 1) keysafe; \
 	else \
 		ln -sf dist/build/keysafe/keysafe keysafe; \
 	fi
 
 clean:
-	rm -rf keysafe dist .stack-work
+	if [ "$(BUILDER)" != ./Setup ] && [ "$(BUILDER)" != cabal ]; then $(BUILDER) clean; fi
+	rm -rf keysafe dist .stack-work Setup Setup.hi Setup.o
 
 install: install-files
 	useradd --system keysafe
diff --git a/keysafe.1 b/keysafe.1
--- a/keysafe.1
+++ b/keysafe.1
@@ -29,7 +29,7 @@
 because each guess they make costs them.
 .PP
 Keysafe is designed so that it should take millions of dollars of computer
-time to crack any fairly good password. With a truely good
+time to crack any fairly good password. With a truly good
 password, such as four random words, the cracking cost should be many
 trillions of dollars. Keysafe checks your password strength (using the
 zxcvbn library), and shows an estimate of the cost to crack your password,
@@ -64,21 +64,21 @@
 connections. It's recommended to only expose keysafe servers over a tor
 hidden service.
 .PP
-.IP --backup-server BACKUPDIR
+.IP "--backup-server BACKUPDIR"
 Run on a server, populates the BACKUPDIR with a gpg encrypted backup
 of all the objects stored in the --store-directory. This is designed
 to be rsynced offsite (with --delete) to back up a keysafe server with
 minimal information leakage.
 .PP
-.IP --restore-server BACKUPDIR
+.IP "--restore-server BACKUPDIR"
 Restore all objects present in the gpg-encrypted
 backups in the specified directory.
 .PP
-.IP --chaff HOSTNAME
+.IP "--chaff HOSTNAME"
 Upload random data to a keysafe server. --port can be used to specify
 the server's port. Continues uploading data until interrupted with ctrl-c.
 .PP
-.IP --chaff-max-delay SECONDS
+.IP "--chaff-max-delay SECONDS"
 Specify a delay between chaff uploads. Will delay a
 random amount between 0 and this many seconds.
 .PP
@@ -94,17 +94,17 @@
 .IP --test
 Run test suite.
 .PP
-.IP --gpgkeyid KEYID
+.IP "--gpgkeyid KEYID"
 Specify keyid of gpg key to back up or restore. This is useful if you
 have multiple gpg keys. But, when this option is used to back up a key,
 you have to also provide it to restore that key.
 .PP
-.IP --keyfile FILE
+.IP "--keyfile FILE"
 To back up anything other than a gpg secret key, use this option.
 To restore from the backup, you must use this same option, and pass the
 exact same filename.
 .PP
-.IP --store-directory dir
+.IP "--store-directory dir"
 Where to store data locally. For the client, data is
 stored here before it is uploaded to the server. For
 the server, this is where it stores its data.
@@ -115,7 +115,7 @@
 readline interface when run in a terminal, and GUI otherwise.
 The GUI currently is implemented using zenity(1).
 .PP
-.IP --totalshares M --neededshares N
+.IP "--totalshares M --neededshares N"
 These options have to be specified together.
 The default values are --totalshares 3 --neededshares 2.
 Keysafe uses Shamir secret sharing to create M shares of the encrypted
@@ -124,37 +124,37 @@
 these options when backing up a secret key, you also must specify them
 with the same values to restore that secret key.
 .PP
-.IP --name N
+.IP "--name N"
 Specify name used for key backup/restore, avoiding the usual prompt.
 .PP
-.IP --othername N
+.IP "--othername N"
 Specify other name used for key backup/restore, avoiding the usual prompt.
 .PP
-.IP --add-storage-directory DIR
+.IP "--add-storage-directory DIR"
 Add the directory to the list of locations keysafe
 will use for backup/restore of keys. Keysafe will use
 the directory first, before any of its built-in servers.
 .PP
-.IP --add-server HOST[:PORT]
+.IP "--add-server HOST[:PORT]"
 Add the server to the server list which keysafe will
 use for backup/restore of keys. Keysafe will use the
 server first before any of its built-in servers.
 .PP
-.IP --port P
+.IP "--port P"
 Port for server to listen on. (default: 80)
 .PP
-.IP --address A
+.IP "--address A"
 Address for server to bind to. (Use "*" to bind to
 all addresses.) (default: "127.0.0.1")
 .PP
-.IP --months-to-fill-half-disk N
+.IP "--months-to-fill-half-disk N"
 Server rate-limits requests and requires proof of
 work, to avoid too many objects being stored. This is
 an lower bound on how long it could possibly take for
 half of the current disk space to be
 filled. (default: 12)
 .PP
-.IP --motd MESSAGE
+.IP "--motd MESSAGE"
 The server's Message Of The Day.
 .PP
 .IP --testmode
diff --git a/keysafe.cabal b/keysafe.cabal
--- a/keysafe.cabal
+++ b/keysafe.cabal
@@ -1,5 +1,5 @@
 Name: keysafe
-Version: 0.20161007
+Version: 0.20161022
 Cabal-Version: >= 1.8
 Maintainer: Joey Hess <joey@kitenet.net>
 Author: Joey Hess
diff --git a/keysafe.desktop b/keysafe.desktop
--- a/keysafe.desktop
+++ b/keysafe.desktop
@@ -6,3 +6,4 @@
 Terminal=false
 Exec=/usr/bin/keysafe
 Categories=Network;
+Keywords=backup;key;encryption;gnupg;openpgp;pgp;gpg
diff --git a/keysafe.hs b/keysafe.hs
--- a/keysafe.hs
+++ b/keysafe.hs
@@ -144,7 +144,7 @@
 				if queued
 					then do
 						willautostart <- isAutoStartFileInstalled
-						showInfo ui "Backup queued" $ "Some data was not sucessfully uploaded to servers, and has been queued for later upload."
+						showInfo ui "Backup queued" $ "Some data was not successfully uploaded to servers, and has been queued for later upload."
 							++ if willautostart then "" else " Run keysafe --uploadqueued at a later point to finish the backup."
 					else showInfo ui "Backup success" "Your secret key was successfully encrypted and backed up."
 			StoreFailure s -> showError ui ("There was a problem storing your encrypted secret key: " ++ s)
diff --git a/keysafe.service b/keysafe.service
--- a/keysafe.service
+++ b/keysafe.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=keysafe server
+Documentation=https://joeyh.name/code/keysafe/
 
 [Service]
 Environment='DAEMON_PARAMS=--port 4242 --store-directory=/var/lib/keysafe/'
