Server Authentication

Secure your server and formations

MUXI uses HMAC signatures for server management (deploy, control) and API keys for formation access (chat, queries). This guide covers both authentication layers.

Overview

Two authentication levels:

Level Used For Method
Server API Deploy, manage formations HMAC signature
Formation API Chat, queries API keys

Server API (HMAC)

How It Works

  1. Client signs request with secret key
  2. Server verifies signature
  3. Request proceeds if valid

Credentials

Generated by muxi-server init:

# ~/.muxi/server/config.yaml
auth:
  enabled: true
  keys:
    - id: MUXI_e8f3a9b2
      secret: sk_9f2e8d7c6b5a4f3e2d1c0b9a8f7e6d5c

Signing Requests

Signature format:

message = "{timestamp};{method};{path};{body_hash}"
signature = HMAC-SHA256(secret, message)

Headers

X-MUXI-Key-ID: MUXI_e8f3a9b2
X-MUXI-Timestamp: 1705484123
X-MUXI-Signature: base64_encoded_signature

Example (Python)

import hmac
import hashlib
import base64
import time
import requests

def sign_request(key_id, secret, method, path, body=""):
    timestamp = str(int(time.time()))
    body_hash = hashlib.sha256(body.encode()).hexdigest()
    message = f"{timestamp};{method};{path};{body_hash}"

    signature = hmac.new(
        secret.encode(),
        message.encode(),
        hashlib.sha256
    ).digest()

    return {
        "X-MUXI-Key-ID": key_id,
        "X-MUXI-Timestamp": timestamp,
        "X-MUXI-Signature": base64.b64encode(signature).decode()
    }

# Usage
headers = sign_request(
    "MUXI_e8f3a9b2",
    "sk_9f2e8d7c6b5a4f3e2d1c0b9a8f7e6d5c",
    "GET",
    "/rpc/formations"
)

response = requests.get(
    "http://localhost:7890/rpc/formations",
    headers=headers
)

Example (curl)

# Generate signature (use a script)
TIMESTAMP=$(date +%s)
KEY_ID="MUXI_e8f3a9b2"
SECRET="sk_9f2e8d7c6b5a4f3e2d1c0b9a8f7e6d5c"
METHOD="GET"
PATH="/rpc/formations"

# Sign and request
curl -X GET http://localhost:7890/rpc/formations \
  -H "X-MUXI-Key-ID: $KEY_ID" \
  -H "X-MUXI-Timestamp: $TIMESTAMP" \
  -H "X-MUXI-Signature: $SIGNATURE"

Formation API Keys

Formations use simpler API key authentication:

# formation.afs
server:
  api_keys:
    admin_key: "${{ secrets.ADMIN_KEY }}"
    client_key: "${{ secrets.CLIENT_KEY }}"

Admin Key

Full access to formation:

curl -X POST http://localhost:8001/v1/chat \
  -H "X-MUXI-Admin-Key: fma_abc123..."

Client Key

Limited access (chat only):

curl -X POST http://localhost:8001/v1/chat \
  -H "X-MUXI-Client-Key: fmc_xyz789..."

CLI Authentication

The CLI handles authentication automatically:

# Configure server profile
muxi profiles add production

# CLI signs requests automatically
muxi server list

Profiles stored in ~/.muxi/cli/servers.yaml.

SDK Authentication

SDKs handle signing:

from muxi import ServerClient

client = ServerClient(
    url="http://localhost:7890",
    key_id="MUXI_e8f3a9b2",
    secret_key="sk_..."
)

# Requests are signed automatically
formations = client.list_formations()

Disable Authentication

For development only:

# ~/.muxi/server/config.yaml
auth:
  enabled: false

Never disable in production!

Multiple Keys

Add keys for different clients:

auth:
  keys:
    - id: MUXI_production
      secret: sk_prod_...
    - id: MUXI_ci
      secret: sk_ci_...
    - id: MUXI_dev
      secret: sk_dev_...

Key Rotation

  1. Add new key to config
  2. Update clients to use new key
  3. Remove old key from config
  4. Restart server

Troubleshooting

401 Unauthorized

  • Check key ID matches config
  • Verify timestamp is current (within 5 minutes)
  • Confirm signature calculation

Signature Mismatch

  • Verify body hash includes exact body
  • Check method is uppercase (GET, POST)
  • Ensure path starts with /

Next Steps