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
- Client signs request with secret key
- Server verifies signature
- 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
- Add new key to config
- Update clients to use new key
- Remove old key from config
- 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
- Configuration - Server settings
- CLI Setup - Managing server profiles