diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..07f6a2d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,36 @@ +# Python +__pycache__/ +*.py[cod] +.venv/ +*.egg-info/ +.pytest_cache/ + +# Node +frontend/node_modules/ +frontend/dist/ + +# Data +data/ +*.db + +# Git +.git/ +.gitignore + +# IDE +.idea/ +.vscode/ +*.swp + +# Tests +tests/ +frontend/src/test/ + +# Docs +*.md +!README.md + +# Other +references/ +*.pem +.env* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5ab2f49 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,39 @@ +# Stage 1: Build frontend +FROM node:20-slim AS frontend-builder + +WORKDIR /build + +COPY frontend/package*.json ./ +RUN npm ci + +COPY frontend/ ./ +RUN npm run build + + +# Stage 2: Python runtime +FROM python:3.12-slim + +WORKDIR /app + +# Install uv +COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv + +# Copy dependency files first for layer caching +COPY pyproject.toml uv.lock ./ + +# Install dependencies (no dev/test deps) +RUN uv sync --frozen --no-dev + +# Copy application code +COPY app/ ./app/ + +# Copy built frontend from first stage +COPY --from=frontend-builder /build/dist ./frontend/dist + +# Create data directory for SQLite database +RUN mkdir -p /app/data + +EXPOSE 8000 + +# Run the application +CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/README.md b/README.md index 8214d42..eae822a 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ For real, this code is bad and totally LLM generated. If you insist on extending - UV (Python package manager): `curl -LsSf https://astral.sh/uv/install.sh | sh` - MeshCore-compatible radio connected via USB serial +*Prefer Docker? See the [Docker section](#docker) below.* + ## Quick Start ### Backend @@ -187,6 +189,58 @@ npm test ``` +
+Docker + +Build and run with Docker, passing through your serial device: + +```bash +# Build the image +docker build -t remoteterm-meshcore . + +# Run with serial passthrough (replace /dev/ttyUSB0 with your device) +docker run -d \ + --name remoteterm \ + --device=/dev/ttyUSB0 \ + -e MESHCORE_SERIAL_PORT=/dev/ttyUSB0 \ + -v remoteterm-data:/app/data \ + -p 8000:8000 \ + remoteterm-meshcore + +# View logs +docker logs -f remoteterm +``` + +**Finding your serial device:** + +```bash +# Linux +ls /dev/ttyUSB* /dev/ttyACM* + +# macOS +ls /dev/cu.usbserial-* /dev/cu.usbmodem* +``` + +**Persistent data:** The `-v remoteterm-data:/app/data` flag creates a named volume for the SQLite database, so your messages and contacts persist across container restarts. + +**HTTPS with Docker:** For WebGPU cracking support over non-localhost connections: + +```bash +openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost' + +docker run -d \ + --name remoteterm \ + --device=/dev/ttyUSB0 \ + -e MESHCORE_SERIAL_PORT=/dev/ttyUSB0 \ + -v remoteterm-data:/app/data \ + -v $(pwd)/cert.pem:/app/cert.pem:ro \ + -v $(pwd)/key.pem:/app/key.pem:ro \ + -p 8000:8000 \ + remoteterm-meshcore \ + uv run uvicorn app.main:app --host 0.0.0.0 --port 8000 --ssl-keyfile=/app/key.pem --ssl-certfile=/app/cert.pem +``` +
+ ## API Docs With the backend running, visit http://localhost:8000/docs for interactive API documentation.