diff --git a/README.md b/README.md
index 29729b7ab505db553e3bf4394cc625b1f43f8420..0eab987978ce540c1568b9c7f85bbc66299b240a 100644
--- a/README.md
+++ b/README.md
@@ -37,8 +37,8 @@ The user can now ssh to the production machine, and continue to ssh to any machi
 
 # Usage
 Cashier comes in two parts, a [cli](cmd/cashier) and a [server](cmd/cashierd).
-The client is configured using command-line flags.
-The server is configured using a JSON configuration file - [example](exampleconfig.json).
+The client is configured using a [HCL](https://github.com/hashicorp/hcl) configuration file - [example](example-client.cfg).
+The server is configured using a JSON configuration file - [example](example-server.json).
 
 For the server you need the following:
 - A new ssh private key. Generate one in the usual way using `ssh-keygen -f ssh_ca` - this is your CA signing key. At this time Cashier supports RSA, ECDSA and Ed25519 keys. *Important* This key should be kept safe - *ANY* ssh key signed with this key will be able to access your machines.
@@ -50,11 +50,11 @@ For the server you need the following:
 ```
 go get github.com/cashier/cmd/...
 ```
-2. Create a signing key with `ssh-keygen` and a [config.json](exampleconfig.json)
+2. Create a signing key with `ssh-keygen` and a [config.json](example-server.json)
 3. Run the cashier server with `cashierd` and the cli with `cashier`.
 
 ## Using docker
-1. Create a signing key with `ssh-keygen` and a [config.json](exampleconfig.json)
+1. Create a signing key with `ssh-keygen` and a [config.json](example-server.json)
 2. Run
 ```
 docker run -it --rm -p 10000:10000 --name cashier -v $(pwd):/cashier nsheridan/cashier
diff --git a/cmd/cashier/config.go b/cmd/cashier/config.go
new file mode 100644
index 0000000000000000000000000000000000000000..b6e583a5b9c0bab29b11c237253b2e364a78963d
--- /dev/null
+++ b/cmd/cashier/config.go
@@ -0,0 +1,33 @@
+package main
+
+import (
+	"github.com/spf13/viper"
+)
+
+type config struct {
+	CA       string `mapstructure:"ca"`
+	Keytype  string `mapstructure:"key_type"`
+	Keysize  int    `mapstructure:"key_size"`
+	Validity string `mapstructure:"validity"`
+}
+
+func setDefaults() {
+	viper.SetDefault("ca", "http://localhost:10000")
+	viper.SetDefault("key_type", "rsa")
+	viper.SetDefault("key_size", 2048)
+	viper.SetDefault("validity", "24h")
+}
+
+func readConfig(path string) (*config, error) {
+	setDefaults()
+	viper.SetConfigFile(path)
+	viper.SetConfigType("hcl")
+	if err := viper.ReadInConfig(); err != nil {
+		return nil, err
+	}
+	c := &config{}
+	if err := viper.Unmarshal(c); err != nil {
+		return nil, err
+	}
+	return c, nil
+}
diff --git a/cmd/cashier/main.go b/cmd/cashier/main.go
index 8bcc3e76c06d72c75307b31e303edfc6eea3903f..2bac63a7ca3d418d43aa4e2f58147c3a06c75aef 100644
--- a/cmd/cashier/main.go
+++ b/cmd/cashier/main.go
@@ -10,6 +10,8 @@ import (
 	"net"
 	"net/http"
 	"os"
+	"os/user"
+	"path"
 	"time"
 
 	"github.com/nsheridan/cashier/lib"
@@ -19,10 +21,8 @@ import (
 )
 
 var (
-	ca       = flag.String("ca", "http://localhost:10000", "CA server")
-	keybits  = flag.Int("bits", 2048, "Key size. Ignored for ed25519 keys")
-	validity = flag.Duration("validity", time.Hour*24, "Key validity")
-	keytype  = flag.String("key_type", "rsa", "Type of private key to generate - rsa, ecdsa or ed25519")
+	u, _ = user.Current()
+	cfg  = flag.String("config", path.Join(u.HomeDir, ".cashier.cfg"), "Path to config file")
 )
 
 func installCert(a agent.Agent, cert *ssh.Certificate, key key) error {
@@ -37,8 +37,8 @@ func installCert(a agent.Agent, cert *ssh.Certificate, key key) error {
 	return nil
 }
 
-func send(s []byte, token string) (*lib.SignResponse, error) {
-	req, err := http.NewRequest("POST", *ca+"/sign", bytes.NewReader(s))
+func send(s []byte, token, ca string) (*lib.SignResponse, error) {
+	req, err := http.NewRequest("POST", ca+"/sign", bytes.NewReader(s))
 	if err != nil {
 		return nil, err
 	}
@@ -65,17 +65,21 @@ func send(s []byte, token string) (*lib.SignResponse, error) {
 	return c, nil
 }
 
-func sign(pub ssh.PublicKey, token string) (*ssh.Certificate, error) {
+func sign(pub ssh.PublicKey, token string, conf *config) (*ssh.Certificate, error) {
+	validity, err := time.ParseDuration(conf.Validity)
+	if err != nil {
+		return nil, err
+	}
 	marshaled := ssh.MarshalAuthorizedKey(pub)
 	marshaled = marshaled[:len(marshaled)-1]
 	s, err := json.Marshal(&lib.SignRequest{
 		Key:        string(marshaled),
-		ValidUntil: time.Now().Add(*validity),
+		ValidUntil: time.Now().Add(validity),
 	})
 	if err != nil {
 		return nil, err
 	}
-	resp, err := send(s, token)
+	resp, err := send(s, token, conf.CA)
 	if err != nil {
 		return nil, err
 	}
@@ -95,13 +99,16 @@ func sign(pub ssh.PublicKey, token string) (*ssh.Certificate, error) {
 
 func main() {
 	flag.Parse()
-
-	fmt.Printf("Your browser has been opened to visit %s\n", *ca)
-	if err := browser.OpenURL(*ca); err != nil {
+	c, err := readConfig(*cfg)
+	if err != nil {
+		log.Fatalf("Error parsing config file: %v\n", err)
+	}
+	fmt.Printf("Your browser has been opened to visit %s\n", c.CA)
+	if err := browser.OpenURL(c.CA); err != nil {
 		fmt.Println("Error launching web browser. Go to the link in your web browser")
 	}
 	fmt.Println("Generating new key pair")
-	priv, pub, err := generateKey(*keytype, *keybits)
+	priv, pub, err := generateKey(c.Keytype, c.Keysize)
 	if err != nil {
 		log.Fatalln("Error generating key pair: ", err)
 	}
@@ -110,7 +117,7 @@ func main() {
 	var token string
 	fmt.Scanln(&token)
 
-	cert, err := sign(pub, token)
+	cert, err := sign(pub, token, c)
 	if err != nil {
 		log.Fatalln(err)
 	}
diff --git a/example-client.cfg b/example-client.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..b9e8232b5d2ca61717d824a89b15e4b1ea63ab29
--- /dev/null
+++ b/example-client.cfg
@@ -0,0 +1,4 @@
+ca = "https://sshca.example.com"  // Address of the cashierd CA
+key_type = "rsa"  // Type of ssh key to generate - rsa, ecdsa, ed25519
+key_size = 2048  // Size of key to generate. ecdsa must be one of 256, 384, 521. This value is ignored for ed25519 keys.
+validity = "24h"  // How long the cert will be valid for. Must be a valid go time.Duration.
diff --git a/exampleconfig.json b/example-server.json
similarity index 100%
rename from exampleconfig.json
rename to example-server.json