diff --git a/README.md b/README.md index c05dc49..b7904b4 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ Support the developer of this open-source project - **Vessel Tracking** - AIS ship tracking with VHF DSC distress monitoring - **ACARS Messaging** - Aircraft datalink messages via acarsdec - **Listening Post** - Frequency scanner with audio monitoring +- **Weather Satellites** - NOAA APT and Meteor LRPT image decoding via SatDump +- **ISS SSTV** - Slow-scan TV image reception from the International Space Station - **Satellite Tracking** - Pass prediction using TLE data - **ADS-B History** - Persistent aircraft history with reporting dashboard (Postgres optional) - **WiFi Scanning** - Monitor mode reconnaissance via aircrack-ng @@ -55,67 +57,106 @@ cd intercept sudo -E venv/bin/python intercept.py ``` -### Docker (Alternative) +### Docker ```bash git clone https://github.com/smittix/intercept.git cd intercept -docker compose up -d +docker compose --profile basic up -d --build ``` -> **Note:** Docker requires privileged mode for USB SDR access. See `docker-compose.yml` for configuration options. - -### ADS-B History (Optional) - -The ADS-B history feature persists aircraft messages to Postgres for long-term analysis. - -```bash -# Start with ADS-B history and Postgres -docker compose --profile history up -d -``` - -Set the following environment variables (for example in a `.env` file): - -```bash -INTERCEPT_ADSB_HISTORY_ENABLED=true -INTERCEPT_ADSB_DB_HOST=adsb_db -INTERCEPT_ADSB_DB_PORT=5432 -INTERCEPT_ADSB_DB_NAME=intercept_adsb -INTERCEPT_ADSB_DB_USER=intercept -INTERCEPT_ADSB_DB_PASSWORD=intercept -``` - -### Other ADS-B Settings - -Set these as environment variables for either local installs or Docker: - -| Variable | Default | Description | -|----------|---------|-------------| -| `INTERCEPT_ADSB_AUTO_START` | `false` | Auto-start ADS-B tracking when the dashboard loads | -| `INTERCEPT_SHARED_OBSERVER_LOCATION` | `true` | Share observer location across ADS-B/AIS/SSTV/Satellite modules | - -**Local install example** - -```bash -INTERCEPT_ADSB_AUTO_START=true \ -INTERCEPT_SHARED_OBSERVER_LOCATION=false \ -python app.py -``` - -**Docker example (.env)** - -```bash -INTERCEPT_ADSB_AUTO_START=true -INTERCEPT_SHARED_OBSERVER_LOCATION=false -``` - -To store Postgres data on external storage, set `PGDATA_PATH` (defaults to `./pgdata`): - -```bash -PGDATA_PATH=/mnt/usbpi1/intercept/pgdata -``` - -Then open **/adsb/history** for the reporting dashboard. +> **Note:** Docker requires privileged mode for USB SDR access. SDR devices are passed through via `/dev/bus/usb`. + +#### Multi-Architecture Builds (amd64 + arm64) + +Cross-compile on an x64 machine and push to a registry. This is much faster than building natively on an RPi. + +```bash +# One-time setup on your x64 build machine +docker run --privileged --rm tonistiigi/binfmt --install all +docker buildx create --name intercept-builder --use --bootstrap + +# Build and push for both architectures +REGISTRY=ghcr.io/youruser ./build-multiarch.sh --push + +# On the RPi5, just pull and run +INTERCEPT_IMAGE=ghcr.io/youruser/intercept:latest docker compose --profile basic up -d +``` + +Build script options: + +| Flag | Description | +|------|-------------| +| `--push` | Push to container registry | +| `--load` | Load into local Docker (single platform only) | +| `--arm64-only` | Build arm64 only (for RPi deployment) | +| `--amd64-only` | Build amd64 only | + +Environment variables: `REGISTRY`, `IMAGE_NAME`, `IMAGE_TAG` + +#### Using a Pre-built Image + +If you've pushed to a registry, you can skip building entirely on the target machine: + +```bash +# Set in .env or export +INTERCEPT_IMAGE=ghcr.io/youruser/intercept:latest + +# Then just run +docker compose --profile basic up -d +``` + +### ADS-B History (Optional) + +The ADS-B history feature persists aircraft messages to Postgres for long-term analysis. + +```bash +# Start with ADS-B history and Postgres +docker compose --profile history up -d +``` + +Set the following environment variables (for example in a `.env` file): + +```bash +INTERCEPT_ADSB_HISTORY_ENABLED=true +INTERCEPT_ADSB_DB_HOST=adsb_db +INTERCEPT_ADSB_DB_PORT=5432 +INTERCEPT_ADSB_DB_NAME=intercept_adsb +INTERCEPT_ADSB_DB_USER=intercept +INTERCEPT_ADSB_DB_PASSWORD=intercept +``` + +### Other ADS-B Settings + +Set these as environment variables for either local installs or Docker: + +| Variable | Default | Description | +|----------|---------|-------------| +| `INTERCEPT_ADSB_AUTO_START` | `false` | Auto-start ADS-B tracking when the dashboard loads | +| `INTERCEPT_SHARED_OBSERVER_LOCATION` | `true` | Share observer location across ADS-B/AIS/SSTV/Satellite modules | + +**Local install example** + +```bash +INTERCEPT_ADSB_AUTO_START=true \ +INTERCEPT_SHARED_OBSERVER_LOCATION=false \ +python app.py +``` + +**Docker example (.env)** + +```bash +INTERCEPT_ADSB_AUTO_START=true +INTERCEPT_SHARED_OBSERVER_LOCATION=false +``` + +To store Postgres data on external storage, set `PGDATA_PATH` (defaults to `./pgdata`): + +```bash +PGDATA_PATH=/mnt/usbpi1/intercept/pgdata +``` + +Then open **/adsb/history** for the reporting dashboard. ### Open the Interface @@ -195,6 +236,7 @@ Created by **smittix** - [GitHub](https://github.com/smittix) [acarsdec](https://github.com/TLeconte/acarsdec) | [aircrack-ng](https://www.aircrack-ng.org/) | [Leaflet.js](https://leafletjs.com/) | +[SatDump](https://github.com/SatDump/SatDump) | [Celestrak](https://celestrak.org/) | [Priyom.org](https://priyom.org/) diff --git a/build-multiarch.sh b/build-multiarch.sh new file mode 100755 index 0000000..4798be8 --- /dev/null +++ b/build-multiarch.sh @@ -0,0 +1,139 @@ +#!/bin/bash +# INTERCEPT - Multi-architecture Docker image builder +# +# Builds for both linux/amd64 and linux/arm64 using Docker buildx. +# Run this on your x64 machine to cross-compile the arm64 image +# instead of building natively on the RPi5. +# +# Prerequisites (one-time setup): +# docker run --privileged --rm tonistiigi/binfmt --install all +# docker buildx create --name intercept-builder --use --bootstrap +# +# Usage: +# ./build-multiarch.sh # Build both platforms, load locally +# ./build-multiarch.sh --push # Build and push to registry +# ./build-multiarch.sh --arm64-only # Build arm64 only (for RPi) +# REGISTRY=ghcr.io/user ./build-multiarch.sh --push +# +# Environment variables: +# REGISTRY - Container registry (default: docker.io/library) +# IMAGE_NAME - Image name (default: intercept) +# IMAGE_TAG - Image tag (default: latest) + +set -euo pipefail + +# Configuration +REGISTRY="${REGISTRY:-}" +IMAGE_NAME="${IMAGE_NAME:-intercept}" +IMAGE_TAG="${IMAGE_TAG:-latest}" +BUILDER_NAME="intercept-builder" +PLATFORMS="linux/amd64,linux/arm64" + +# Parse arguments +PUSH=false +LOAD=false +ARM64_ONLY=false + +for arg in "$@"; do + case $arg in + --push) PUSH=true ;; + --load) LOAD=true ;; + --arm64-only) + ARM64_ONLY=true + PLATFORMS="linux/arm64" + ;; + --amd64-only) + PLATFORMS="linux/amd64" + ;; + --help|-h) + echo "Usage: $0 [--push] [--load] [--arm64-only] [--amd64-only]" + echo "" + echo "Options:" + echo " --push Push to container registry" + echo " --load Load into local Docker (single platform only)" + echo " --arm64-only Build arm64 only (for RPi5 deployment)" + echo " --amd64-only Build amd64 only" + echo "" + echo "Environment variables:" + echo " REGISTRY Container registry (e.g. ghcr.io/username)" + echo " IMAGE_NAME Image name (default: intercept)" + echo " IMAGE_TAG Image tag (default: latest)" + echo "" + echo "Examples:" + echo " $0 --push # Build both, push" + echo " REGISTRY=ghcr.io/myuser $0 --push # Push to GHCR" + echo " $0 --arm64-only --load # Build arm64, load locally" + echo " $0 --arm64-only --push && ssh rpi docker pull # Build + deploy to RPi" + exit 0 + ;; + *) + echo "Unknown option: $arg" + exit 1 + ;; + esac +done + +# Build full image reference +if [ -n "$REGISTRY" ]; then + FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}" +else + FULL_IMAGE="${IMAGE_NAME}:${IMAGE_TAG}" +fi + +echo "============================================" +echo " INTERCEPT Multi-Architecture Builder" +echo "============================================" +echo " Image: ${FULL_IMAGE}" +echo " Platforms: ${PLATFORMS}" +echo " Push: ${PUSH}" +echo "============================================" +echo "" + +# Check if buildx builder exists, create if not +if ! docker buildx inspect "$BUILDER_NAME" >/dev/null 2>&1; then + echo "Creating buildx builder: ${BUILDER_NAME}" + docker buildx create --name "$BUILDER_NAME" --use --bootstrap + + # Check for QEMU support + if ! docker run --rm --privileged tonistiigi/binfmt --install all >/dev/null 2>&1; then + echo "WARNING: QEMU binfmt setup may have failed." + echo "Run: docker run --privileged --rm tonistiigi/binfmt --install all" + fi +else + docker buildx use "$BUILDER_NAME" +fi + +# Build command +BUILD_CMD="docker buildx build --platform ${PLATFORMS} --tag ${FULL_IMAGE}" + +if [ "$PUSH" = true ]; then + BUILD_CMD="${BUILD_CMD} --push" + echo "Will push to: ${FULL_IMAGE}" +elif [ "$LOAD" = true ]; then + # --load only works with single platform + if echo "$PLATFORMS" | grep -q ","; then + echo "ERROR: --load only works with a single platform." + echo "Use --arm64-only or --amd64-only with --load." + exit 1 + fi + BUILD_CMD="${BUILD_CMD} --load" + echo "Will load into local Docker" +fi + +echo "" +echo "Building..." +echo "Command: ${BUILD_CMD} ." +echo "" + +$BUILD_CMD . + +echo "" +echo "============================================" +echo " Build complete!" +if [ "$PUSH" = true ]; then + echo " Image pushed to: ${FULL_IMAGE}" + echo "" + echo " Pull on RPi5:" + echo " docker pull ${FULL_IMAGE}" +fi +echo "============================================" diff --git a/docker-compose.yml b/docker-compose.yml index 4039f15..be409e8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,14 +1,18 @@ # INTERCEPT - Signal Intelligence Platform # Docker Compose configuration for easy deployment # -# Basic usage: -# docker compose --profile basic up -d +# Basic usage (build locally): +# docker compose --profile basic up -d --build +# +# Basic usage (pre-built image from registry): +# INTERCEPT_IMAGE=ghcr.io/user/intercept:latest docker compose --profile basic up -d # # With ADS-B history (Postgres): # docker compose --profile history up -d services: intercept: + image: ${INTERCEPT_IMAGE:-} build: . container_name: intercept profiles: @@ -54,6 +58,7 @@ services: # ADS-B history with Postgres persistence # Enable with: docker compose --profile history up -d intercept-history: + image: ${INTERCEPT_IMAGE:-} build: . container_name: intercept-history profiles: diff --git a/templates/partials/modes/weather-satellite.html b/templates/partials/modes/weather-satellite.html index 0e557f1..04cf11b 100644 --- a/templates/partials/modes/weather-satellite.html +++ b/templates/partials/modes/weather-satellite.html @@ -31,39 +31,145 @@ +
Weather satellites transmit at ~137 MHz. Your stock SDR antenna likely won't work well at this frequency.
++ 137 MHz band — your stock SDR antenna will NOT work. +
++ Weather satellites transmit at 137.1–137.9 MHz. The quarter-wave + at this frequency is ~53 cm, + far longer than the small telescopic antenna shipped with most SDRs + (tuned for ~1 GHz). You need a purpose-built antenna. +
+ + ++ Best starter antenna. Good enough for clear NOAA images with a direct overhead pass. +
++ Better than V-dipole. The reflector rejects ground noise and the RHCP phasing matches the satellite signal. +
++ Gold standard for weather satellite reception. No tracking needed — covers the whole sky. +
+| Wavelength (137 MHz) | +218.8 cm | +
| Quarter wave (element length) | +53.4 cm | +
| Best pass elevation | +> 30° | +
| Typical pass duration | +10-15 min | +
| Polarization | +RHCP | +
| NOAA (APT) bandwidth | +~40 kHz | +
| Meteor (LRPT) bandwidth | +~140 kHz | +