Deployment tool for embedded Linux satellites — push, track, rollback over SSH and CSP
Project description
satDeploy
satdeploy demo against a local throwaway target. Same hashing, backups, git provenance, and rollback code paths as a production deploy.
We flew DISCO-2, a 3U student CubeSat, and then spent weeks trying to recreate what was on it.
The payload ran a Yocto Linux image with several apps on it, each on its own release cadence, each updated the same way: rebuild locally, copy the binary over USB or SCP, and post "I updated the binary" in Slack. By launch, nobody could list every commit running on the hardware with confidence. After launch, rebuilding the same set on our flatsat took weeks of chasing memory and old tmux sessions, and we still ran into lib version mismatches we hadn't known were there.
satDeploy is what we built so it doesn't happen again. Every deploy is versioned, hash-verified, and tagged with the git commit it came from. Every file can be rolled back with one command. It works over SSH for networked targets on the bench, and over CSP (CAN bus, KISS serial, ZMQ) for air-gapped satellite links.
DISCO-2 is a 3U student CubeSat from Aarhus University, SDU, and ITU Copenhagen, launched on SpaceX Transporter-16 (March 30, 2026) to image Arctic glaciers from a 510 km sun-synchronous orbit. Coverage: Danish Space News, The Danish Dream, project site.
Early stage, but heading to orbit. We built satDeploy after DISCO-2 launched, so the current payload is flying without it. The next uplink window will push satDeploy to the DISCO-2 payload, and every deploy after that will be versioned, hash-verified, and rollback-able from the ground. Right now it runs on our flatsat, and we're actively putting it in front of other satellite teams — the more hardware it sees on the bench, the more rough edges we find and fix together before anything flies. If you run a satellite program, we'd love to see it on your flatsat. Open an issue or reach out.
Try it now
Zero dependencies on your laptop beyond Python and git.
pipx install satdeploy # or: pip install satdeploy
satdeploy demo
satdeploy demo sets up a throwaway git repo and a local target directory, then pre-installs test_app v1.0.0. Run the real product loop against it:
satdeploy status # See what's deployed
satdeploy push test_app # Deploy v2 (new hash, new commit)
satdeploy rollback test_app # Undo in one command, git tag carries through
satdeploy demo stop # Tear it down when you're done
The demo runs against a directory on your own machine instead of a satellite, so test_app (a small shell script the demo ships) executes right there on your laptop. Against real hardware, the binary lives on the target and you watch its effects there.
Deploy to real hardware
SSH (networked target)
Your target has network access. You don't need any C components, just the Python CLI.
satdeploy init # select "ssh", enter your target's IP
Then edit ~/.satdeploy/config.yaml:
name: flatsat
transport: ssh
host: 192.168.1.50
user: root
apps:
controller:
local: ./build/controller # path to your local binary
remote: /opt/bin/controller # where it goes on target
service: controller.service # systemd service to restart (or null)
Deploy:
satdeploy push controller
satdeploy status
satdeploy rollback controller # undo
satdeploy logs controller # service logs
CSP (air-gapped target, CAN/serial, experimental)
The CSP path has more moving parts. You need three pieces running:
| Piece | Where it runs | How to get it |
|---|---|---|
| Python CLI or CSH APM | Ground station | pip install satdeploy or build the APM |
satdeploy-agent |
Target satellite | Yocto recipe or cross-compile |
| CSH | Ground station | Bridges ZMQ ↔ CAN/serial |
Start the agent on the target:
satdeploy-agent -i CAN -p can0 # CAN bus
satdeploy-agent -i KISS -p /dev/ttyS1 # Serial link
satdeploy-agent -i ZMQ -p localhost # ZMQ (local testing only)
On the ground station, satdeploy init (select "csp") gives you a config like:
name: my-satellite
transport: csp
zmq_endpoint: tcp://localhost:9600 # CSH's ZMQ address
agent_node: 55 # your satellite's CSP node ID
ground_node: 40 # your ground station's CSP node ID
apps:
controller:
local: ./build/controller
remote: /opt/bin/controller
Then satdeploy push controller works the same as SSH.
If you just want to see the workflow without any of this, use satdeploy demo.
Docs
- Command reference: every command and flag
- Configuration reference: full config schema, transports, dependency ordering
- Building from source: Python CLI, agent cross-compile, APM build, CSP version pinning
Requirements
- Python 3.8+
- git (for the demo, and for provenance tracking on real deploys)
- SSH access to target (SSH transport)
satdeploy-agenton target + CSH on ground station (CSP transport)- systemd on target
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file satdeploy-0.3.8.tar.gz.
File metadata
- Download URL: satdeploy-0.3.8.tar.gz
- Upload date:
- Size: 101.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbef1c4fa593008ff7ff6a90a90f65f4f0a4783852444ead0279928803fb9759
|
|
| MD5 |
a2bb89fc2aed21fd01972de9056613ba
|
|
| BLAKE2b-256 |
12e515917107649df022f448ba870aa197874e089eca8ae1cef8a184e844f5f4
|
Provenance
The following attestation bundles were made for satdeploy-0.3.8.tar.gz:
Publisher:
pypi-publish.yml on MahmoodSeoud/satDeploy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
satdeploy-0.3.8.tar.gz -
Subject digest:
dbef1c4fa593008ff7ff6a90a90f65f4f0a4783852444ead0279928803fb9759 - Sigstore transparency entry: 1296399295
- Sigstore integration time:
-
Permalink:
MahmoodSeoud/satDeploy@527494f5837a92372d9cff54035969a5c9291552 -
Branch / Tag:
refs/tags/v0.3.8 - Owner: https://github.com/MahmoodSeoud
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@527494f5837a92372d9cff54035969a5c9291552 -
Trigger Event:
release
-
Statement type:
File details
Details for the file satdeploy-0.3.8-py3-none-any.whl.
File metadata
- Download URL: satdeploy-0.3.8-py3-none-any.whl
- Upload date:
- Size: 61.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c37251f742ccdaba94552b5dd858deafcf90891e8237d9e2fb1e5eccce5a967d
|
|
| MD5 |
5b8f4016f8845f195f90c2c8829e77bf
|
|
| BLAKE2b-256 |
f9e9c51e5ca3ed44d327e7e1d80ab57eaa62f30f3f9d44361dd012ac9e8c96f9
|
Provenance
The following attestation bundles were made for satdeploy-0.3.8-py3-none-any.whl:
Publisher:
pypi-publish.yml on MahmoodSeoud/satDeploy
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
satdeploy-0.3.8-py3-none-any.whl -
Subject digest:
c37251f742ccdaba94552b5dd858deafcf90891e8237d9e2fb1e5eccce5a967d - Sigstore transparency entry: 1296399416
- Sigstore integration time:
-
Permalink:
MahmoodSeoud/satDeploy@527494f5837a92372d9cff54035969a5c9291552 -
Branch / Tag:
refs/tags/v0.3.8 - Owner: https://github.com/MahmoodSeoud
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@527494f5837a92372d9cff54035969a5c9291552 -
Trigger Event:
release
-
Statement type: