Docker
The included Dockerfile uses a multi-stage build: Rust nightly for compilation, Debian slim for runtime.
Build the image
# All channels (default)
docker build -t oxicrab .
# Specific channels only (smaller image)
docker build -t oxicrab --build-arg FEATURES="channel-telegram,channel-slack" .
Run
# Mount your config directory
docker run -d \
--name oxicrab \
--restart unless-stopped \
-v ~/.oxicrab:/home/oxicrab/.oxicrab \
-p 8080:8080 \
oxicrab
The -p 8080:8080 port mapping is only needed if you use the Twilio channel (webhook server). Other channels use outbound connections only.
CLI mode
# Single message
docker run --rm \
-v ~/.oxicrab:/home/oxicrab/.oxicrab \
oxicrab agent -m "What's the weather?"
# Interactive
docker run --rm -it \
-v ~/.oxicrab:/home/oxicrab/.oxicrab \
oxicrab agent
View logs
docker logs -f oxicrab
# Debug logging
docker run -d \
--name oxicrab \
-e RUST_LOG=debug \
-v ~/.oxicrab:/home/oxicrab/.oxicrab \
oxicrab
WhatsApp: The first run displays a QR code in the terminal. Use
docker run -it (interactive) for the initial link, then switch to -d (detached) for subsequent runs. The session is persisted in the mounted volume.Docker Compose
docker-compose.yml
services:
oxicrab:
build: .
container_name: oxicrab
restart: unless-stopped
volumes:
- ~/.oxicrab:/home/oxicrab/.oxicrab
ports:
- "8080:8080" # Only needed for Twilio webhooks
environment:
- RUST_LOG=info
# Start
docker compose up -d
# Logs
docker compose logs -f
# Rebuild after updates
docker compose up -d --build
systemd (Linux)
A ready-to-use service file ships with the repo at deploy/oxicrab.service. It's designed as a user service — no root required.
1. Build and install the binary
cargo build --release
sudo cp target/release/oxicrab /usr/local/bin/oxicrab
2. Install the user service
mkdir -p ~/.config/systemd/user
cp deploy/oxicrab.service ~/.config/systemd/user/
Binary path: The shipped service file expects
/usr/local/bin/oxicrab. If your binary is elsewhere, edit the ExecStart line before installing.3. Enable and start
systemctl --user daemon-reload
systemctl --user enable oxicrab
systemctl --user start oxicrab
# Enable lingering so the service runs without an active login session
loginctl enable-linger $USER
4. Manage
# Check status
systemctl --user status oxicrab
# View logs (syslog identifier: oxicrab)
journalctl --user -u oxicrab -f
# Restart after config changes
systemctl --user restart oxicrab
# Stop
systemctl --user stop oxicrab
What the service file does
deploy/oxicrab.service
[Unit]
Description=oxicrab AI assistant gateway
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=5
[Service]
Type=simple
ExecStart=/usr/local/bin/oxicrab gateway
Restart=on-failure
RestartSec=5
Environment=RUST_LOG=info
Environment=RUST_BACKTRACE=1
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=oxicrab
# Hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=%h/.oxicrab
PrivateTmp=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictNamespaces=true
RestrictSUIDSGID=true
MemoryDenyWriteExecute=true
LockPersonality=true
# Resource limits
LimitNOFILE=65536
TimeoutStopSec=30
[Install]
WantedBy=default.target
Key hardening features:
- StartLimitBurst=5 — prevents crash loops from hammering restarts (max 5 restarts in 5 minutes)
- ProtectSystem=strict — mounts
/read-only except explicitly allowed paths - ReadWritePaths=%h/.oxicrab —
%hexpands to the user's home directory - MemoryDenyWriteExecute — prevents dynamic code generation exploits
- LimitNOFILE=65536 — enough file descriptors for many concurrent connections
- SyslogIdentifier=oxicrab — clean log filtering with
journalctl -t oxicrab
System-wide service (alternative)
To run as a dedicated system user instead:
# Create service user
sudo useradd -r -m -s /usr/sbin/nologin oxicrab
sudo mkdir -p /home/oxicrab/.oxicrab
sudo cp ~/.oxicrab/config.json /home/oxicrab/.oxicrab/config.json
sudo chown -R oxicrab:oxicrab /home/oxicrab/.oxicrab
# Install as system service
sudo cp deploy/oxicrab.service /etc/systemd/system/
# Edit to add User=oxicrab and Group=oxicrab under [Service]
# Change WantedBy=default.target to WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable oxicrab
sudo systemctl start oxicrab
launchd (macOS)
A ready-to-use plist ships with the repo at deploy/com.oxicrab.gateway.plist. It runs as a launch agent (per-user, starts on login).
1. Build and install the binary
cargo build --release
cp target/release/oxicrab /usr/local/bin/oxicrab
2. Create the log directory
sudo mkdir -p /usr/local/var/log
3. Install the plist
cp deploy/com.oxicrab.gateway.plist ~/Library/LaunchAgents/
Binary path: The shipped plist expects
/usr/local/bin/oxicrab. If your binary is elsewhere, edit the ProgramArguments before installing.4. Load and start
launchctl load ~/Library/LaunchAgents/com.oxicrab.gateway.plist
5. Manage
# Check status
launchctl list | grep oxicrab
# View logs
tail -f /usr/local/var/log/oxicrab.log
# Restart after config changes
launchctl unload ~/Library/LaunchAgents/com.oxicrab.gateway.plist
launchctl load ~/Library/LaunchAgents/com.oxicrab.gateway.plist
# Stop permanently
launchctl unload ~/Library/LaunchAgents/com.oxicrab.gateway.plist
What the plist does
deploy/com.oxicrab.gateway.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.oxicrab.gateway</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/oxicrab</string>
<string>gateway</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>RUST_LOG</key>
<string>info</string>
<key>RUST_BACKTRACE</key>
<string>1</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
<key>ThrottleInterval</key>
<integer>5</integer>
<key>StandardOutPath</key>
<string>/usr/local/var/log/oxicrab.log</string>
<key>StandardErrorPath</key>
<string>/usr/local/var/log/oxicrab.log</string>
<key>SoftResourceLimits</key>
<dict>
<key>NumberOfFiles</key>
<integer>65536</integer>
</dict>
<key>HardResourceLimits</key>
<dict>
<key>NumberOfFiles</key>
<integer>65536</integer>
</dict>
<key>ProcessType</key>
<string>Background</string>
</dict>
</plist>
Key features:
- KeepAlive / SuccessfulExit=false — restarts only on crash (exit code != 0), not on clean shutdown
- ThrottleInterval=5 — minimum 5 seconds between restart attempts (crash loop protection)
- NumberOfFiles=65536 — raises the file descriptor limit for many concurrent connections
- ProcessType=Background — tells macOS this is a low-priority background service (won't contend with foreground apps)
- Unified log path — stdout and stderr both go to
/usr/local/var/log/oxicrab.log
Log rotation: macOS doesn't rotate launch agent logs automatically. Add a newsyslog entry or use a cron job:
This keeps 7 rotated copies, rotating when the file exceeds 1 MB.
echo '/usr/local/var/log/oxicrab.log 644 7 1000 * J' | sudo tee -a /etc/newsyslog.confThis keeps 7 rotated copies, rotating when the file exceeds 1 MB.