This guide covers deploying ServerMonitor to a server (Raspberry Pi, VPS, or any Linux host) using Docker Compose.
- Docker and Docker Compose installed on the target machine
- Git (to clone the repo)
- Network access from the target machine to all monitored systems (SSH, Docker API, qBit Web UI, UniFi controller)
ssh your-server
mkdir -p ~/container && cd ~/container
git clone <repo-url> ServerMonitor
cd ServerMonitorOr if you're syncing from a local machine:
rsync -avz --exclude node_modules --exclude target --exclude dist \
./ your-server:~/container/ServerMonitor/cp backend/config.example.yaml backend/config.yaml
nano backend/config.yamlFill in the actual IPs, usernames, and passwords for your systems. Only enable the collectors you need -- set enabled: false on the rest.
Minimal example (just one Linux server):
poll_interval: 5
systems:
- id: my-server
name: "My Server"
type: linux
enabled: true
config:
host: 192.168.1.100
port: 22
username: monitor
password: your-passwordLinux servers: The SSH user needs read access to /proc/stat, /proc/meminfo, /proc/net/dev, and permission to run df, sensors (optional, for temperatures).
Docker: Either mount the local socket (default in docker-compose.yml) or expose the Docker API on a TCP port (tcp://host:2375). For remote Docker hosts, make sure the API port is reachable.
qBittorrent: Enable the Web UI in qBittorrent settings. Note the port (default 8080) and credentials.
UniFi: Generate an API key from your UniFi controller's settings. The controller must be reachable over HTTPS (port 443 by default). Set verify_ssl: false if using a self-signed certificate.
UNAS/NAS: SSH access with permissions to run zpool, df, lsblk, and smartctl.
docker compose up --build -dThis builds both images and starts:
- backend on port 8742 (host networking, Rust binary)
- frontend on port 4829 (Nginx serving the Vue SPA + reverse proxy)
Verify everything is running:
docker compose ps
docker compose logs --tail=30 backend
docker compose logs --tail=30 frontendOpen http://<server-ip>:4829 in your browser.
- The dashboard should load at
http://<server-ip>:4829 - Check the connection indicator in the top nav -- it should show "Connected"
- System cards should appear within 5-10 seconds as the first collection cycle completes
- If a system shows "offline", check that the target is reachable from the server and credentials are correct
Quick API test:
curl http://localhost:8742/api/health
curl http://localhost:8742/api/systemsInstead of building locally, you can use pre-built images from GitHub Container Registry:
# docker-compose.yml (override backend service)
services:
backend:
image: ghcr.io/<owner>/server-monitor:latest
network_mode: host
volumes:
- ./backend/config.yaml:/app/config.yaml:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- SERVERMONITOR_CONFIG_PATH=/app/config.yaml
restart: unless-stoppedPull the latest code and rebuild:
cd ~/container/ServerMonitor
git pull
docker compose up --build -dTo rebuild a single service:
docker compose up --build -d backend # just the backend
docker compose up --build -d frontend # just the frontendServerMonitor runs well on a Raspberry Pi 4 (2GB+ RAM recommended). A few things to keep in mind:
- First build is slow -- Rust compilation takes a while on ARM. Use the pre-built multi-arch Docker image (
ghcr.io/<owner>/server-monitor:latest) to skip building entirely. - Memory: With all collectors enabled, expect ~30-50MB total RAM usage for the Rust backend (significantly less than the Python version).
- Docker socket: The compose file already mounts
/var/run/docker.sockso the Docker collector can monitor containers on the Pi itself. - Temperatures: If the Pi is also one of your monitored Linux servers,
sensorsmay not be available. The collector will fall back to reading/sys/class/thermal/thermal_zone*/temp.
# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# Log out and back in
# Install Docker Compose plugin
sudo apt install docker-compose-plugin
# Clone and deploy
mkdir -p ~/container && cd ~/container
git clone <repo-url> ServerMonitor
cd ServerMonitor
cp backend/config.example.yaml backend/config.yaml
nano backend/config.yaml # configure your systems
docker compose up --build -dIf you prefer to run directly on the host:
# Install Rust (if not installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
cd backend
cargo build --release
# Set config path (optional, defaults to config.yaml in cwd)
export SERVERMONITOR_CONFIG_PATH=./config.yaml
./target/release/server-monitorcd frontend
bun install
bun run buildServe the frontend/dist/ directory with any web server. You'll need to configure a reverse proxy for /api and /ws to point to the backend.
Example Nginx config:
server {
listen 4829;
root /path/to/frontend/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://127.0.0.1:8742;
}
location /ws {
proxy_pass http://127.0.0.1:8742;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
}To run with fake data (useful for development or demos):
cd backend
SERVERMONITOR_MOCK_MODE=true cargo run --releaseOr in Docker Compose, add to the backend environment:
environment:
- SERVERMONITOR_CONFIG_PATH=/app/config.yaml
- SERVERMONITOR_MOCK_MODE=true- Check backend logs:
docker compose logs backend - Verify config.yaml has at least one system with
enabled: true - Test connectivity from the server to the target system (e.g.,
ssh user@hostorcurl http://host:port)
- The frontend automatically reconnects and falls back to HTTP polling -- this is by design
- If you're behind a reverse proxy or load balancer, make sure WebSocket upgrade headers are forwarded
- Check that port 8742 is not blocked by a firewall
- The collector can't reach the target. Common causes:
- Wrong IP/port/credentials in config.yaml
- Firewall blocking the connection
- Target service not running (e.g., Docker API not exposed, qBit Web UI disabled)
- Check the error in backend logs for specifics
- Local socket: Make sure
/var/run/docker.sockis mounted (it is by default in docker-compose.yml) - Remote TCP: Docker API must be explicitly exposed on the target host (
dockerd -H tcp://0.0.0.0:2375). This has no authentication -- only use on trusted networks.
- Increase
poll_intervalin config.yaml (e.g., from 5 to 15 seconds) - Disable collectors you don't need
- Hot-reload config without restart:
curl -X POST http://localhost:8742/api/reload