diff --git a/.travis.yml b/.travis.yml
index a377de10306130f8e66cc3d4d8dc909456f9e14e..5ca72338bfbc3e5d12e0d791bbc1420c6172a0e7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,14 +16,13 @@ matrix:
 
 before_install:
   - go get -v github.com/golang/lint/golint
-  - go install ./cmd/dbinit
 
 install:
   - go version
 
 before_script:
-  - dbinit -db_user user -db_password passwd
-  - dbinit -db_type mongo -admin_user '' -db_user user -db_password passwd
+  - mysql < db/seed.sql
+  - mongo db/seed.js
 
 sudo: false
 script:
diff --git a/README.md b/README.md
index a9d68a61d858e791010d107a2dd33d9fc03b0df6..b4f356dd9f1d539043b80b05c88e16542c651594 100644
--- a/README.md
+++ b/README.md
@@ -100,11 +100,11 @@ For any option that takes a file path as a parameter (e.g. SSH signing key, TLS
 - A [Vault](https://www.vaultproject.io) path + key starting with `/vault/` e.g. `/vault/secret/cashier/ssh_signing_key`. You should add a [vault](#vault) config as needed.
 
 ## server
-- `use_tls` : boolean. If this is set then `tls_key` and `tls_cert` are required.
+- `use_tls` : boolean. If this is set then either `tls_key` and `tls_cert` are required, or `letsencrypt_servername` is required.
 - `tls_key` : string. Path to the TLS key. See the [note](#a-note-on-files) on files above.
 - `tls_cert` : string. Path to the TLS cert. See the [note](#a-note-on-files) on files above.
 - `letsencrypt_servername`: string. If set will request a certificate from LetsEncrypt. This should match the expected FQDN of the server.
-- `letsencrypt_cachedir: string. Directory to cache the LetsEncrypt certificate.
+- `letsencrypt_cachedir`: string. Directory to cache the LetsEncrypt certificate.
 - `address` : string. IP address to listen on. If unset the server listens on all addresses.
 - `port` : int. Port to listen on.
 - `user` : string. User to which the server drops privileges to.
@@ -151,8 +151,9 @@ server {
 }
 ```
 
-Prior to using MySQL, MongoDB or SQLite you need to create the database and tables using the [dbinit tool](cmd/dbinit/dbinit.go).  
-dbinit hasn't been tested with mongo replica sets.
+Prior to using MySQL, MongoDB or SQLite you need to create the database and tables using [one of the provided files](db).  
+e.g. `mysql < db/seed.sql` or `mongo db/seed.js`.  
+Obviously you should setup a role user for running in prodution.
 
 ### datastore
 
diff --git a/client/client.go b/client/client.go
index e69f3534bb520b0fd6ea8ddecd14db58ea8e436b..b13c4cbdd9c5ad88246f741077df7d704b298b27 100644
--- a/client/client.go
+++ b/client/client.go
@@ -79,11 +79,8 @@ func Sign(pub ssh.PublicKey, token string, conf *Config) (*ssh.Certificate, erro
 	if err != nil {
 		return nil, err
 	}
-	marshaled := ssh.MarshalAuthorizedKey(pub)
-	// Remove the trailing newline.
-	marshaled = marshaled[:len(marshaled)-1]
 	s, err := json.Marshal(&lib.SignRequest{
-		Key:        string(marshaled),
+		Key:        lib.GetPublicKey(pub),
 		ValidUntil: time.Now().Add(validity),
 	})
 	if err != nil {
diff --git a/cmd/cashierd/main.go b/cmd/cashierd/main.go
index 31ee240b54317d664e3a0e8a34d4191f8476de5d..fb67a36685f2e8077b2d587fd3eb10b4592987bc 100644
--- a/cmd/cashierd/main.go
+++ b/cmd/cashierd/main.go
@@ -34,7 +34,6 @@ import (
 	"github.com/nsheridan/cashier/server/static"
 	"github.com/nsheridan/cashier/server/store"
 	"github.com/nsheridan/cashier/server/templates"
-	"github.com/nsheridan/cashier/server/util"
 	"github.com/nsheridan/cashier/server/wkfs/vaultfs"
 	"github.com/nsheridan/wkfs/s3"
 	"github.com/sid77/drop"
@@ -169,7 +168,7 @@ func signHandler(a *appContext, w http.ResponseWriter, r *http.Request) (int, er
 	}
 	json.NewEncoder(w).Encode(&lib.SignResponse{
 		Status:   "ok",
-		Response: util.GetPublicKey(cert),
+		Response: lib.GetPublicKey(cert),
 	})
 	return http.StatusOK, nil
 }
@@ -358,6 +357,9 @@ func main() {
 			}
 			tlsConfig.GetCertificate = m.GetCertificate
 		} else {
+			if conf.Server.TLSCert == "" || conf.Server.TLSKey == "" {
+				log.Fatal("TLS cert or key not specified in config")
+			}
 			tlsConfig.Certificates = make([]tls.Certificate, 1)
 			tlsConfig.Certificates[0], err = loadCerts(conf.Server.TLSCert, conf.Server.TLSKey)
 			if err != nil {
diff --git a/cmd/dbinit/dbinit.go b/cmd/dbinit/dbinit.go
deleted file mode 100644
index 4cf0834675f41618dfbe4c43a9435f49eed4e27a..0000000000000000000000000000000000000000
--- a/cmd/dbinit/dbinit.go
+++ /dev/null
@@ -1,126 +0,0 @@
-package main
-
-import (
-	"database/sql"
-	"flag"
-	"fmt"
-	"log"
-	"strings"
-
-	mgo "gopkg.in/mgo.v2"
-
-	"github.com/go-sql-driver/mysql"
-	_ "github.com/mattn/go-sqlite3"
-)
-
-var (
-	host        = flag.String("host", "localhost", "host[:port]")
-	adminUser   = flag.String("admin_user", "root", "Admin user")
-	adminPasswd = flag.String("admin_password", "", "Admin password")
-	dbUser      = flag.String("db_user", "user", "Database user")
-	dbPasswd    = flag.String("db_password", "passwd", "Admin password")
-	dbType      = flag.String("db_type", "mysql", "Database engine (\"mysql\", \"sqlite\" or \"mongo\")")
-	sqliteDB    = flag.String("db_path", "certs.db", "Path to SQLite database")
-	authDB      = flag.String("authdb", "admin", "Admin database (mongo)")
-
-	certsDB     = "certs"
-	issuedTable = "issued_certs"
-	createTable = `CREATE TABLE IF NOT EXISTS ` + issuedTable + ` (
-			key_id VARCHAR(255) NOT NULL,
-			principals VARCHAR(255) NULL,
-			created_at DATETIME NULL,
-			expires_at DATETIME NULL,
-			revoked BOOLEAN DEFAULT NULL,
-			raw_key TEXT NULL,
-			PRIMARY KEY (key_id)
-		);`
-)
-
-func initSQLite() {
-	db, err := sql.Open("sqlite3", *sqliteDB)
-	if err != nil {
-		log.Fatal(err)
-	}
-	defer db.Close()
-
-	if _, err = db.Exec(createTable); err != nil {
-		log.Fatal(err)
-	}
-}
-
-func initMySQL() {
-	var createTableStmt = []string{
-		`CREATE DATABASE IF NOT EXISTS ` + certsDB + ` DEFAULT CHARACTER SET = 'utf8' DEFAULT COLLATE 'utf8_general_ci';`,
-		`USE ` + certsDB + `;`,
-		createTable,
-		`GRANT ALL PRIVILEGES ON certs.* TO '` + *dbUser + `'@'%' IDENTIFIED BY '` + *dbPasswd + `';`,
-	}
-
-	if len(strings.Split(*host, ":")) != 2 {
-		*host = fmt.Sprintf("%s:3306", *host)
-	}
-	conn := &mysql.Config{
-		User:   *adminUser,
-		Passwd: *adminPasswd,
-		Net:    "tcp",
-		Addr:   *host,
-	}
-	db, err := sql.Open("mysql", conn.FormatDSN())
-	if err != nil {
-		log.Fatalf("Error connecting to database: %v", err)
-	}
-	defer db.Close()
-	if err := db.Ping(); err != nil {
-		log.Fatalf("Unable to connect to database.")
-	}
-	for _, stmt := range createTableStmt {
-		_, err := db.Exec(stmt)
-		if err != nil {
-			log.Fatalf("Error running setup: %v", err)
-		}
-	}
-}
-
-func initMongo() {
-	di := &mgo.DialInfo{
-		Addrs:    strings.Split(*host, ","),
-		Username: *adminUser,
-		Password: *adminPasswd,
-		Database: *authDB,
-	}
-	session, err := mgo.DialWithInfo(di)
-	if err != nil {
-		log.Fatalln(err)
-	}
-	defer session.Close()
-	d := session.DB(certsDB)
-	if err := d.UpsertUser(&mgo.User{
-		Username: *dbUser,
-		Password: *dbPasswd,
-		Roles:    []mgo.Role{mgo.RoleReadWrite},
-	}); err != nil {
-		log.Fatalln(err)
-	}
-	c := d.C(issuedTable)
-	i := mgo.Index{
-		Key:    []string{"keyid"},
-		Unique: true,
-	}
-	if err != c.EnsureIndex(i) {
-		log.Fatalln(err)
-	}
-}
-
-func main() {
-	flag.Parse()
-	switch *dbType {
-	case "mysql":
-		initMySQL()
-	case "mongo":
-		initMongo()
-	case "sqlite":
-		initSQLite()
-	default:
-		log.Fatalf("Invalid database type")
-	}
-}
diff --git a/db/seed.js b/db/seed.js
new file mode 100644
index 0000000000000000000000000000000000000000..c9d62fabc3219e769bf74ed1fa73421a79af9ac9
--- /dev/null
+++ b/db/seed.js
@@ -0,0 +1,3 @@
+conn = new Mongo();
+db = conn.getDB("certs");
+db.issued_certs.createIndex({"keyid": 1}, {unique: true});
diff --git a/db/seed.sql b/db/seed.sql
new file mode 100644
index 0000000000000000000000000000000000000000..cf5e62abf84da1140b4b8b4a3ceda9a4a00571f6
--- /dev/null
+++ b/db/seed.sql
@@ -0,0 +1,13 @@
+CREATE DATABASE IF NOT EXISTS `certs`;
+
+USE `certs`;
+
+CREATE TABLE `issued_certs` (
+  `key_id` varchar(255) NOT NULL,
+  `principals` varchar(255) DEFAULT NULL,
+  `created_at` datetime DEFAULT NULL,
+  `expires_at` datetime DEFAULT NULL,
+  `revoked` tinyint(1) DEFAULT NULL,
+  `raw_key` text,
+  PRIMARY KEY (`key_id`)
+);
diff --git a/lib/const.go b/lib/proto.go
similarity index 59%
rename from lib/const.go
rename to lib/proto.go
index 1ba274931d7ffa6ea59b67d8683f3c3d8b4e925c..f3d7115605265e9a789d72a911f393c4ab7a3a2f 100644
--- a/lib/const.go
+++ b/lib/proto.go
@@ -9,9 +9,7 @@ type SignRequest struct {
 }
 
 // SignResponse is sent by the server.
-// `Status' is "ok" or "error".
-// `Response' contains a signed certificate or an error message.
 type SignResponse struct {
-	Status   string `json:"status"`
-	Response string `json:"response"`
+	Status   string `json:"status"`   // Status will be "ok" or "error".
+	Response string `json:"response"` // Response will contain either the signed certificate or the error message.
 }
diff --git a/server/util/util.go b/lib/util.go
similarity index 60%
rename from server/util/util.go
rename to lib/util.go
index 10f5eca6e3152e51dcc2b9ef3cd94c9d77c38b9e..b1c7b87016343712bcbbb534cfbecef733a083e6 100644
--- a/server/util/util.go
+++ b/lib/util.go
@@ -1,10 +1,10 @@
-package util
+package lib
 
 import "golang.org/x/crypto/ssh"
 
 // GetPublicKey marshals a ssh certificate to a string.
-func GetPublicKey(cert *ssh.Certificate) string {
-	marshaled := ssh.MarshalAuthorizedKey(cert)
+func GetPublicKey(pub ssh.PublicKey) string {
+	marshaled := ssh.MarshalAuthorizedKey(pub)
 	// Strip trailing newline
 	return string(marshaled[:len(marshaled)-1])
 }
diff --git a/server/util/util_test.go b/lib/util_test.go
similarity index 95%
rename from server/util/util_test.go
rename to lib/util_test.go
index d294d86d2ec1b20a7bf5410a347a48c974e1960f..9e89297073d63f53c2b2f5110b53efce22b0c485 100644
--- a/server/util/util_test.go
+++ b/lib/util_test.go
@@ -1,4 +1,4 @@
-package util
+package lib
 
 import (
 	"testing"
diff --git a/server/store/store.go b/server/store/store.go
index a447e726b3821e73d9de3db2f9fe52493768c15c..8af77e330618554fee94580daed704aa87c6c7cb 100644
--- a/server/store/store.go
+++ b/server/store/store.go
@@ -5,8 +5,8 @@ import (
 
 	"golang.org/x/crypto/ssh"
 
+	"github.com/nsheridan/cashier/lib"
 	"github.com/nsheridan/cashier/server/config"
-	"github.com/nsheridan/cashier/server/util"
 )
 
 // New returns a new configured database.
@@ -54,6 +54,6 @@ func parseCertificate(cert *ssh.Certificate) *CertRecord {
 		Principals: cert.ValidPrincipals,
 		CreatedAt:  parseTime(cert.ValidAfter),
 		Expires:    parseTime(cert.ValidBefore),
-		Raw:        util.GetPublicKey(cert),
+		Raw:        lib.GetPublicKey(cert),
 	}
 }
diff --git a/server/store/store_test.go b/server/store/store_test.go
index dbe2d955a0d51d344a806d826477ccf1c626c987..281a6149e9ec5704dc19bec1cf97a7de5b829b47 100644
--- a/server/store/store_test.go
+++ b/server/store/store_test.go
@@ -3,9 +3,11 @@ package store
 import (
 	"crypto/rand"
 	"crypto/rsa"
+	"database/sql"
 	"io/ioutil"
 	"os"
-	"os/exec"
+	"os/user"
+	"strings"
 	"testing"
 	"time"
 
@@ -15,10 +17,6 @@ import (
 	"golang.org/x/crypto/ssh"
 )
 
-var (
-	dbConfig = map[string]string{"username": "user", "password": "passwd", "address": "localhost"}
-)
-
 func TestParseCertificate(t *testing.T) {
 	t.Parallel()
 	a := assert.New(t)
@@ -93,8 +91,8 @@ func TestMySQLStore(t *testing.T) {
 	if os.Getenv("MYSQL_TEST") == "" {
 		t.Skip("No MYSQL_TEST environment variable")
 	}
-	dbConfig["type"] = "mysql"
-	db, err := NewSQLStore(dbConfig)
+	u, _ := user.Current()
+	db, err := NewSQLStore(map[string]string{"type": "mysql", "username": u.Username})
 	if err != nil {
 		t.Error(err)
 	}
@@ -106,8 +104,7 @@ func TestMongoStore(t *testing.T) {
 	if os.Getenv("MONGO_TEST") == "" {
 		t.Skip("No MONGO_TEST environment variable")
 	}
-	dbConfig["type"] = "mongo"
-	db, err := NewMongoStore(dbConfig)
+	db, err := NewMongoStore(map[string]string{"type": "mongo"})
 	if err != nil {
 		t.Error(err)
 	}
@@ -121,11 +118,21 @@ func TestSQLiteStore(t *testing.T) {
 		t.Error(err)
 	}
 	defer os.Remove(f.Name())
-	// This is so jank.
-	args := []string{"run", "../../cmd/dbinit/dbinit.go", "-db_type", "sqlite", "-db_path", f.Name()}
-	if err := exec.Command("go", args...).Run(); err != nil {
+
+	seed, err := ioutil.ReadFile("../../db/seed.sql")
+	if err != nil {
 		t.Error(err)
 	}
+	stmts := strings.Split(string(seed), ";")
+	d, _ := sql.Open("sqlite3", f.Name())
+	for _, stmt := range stmts {
+		if !strings.Contains(stmt, "CREATE TABLE") {
+			continue
+		}
+		d.Exec(stmt)
+	}
+	d.Close()
+
 	config := map[string]string{"type": "sqlite", "filename": f.Name()}
 	db, err := NewSQLStore(config)
 	if err != nil {