Hockeypuck OpenPGP Public Keyserver

1. Configuration

Hockeypuck reads configuration from a TOML-format configuration file, which should be supplied on the command line using the `-c` flag. This file is preprocessed as a Go template (See Templating below).

1.1. Hosting

[hockeypuck]
contact="DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"
hostname="keys.example.com"
nodename="node1.keys.example.com"
enableVhosts=true

These settings are displayed on the stats page (/pks/lookup?op=stats).

1.1.1. Logging

[hockeypuck]
logfile="/path/to/logfile"
loglevel=<one of: DEBUG,INFO,WARNING,ERROR,FATAL,PANIC>

If not configured, hockeypuck will log INFO level messages and higher severity to standard error.

1.1.2. Static HTML files

Hockeypuck will serve static files from / out of the webroot path, so long as the path names do not conflict with HKP routed requests (like /pks/lookup).

[hockeypuck]
webroot="/path/to/www/files"

index.html will be served by default if the path resolves to a directory and the file exists.

1.1.3. Custom HTML templates

By default, Hockeypuck will respond to HKP operations op=index, op=vindex and op=stats with an application/json response. The underlying structs for these responses can be used in HTML templates of your own design to customize the output.

Specify these templates with:

[hockeypuck]
indexTemplate="/path/to/template"
vindexTemplate="/path/to/template"
statsTemplate="/path/to/template"

The path must be to a file containing a valid Go html/template.

indexTemplate and vindexTemplate operate on a struct containing two top-level fields,

statsTemplate operates on an instance of sks.Stats.

See the packaged templates for an example.

1.1.4. Remote administration

[hockeypuck]
adminKeys=[
    "DECAFBADDECAFBADDECAFBADDECAFBADDECAFBAD",
]

The listed fingerprints identify keys that may sign administration requests for this server. It is strongly recommended that the server contact advertised on the stats page (see above) is not one of the admin keys.

Currently, administration requests are restricted to key deletion and key replacement. See Remote Administration for details.

1.2. HKP

[hockeypuck.hkp]
bind=":11371"
advertisedBind="keys.example.com:80"
logRequestDetails=false

1.2.1. Queries

[hockeypuck.hkp.queries]
selfSignedOnly=false
keywordSearchDisabled=false

1.2.2. HKPS

If this section is populated, Hockeypuck will listen on HKPS.

[hockeypuck.hkps]
bind=":443"
logRequestDetails=false
cert="/path/to/cert"
key="/path/to/key"

1.3. OpenPGP

[hockeypuck.openpgp]
maxPacketLength=8192
maxKeyLength=1048576
blacklist=[
    # "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
]
nworkers=8

1.3.1. Storage

PostgreSQL >= 9.4 is required for use with Hockeypuck, as the JSONB data type is used to store most of the public key material. Some fields are broken out into separate columns for indexing. For details, refer to the PostgreSQL storage backend, pghkp/storage.go. Hockeypuck has been tested with versions of PostgreSQL up to and including 16.

To use PostgreSQL:

[hockeypuck.openpgp.db]
driver="postgres-jsonb"
dsn="database=hkp host=/var/run/postgresql port=5432 sslmode=disable"

See the pq driver package documentation for details on how to construct the connection string.

1.3.2. Headers

The headers added to the ASCII-armored output can be optionally customised.

[hockeypuck.openpgp.headers]
comment="Hockeypuck"
version="2.2.0"

1.4. Recon

Hockeypuck supports the SKS synchronisation protocol. SKS consists of two interlinked protocols, "recon" and "recovery". Recon is initiated unidirectionally, and identifies differences between the datasets of the two servers based on hash digests of the entries. Recovery takes place bidirectionally after recon is complete, and transfers the actual differences in the datasets.

Recon is handled by the conflux package, which then initiates recovery over HKP.

[hockeypuck.conflux.recon]
httpAddr=":11371"
reconAddr=":11370"
allowCIDRs=["127.0.0.1/8"]
filters=["preProduction"]
seenCacheSize=256
gossipIntervalSecs=60
maxOutstandingReconRequests=100
logname="conflux.recon"

1.4.1. Partners

[hockeypuck.conflux.recon.partner.peer1]
httpAddr="keys.example.com:11371"
reconAddr="keys.example.com:11370"
[hockeypuck.conflux.recon.partner.peer2]
httpAddr="juju-azure-dev-y9157oo521.cloudapp.net:11371"
reconAddr="juju-azure-dev-y9157oo521.cloudapp.net:11370"
...

Create a section for each partner [hockeypuck.conflux.recon.partner.NAME], where NAME contains only characters from [A-Za-z0-9_].

Each partner section must include a httpAddr and a reconAddr entry, in host:port format. These are usually the same host, but they might differ, especially if the HKP service is reverse-proxied.

1.4.2. Prefix tree

[hockeypuck.conflux.recon.leveldb]
path="/path/to/prefix/tree"

The prefix tree is used to keep track of which keys the peer has, for synchronization purposes.

1.5. Metrics

Hockeypuck exposes a metrics endpoint for aggregation by Prometheus.

[hockeypuck.metrics]
metricsAddr=":9626"
metricsPath="/metrics"

2. Templating

The configuration file supports templating using the Go text/template package with Sprig extensions. The template is rendered before the configuration file is parsed, so the configuration file can contain environment variables.

For example, setting the database configuration to use environment variables:

[hockeypuck.openpgp.db]
driver="postgres-jsonb"
dsn="database=hkp host=postgres user={{ .POSTGRES_USER }} password={{ .POSTGRES_PASSWORD }} port=5432 sslmode=disable"

You can also use the osenv custom function to read environment variables by prefix:

{{ range $key, $value := osenv "HKP_" }}
{{ $key }}={{ $value }}
{{ end }}

Authors

Casey Marshall, Andrew Gallagher