Post

Server API Key Authentication

Understanding how Krill servers use API keys for client authentication and how to manage them

Server API Key Authentication

Overview

Krill uses a cluster PIN authentication model to secure communication between clients, servers, and peers. Each Krill cluster shares a single 4-digit PIN that all members use. During installation or first-time setup, the user enters the PIN. The server stores a hash of the PIN and derives a Bearer token from it using PBKDF2. All authenticated HTTP requests use this derived Bearer token. This document explains how the PIN model works, where credentials are stored, and how to manage them.

Architecture

Authentication Flow Diagram

sequenceDiagram
    participant Client as Krill Client
    participant Server as Krill Server
    participant Store as Credential Files

    Note over Server: Server starts and<br/>loads pin_derived_key from file

    Client->>Server: HTTPS Request
    Note right of Client: Includes Authorization: Bearer <pin_derived_key>

    Server->>Store: Read stored pin_derived_key
    Store-->>Server: Return derived key

    alt Bearer Token Valid
        Server-->>Client: 200 OK + Response
    else Token Missing/Invalid
        Server-->>Client: 401 Unauthorized
    end

Request Authentication Flow

flowchart TD
    A[Incoming Request] --> B{Authorization Header Present?}
    B -->|No| C[Return 401 Unauthorized]
    B -->|Yes| D{Bearer Token Matches Derived Key?}
    D -->|No| C
    D -->|Yes| E[Process Request]
    E --> F[Return Response]

How the Cluster PIN Works

The cluster PIN is a 4-digit numeric code shared across all servers and clients in a Krill cluster. It serves as the single source of trust for the entire mesh.

  1. PIN Entry: The user enters the 4-digit PIN during initial setup (Debian installer prompt, or FTUE in the mobile/desktop app).
  2. Hash Storage: The server stores a bcrypt hash of the PIN in pin_hash for verification during PIN resets or re-entry.
  3. Key Derivation: The server derives a deterministic Bearer token from the PIN using PBKDF2 (with a fixed salt tied to the cluster). This derived key is stored in pin_derived_key.
  4. Bearer Authentication: All authenticated HTTP requests include Authorization: Bearer <pin_derived_key>. Because every member of the cluster derives the same key from the same PIN, any member can authenticate with any other member.

Why PBKDF2?

  • Deterministic: Given the same PIN and salt, every server derives the same Bearer token. No key exchange is needed.
  • Slow to brute-force: PBKDF2 with a high iteration count makes offline attacks against the 4-digit PIN computationally expensive.
  • Standard: PBKDF2 is widely supported and well-understood.

Server-Side Implementation

Credential Files

When you install Krill Server via the Debian package, the installer prompts for a 4-digit cluster PIN and generates the credential files.

Credential File Location: /etc/krill/credentials/

FileDescriptionPermissions
pin_hashBcrypt hash of the cluster PIN0400 (owner read-only)
pin_derived_keyPBKDF2-derived Bearer token0400 (owner read-only)

Directory Structure

1
2
3
4
5
6
7
8
9
10
/etc/krill/
├── credentials/          # Secure credentials directory (mode 0700)
│   ├── pin_hash          # Bcrypt hash of cluster PIN (mode 0400)
│   └── pin_derived_key   # PBKDF2-derived Bearer token (mode 0400)
├── certs/               # TLS certificates
│   ├── krill.crt
│   ├── krill.key
│   ├── krill.pfx
│   └── .pfx_password
└── version              # Package version

Security Permissions

The credential files use restrictive permissions following Debian security best practices:

PathModeOwnerDescription
/etc/krill/credentials/0700krill:krillCredentials directory
/etc/krill/credentials/pin_hash0400krill:krillRead-only by krill user
/etc/krill/credentials/pin_derived_key0400krill:krillRead-only by krill user

Managing the Cluster PIN

Setting the PIN During Installation

The Debian installer prompts for a 4-digit PIN during apt install krill. If you are adding a server to an existing cluster, enter the same PIN used by the other servers.

Resetting the PIN

If you need to change the cluster PIN (e.g., if it was compromised), use the included reset utility:

1
2
3
4
5
# SSH into your Krill server
ssh user@your-krill-server

# Run the PIN reset tool
sudo krill-reset-pin

The krill-reset-pin tool will:

  1. Prompt for the new 4-digit PIN
  2. Regenerate pin_hash and pin_derived_key
  3. Restart the Krill service

Important: After resetting the PIN on one server, you must reset it to the same new PIN on all other servers and re-enter it in all client apps to restore cluster connectivity.

Restoring Correct Permissions

If permissions become corrupted, restore them with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# SSH into your Krill server
ssh user@your-krill-server

# Fix directory permissions
sudo chmod 0700 /etc/krill/credentials
sudo chown krill:krill /etc/krill/credentials

# Fix credential file permissions
sudo chmod 0400 /etc/krill/credentials/pin_hash
sudo chmod 0400 /etc/krill/credentials/pin_derived_key
sudo chown krill:krill /etc/krill/credentials/pin_hash
sudo chown krill:krill /etc/krill/credentials/pin_derived_key

# Verify permissions
ls -la /etc/krill/credentials/

Expected output:

1
2
3
4
drwx------ 2 krill krill 4096 Jan 12 12:00 .
drwxr-x--- 4 krill krill 4096 Jan 12 12:00 ..
-r-------- 1 krill krill   60 Jan 12 12:00 pin_derived_key
-r-------- 1 krill krill   60 Jan 12 12:00 pin_hash

Client Configuration

Entering the PIN in Apps

During first-time user experience (FTUE), the mobile, desktop, or WASM app prompts the user to enter the 4-digit cluster PIN. The app derives the same Bearer token using PBKDF2 and uses it for all subsequent requests.

Using the Bearer Token in Requests

Clients include the PIN-derived Bearer token in the Authorization header for all authenticated requests:

1
2
# Example curl request with Bearer token
curl -H "Authorization: Bearer <pin_derived_key>" https://krill-server:8442/api/nodes

Protected Endpoints

The following endpoints require Bearer token authentication:

  • All /api/* endpoints
  • Node management endpoints
  • Configuration endpoints
  • SSE /sse endpoint

Unprotected Endpoints

Some endpoints remain accessible without authentication:

  • /health - Health check endpoint

WASM Kiosk Mode

The WASM web client no longer uses ?api_key= URL parameters. Instead, the PIN is entered through the standard FTUE flow in the browser, and the derived Bearer token is stored in the browser session.

Reinstallation Behavior

When the Krill package is reinstalled or upgraded:

  • Reinstall: The installer prompts for the cluster PIN and regenerates credential files
  • Upgrade: The existing credential files are preserved
  • Purge: Credential files are securely deleted (overwritten with random data before removal)

Security Considerations

Best Practices

  1. Choose a non-obvious PIN – avoid 0000, 1234, and similar patterns
  2. Reset the PIN if you suspect compromise using krill-reset-pin
  3. Use HTTPS to prevent token interception (Krill enforces TLS by default)
  4. Monitor access logs for unauthorized access attempts
  5. Physical security matters – the PIN protects against network-level attacks, not physical access to the Pi

Secure Deletion

When the Krill package is purged, credential files are securely deleted:

1
2
3
4
5
# The postrm script performs:
dd if=/dev/urandom of=/etc/krill/credentials/pin_hash bs=64 count=1 2>/dev/null
dd if=/dev/urandom of=/etc/krill/credentials/pin_derived_key bs=64 count=1 2>/dev/null
rm -f /etc/krill/credentials/pin_hash
rm -f /etc/krill/credentials/pin_derived_key

This ensures the credentials cannot be recovered from disk after removal.

Troubleshooting

401 Unauthorized Errors

If you receive 401 errors when making requests:

  1. Verify the PIN-derived key exists:
    1
    
    sudo cat /etc/krill/credentials/pin_derived_key
    
  2. Check the header format – ensure you are using Authorization: Bearer:
    1
    2
    
    curl -v -H "Authorization: Bearer $(sudo cat /etc/krill/credentials/pin_derived_key)" \
      https://your-server:8442/api/nodes
    
  3. Verify the Krill service is running:
    1
    
    sudo systemctl status krill
    
  4. Check the server logs:
    1
    
    sudo journalctl -u krill -f
    
  5. Verify all cluster members use the same PIN: If one server was reset to a different PIN, other members will receive 401 errors.

Permission Denied Errors

If the Krill server cannot read the credential files:

  1. Check file permissions:
    1
    
    ls -la /etc/krill/credentials/
    
  2. Verify ownership:
    1
    
    stat /etc/krill/credentials/pin_derived_key
    
  3. Fix permissions if needed:
    1
    2
    
    sudo chown krill:krill /etc/krill/credentials/pin_derived_key
    sudo chmod 0400 /etc/krill/credentials/pin_derived_key
    

Credential Files Missing

If the credential files do not exist:

1
2
# Reset the PIN which regenerates all credential files
sudo krill-reset-pin

See Also


Last verified: 2026-04-03

This post is licensed under CC BY 4.0 by Sautner Studio, LLC.