mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-03-30 12:05:38 +00:00
- Clarified comments in docker-compose.yml regarding build configuration and updated pull_policy to 'missing' for clearer intent. - Enhanced docker-setup.sh to ensure .env file creation and updates are more robust, with improved error handling and verification steps for Docker image configuration.
374 lines
14 KiB
Bash
Executable File
374 lines
14 KiB
Bash
Executable File
#!/bin/bash
|
|
# Setup script for Docker deployment
|
|
# Creates necessary directories and copies example config
|
|
|
|
set -e
|
|
|
|
echo "Setting up meshcore-bot Docker environment..."
|
|
|
|
# Create data directories
|
|
echo "Creating data directories..."
|
|
mkdir -p data/{config,databases,logs,backups}
|
|
|
|
# Copy example config if config doesn't exist
|
|
if [ ! -f "data/config/config.ini" ]; then
|
|
if [ -f "config.ini.example" ]; then
|
|
echo "Copying config.ini.example to data/config/config.ini..."
|
|
cp config.ini.example data/config/config.ini
|
|
else
|
|
echo "⚠️ Warning: config.ini.example not found. Please create data/config/config.ini manually."
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "✓ Config file already exists at data/config/config.ini"
|
|
fi
|
|
|
|
# Detect platform
|
|
PLATFORM=$(uname -s)
|
|
CONFIG_FILE="data/config/config.ini"
|
|
|
|
# Function to update config.ini using sed (works with both existing and new configs)
|
|
update_config() {
|
|
local section=$1
|
|
local key=$2
|
|
local value=$3
|
|
|
|
# Check if section exists
|
|
if ! grep -q "^\[$section\]" "$CONFIG_FILE"; then
|
|
echo "" >> "$CONFIG_FILE"
|
|
echo "[$section]" >> "$CONFIG_FILE"
|
|
fi
|
|
|
|
# Check if key exists in section (look for key= with optional spaces)
|
|
if grep -q "^$key[[:space:]]*=" "$CONFIG_FILE"; then
|
|
# Update existing key (use | as delimiter to avoid issues with / in paths)
|
|
if [[ "$PLATFORM" == "Darwin" ]]; then
|
|
sed -i '' "s|^$key[[:space:]]*=.*|$key = $value|" "$CONFIG_FILE"
|
|
else
|
|
sed -i "s|^$key[[:space:]]*=.*|$key = $value|" "$CONFIG_FILE"
|
|
fi
|
|
else
|
|
# Add new key after section header
|
|
if [[ "$PLATFORM" == "Darwin" ]]; then
|
|
sed -i '' "/^\[$section\]/a\\
|
|
$key = $value
|
|
" "$CONFIG_FILE"
|
|
else
|
|
sed -i "/^\[$section\]/a $key = $value" "$CONFIG_FILE"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Update database and log paths for Docker
|
|
echo ""
|
|
echo "Updating config.ini for Docker paths..."
|
|
|
|
UPDATED_COUNT=0
|
|
|
|
# Update Bot database path
|
|
update_config "Bot" "db_path" "/data/databases/meshcore_bot.db"
|
|
echo " ✓ Updated [Bot] db_path"
|
|
((UPDATED_COUNT++))
|
|
|
|
# Update Logging file path
|
|
update_config "Logging" "log_file" "/data/logs/meshcore_bot.log"
|
|
echo " ✓ Updated [Logging] log_file"
|
|
((UPDATED_COUNT++))
|
|
|
|
# Update Web_Viewer database path (if section exists)
|
|
if grep -q "^\[Web_Viewer\]" "$CONFIG_FILE"; then
|
|
update_config "Web_Viewer" "db_path" "/data/databases/bot_data.db"
|
|
echo " ✓ Updated [Web_Viewer] db_path"
|
|
((UPDATED_COUNT++))
|
|
fi
|
|
|
|
# Update PacketCapture paths (if section exists)
|
|
if grep -q "^\[PacketCapture\]" "$CONFIG_FILE"; then
|
|
# Only update output_file if it's set to a relative path
|
|
CURRENT_OUTPUT=$(grep "^output_file[[:space:]]*=" "$CONFIG_FILE" 2>/dev/null | sed 's/^output_file[[:space:]]*=[[:space:]]*//' | tr -d ' ' || echo "")
|
|
if [ -n "$CURRENT_OUTPUT" ] && [[ ! "$CURRENT_OUTPUT" == /* ]]; then
|
|
# Relative path - update to logs directory
|
|
update_config "PacketCapture" "output_file" "/data/logs/packets.jsonl"
|
|
echo " ✓ Updated [PacketCapture] output_file"
|
|
((UPDATED_COUNT++))
|
|
fi
|
|
|
|
# Update private_key_path if it's a relative path
|
|
CURRENT_KEY=$(grep "^private_key_path[[:space:]]*=" "$CONFIG_FILE" 2>/dev/null | sed 's/^private_key_path[[:space:]]*=[[:space:]]*//' | tr -d ' ' || echo "")
|
|
if [ -n "$CURRENT_KEY" ] && [[ ! "$CURRENT_KEY" == /* ]]; then
|
|
# Relative path - update to config directory (read-only is fine for keys)
|
|
update_config "PacketCapture" "private_key_path" "/data/config/private_key"
|
|
echo " ✓ Updated [PacketCapture] private_key_path"
|
|
((UPDATED_COUNT++))
|
|
fi
|
|
fi
|
|
|
|
# Update MapUploader private_key_path (if section exists)
|
|
if grep -q "^\[MapUploader\]" "$CONFIG_FILE"; then
|
|
CURRENT_KEY=$(grep "^private_key_path[[:space:]]*=" "$CONFIG_FILE" 2>/dev/null | sed 's/^private_key_path[[:space:]]*=[[:space:]]*//' | tr -d ' ' || echo "")
|
|
if [ -n "$CURRENT_KEY" ] && [[ ! "$CURRENT_KEY" == /* ]]; then
|
|
# Relative path - update to config directory
|
|
update_config "MapUploader" "private_key_path" "/data/config/private_key"
|
|
echo " ✓ Updated [MapUploader] private_key_path"
|
|
((UPDATED_COUNT++))
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "✓ Updated $UPDATED_COUNT path(s) for Docker deployment"
|
|
|
|
# Try to detect serial device
|
|
echo ""
|
|
echo "Detecting serial devices..."
|
|
|
|
SERIAL_DEVICE=""
|
|
DOCKER_DEVICE_PATH=""
|
|
|
|
if [[ "$PLATFORM" == "Linux" ]]; then
|
|
# Linux: Prefer /dev/serial/by-id/ for stable device identification
|
|
if [ -d "/dev/serial/by-id" ] && [ -n "$(ls -A /dev/serial/by-id 2>/dev/null)" ]; then
|
|
# Look for common MeshCore device patterns (case-insensitive)
|
|
# Prioritize devices that might be MeshCore-related
|
|
DEVICE=$(ls /dev/serial/by-id/* 2>/dev/null | grep -iE "(meshcore|heltec|rak|ch340|cp210|ft232)" | head -1)
|
|
# If no specific match, take the first USB serial device
|
|
if [ -z "$DEVICE" ]; then
|
|
DEVICE=$(ls /dev/serial/by-id/* 2>/dev/null | grep -i "usb" | head -1)
|
|
fi
|
|
# Last resort: any serial device
|
|
if [ -z "$DEVICE" ]; then
|
|
DEVICE=$(ls /dev/serial/by-id/* 2>/dev/null | head -1)
|
|
fi
|
|
|
|
if [ -n "$DEVICE" ] && [ -e "$DEVICE" ]; then
|
|
SERIAL_DEVICE="$DEVICE"
|
|
# For Docker, we'll map to /dev/ttyUSB0 in container
|
|
DOCKER_DEVICE_PATH="/dev/ttyUSB0"
|
|
echo "✓ Found serial device (by-id): $SERIAL_DEVICE"
|
|
fi
|
|
fi
|
|
|
|
# Fallback to /dev/ttyUSB* or /dev/ttyACM* if by-id not found
|
|
if [ -z "$SERIAL_DEVICE" ]; then
|
|
# Try ttyUSB first (more common)
|
|
for dev in /dev/ttyUSB* /dev/ttyACM*; do
|
|
if [ -e "$dev" ]; then
|
|
SERIAL_DEVICE="$dev"
|
|
DOCKER_DEVICE_PATH="/dev/ttyUSB0"
|
|
echo "✓ Found serial device: $SERIAL_DEVICE"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Update docker-compose.yml if device found (Linux only)
|
|
if [ -n "$SERIAL_DEVICE" ] && [ -f "docker-compose.yml" ]; then
|
|
echo "Updating docker-compose.yml with device mapping..."
|
|
|
|
# Check if devices section exists (commented or uncommented)
|
|
if grep -qE "^ #? devices:" docker-compose.yml; then
|
|
# Uncomment and update existing devices section
|
|
if [[ "$PLATFORM" == "Darwin" ]]; then
|
|
# Uncomment devices line
|
|
sed -i '' 's/^ # devices:/ devices:/' docker-compose.yml
|
|
# Update device path - find commented device line and replace
|
|
sed -i '' "s|^ # - /dev/.*| - $SERIAL_DEVICE:$DOCKER_DEVICE_PATH|" docker-compose.yml
|
|
# Also handle if already uncommented
|
|
sed -i '' "s|^ - /dev/.*| - $SERIAL_DEVICE:$DOCKER_DEVICE_PATH|" docker-compose.yml
|
|
else
|
|
# Uncomment devices line
|
|
sed -i 's/^ # devices:/ devices:/' docker-compose.yml
|
|
# Update device path - find commented device line and replace
|
|
sed -i "s|^ # - /dev/.*| - $SERIAL_DEVICE:$DOCKER_DEVICE_PATH|" docker-compose.yml
|
|
# Also handle if already uncommented
|
|
sed -i "s|^ - /dev/.*| - $SERIAL_DEVICE:$DOCKER_DEVICE_PATH|" docker-compose.yml
|
|
fi
|
|
else
|
|
# Add devices section after restart line
|
|
if [[ "$PLATFORM" == "Darwin" ]]; then
|
|
sed -i '' "/^ restart: unless-stopped/a\\
|
|
\\
|
|
# Device access for serial ports (Linux)\\
|
|
devices:\\
|
|
- $SERIAL_DEVICE:$DOCKER_DEVICE_PATH
|
|
" docker-compose.yml
|
|
else
|
|
sed -i "/^ restart: unless-stopped/a\\
|
|
\\
|
|
# Device access for serial ports (Linux)\\
|
|
devices:\\
|
|
- $SERIAL_DEVICE:$DOCKER_DEVICE_PATH
|
|
" docker-compose.yml
|
|
fi
|
|
fi
|
|
echo "✓ Updated docker-compose.yml with device: $SERIAL_DEVICE -> $DOCKER_DEVICE_PATH"
|
|
fi
|
|
|
|
elif [[ "$PLATFORM" == "Darwin" ]]; then
|
|
# macOS: Use /dev/cu.* devices
|
|
DEVICE=$(ls /dev/cu.usbmodem* /dev/cu.usbserial* 2>/dev/null | head -1)
|
|
if [ -n "$DEVICE" ]; then
|
|
SERIAL_DEVICE="$DEVICE"
|
|
echo "✓ Found serial device: $SERIAL_DEVICE"
|
|
echo " Note: Docker Desktop on macOS doesn't support device passthrough."
|
|
echo " Consider using TCP connection or running natively on macOS."
|
|
fi
|
|
fi
|
|
|
|
# Update config.ini with serial device if found
|
|
if [ -n "$SERIAL_DEVICE" ]; then
|
|
if [[ "$PLATFORM" == "Linux" ]] && [[ "$SERIAL_DEVICE" == /dev/serial/by-id/* ]]; then
|
|
# On Linux with by-id path, resolve to actual device for Docker compatibility
|
|
# Docker containers may not resolve symlinks correctly, so use the actual device
|
|
ACTUAL_DEVICE=$(readlink -f "$SERIAL_DEVICE" 2>/dev/null || echo "")
|
|
if [ -n "$ACTUAL_DEVICE" ] && [ -e "$ACTUAL_DEVICE" ]; then
|
|
# Use actual device path for better Docker compatibility
|
|
update_config "Connection" "serial_port" "$ACTUAL_DEVICE"
|
|
echo "✓ Updated config.ini with serial port: $ACTUAL_DEVICE"
|
|
echo " (resolved from $SERIAL_DEVICE)"
|
|
else
|
|
# Fallback to by-id path if resolution fails
|
|
update_config "Connection" "serial_port" "$SERIAL_DEVICE"
|
|
echo "✓ Updated config.ini with serial port: $SERIAL_DEVICE"
|
|
echo " ⚠️ Note: If Docker can't access this symlink, use the actual device path"
|
|
fi
|
|
elif [[ "$PLATFORM" == "Linux" ]]; then
|
|
# On Linux, use the device path directly
|
|
update_config "Connection" "serial_port" "$SERIAL_DEVICE"
|
|
echo "✓ Updated config.ini with serial port: $SERIAL_DEVICE"
|
|
else
|
|
# macOS: just note it, but user needs to handle differently
|
|
update_config "Connection" "serial_port" "$SERIAL_DEVICE"
|
|
echo "✓ Updated config.ini with serial port: $SERIAL_DEVICE"
|
|
echo " ⚠️ Remember: Docker Desktop on macOS can't access serial devices directly."
|
|
fi
|
|
else
|
|
echo "⚠️ No serial device detected. You may need to:"
|
|
echo " - Connect your MeshCore device"
|
|
echo " - Manually set serial_port in config.ini"
|
|
echo " - Or use TCP/BLE connection instead"
|
|
fi
|
|
|
|
# Detect git branch and set Docker image tag
|
|
echo ""
|
|
echo "Detecting git branch for Docker image tag..."
|
|
|
|
# Try to get current branch name
|
|
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
|
|
DOCKER_IMAGE_TAG="latest"
|
|
DOCKER_IMAGE_REGISTRY="ghcr.io/agessaman/meshcore-bot"
|
|
|
|
if [ -n "$GIT_BRANCH" ]; then
|
|
# Map branch names to image tags
|
|
case "$GIT_BRANCH" in
|
|
main|master)
|
|
DOCKER_IMAGE_TAG="latest"
|
|
;;
|
|
*)
|
|
# Use branch name as tag (e.g., dev -> dev, feature/xyz -> feature-xyz)
|
|
DOCKER_IMAGE_TAG=$(echo "$GIT_BRANCH" | sed 's/[\/_]/-/g')
|
|
;;
|
|
esac
|
|
echo " ✓ Detected branch: $GIT_BRANCH -> image tag: $DOCKER_IMAGE_TAG"
|
|
else
|
|
echo " ⚠️ Not a git repository or branch detection failed, using 'latest'"
|
|
fi
|
|
|
|
# Create or update .env file for docker-compose
|
|
# Ensure this always runs, even if there were non-critical errors earlier
|
|
ENV_FILE=".env"
|
|
|
|
# Temporarily disable exit on error for .env creation
|
|
set +e
|
|
|
|
# Check if .env file exists and has the tag variable
|
|
if [ ! -f "$ENV_FILE" ]; then
|
|
# Create new .env file
|
|
cat > "$ENV_FILE" << EOF
|
|
# Docker image configuration (auto-generated by docker-setup.sh)
|
|
DOCKER_IMAGE_REGISTRY=$DOCKER_IMAGE_REGISTRY
|
|
DOCKER_IMAGE_TAG=$DOCKER_IMAGE_TAG
|
|
EOF
|
|
if [ $? -eq 0 ]; then
|
|
echo " ✓ Created .env file with image tag: $DOCKER_IMAGE_TAG"
|
|
else
|
|
echo " ⚠️ Warning: Failed to create .env file"
|
|
fi
|
|
elif ! grep -q "^DOCKER_IMAGE_TAG=" "$ENV_FILE" 2>/dev/null; then
|
|
# .env exists but doesn't have the tag - append it
|
|
{
|
|
echo ""
|
|
echo "# Docker image configuration (auto-generated by docker-setup.sh)"
|
|
echo "DOCKER_IMAGE_REGISTRY=$DOCKER_IMAGE_REGISTRY"
|
|
echo "DOCKER_IMAGE_TAG=$DOCKER_IMAGE_TAG"
|
|
} >> "$ENV_FILE"
|
|
if [ $? -eq 0 ]; then
|
|
echo " ✓ Added Docker image configuration to .env file with tag: $DOCKER_IMAGE_TAG"
|
|
else
|
|
echo " ⚠️ Warning: Failed to append to .env file"
|
|
fi
|
|
else
|
|
# Update existing .env file
|
|
if [[ "$PLATFORM" == "Darwin" ]]; then
|
|
sed -i '' "s|^DOCKER_IMAGE_TAG=.*|DOCKER_IMAGE_TAG=$DOCKER_IMAGE_TAG|" "$ENV_FILE" 2>/dev/null
|
|
sed -i '' "s|^DOCKER_IMAGE_REGISTRY=.*|DOCKER_IMAGE_REGISTRY=$DOCKER_IMAGE_REGISTRY|" "$ENV_FILE" 2>/dev/null
|
|
else
|
|
sed -i "s|^DOCKER_IMAGE_TAG=.*|DOCKER_IMAGE_TAG=$DOCKER_IMAGE_TAG|" "$ENV_FILE" 2>/dev/null
|
|
sed -i "s|^DOCKER_IMAGE_REGISTRY=.*|DOCKER_IMAGE_REGISTRY=$DOCKER_IMAGE_REGISTRY|" "$ENV_FILE" 2>/dev/null
|
|
fi
|
|
if [ $? -eq 0 ]; then
|
|
echo " ✓ Updated .env file with image tag: $DOCKER_IMAGE_TAG"
|
|
else
|
|
echo " ⚠️ Warning: Failed to update .env file"
|
|
fi
|
|
fi
|
|
|
|
# Re-enable exit on error
|
|
set -e
|
|
|
|
# Verify .env file was created/updated
|
|
if [ -f "$ENV_FILE" ] && grep -q "^DOCKER_IMAGE_TAG=" "$ENV_FILE" 2>/dev/null; then
|
|
ACTUAL_TAG=$(grep "^DOCKER_IMAGE_TAG=" "$ENV_FILE" | cut -d'=' -f2 | tr -d ' ')
|
|
echo " ✓ Verified .env file contains DOCKER_IMAGE_TAG=$ACTUAL_TAG"
|
|
else
|
|
echo " ⚠️ Warning: .env file may not have been created correctly"
|
|
echo " Creating .env file manually..."
|
|
cat > "$ENV_FILE" << EOF
|
|
# Docker image configuration (auto-generated by docker-setup.sh)
|
|
DOCKER_IMAGE_REGISTRY=$DOCKER_IMAGE_REGISTRY
|
|
DOCKER_IMAGE_TAG=$DOCKER_IMAGE_TAG
|
|
EOF
|
|
if [ -f "$ENV_FILE" ]; then
|
|
echo " ✓ Manually created .env file with tag: $DOCKER_IMAGE_TAG"
|
|
else
|
|
echo " ✗ Error: Could not create .env file. Please create it manually:"
|
|
echo " echo 'DOCKER_IMAGE_REGISTRY=$DOCKER_IMAGE_REGISTRY' > .env"
|
|
echo " echo 'DOCKER_IMAGE_TAG=$DOCKER_IMAGE_TAG' >> .env"
|
|
fi
|
|
fi
|
|
|
|
# Set permissions (container runs as UID 1000)
|
|
echo ""
|
|
echo "Setting permissions..."
|
|
chmod -R 755 data/
|
|
chown -R 1000:1000 data/ 2>/dev/null || echo "Note: Could not set ownership (may need sudo)"
|
|
|
|
echo ""
|
|
echo "✓ Setup complete!"
|
|
echo ""
|
|
echo "Next steps:"
|
|
if [ -z "$SERIAL_DEVICE" ]; then
|
|
echo "1. Connect your MeshCore device or configure TCP/BLE connection"
|
|
fi
|
|
echo "1. Review data/config/config.ini and adjust settings if needed"
|
|
echo "2. Build the Docker image (to avoid pull warnings):"
|
|
echo " docker compose build"
|
|
echo ""
|
|
echo "3. Start the container:"
|
|
echo " docker compose up -d"
|
|
echo ""
|
|
echo " Or build and start in one command:"
|
|
echo " docker compose up -d --build"
|
|
echo ""
|
|
echo "4. View logs:"
|
|
echo " docker compose logs -f"
|