Open-source project
sgoudelis/ground-station avatar
sgoudelis/ground-station

sgoudelis/ground-station: a browser-based satellite ground station suite

Browser-based ground station suite for satellite tracking, SDR reception, hardware control, and telemetry decoding

4,826 stars839 forksJavaScriptGPL-3.0

At a glance

What is it?
Ground Station bundles satellite tracking, SDR reception, rotator and rig control, and telemetry decoding into one web interface. It is GPL-3.0, JavaScript on the frontend, Python on the backend, and installs as a Docker image.
Who is it for?
Adopt it if you already own an SDR and a rotator and want one web interface for passes, recordings and decoding instead of a folder of scripts. Skip it if you need a headless decoder you can call from another program, or if you cannot run Docker with host USB access.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What sgoudelis/ground-station actually replaces

A typical amateur satellite setup is a stack of unrelated programs: one for TLE propagation, one for rotator control, one for the SDR, one for decoding, and a text file or spreadsheet holding the schedule. Ground Station's stated goal is to collapse that into a single browser-based application for tracking satellites and celestial targets, controlling station hardware, and receiving, decoding and recording SDR signals. The README names its audience directly: amateur radio operators, satellite enthusiasts and researchers.

The scope is wider than a tracker. The repository topics list antenna, rotator, rig, waterfall, FFT, BPSK, FSK, TLE and SatNOGS alongside React and Python, so the project is claiming the whole chain from orbit prediction down to demodulated bits. That is the interesting bet. Most tools in this space pick one layer and do it well. Ground Station picks all of them and pays for it in installation complexity.

How the frontend, backend and SDR chain fit together

The repository layout is a two-part application. frontend/ is a React application built with Vite; backend/ is Python 3.12. The Dockerfile shows the split explicitly: a first stage runs npm ci and npm run build against frontend/package.json to produce static assets, and a second stage based on Ubuntu Noble installs the Python toolchain and the SDR C libraries (librtlsdr, libairspy, libairspyhf, libhackrf) plus SoapySDR's dependencies such as libboost, swig, cmake and libpython3-dev.

That second stage is where the design becomes clear. The SDR drivers are native libraries compiled into the image, not pip packages, which is why the image is large and why device support is fixed at build time. The frontend talks to the backend over HTTP and sockets; the release notes for v0.8.6 mention "post-login socket hydration", which indicates a socket layer carries live state such as tracking telemetry and waterfall data to the browser. Hardware control sits behind the same backend, and v0.8.12 describes rotator selection with error dialogs and cleanup of stale tracker ownership, so the backend arbitrates which client owns a rotator at any moment.

Satellite data arrives from external providers. The v0.8.4 notes state that independent providers continue when CelesTrak fails and that updates are scheduled every 12 hours. That same release fixed OMM epoch normalization, which had been interpreting naive timestamps in the wrong timezone. If you have ever watched a pass prediction drift by minutes and blamed your clock, that class of bug is exactly what this fix targets.

Installing Ground Station with Docker and reaching the web interface

The README gives no step-by-step install section in the text available here, but the repository ships a Dockerfile and a deploy/ directory, and the release notes repeatedly reference Docker support, including SDRplay RSP API v3.15 in v0.8.3. The documented path is therefore a container build rather than a pip install.

The Dockerfile itself shows what the build does. The frontend stage copies frontend/package.json and frontend/package-lock.json, runs npm ci with the --no-audit and --no-fund flags, checks that node_modules/.bin/vite exists, copies the frontend source, copies .env.production to .env, and runs npm run build:

dockerfile
RUN npm ci --no-audit --no-fund && test -x node_modules/.bin/vite

That single line is the whole dependency step, and it tells you two things. The build expects a lockfile to be present, and it deliberately skips the npm audit network request so the image build does not depend on reaching the registry's audit endpoint.

The backend stage then installs the system packages and the SDR development headers before the Python application is set up:

dockerfile
RUN apt-get update && apt-get install -y --no-install-recommends \
    gcc \
    git \
    build-essential \
    sudo \
    python3 \
    python3-dev \
    python3.12 \
    python3.12-venv \
    python3.12-dev \
    python3-pip \
    dh-autoreconf \
    python3-full \
    software-properties-common \
    librtlsdr-dev \
    libairspy-dev \
    libairspyhf-dev \
    libhackrf-dev \
    libboost-all-dev \
    swig \
    avahi-daemon \
    libavahi-client-dev \
    cmake g++ libpython3-dev python3-numpy \
    avahi-daemon \
    avahi-utils \
    libnss-mdns \
    dbus \
    gpg-agent \
    libsamplerate0-dev \
    python3-mako \
    python3-requests \
    libfftw3-dev \
    libabsl-dev \
    libarmadillo-dev \
    libblas-dev \
    libgflags-dev \
    libgoogle-glog-dev \
    libgtest-dev \
    liblapack-dev \
    libmatio-dev \
    libpcap-dev \
    libprotobuf-dev \
    libpugixml-dev \

That list is the real cost of the project. It is a compiling toolchain plus four SDR driver development packages plus SoapySDR's build dependencies, and it is why the image is large and why the first build takes a while.

Once the container is up, the first real task is the setup wizard. The release notes describe a station-location step with validated manual altitude entry, station-coordinate timezone detection, and a manual timezone override under account menu, Preferences, Regional and Language, Timezone. Set the station coordinates and timezone there before trusting any pass prediction, because the v0.8.4 OMM fix and the v0.8.7 timezone work both affect what the tracker believes about time.

Where Ground Station gets in your way

The container-first design is the main constraint. SDR support is baked into the image at build time, so adding a device that the Dockerfile does not install a driver for means editing the Dockerfile and rebuilding, not installing a package at runtime. The v0.8.6 release added MiriSDR through SoapyMiri, which shows the pattern: new hardware arrives as a new build dependency, not as a plugin you drop in.

Timezone and epoch handling has been a recurring source of bugs. v0.8.4 is labelled a major bug fix for OMM epoch normalization, and v0.8.7 added station-coordinate timezone detection with an override. That is two releases in a month touching the same conceptual area. Anyone running an unattended station should verify pass times against an independent source after upgrading.

The scheduler is described as gaining "clearer SDR session state" and "transmitter loading feedback" in v0.8.9, which suggests that observing how a scheduled task is progressing was previously unclear. If your workflow depends on knowing exactly when a recording starts, that history is worth reading before you trust a long unattended schedule.

Finally, Ground Station is the wrong tool if you want a library. There is no documented Python API for driving the decoder from your own code. If your pipeline already has its own scheduler and you only need demodulation, a standalone decoder fits better than a web application with a database.

Ground Station against SatNOGS and plain rtl-sdr scripts

The natural comparison is SatNOGS, which the repository topics reference. SatNOGS is built around a network of distributed stations reporting observations to a central server; the client is designed to run unattended and contribute to that network. Ground Station is the opposite shape: a local, interactive application where the operator watches the waterfall, tunes the receiver and controls the rotator from a browser. If your goal is to contribute observations to a shared network, SatNOGS is the fit. If your goal is to sit at your own station and see what is happening, Ground Station's multi-target tracking console and per-target controls are the point.

The other alternative is the collection of command-line tools most operators already have: predict for passes, rtl_fm or SoapySDR utilities for capture, and a separate decoder. That stack is lighter, scriptable and easy to run headless on a Raspberry Pi. What it does not give you is a shared state model: the rotator does not know what the SDR is tuned to, and the schedule lives in your shell history. Ground Station's value is that the tracker, the radio and the recorder agree on what the current target is. The cost is a Docker image with a full Python and Node build chain behind it.

Licence, maintenance and the cost of upgrading

Ground Station is GPL-3.0. If you run it as a local station for yourself, the licence is not something you need to think about. If you intend to modify it and distribute the result, or to offer it as a hosted service, the copyleft terms apply to the combined work, and the repository includes a CLA.md and CONTRIBUTING.md that govern contributions back. That is a description of the licence, not legal advice; read LICENSE and the CLA before building a product on top of it.

The project is not archived and the last push was on 2026-09-22, one day before the date used here, with releases v0.8.10, v0.8.11 and v0.8.12 landing between 2026-09-15 and 2026-09-19. That cadence is the upgrade cost. Three releases in a week, several of them touching timezone handling, localization and the scheduler, means you should not treat an upgrade as a background operation. The release notes for v0.8.7 explicitly state that existing timezone preferences are preserved when upgrading from v0.8.6 or earlier, which is the kind of compatibility note you want to read before each move. The README documents a streamed database restore for files up to 1 GB, but it does not document a rollback path for a failed upgrade, so back up the data directory before you pull a new image.

Editorial conclusion

Adopt it if you already own an SDR and a rotator and want one web interface for passes, recordings and decoding instead of a folder of scripts. Skip it if you need a headless decoder you can call from another program, or if you cannot run Docker with host USB access. Before committing, check the docs directory for the supported SDR list, confirm your device appears through SoapySDR, and verify how the SQLite database and recordings are backed up, because the README documents a restore path for files up to 1 GB but not a rollback path for a bad upgrade.

Frequently asked questions

What does sgoudelis/ground-station do?

It is a browser-based application for tracking satellites and celestial targets, controlling station hardware, and receiving, decoding and recording SDR signals. The README lists amateur radio operators, satellite enthusiasts and researchers as the intended users.

Is sgoudelis/ground-station the same thing as AWS Ground Station or a Starlink ground station?

No. Those are commercial satellite communications services. sgoudelis/ground-station is an open-source GPL-3.0 application you run yourself for satellite tracking, SDR reception, hardware control and telemetry decoding.

How is sgoudelis/ground-station installed?

The repository ships a Dockerfile and a deploy directory. The Dockerfile builds the React frontend with Vite in one stage and a Python 3.12 backend with the SDR C libraries in a second stage, so the documented path is a container build rather than a pip install.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. README
  4. Releases
  5. sgoudelis/ground-station on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sgoudelis-ground-station.svg)](https://hysenlabs.com/projects/sgoudelis-ground-station)