mirror of
https://github.com/jorijn/meshcore-stats.git
synced 2026-03-28 17:42:55 +01:00
fix: improve Docker configuration and documentation
- Change Python path defaults to Docker paths (/data/state, /out) - Remove STATE_DIR/OUT_DIR from Dockerfile ENV (Python defaults now correct) - Remove REPEATER_FETCH_ACL feature (unsupported) - Fix nginx tmpfs permissions with uid=101,gid=101 - Remove Ofelia [global] save=true (caused config parse error) - Switch to bind mounts for ./out instead of named volume - Comment out devices section (not available on macOS Docker) - Add TCP and BLE transport options to meshcore.conf.example - Document correct macOS socat command for serial-over-TCP - Update README with macOS Docker workaround instructions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -90,14 +90,11 @@ COPY --chown=meshmon:meshmon docker/ofelia.ini /app/ofelia.ini
|
|||||||
# - PYTHONUNBUFFERED: Ensure logs are output immediately
|
# - PYTHONUNBUFFERED: Ensure logs are output immediately
|
||||||
# - PYTHONDONTWRITEBYTECODE: Don't create .pyc files
|
# - PYTHONDONTWRITEBYTECODE: Don't create .pyc files
|
||||||
# - MPLCONFIGDIR: Matplotlib font cache directory
|
# - MPLCONFIGDIR: Matplotlib font cache directory
|
||||||
# - STATE_DIR/OUT_DIR: Default paths for Docker volumes
|
|
||||||
ENV PATH="/opt/venv/bin:$PATH" \
|
ENV PATH="/opt/venv/bin:$PATH" \
|
||||||
PYTHONPATH=/app/src \
|
PYTHONPATH=/app/src \
|
||||||
PYTHONUNBUFFERED=1 \
|
PYTHONUNBUFFERED=1 \
|
||||||
PYTHONDONTWRITEBYTECODE=1 \
|
PYTHONDONTWRITEBYTECODE=1 \
|
||||||
MPLCONFIGDIR=/tmp/matplotlib \
|
MPLCONFIGDIR=/tmp/matplotlib
|
||||||
STATE_DIR=/data/state \
|
|
||||||
OUT_DIR=/out
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
39
README.md
39
README.md
@@ -127,8 +127,10 @@ cd meshcore-stats
|
|||||||
cp meshcore.conf.example meshcore.conf
|
cp meshcore.conf.example meshcore.conf
|
||||||
# Edit meshcore.conf with your settings
|
# Edit meshcore.conf with your settings
|
||||||
|
|
||||||
# Create data directory
|
# Create data directories with correct ownership for container (UID 1000)
|
||||||
mkdir -p data/state
|
mkdir -p data/state out
|
||||||
|
sudo chown -R 1000:1000 data out
|
||||||
|
# Alternative: chmod -R 777 data out (less secure, use chown if possible)
|
||||||
|
|
||||||
# Start the containers
|
# Start the containers
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
@@ -216,7 +218,9 @@ image: ghcr.io/jorijn/meshcore-stats@sha256:abc123...
|
|||||||
| Path | Purpose |
|
| Path | Purpose |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| `./data/state` | SQLite database and circuit breaker state |
|
| `./data/state` | SQLite database and circuit breaker state |
|
||||||
| `output_data` | Generated static site (shared with nginx) |
|
| `./out` | Generated static site (served by nginx) |
|
||||||
|
|
||||||
|
Both directories must be writable by UID 1000 (the container user). See Quick Start for setup.
|
||||||
|
|
||||||
#### Resource Limits
|
#### Resource Limits
|
||||||
|
|
||||||
@@ -358,6 +362,34 @@ If repeater collection shows "cooldown active":
|
|||||||
rm data/state/repeater_circuit.json
|
rm data/state/repeater_circuit.json
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Docker on macOS: Serial Devices Not Available
|
||||||
|
|
||||||
|
Docker on macOS (including Docker Desktop and OrbStack) runs containers inside a Linux virtual machine. USB and serial devices connected to the Mac host cannot be passed through to this VM, so the `devices:` section in docker-compose.yml will fail with:
|
||||||
|
|
||||||
|
```
|
||||||
|
error gathering device information while adding custom device "/dev/cu.usbserial-0001": no such file or directory
|
||||||
|
```
|
||||||
|
|
||||||
|
**Workarounds:**
|
||||||
|
|
||||||
|
1. **Use TCP transport**: Run a serial-to-TCP bridge on the host and configure the container to connect via TCP:
|
||||||
|
```bash
|
||||||
|
# On macOS host, expose serial port over TCP (install socat via Homebrew)
|
||||||
|
socat TCP-LISTEN:5000,fork,reuseaddr OPEN:/dev/cu.usbserial-0001,rawer,nonblock,ispeed=115200,ospeed=115200
|
||||||
|
```
|
||||||
|
Then configure in meshcore.conf:
|
||||||
|
```bash
|
||||||
|
MESH_TRANSPORT=tcp
|
||||||
|
MESH_TCP_HOST=host.docker.internal
|
||||||
|
MESH_TCP_PORT=5000
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Run natively on macOS**: Use the cron-based setup instead of Docker (see "Cron Setup" section).
|
||||||
|
|
||||||
|
3. **Use a Linux host**: Docker on Linux can pass through USB devices directly.
|
||||||
|
|
||||||
|
Note: OrbStack has [USB passthrough on their roadmap](https://github.com/orbstack/orbstack/issues/89) but it is not yet available.
|
||||||
|
|
||||||
## Environment Variables Reference
|
## Environment Variables Reference
|
||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
@@ -375,7 +407,6 @@ If repeater collection shows "cooldown active":
|
|||||||
| `REPEATER_NAME` | - | Repeater advertised name |
|
| `REPEATER_NAME` | - | Repeater advertised name |
|
||||||
| `REPEATER_KEY_PREFIX` | - | Repeater public key prefix |
|
| `REPEATER_KEY_PREFIX` | - | Repeater public key prefix |
|
||||||
| `REPEATER_PASSWORD` | - | Repeater login password |
|
| `REPEATER_PASSWORD` | - | Repeater login password |
|
||||||
| `REPEATER_FETCH_ACL` | 0 | Also fetch ACL from repeater |
|
|
||||||
| **Display Names** | | |
|
| **Display Names** | | |
|
||||||
| `REPEATER_DISPLAY_NAME` | Repeater Node | Display name for repeater in UI |
|
| `REPEATER_DISPLAY_NAME` | Repeater Node | Display name for repeater in UI |
|
||||||
| `COMPANION_DISPLAY_NAME` | Companion Node | Display name for companion in UI |
|
| `COMPANION_DISPLAY_NAME` | Companion Node | Display name for companion in UI |
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ services:
|
|||||||
# Changes to Python files take effect immediately (no rebuild needed)
|
# Changes to Python files take effect immediately (no rebuild needed)
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/state:/data/state
|
- ./data/state:/data/state
|
||||||
- output_data:/out
|
- ./out:/out
|
||||||
# Development mounts (read-only to prevent accidental writes)
|
# Development mounts (read-only to prevent accidental writes)
|
||||||
- ./src:/app/src:ro
|
- ./src:/app/src:ro
|
||||||
- ./scripts:/app/scripts:ro
|
- ./scripts:/app/scripts:ro
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
# Prerequisites:
|
# Prerequisites:
|
||||||
# 1. Copy meshcore.conf.example to meshcore.conf and configure
|
# 1. Copy meshcore.conf.example to meshcore.conf and configure
|
||||||
# 2. Ensure your user has access to the serial device (dialout group)
|
# 2. Ensure your user has access to the serial device (dialout group)
|
||||||
# 3. Create data directory: mkdir -p ./data/state
|
# 3. Create data directories with correct ownership:
|
||||||
|
# mkdir -p ./data/state ./out && sudo chown -R 1000:1000 ./data ./out
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
@@ -29,8 +30,8 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
# Persistent storage for SQLite database and circuit breaker state
|
# Persistent storage for SQLite database and circuit breaker state
|
||||||
- ./data/state:/data/state
|
- ./data/state:/data/state
|
||||||
# Shared volume for generated static site (used by nginx)
|
# Generated static site (served by nginx)
|
||||||
- output_data:/out
|
- ./out:/out
|
||||||
|
|
||||||
# Run as meshmon user (UID 1000)
|
# Run as meshmon user (UID 1000)
|
||||||
user: "1000:1000"
|
user: "1000:1000"
|
||||||
@@ -89,7 +90,7 @@ services:
|
|||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
# Mount generated static site from meshcore-stats container
|
# Mount generated static site from meshcore-stats container
|
||||||
- output_data:/usr/share/nginx/html:ro
|
- ./out:/usr/share/nginx/html:ro
|
||||||
# Custom nginx configuration
|
# Custom nginx configuration
|
||||||
- ./docker/nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
- ./docker/nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
|
|
||||||
@@ -101,8 +102,8 @@ services:
|
|||||||
# NET_BIND_SERVICE not needed for port 8080 (unprivileged)
|
# NET_BIND_SERVICE not needed for port 8080 (unprivileged)
|
||||||
read_only: true
|
read_only: true
|
||||||
tmpfs:
|
tmpfs:
|
||||||
- /var/cache/nginx:noexec,nosuid,size=16m
|
- /var/cache/nginx:noexec,nosuid,size=16m,uid=101,gid=101
|
||||||
- /var/run:noexec,nosuid,size=1m
|
- /var/run:noexec,nosuid,size=1m,uid=101,gid=101
|
||||||
|
|
||||||
# Resource limits
|
# Resource limits
|
||||||
deploy:
|
deploy:
|
||||||
@@ -132,7 +133,3 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
meshcore-stats:
|
meshcore-stats:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
# Named volume for sharing generated site between containers
|
|
||||||
volumes:
|
|
||||||
output_data:
|
|
||||||
|
|||||||
@@ -4,10 +4,6 @@
|
|||||||
# This file defines the cron-like schedule for all MeshCore Stats tasks.
|
# This file defines the cron-like schedule for all MeshCore Stats tasks.
|
||||||
# Jobs run inside the same container (job-local).
|
# Jobs run inside the same container (job-local).
|
||||||
|
|
||||||
[global]
|
|
||||||
# Save last run state for job status
|
|
||||||
save = true
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Data Collection Jobs
|
# Data Collection Jobs
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|||||||
@@ -2,55 +2,66 @@
|
|||||||
# Copy this file to meshcore.conf and customize for your setup:
|
# Copy this file to meshcore.conf and customize for your setup:
|
||||||
# cp meshcore.conf.example meshcore.conf
|
# cp meshcore.conf.example meshcore.conf
|
||||||
#
|
#
|
||||||
# This file is automatically loaded by the scripts. No need to source it manually.
|
# Format: KEY=value (no 'export' keyword, no spaces around '=')
|
||||||
# Environment variables always take precedence over this file (useful for Docker).
|
# This format is compatible with both Docker env_file and shell 'source' command.
|
||||||
|
# Comments start with # and blank lines are ignored.
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Connection Settings
|
# Connection Settings
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
export MESH_TRANSPORT=serial
|
MESH_TRANSPORT=serial
|
||||||
export MESH_SERIAL_PORT=/dev/ttyUSB0 # Adjust for your system (e.g., /dev/ttyACM0, /dev/cu.usbserial-*)
|
MESH_SERIAL_PORT=/dev/ttyUSB0
|
||||||
export MESH_SERIAL_BAUD=115200
|
# MESH_SERIAL_BAUD=115200
|
||||||
export MESH_DEBUG=0 # Set to 1 for verbose meshcore debug output
|
# MESH_DEBUG=0
|
||||||
|
|
||||||
|
# TCP transport (for macOS Docker or remote serial servers)
|
||||||
|
# MESH_TRANSPORT=tcp
|
||||||
|
# MESH_TCP_HOST=host.docker.internal
|
||||||
|
# MESH_TCP_PORT=5000
|
||||||
|
|
||||||
|
# BLE transport (Bluetooth Low Energy)
|
||||||
|
# MESH_TRANSPORT=ble
|
||||||
|
# MESH_BLE_ADDR=AA:BB:CC:DD:EE:FF
|
||||||
|
# MESH_BLE_PIN=123456
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Remote Repeater Identity
|
# Remote Repeater Identity
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# At least REPEATER_NAME or REPEATER_KEY_PREFIX is required to identify your repeater
|
# At least REPEATER_NAME or REPEATER_KEY_PREFIX is required to identify your repeater
|
||||||
|
|
||||||
export REPEATER_NAME="Your Repeater Name" # Advertised name shown in contacts
|
REPEATER_NAME=Your Repeater Name
|
||||||
# export REPEATER_KEY_PREFIX="a1b2c3" # Alternative: hex prefix of public key
|
# REPEATER_KEY_PREFIX=a1b2c3
|
||||||
export REPEATER_PASSWORD="your-password" # Admin password for repeater login
|
REPEATER_PASSWORD=your-password
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Display Names (shown in UI)
|
# Display Names (shown in UI)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
export REPEATER_DISPLAY_NAME="My Repeater"
|
REPEATER_DISPLAY_NAME=My Repeater
|
||||||
export COMPANION_DISPLAY_NAME="My Companion"
|
COMPANION_DISPLAY_NAME=My Companion
|
||||||
|
|
||||||
# Public key prefixes (shown below node name in sidebar, e.g., "!a1b2c3d4")
|
# Public key prefixes (shown below node name in sidebar, e.g., "!a1b2c3d4")
|
||||||
# export REPEATER_PUBKEY_PREFIX="!a1b2c3d4"
|
# REPEATER_PUBKEY_PREFIX=!a1b2c3d4
|
||||||
# export COMPANION_PUBKEY_PREFIX="!e5f6g7h8"
|
# COMPANION_PUBKEY_PREFIX=!e5f6g7h8
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Location Metadata (for reports and sidebar display)
|
# Location Metadata (for reports and sidebar display)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
export REPORT_LOCATION_NAME="City, Country" # Full location name for reports
|
REPORT_LOCATION_NAME=City, Country
|
||||||
export REPORT_LOCATION_SHORT="City, XX" # Short version for sidebar/meta
|
REPORT_LOCATION_SHORT=City, XX
|
||||||
export REPORT_LAT=0.0 # Latitude in decimal degrees
|
REPORT_LAT=0.0
|
||||||
export REPORT_LON=0.0 # Longitude in decimal degrees
|
REPORT_LON=0.0
|
||||||
export REPORT_ELEV=0 # Elevation
|
REPORT_ELEV=0
|
||||||
export REPORT_ELEV_UNIT=m # "m" for meters, "ft" for feet
|
REPORT_ELEV_UNIT=m
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Hardware Info (shown in sidebar)
|
# Hardware Info (shown in sidebar)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
export REPEATER_HARDWARE="Your Repeater Model" # e.g., "SenseCAP P1-Pro", "LILYGO T-Beam"
|
REPEATER_HARDWARE=Your Repeater Model
|
||||||
export COMPANION_HARDWARE="Your Companion Model" # e.g., "Elecrow ThinkNode-M1", "Heltec V3"
|
COMPANION_HARDWARE=Your Companion Model
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Radio Configuration Presets
|
# Radio Configuration Presets
|
||||||
@@ -59,58 +70,54 @@ export COMPANION_HARDWARE="Your Companion Model" # e.g., "Elecrow ThinkNode-M1",
|
|||||||
# or set custom values. These are for display purposes only.
|
# or set custom values. These are for display purposes only.
|
||||||
|
|
||||||
# MeshCore EU/UK Narrow (default)
|
# MeshCore EU/UK Narrow (default)
|
||||||
export RADIO_FREQUENCY="869.618 MHz"
|
RADIO_FREQUENCY=869.618 MHz
|
||||||
export RADIO_BANDWIDTH="62.5 kHz"
|
RADIO_BANDWIDTH=62.5 kHz
|
||||||
export RADIO_SPREAD_FACTOR="SF8"
|
RADIO_SPREAD_FACTOR=SF8
|
||||||
export RADIO_CODING_RATE="CR8"
|
RADIO_CODING_RATE=CR8
|
||||||
|
|
||||||
# # MeshCore EU/UK Wide
|
# MeshCore EU/UK Wide
|
||||||
# export RADIO_FREQUENCY="869.525 MHz"
|
# RADIO_FREQUENCY=869.525 MHz
|
||||||
# export RADIO_BANDWIDTH="250 kHz"
|
# RADIO_BANDWIDTH=250 kHz
|
||||||
# export RADIO_SPREAD_FACTOR="SF10"
|
# RADIO_SPREAD_FACTOR=SF10
|
||||||
# export RADIO_CODING_RATE="CR5"
|
# RADIO_CODING_RATE=CR5
|
||||||
|
|
||||||
# # MeshCore US Standard
|
# MeshCore US Standard
|
||||||
# export RADIO_FREQUENCY="906.875 MHz"
|
# RADIO_FREQUENCY=906.875 MHz
|
||||||
# export RADIO_BANDWIDTH="250 kHz"
|
# RADIO_BANDWIDTH=250 kHz
|
||||||
# export RADIO_SPREAD_FACTOR="SF10"
|
# RADIO_SPREAD_FACTOR=SF10
|
||||||
# export RADIO_CODING_RATE="CR5"
|
# RADIO_CODING_RATE=CR5
|
||||||
|
|
||||||
# # MeshCore US Fast
|
# MeshCore US Fast
|
||||||
# export RADIO_FREQUENCY="906.875 MHz"
|
# RADIO_FREQUENCY=906.875 MHz
|
||||||
# export RADIO_BANDWIDTH="500 kHz"
|
# RADIO_BANDWIDTH=500 kHz
|
||||||
# export RADIO_SPREAD_FACTOR="SF7"
|
# RADIO_SPREAD_FACTOR=SF7
|
||||||
# export RADIO_CODING_RATE="CR5"
|
# RADIO_CODING_RATE=CR5
|
||||||
|
|
||||||
# # MeshCore ANZ (Australia/New Zealand)
|
# MeshCore ANZ (Australia/New Zealand)
|
||||||
# export RADIO_FREQUENCY="917.0 MHz"
|
# RADIO_FREQUENCY=917.0 MHz
|
||||||
# export RADIO_BANDWIDTH="250 kHz"
|
# RADIO_BANDWIDTH=250 kHz
|
||||||
# export RADIO_SPREAD_FACTOR="SF10"
|
# RADIO_SPREAD_FACTOR=SF10
|
||||||
# export RADIO_CODING_RATE="CR5"
|
# RADIO_CODING_RATE=CR5
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Intervals and Timeouts
|
# Intervals and Timeouts
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
export COMPANION_STEP=60 # Collection interval for companion (seconds)
|
# COMPANION_STEP=60
|
||||||
export REPEATER_STEP=900 # Collection interval for repeater (seconds, 15min default)
|
# REPEATER_STEP=900
|
||||||
export REMOTE_TIMEOUT_S=10 # Minimum timeout for LoRa requests
|
# REMOTE_TIMEOUT_S=10
|
||||||
export REMOTE_RETRY_ATTEMPTS=2 # Number of retry attempts
|
# REMOTE_RETRY_ATTEMPTS=2
|
||||||
export REMOTE_RETRY_BACKOFF_S=4 # Seconds between retries
|
# REMOTE_RETRY_BACKOFF_S=4
|
||||||
|
|
||||||
# Circuit breaker settings (prevents spamming LoRa when repeater is unreachable)
|
# Circuit breaker settings (prevents spamming LoRa when repeater is unreachable)
|
||||||
export REMOTE_CB_FAILS=6 # Failures before circuit breaker opens
|
# REMOTE_CB_FAILS=6
|
||||||
export REMOTE_CB_COOLDOWN_S=3600 # Cooldown period in seconds (1 hour)
|
# REMOTE_CB_COOLDOWN_S=3600
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Paths
|
# Paths (Native installation only)
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
# Docker: Leave these commented. The container uses /data/state and /out by default.
|
||||||
|
# Native: Uncomment for local cron-based installation:
|
||||||
|
# STATE_DIR=./data/state
|
||||||
|
# OUT_DIR=./out
|
||||||
|
|
||||||
export STATE_DIR=./data/state # SQLite database and circuit breaker state
|
|
||||||
export OUT_DIR=./out # Generated static site output
|
|
||||||
|
|
||||||
# =============================================================================
|
|
||||||
# Optional
|
|
||||||
# =============================================================================
|
|
||||||
|
|
||||||
export REPEATER_FETCH_ACL=0 # Set to 1 to fetch ACL from repeater
|
|
||||||
|
|||||||
@@ -233,20 +233,6 @@ async def collect_repeater() -> int:
|
|||||||
else:
|
else:
|
||||||
log.warn(f"req_status_sync failed: {err}")
|
log.warn(f"req_status_sync failed: {err}")
|
||||||
|
|
||||||
# Optional ACL query (using _sync version)
|
|
||||||
if cfg.repeater_fetch_acl:
|
|
||||||
log.debug("Querying repeater ACL...")
|
|
||||||
success, payload, err = await query_repeater_with_retry(
|
|
||||||
mc,
|
|
||||||
contact,
|
|
||||||
"req_acl_sync",
|
|
||||||
lambda: cmd.req_acl_sync(contact, timeout=0, min_timeout=cfg.remote_timeout_s),
|
|
||||||
)
|
|
||||||
if success:
|
|
||||||
log.debug(f"req_acl_sync: {payload}")
|
|
||||||
else:
|
|
||||||
log.debug(f"req_acl_sync failed: {err}")
|
|
||||||
|
|
||||||
# Update circuit breaker
|
# Update circuit breaker
|
||||||
if status_ok:
|
if status_ok:
|
||||||
cb.record_success()
|
cb.record_success()
|
||||||
|
|||||||
@@ -145,7 +145,6 @@ class Config:
|
|||||||
self.repeater_name = get_str("REPEATER_NAME")
|
self.repeater_name = get_str("REPEATER_NAME")
|
||||||
self.repeater_key_prefix = get_str("REPEATER_KEY_PREFIX")
|
self.repeater_key_prefix = get_str("REPEATER_KEY_PREFIX")
|
||||||
self.repeater_password = get_str("REPEATER_PASSWORD")
|
self.repeater_password = get_str("REPEATER_PASSWORD")
|
||||||
self.repeater_fetch_acl = get_bool("REPEATER_FETCH_ACL", False)
|
|
||||||
|
|
||||||
# Intervals and timeouts
|
# Intervals and timeouts
|
||||||
self.companion_step = get_int("COMPANION_STEP", 60)
|
self.companion_step = get_int("COMPANION_STEP", 60)
|
||||||
@@ -156,9 +155,9 @@ class Config:
|
|||||||
self.remote_cb_fails = get_int("REMOTE_CB_FAILS", 6)
|
self.remote_cb_fails = get_int("REMOTE_CB_FAILS", 6)
|
||||||
self.remote_cb_cooldown_s = get_int("REMOTE_CB_COOLDOWN_S", 3600)
|
self.remote_cb_cooldown_s = get_int("REMOTE_CB_COOLDOWN_S", 3600)
|
||||||
|
|
||||||
# Paths
|
# Paths (defaults are Docker container paths; native installs override via config)
|
||||||
self.state_dir = get_path("STATE_DIR", "./data/state")
|
self.state_dir = get_path("STATE_DIR", "/data/state")
|
||||||
self.out_dir = get_path("OUT_DIR", "./out")
|
self.out_dir = get_path("OUT_DIR", "/out")
|
||||||
|
|
||||||
# Report location metadata
|
# Report location metadata
|
||||||
self.report_location_name = get_str(
|
self.report_location_name = get_str(
|
||||||
|
|||||||
Reference in New Issue
Block a user