Skip to content

Public Key Embedding

The license server uses Ed25519 public key cryptography to validate server licenses. The public key can be embedded at build time for easier deployment, or loaded from a file at runtime.

Embedding the public key at build time has several advantages:

  • Simpler deployment — no need to distribute the license.pub file separately.
  • Reduced configuration — the server works out of the box without additional setup.
  • Better security — the key is baked into the binary, reducing the attack surface.
  1. Generate a key pair (developer/CI only):

    Terminal window
    ./license-tool generate-keys
    # Creates: license.key (private) and license.pub (public)
  2. Build with the embedded key using one of the methods below.

  3. At runtime, the server checks the EmbeddedPublicKey variable first. If it is set, no file loading is needed. If it is empty, the server falls back to loading from disk.


The Makefile automatically reads license.pub and embeds it:

PUBLIC_KEY_FILE?=license.pub
PUBLIC_KEY_EMBEDDED=$(shell cat "$(PUBLIC_KEY_FILE)" | base64 -w0)
LDFLAGS=-ldflags "-X 'git.prd.embidio.de/hive/license-server/internal/license.EmbeddedPublicKey=$(PUBLIC_KEY_EMBEDDED)'"

Build the server:

Terminal window
make build-server
# Automatically embeds license.pub if present

GoReleaser uses the PUBLIC_KEY_EMBEDDED environment variable:

before:
hooks:
- test -f license.pub || echo "WARNING: license.pub not found"
builds:
- ldflags:
- -X 'git.prd.embidio.de/hive/license-server/internal/license.EmbeddedPublicKey={{ .Env.PUBLIC_KEY_EMBEDDED }}'
Terminal window
# Set environment variable
export PUBLIC_KEY_EMBEDDED=$(cat license.pub | base64 -w0)
# Build release
goreleaser release --clean
Terminal window
PUBLIC_KEY=$(cat license.pub | base64 -w0)
go build -ldflags="-X 'git.prd.embidio.de/hive/license-server/internal/license.EmbeddedPublicKey=$PUBLIC_KEY'" ./cmd/server

If no key is embedded at build time, the server looks for license.pub at runtime in these locations, in order:

  1. ./license.pub (current working directory)
  2. ./configs/license.pub
  3. /etc/license-server/license.pub

The embedding relies on two components:

internal/license/server_license.go:

// EmbeddedPublicKey contains the Ed25519 public key embedded at build time.
var EmbeddedPublicKey string

internal/config/config.go:

func (c *Config) loadPublicKey() error {
// 1. Try embedded public key first
if license.EmbeddedPublicKey != "" {
c.ServerLicensePublicKey = []byte(license.EmbeddedPublicKey)
return nil
}
// 2. Fall back to file loading
// ...
}

The public key is stored in PEM format:

-----BEGIN ED25519 PUBLIC KEY-----
MCowBQYDK2VwAyEA... (base64 encoded bytes)
-----END ED25519 PUBLIC KEY-----

At build time, the entire PEM block is base64-encoded again for embedding as a string constant via -ldflags.


  • NEVER commit to version control.
  • NEVER embed in binaries.
  • Store securely (HSM, secrets manager, encrypted storage).
  • Used only for signing server licenses.
  • Keep on developer/CI machine only.
  • Safe to embed in binaries.
  • Safe to commit to version control (if desired).
  • Used only for verification (read-only operation).
  • Cannot be used to create licenses.

Terminal window
# One-time: Generate key pair
./license-tool generate-keys
# Keep license.key secure!
# license.pub will be embedded in builds
# Build with embedded key
make build-release
# Create server license (using private key)
./license-tool create \
--licensee "Customer Company" \
--valid-days 365 \
--private-key license.key \
--output server.license
Terminal window
# Extract release package
tar -xzf license-server_v1.0.0_linux_amd64.tar.gz
# Copy configuration
cp config.example.yaml config.yaml
# Edit config.yaml to set server license
# license:
# server_license: "<base64-encoded-license>"
# Start server (public key is already embedded!)
./license-server serve

To check if a binary has an embedded public key:

Terminal window
# Extract embedded strings (Linux)
strings license-server | grep "BEGIN ED25519 PUBLIC KEY"
# Or check at runtime
./license-server version --verbose

If the key IS embedded: This should not happen. Check build logs and verify that the -ldflags value was set correctly.

If the key is NOT embedded: Place license.pub in one of the fallback locations:

Terminal window
cp license.pub ./
# OR
cp license.pub ./configs/
# OR
sudo cp license.pub /etc/license-server/

If you want to build without embedding the key (for testing):

Terminal window
# Temporarily rename/remove license.pub
mv license.pub license.pub.bak
make build-server
mv license.pub.bak license.pub