resonate-server-deployment — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited resonate-server-deployment (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Deploy the Resonate server on Linux systems using systemd for process management. This skill covers installation, configuration of public URLs, JWT authentication setup, and common troubleshooting scenarios.
Deploying on GCP instead? See resonate-server-deployment-cloud-run for the Cloud Run + Cloud SQL variant.
# Download and run
curl -L -o deploy-resonate.sh https://example.com/deploy-resonate.sh
chmod +x deploy-resonate.sh
sudo ./deploy-resonate.sh# Generate RSA key pair first
openssl genrsa -out private_key.pem 2048
openssl rsa -in private_key.pem -pubout -out public_key.pem
# Deploy with configuration (setting the public key enables JWT auth)
sudo RESONATE_SERVER__URL=https://resonate.example.com \
RESONATE_AUTH__PUBLICKEY=/path/to/public_key.pem \
./deploy-resonate.sh| Environment Variable | Default | Description |
|---|---|---|
RESONATE_VERSION | v0.9.8 | Server version the install script downloads |
RESONATE_SERVER__PORT | 8001 | HTTP API port |
RESONATE_SERVER__URL | (none) | Public URL for the server (e.g., https://resonate.example.com) |
RESONATE_AUTH__PUBLICKEY | (none) | Path to JWT public key file; setting it enables JWT auth (there is no separate enable flag) |
The Resonate server binary accepts these flags:
resonate serve [flags]
Flags:
--server-url string Public URL for the server (included in response headers)
--server-port int HTTP API port (default 8001)
--auth-publickey string Path to JWT public key for authentication
--storage-type string Storage backend: sqlite or postgres (default sqlite)
--storage-postgres-url string PostgreSQL connection URLAll flags are also settable via RESONATE_-prefixed environment variables with __ for nesting, e.g. RESONATE_SERVER__URL, RESONATE_AUTH__PUBLICKEY, RESONATE_STORAGE__POSTGRES__URL.
Internet
│
▼
┌────────────────┐
│ Nginx/Caddy │ (SSL termination)
│ Port 443 │
└────────────────┘
│
▼
┌────────────────┐
│ Resonate Server│ (systemd service)
│ Port 8001 │
└────────────────┘
│
┌────────┴────────┐
▼ ▼
┌──────────┐ ┌──────────┐
│ Worker 1 │ │ Worker 2 │
└──────────┘ └──────────┘# /etc/systemd/system/resonate.service
[Unit]
Description=Resonate Server
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/var/lib/resonate
ExecStart=/usr/local/bin/resonate serve
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=resonate
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target# /etc/systemd/system/resonate.service
[Unit]
Description=Resonate Server
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/var/lib/resonate
ExecStart=/usr/local/bin/resonate serve \
--server-url https://resonate.example.com \
--auth-publickey /etc/resonate/public_key.pem
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=resonate
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target# Generate private key (keep secret!)
openssl genrsa -out private_key.pem 2048
# Extract public key (deploy with server)
openssl rsa -in private_key.pem -pubout -out public_key.pem# macOS
brew install mike-engel/jwt-cli/jwt-cli
# Linux (download binary)
curl -L -o jwt https://github.com/mike-engel/jwt-cli/releases/latest/download/jwt-linux
chmod +x jwt
sudo mv jwt /usr/local/bin/IMPORTANT: An empty payload {} will DENY all access. You must include a prefix claim.
# Unrestricted access (empty prefix = all promises)
jwt encode --secret @private_key.pem -A RS256 '{"prefix":""}'
# Admin access (alternative way to get full access)
jwt encode --secret @private_key.pem -A RS256 '{"role":"admin"}'
# Restricted to prefix (only access promises starting with "my-app")
jwt encode --secret @private_key.pem -A RS256 '{"prefix":"my-app"}'
# Unrestricted with expiration
jwt encode --secret @private_key.pem -A RS256 --exp='+30 days' '{"prefix":""}'Prefix claim behavior:
| Payload | Access |
|---|---|
{} | DENIED (no prefix claim = unauthorized) |
{"prefix": ""} | ALL promises (empty string = unrestricted) |
{"prefix": "my-app"} | Only promises starting with my-app |
{"role": "admin"} | ALL promises (admin role) |
# Copy public key to server
scp public_key.pem root@server:/etc/resonate/
# Update service (public key present → JWT auth on)
sudo RESONATE_AUTH__PUBLICKEY=/etc/resonate/public_key.pem \
./deploy-resonate.sh --update-servicePass the server URL and a JWT token to the client. TypeScript shown — every SDK takes a URL + token the same way; see the per-SDK skill (resonate-basic-ephemeral-world-usage-{typescript,python,rust,go}) for client init in your language. The RESONATE_TOKEN env var and the Authorization: Bearer <jwt> header are identical across all SDKs.
// SDK client
const resonate = new Resonate({
url: "https://resonate.example.com",
token: process.env.RESONATE_TOKEN // JWT token
});
// Direct HTTP calls
const headers = {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
};The --server-url flag tells the Resonate server its public address. This is critical when:
Without `--server-url`:
http://localhost:8001 in responsesWith `--server-url`:
https://resonate.example.com in responses/usr/local/bin/
└── resonate # Server binary
/etc/resonate/
├── public_key.pem # JWT public key (if auth enabled)
└── resonate.yml # Optional config file
/var/lib/resonate/
└── resonate.db # SQLite database (default)
/etc/systemd/system/
└── resonate.service # Systemd service file# Follow logs
journalctl -u resonate -f
# Last 100 lines
journalctl -u resonate -n 100
# Logs since boot
journalctl -u resonate -b
# Logs from specific time
journalctl -u resonate --since "2024-01-28 10:00:00"# Status
systemctl status resonate
# Start/Stop/Restart
systemctl start resonate
systemctl stop resonate
systemctl restart resonate
# Enable/Disable on boot
systemctl enable resonate
systemctl disable resonate
# Reload service file after changes
systemctl daemon-reload# View current service configuration
systemctl cat resonate
# Check what command is running
ps aux | grep resonate
# Test server is responding
curl http://localhost:8001/promisesSymptoms:
Causes & Fixes:
// Add token to client
const resonate = new Resonate({
url: "https://resonate.example.com",
token: process.env.RESONATE_TOKEN
}); # Generate new token (a payload with no prefix/role claim is DENIED — include one)
jwt encode --secret @private_key.pem -A RS256 --exp='+30 days' '{"prefix":""}' # Verify key matches
openssl rsa -in private_key.pem -pubout | diff - public_key.pem # Decode and verify token
jwt decode $TOKENSymptoms:
curl http://localhost:8001 hangs or refuses connectionCauses & Fixes:
journalctl -u resonate -n 50
# Look for error messages netstat -tlnp | grep 8001
# Kill conflicting process or change port # Check UFW (Ubuntu)
ufw status
# Allow internal access only (recommended)
# Don't expose 8001 directly - use reverse proxySymptoms:
Causes & Fixes:
# Should be public URL if server is remote
RESONATE_URL=https://resonate.example.com
# NOT http://localhost:8001 (unless worker is on same machine) # Server doesn't know its public URL
# Update service with --server-url flag # Test with curl
curl -v https://resonate.example.com/promises
# Check certificate is validSymptoms:
Causes & Fixes:
# Only one server should access the DB
ps aux | grep resonate
# Kill duplicates # Check where DB is being created
find / -name "resonate.db" 2>/dev/null
# Ensure WorkingDirectory is set in service file df -h
# Clean up or expand disk--server-url set to public URL/etc/resonate/server {
listen 443 ssl;
server_name resonate.example.com;
ssl_certificate /etc/letsencrypt/live/resonate.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/resonate.example.com/privkey.pem;
location / {
proxy_pass http://localhost:8001;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# For long-polling
proxy_read_timeout 120s;
proxy_send_timeout 120s;
}
}resonate.example.com {
reverse_proxy localhost:8001
}Key deployment steps:
--server-url for public accessibility--auth-publickey if neededCritical flags:
--server-url: Server's public URL (required for external access)--auth-publickey: JWT public key path (required for auth)~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.