mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-10-30 09:32:32 +00:00
An oversized webhook or channel body was handed to the firmware whole. The device dropped it without an ack, retries stalled the transport, and the radio looked dead. Split to the frame budget, keep links intact, and tag multi-part sends so they can be reassembled. Reserve the wx location prefix from that same budget, and let NOAA alert polling be turned off without disabling the rest of the weather service.
564 lines
14 KiB
Markdown
564 lines
14 KiB
Markdown
# Docker Deployment Guide
|
|
|
|
This guide explains how to deploy meshcore-bot using Docker and Docker Compose.
|
|
|
|
## Prerequisites
|
|
|
|
- Docker Engine 20.10+ or Docker Desktop
|
|
- Docker Compose 2.0+ (included with Docker Desktop)
|
|
|
|
## Quick Start
|
|
|
|
1. **Clone the repository** (if you haven't already):
|
|
```bash
|
|
git clone <repository-url>
|
|
cd meshcore-bot
|
|
```
|
|
|
|
2. **Run the setup script** (recommended):
|
|
```bash
|
|
./docker-setup.sh
|
|
```
|
|
|
|
This will create the necessary directories and copy the example config file.
|
|
|
|
**Or manually:**
|
|
```bash
|
|
mkdir -p data/{config,databases,logs,backups}
|
|
cp config.ini.example data/config/config.ini
|
|
```
|
|
|
|
3. **Edit configuration file**:
|
|
```bash
|
|
# Edit data/config/config.ini with your settings
|
|
nano data/config/config.ini # or your preferred editor
|
|
```
|
|
|
|
4. **Update database paths in config.ini**:
|
|
The setup script (`./docker-setup.sh`) will automatically update these paths, but you can also set them manually:
|
|
```ini
|
|
[Bot]
|
|
db_path = /data/databases/meshcore_bot.db
|
|
|
|
[Web_Viewer]
|
|
db_path = /data/databases/meshcore_bot.db
|
|
|
|
[Logging]
|
|
log_file = /data/logs/meshcore_bot.log
|
|
```
|
|
|
|
**Important**: The log file path must be absolute (`/data/logs/...`), not relative. Relative paths will resolve to the config directory which is read-only.
|
|
|
|
5. **Start the container**:
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
6. **View logs**:
|
|
```bash
|
|
docker-compose logs -f
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Volume Mappings
|
|
|
|
The `docker-compose.yml` file maps the following directories:
|
|
|
|
- `./data/config` → `/data/config` (read-only) - Configuration files
|
|
- `./data/databases` → `/data/databases` - SQLite database files
|
|
- `./data/logs` → `/data/logs` - Log files
|
|
- `./data/backups` → `/data/backups` - Database backups
|
|
|
|
### Serial Port Access
|
|
|
|
**⚠️ Important: Docker Desktop on macOS does NOT support serial device passthrough.**
|
|
If you're using a serial connection, you have several options:
|
|
|
|
**Option 1: Use TCP Connection (Recommended for macOS)**
|
|
If your MeshCore device supports TCP/IP (via gateway or bridge), configure it in `config.ini`:
|
|
```ini
|
|
[Connection]
|
|
connection_type = tcp
|
|
# Your device's IP or hostname
|
|
hostname = 192.168.1.60
|
|
tcp_port = 5000
|
|
```
|
|
Then comment out or remove the `devices` section in `docker-compose.yml`.
|
|
|
|
**Option 2: Serial-to-TCP Bridge (macOS workaround)**
|
|
Use a tool like `socat` to bridge the serial port to TCP on the host:
|
|
```bash
|
|
# On macOS host, create TCP bridge
|
|
socat TCP-LISTEN:5000,reuseaddr,fork FILE:/dev/cu.usbmodem1101,raw,nonblock,waitlock=/var/run/socat.pid
|
|
```
|
|
Then configure the bot to use TCP connection to `localhost:5000`.
|
|
|
|
**Option 3: Device Mapping (Linux only)**
|
|
On Linux, you can map the serial device directly:
|
|
```yaml
|
|
devices:
|
|
- /dev/ttyUSB0:/dev/ttyUSB0
|
|
```
|
|
|
|
**Option 4: Host Network Mode (Linux only, for BLE)**
|
|
For BLE connections on Linux, you may need host network access:
|
|
```yaml
|
|
network_mode: host
|
|
```
|
|
**Note**: Host network mode gives the container full access to the host network, which has security implications.
|
|
|
|
**Windows 11 (Docker Desktop / WSL2):** See [Connecting COM Ports to Docker on Windows 11](#connecting-com-ports-to-docker-on-windows-11) below.
|
|
|
|
### Web Viewer Port
|
|
|
|
If you enable the web viewer, uncomment and adjust the `ports` section:
|
|
```yaml
|
|
ports:
|
|
- "8080:8080"
|
|
```
|
|
|
|
Make sure your `config.ini` has:
|
|
```ini
|
|
[Web_Viewer]
|
|
enabled = true
|
|
# Required for Docker port mapping
|
|
host = 0.0.0.0
|
|
port = 8080
|
|
```
|
|
|
|
## Building the Image
|
|
|
|
### Using Docker Compose
|
|
|
|
**Important**: To avoid pull warnings, build the image first:
|
|
```bash
|
|
docker compose build
|
|
```
|
|
|
|
Then start the container:
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
Or build and start in one command:
|
|
```bash
|
|
docker compose up -d --build
|
|
```
|
|
|
|
The `--build` flag ensures the image is built locally rather than attempting to pull from a registry.
|
|
|
|
### Using Docker directly
|
|
|
|
```bash
|
|
docker build -t meshcore-bot:latest .
|
|
```
|
|
|
|
## Running the Container
|
|
|
|
### Start in background
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
### Start in foreground (see logs)
|
|
```bash
|
|
docker-compose up
|
|
```
|
|
|
|
### Stop the container
|
|
```bash
|
|
docker-compose down
|
|
```
|
|
|
|
### Restart the container
|
|
```bash
|
|
docker-compose restart
|
|
```
|
|
|
|
## Managing the Container
|
|
|
|
### View logs
|
|
```bash
|
|
# Follow logs
|
|
docker-compose logs -f
|
|
|
|
# Last 100 lines
|
|
docker-compose logs --tail=100
|
|
|
|
# Logs for specific service
|
|
docker-compose logs meshcore-bot
|
|
```
|
|
|
|
### Execute commands in container
|
|
```bash
|
|
docker-compose exec meshcore-bot bash
|
|
```
|
|
|
|
### Update the container
|
|
```bash
|
|
# Pull latest changes
|
|
git pull
|
|
|
|
# Rebuild and restart
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
## Using Pre-built Images
|
|
|
|
Official images are published to **GitHub Container Registry** (`ghcr.io/agessaman/meshcore-bot`) on tagged releases and `main`.
|
|
|
|
1. **Update docker-compose.yml** to use the image:
|
|
```yaml
|
|
services:
|
|
meshcore-bot:
|
|
image: ghcr.io/agessaman/meshcore-bot:latest
|
|
# Remove or comment out the 'build' section
|
|
```
|
|
|
|
2. **Pull and start**:
|
|
```bash
|
|
docker-compose pull
|
|
docker-compose up -d
|
|
```
|
|
|
|
## Multi-architecture images
|
|
|
|
CI builds multi-platform images with SBOM and provenance attestations:
|
|
|
|
| Platform | Typical hardware |
|
|
|----------|------------------|
|
|
| `linux/amd64` | x86-64 servers and desktops |
|
|
| `linux/arm64` | Raspberry Pi 4/5 (64-bit OS), Apple Silicon via emulation |
|
|
| `linux/arm/v7` | Raspberry Pi 3 and older (32-bit Raspberry Pi OS) |
|
|
|
|
On ARM devices, pull the matching platform (Docker usually selects automatically):
|
|
|
|
```bash
|
|
docker pull --platform linux/arm64 ghcr.io/agessaman/meshcore-bot:latest
|
|
```
|
|
|
|
Or build locally for your architecture with `docker compose build`.
|
|
|
|
**Non-Docker installs:** Debian packages are available via `make deb` in the repository. See the [Upgrade guide](upgrade.md).
|
|
|
|
## Troubleshooting
|
|
|
|
### Permission Issues
|
|
|
|
If you encounter permission issues with database or log files:
|
|
|
|
1. **Check file ownership**:
|
|
```bash
|
|
ls -la data/databases/
|
|
ls -la data/logs/
|
|
```
|
|
|
|
2. **Fix permissions** (if needed):
|
|
```bash
|
|
sudo chown -R 1000:1000 data/
|
|
```
|
|
|
|
The container runs as user ID 1000 (meshcore user).
|
|
|
|
### Serial Port Permission Denied
|
|
|
|
If you see `[Errno 13] Permission denied` when accessing serial devices:
|
|
|
|
1. **Check device permissions** (on host):
|
|
```bash
|
|
ls -l /dev/ttyUSB0 # or /dev/ttyACM0
|
|
# Should show: crw-rw---- 1 root dialout ...
|
|
```
|
|
|
|
2. **Ensure device has dialout group** (on host):
|
|
```bash
|
|
# Check current group
|
|
ls -l /dev/ttyUSB0 | awk '{print $4}'
|
|
|
|
# If not dialout, fix it (temporary - will reset on reboot)
|
|
sudo chmod 666 /dev/ttyUSB0
|
|
|
|
# Or make it permanent with udev rules:
|
|
sudo nano /etc/udev/rules.d/99-serial-permissions.rules
|
|
# Add: KERNEL=="ttyUSB[0-9]*", MODE="0666", GROUP="dialout"
|
|
# Then: sudo udevadm control --reload-rules
|
|
```
|
|
|
|
3. **Rebuild the container** (to ensure user is in dialout group):
|
|
```bash
|
|
docker compose build
|
|
docker compose up -d
|
|
```
|
|
|
|
4. **Alternative: Use privileged mode** (less secure, but works):
|
|
```yaml
|
|
# In docker-compose.override.yml
|
|
services:
|
|
meshcore-bot:
|
|
privileged: true
|
|
```
|
|
|
|
### Serial Port Not Found
|
|
|
|
1. **Windows: "No such file or directory: 'COM3'"**
|
|
Docker on Windows (WSL2) cannot see Windows COM ports. See [Connecting COM Ports to Docker on Windows 11](#connecting-com-ports-to-docker-on-windows-11) above.
|
|
|
|
2. **Check device exists** (Linux):
|
|
```bash
|
|
ls -l /dev/ttyUSB0 # or your device
|
|
```
|
|
|
|
3. **Use host network mode** if device mapping doesn't work:
|
|
```yaml
|
|
network_mode: host
|
|
```
|
|
|
|
### Database Locked Errors
|
|
|
|
If you see database locked errors:
|
|
|
|
1. **Stop the container**:
|
|
```bash
|
|
docker-compose down
|
|
```
|
|
|
|
2. **Check for leftover database files**:
|
|
```bash
|
|
ls -la data/databases/*.db-*
|
|
```
|
|
|
|
3. **Remove lock files** (if safe):
|
|
```bash
|
|
rm data/databases/*.db-shm data/databases/*.db-wal
|
|
```
|
|
|
|
4. **Restart**:
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
### Container Won't Start
|
|
|
|
1. **Check logs**:
|
|
```bash
|
|
docker-compose logs
|
|
```
|
|
|
|
2. **Verify config file exists**:
|
|
```bash
|
|
ls -la data/config/config.ini
|
|
```
|
|
|
|
3. **Test config file syntax**:
|
|
```bash
|
|
docker-compose run --rm meshcore-bot python3 -c "import configparser; c = configparser.ConfigParser(); c.read('/data/config/config.ini'); print('Config OK')"
|
|
```
|
|
|
|
### Build Failures on ARM Devices (Orange Pi, Raspberry Pi, etc.)
|
|
|
|
If you encounter network errors during build like:
|
|
```
|
|
failed to add the host (veth...) <=> sandbox (veth...) pair interfaces: operation not supported
|
|
```
|
|
|
|
Try these solutions:
|
|
|
|
1. **Restart Docker daemon**:
|
|
```bash
|
|
sudo systemctl restart docker
|
|
```
|
|
|
|
2. **Check kernel modules are loaded**:
|
|
```bash
|
|
lsmod | grep bridge
|
|
lsmod | grep veth
|
|
```
|
|
If missing, load them:
|
|
```bash
|
|
sudo modprobe bridge
|
|
sudo modprobe veth
|
|
```
|
|
|
|
3. **Build directly with docker build** (bypasses compose networking - RECOMMENDED):
|
|
```bash
|
|
# Build the image directly
|
|
DOCKER_BUILDKIT=0 docker build -t meshcore-bot:latest .
|
|
|
|
# Then use docker compose normally (it will use the existing image)
|
|
docker compose up -d
|
|
```
|
|
This bypasses Docker Compose's networking setup during build, which often fails on ARM devices.
|
|
|
|
4. **Use host network mode for build** (alternative):
|
|
```bash
|
|
DOCKER_BUILDKIT=0 docker build --network=host -t meshcore-bot:latest .
|
|
docker compose up -d
|
|
```
|
|
|
|
5. **Check Docker bridge configuration**:
|
|
```bash
|
|
sudo brctl show
|
|
```
|
|
If bridge doesn't exist, Docker may need to be reconfigured.
|
|
|
|
6. **Check Docker daemon logs**:
|
|
```bash
|
|
sudo journalctl -u docker -n 50
|
|
```
|
|
|
|
7. **Reinstall Docker** (if other solutions fail):
|
|
```bash
|
|
# Backup your data first!
|
|
sudo apt-get remove docker docker-engine docker.io containerd runc
|
|
# Then reinstall Docker following Armbian/Docker official instructions
|
|
```
|
|
|
|
## Production Deployment
|
|
|
|
For production deployments:
|
|
|
|
1. **Use specific image tags** instead of `latest`:
|
|
```yaml
|
|
image: ghcr.io/your-username/meshcore-bot:v1.1.0
|
|
```
|
|
|
|
2. **Set resource limits** in `docker-compose.yml`:
|
|
```yaml
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
cpus: '1.0'
|
|
memory: 512M
|
|
reservations:
|
|
cpus: '0.5'
|
|
memory: 256M
|
|
```
|
|
|
|
3. **Use secrets management** for sensitive configuration:
|
|
- Use Docker secrets (Docker Swarm)
|
|
- Use environment variables for API keys
|
|
- Mount secret files as read-only volumes
|
|
|
|
4. **Enable log rotation** (already configured in docker-compose.yml):
|
|
```yaml
|
|
logging:
|
|
driver: "json-file"
|
|
options:
|
|
max-size: "10m"
|
|
max-file: "3"
|
|
```
|
|
|
|
5. **Set up health checks** (already included in Dockerfile):
|
|
The container includes a basic health check. Monitor with:
|
|
```bash
|
|
docker-compose ps
|
|
```
|
|
|
|
## Backup and Restore
|
|
|
|
### Backup
|
|
|
|
```bash
|
|
# Backup databases
|
|
docker-compose exec meshcore-bot tar czf /data/backups/backup-$(date +%Y%m%d).tar.gz /data/databases
|
|
|
|
# Or from host
|
|
tar czf backups/backup-$(date +%Y%m%d).tar.gz data/databases/
|
|
```
|
|
|
|
### Restore
|
|
|
|
```bash
|
|
# Stop container
|
|
docker-compose down
|
|
|
|
# Restore databases
|
|
tar xzf backups/backup-YYYYMMDD.tar.gz -C data/
|
|
|
|
# Start container
|
|
docker-compose up -d
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
1. **Non-root user**: The container runs as a non-root user (UID 1000)
|
|
|
|
2. **Read-only config**: Config directory is mounted read-only to prevent accidental modifications
|
|
|
|
3. **Network isolation**: By default, containers are isolated. Only expose ports you need
|
|
|
|
4. **Secrets**: Never commit API keys or sensitive data to version control. Use environment variables or secrets management
|
|
|
|
5. **Web viewer**: Set `web_viewer_password` in `[Web_Viewer]` when `host = 0.0.0.0`. Use a reverse proxy with TLS on untrusted networks. See [Web Viewer](web-viewer.md).
|
|
|
|
## Connecting COM Ports to Docker on Windows 11 {#connecting-com-ports-to-docker-on-windows-11}
|
|
|
|
On Windows 11, Docker runs inside a Linux VM (WSL2). Linux does not see Windows COM ports by default, so the bot may fail with:
|
|
|
|
```
|
|
Connection failed: [Errno 2] could not open port COM3: [Errno 2] No such file or directory: 'COM3'
|
|
```
|
|
|
|
Even if the port works in Windows (e.g. in Device Manager or in [app.meshcore.nz](https://app.meshcore.nz)), you must **pass the USB device from Windows into WSL** so the container can use it.
|
|
|
|
**1. Install the USB bridge**
|
|
|
|
Open **PowerShell as Administrator** and run:
|
|
|
|
```powershell
|
|
winget install --id Microsoft.usbipd-win
|
|
```
|
|
|
|
Restart your computer if prompted.
|
|
|
|
**2. Identify and share the radio**
|
|
|
|
With the radio plugged in, in PowerShell:
|
|
|
|
- **Find the device**: Run `usbipd list`. Note the **BUSID** for your radio (e.g. `2-3`).
|
|
- **Bind it**: Run `usbipd bind --busid <YOUR-BUSID>`.
|
|
- **Attach to WSL**: Run `usbipd attach --wsl --busid <YOUR-BUSID>`.
|
|
|
|
**Important:** Close any app that is using the serial port (e.g. the [app.meshcore.nz](https://app.meshcore.nz) browser tab) before binding. Only one process can own the port at a time.
|
|
|
|
**3. Use the Linux device name in Docker**
|
|
|
|
After attaching, the device in WSL is no longer `COM3`. It will typically appear as `/dev/ttyUSB0`. To confirm, inside WSL run:
|
|
|
|
```bash
|
|
ls /dev/tty*
|
|
```
|
|
|
|
**4. Update Docker and config**
|
|
|
|
In `docker-compose.yml`, add (or adjust) the device mapping:
|
|
|
|
```yaml
|
|
devices:
|
|
- "/dev/ttyUSB0:/dev/ttyUSB0"
|
|
```
|
|
|
|
In `config.ini`, set the serial port to the Linux device:
|
|
|
|
```ini
|
|
[Connection]
|
|
connection_type = serial
|
|
serial_port = /dev/ttyUSB0
|
|
```
|
|
|
|
**Notes:**
|
|
|
|
- Bind/attach is **not persistent**. After a reboot or unplugging the radio, run `usbipd bind` and `usbipd attach --wsl` again (or use a script).
|
|
- To attach to the Docker Desktop distro specifically:
|
|
`usbipd attach --wsl --busid <BUSID> --distribution docker-desktop`
|
|
(Use `usbipd --help` to see your exact distribution name.)
|
|
|
|
## Additional Resources
|
|
|
|
- [Docker Documentation](https://docs.docker.com/)
|
|
- [Docker Compose Documentation](https://docs.docker.com/compose/)
|
|
- [Main README](https://github.com/agessaman/meshcore-bot/blob/main/README.md) for general bot configuration
|
|
- [Upgrade guide](upgrade.md) for v0.9 migration notes
|
|
- [Web Viewer](web-viewer.md) for dashboard configuration
|