1 unstable release
Uses new Rust 2024
| 0.1.19 | Oct 18, 2025 |
|---|
#1454 in Network programming
127 downloads per month
1MB
17K
SLoC
Communitas Headless
Headless daemon for running Communitas as a system service.
Overview
Communitas Headless is a daemon application that runs Communitas core without a user interface. It's designed for:
- Server deployments
- Bot applications
- Automated systems
- Background services
- Integration with other applications
Features
- System Service Integration: Supports systemd (Linux) and launchd (macOS)
- JSON-RPC API: Programmatic access to all Communitas features
- Webhook Support: Push notifications for events
- Automated Backups: Scheduled backups of state and data
- Resource Efficient: Minimal CPU and memory footprint
- Multi-Tenant: Support multiple identities/instances
Installation
From Binary
# Download latest release
wget https://github.com/saorsalabs/communitas/releases/latest/communitas-headless
# Make executable
chmod +x communitas-headless
# Move to system path
sudo mv communitas-headless /usr/local/bin/
From Source
cargo install --path communitas-headless
Via Package Manager
# Homebrew (macOS)
brew install saorsalabs/tap/communitas-headless
# APT (Debian/Ubuntu) - coming soon
apt install communitas-headless
Configuration
Create /etc/communitas/headless.toml:
[daemon]
api_port = 9090
api_host = "127.0.0.1"
data_dir = "/var/lib/communitas"
log_level = "info"
[identity]
four_words = "ocean-forest-moon-star"
display_name = "Headless Bot"
device_name = "Server-01"
auto_connect = true
[network]
bootstrap_nodes = [
"bootstrap.communitas.network:8080",
"bootstrap-eu.communitas.network:8080"
]
enable_mdns = false
[storage]
backup_enabled = true
backup_interval = 3600 # seconds
backup_path = "/var/backups/communitas"
[webhooks]
enabled = true
url = "https://your-app.com/webhooks/communitas"
secret = "your-webhook-secret"
events = ["message", "presence", "channel"]
[logging]
format = "json"
output = "file"
file_path = "/var/log/communitas/headless.log"
rotate_size = "100MB"
rotate_count = 5
System Service Setup
systemd (Linux)
Create /etc/systemd/system/communitas.service:
[Unit]
Description=Communitas Headless Daemon
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=communitas
Group=communitas
ExecStart=/usr/local/bin/communitas-headless --config /etc/communitas/headless.toml
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/communitas /var/log/communitas
[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl enable communitas
sudo systemctl start communitas
sudo systemctl status communitas
launchd (macOS)
Create ~/Library/LaunchAgents/com.saorsalabs.communitas.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.saorsalabs.communitas</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/communitas-headless</string>
<string>--config</string>
<string>/Users/you/.config/communitas/headless.toml</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/you/Library/Logs/communitas.log</string>
<key>StandardErrorPath</key>
<string>/Users/you/Library/Logs/communitas-error.log</string>
</dict>
</plist>
Enable and start:
launchctl load ~/Library/LaunchAgents/com.saorsalabs.communitas.plist
launchctl start com.saorsalabs.communitas
JSON-RPC API
Connection
# Via curl
curl -X POST http://localhost:9090/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method": "status", "id": 1}'
# Via Python
import requests
def call_rpc(method, params=None):
response = requests.post('http://localhost:9090/rpc', json={
'jsonrpc': '2.0',
'method': method,
'params': params or {},
'id': 1
})
return response.json()['result']
# Get status
status = call_rpc('status')
print(status)
Available Methods
Core Methods
status- Get daemon statusinfo- Get identity and network informationshutdown- Gracefully shutdown daemon
Message Methods
-
message.send- Send a message{ "channel_id": "ch_123", "content": "Hello!", "recipients": ["ocean-forest-moon-star"] } -
message.list- List messages{ "channel_id": "ch_123", "limit": 50, "offset": 0 }
Channel Methods
channel.create- Create a channelchannel.list- List channelschannel.join- Join a channelchannel.leave- Leave a channel
Identity Methods
identity.get- Get current identityidentity.list_contacts- List contactsidentity.add_contact- Add a contact
Webhooks
When enabled, the daemon will send HTTP POST requests to the configured webhook URL for events:
Webhook Payload
{
"event": "message:new",
"timestamp": "2025-10-15T12:34:56Z",
"signature": "sha256=...",
"data": {
"id": "msg_123",
"channel_id": "ch_456",
"content": "Hello",
"sender": "ocean-forest-moon-star",
"timestamp": "2025-10-15T12:34:56Z"
}
}
Signature Verification
Webhooks are signed with HMAC-SHA256:
import hmac
import hashlib
def verify_webhook(payload, signature, secret):
expected = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
Bot Example
#!/usr/bin/env python3
"""
Simple echo bot using Communitas Headless
"""
import requests
import time
RPC_URL = 'http://localhost:9090/rpc'
def rpc_call(method, params=None):
response = requests.post(RPC_URL, json={
'jsonrpc': '2.0',
'method': method,
'params': params or {},
'id': 1
})
return response.json().get('result')
def echo_bot():
last_message_id = None
while True:
# Get recent messages
messages = rpc_call('message.list', {
'limit': 10,
'after': last_message_id
})
for msg in messages:
if msg['id'] == last_message_id:
continue
# Echo the message
if not msg['content'].startswith('Bot:'):
rpc_call('message.send', {
'channel_id': msg['channel_id'],
'content': f"Bot: {msg['content']}"
})
last_message_id = msg['id']
time.sleep(1)
if __name__ == '__main__':
echo_bot()
Monitoring
Metrics Endpoint
Prometheus metrics available at http://localhost:9090/metrics
Key metrics:
communitas_messages_sent_totalcommunitas_messages_received_totalcommunitas_peers_connectedcommunitas_rpc_requests_totalcommunitas_uptime_seconds
Health Check
curl http://localhost:9090/health
Returns:
{
"status": "healthy",
"uptime": 3600,
"identity": "ocean-forest-moon-star",
"peers_connected": 42,
"version": "0.1.17"
}
Development
Building
cargo build -p communitas-headless --release
Testing
cargo test -p communitas-headless
Running Locally
cargo run -p communitas-headless -- --config test-config.toml
Troubleshooting
Service Won't Start
# Check logs
journalctl -u communitas -f # systemd
tail -f /var/log/communitas/headless.log
# Verify configuration
communitas-headless --config /etc/communitas/headless.toml --validate
API Connection Refused
- Verify daemon is running:
systemctl status communitas - Check port is not blocked:
netstat -tlnp | grep 9090 - Review firewall rules
High Memory Usage
- Reduce backup frequency
- Limit message history retention
- Adjust peer connections in configuration
Security Best Practices
- Run as Dedicated User: Create a
communitasuser - Limit Network Access: Bind API to localhost only
- Secure Configuration: Protect config files (chmod 600)
- Regular Updates: Keep daemon updated
- Monitor Logs: Watch for suspicious activity
- Backup Encryption: Encrypt backup data
Performance
- Memory: ~50MB typical, ~200MB peak
- CPU: <5% on modern hardware
- Disk I/O: Minimal, mostly on message receipt
- Network: ~1KB/s idle, scales with activity
Contributing
See ../../docs/development/contributing.md
License
Dual-licensed under AGPL-3.0-or-later and commercial license.
See Also
Dependencies
~77–115MB
~2M SLoC