5 releases
Uses new Rust 2024
| 0.2.0 | Nov 3, 2025 |
|---|---|
| 0.1.3 | Nov 2, 2025 |
| 0.1.2 | Nov 2, 2025 |
| 0.1.1 | Nov 1, 2025 |
| 0.1.0 | Nov 1, 2025 |
#256 in Concurrency
170KB
4K
SLoC
distronomicon
A Linux tool that checks GitHub for repository releases and performs atomic updates under /opt/<app>. Designed for use with systemd timers.
Installation
From crates.io
cargo install distronomicon
From source
cargo build --release
sudo cp target/release/distronomicon /usr/local/bin/
Usage
All commands require --app <name> to specify the application being managed.
Check for updates
Query GitHub for the latest release without installing:
distronomicon --app myapp check \
--repo owner/repo \
--state-directory /var/lib/distronomicon
Prints up-to-date: v1.2.3, update-available: v1.2.3 -> v1.2.4, or install-available: v1.2.4.
Update to latest release
Download, verify, and install the latest release:
distronomicon --app myapp update \
--repo owner/repo \
--pattern 'myapp-.*\.tar\.gz' \
--checksum-pattern 'SHA256SUMS' \
--state-directory /var/lib/distronomicon \
--restart-command 'systemctl restart myapp'
This will:
- Download the matching release asset
- Verify the checksum
- Extract to
/opt/myapp/releases/<tag> - Update symlinks in
/opt/myapp/bin - Run the restart command (if provided)
- Prune old releases (keeps 3 by default, configurable with
--retain)
Show installed version
distronomicon --app myapp version
Prints the currently installed tag (e.g., v1.2.3), derived from symlinks in the bin directory.
Filesystem Layout
/opt/<app>/
bin/ # Symlinks to current release binaries
myapp -> ../releases/v1.2.3/myapp
releases/
v1.2.2/ # Previous release
v1.2.3/ # Current release
staging/ # Temporary extraction (cleaned after install)
/var/lib/distronomicon/<app>/state.json # Tracks latest tag, ETag, Last-Modified
The --install-root flag changes the base from /opt to another location.
GitHub Authentication
For private repositories or higher rate limits, provide a token:
export GITHUB_TOKEN=ghp_...
distronomicon --app myapp update ...
Or use --github-token flag.
Systemd Timer
Example service and timer files are in the systemd/ directory.
Setup
- Copy the systemd files:
sudo cp systemd/distronomicon@.{service,timer} /etc/systemd/system/
sudo systemctl daemon-reload
- Configure the service using a drop-in override:
sudo systemctl edit distronomicon@myapp.service
- Add the required environment variables:
[Service]
Environment="DISTRONOMICON_REPO=owner/repo"
Environment="DISTRONOMICON_PATTERN=myapp-.*\.tar\.gz"
- Enable and start the timer:
sudo systemctl enable --now distronomicon@myapp.timer
Environment Variables
Required:
DISTRONOMICON_REPO- GitHub repository inowner/repoformatDISTRONOMICON_PATTERN- Regex pattern to match release assets
Optional:
GITHUB_TOKEN- GitHub API token (for private repos or higher rate limits)GITHUB_HOST- GitHub Enterprise host (default:https://api.github.com)STATE_DIRECTORY- State directory (auto-set by systemd viaStateDirectory=)DISTRONOMICON_CHECKSUM_PATTERN- Checksum file pattern (e.g.,SHA256SUMS)DISTRONOMICON_RESTART_COMMAND- Command to run after update (e.g.,systemctl restart myapp)DISTRONOMICON_RETAIN- Number of old releases to keep (default:3)DISTRONOMICON_INSTALL_ROOT- Install base directory (default:/opt)DISTRONOMICON_ALLOW_PRERELEASE- Include prereleases (set totrue)
⚠️ Note: If you change DISTRONOMICON_INSTALL_ROOT, you must also override ReadWritePaths in your drop-in configuration to grant write access to the custom location (required by ProtectSystem=strict).
Example with optional variables:
[Service]
Environment="DISTRONOMICON_REPO=owner/repo"
Environment="DISTRONOMICON_PATTERN=myapp-.*\.tar\.gz"
Environment="GITHUB_TOKEN=ghp_..."
Environment="DISTRONOMICON_CHECKSUM_PATTERN=SHA256SUMS"
Environment="DISTRONOMICON_RESTART_COMMAND=systemctl restart myapp"
Environment="DISTRONOMICON_RETAIN=5"
Environment="DISTRONOMICON_INSTALL_ROOT=/custom/opt"
ReadWritePaths=/custom/opt
Customizing the Timer
By default, the timer checks every 3 minutes. To change the interval:
sudo systemctl edit distronomicon@myapp.timer
[Timer]
OnBootSec=5m
OnUnitActiveSec=10m
Monitoring
Check status:
systemctl status distronomicon@myapp.timer
systemctl list-timers distronomicon@*
journalctl -u distronomicon@myapp.service
Options
--install-root- Change base directory (default:/opt)--skip-verification- Skip checksum verification (not recommended)--retain N- Keep N old releases after update (default: 3)--allow-prerelease- Include prerelease versions--github-host- Use GitHub Enterprise (default:https://api.github.com)-v,-vv- Increase logging verbosity
Future Ideas
Features under consideration for future development
Safety & Reliability
- Dry-run mode - Preview updates without making changes (
--dry-run) - Rollback command - Revert to previous releases when issues are discovered
- Version pinning - Lock to specific versions during maintenance windows
- Health checks - Doctor command to validate symlink integrity
- Update policies - Enforce semantic constraints (max major version, maintenance windows)
Observability
- Metrics - Prometheus/OpenTelemetry exports for monitoring
- Audit logs - Structured event logs (JSONL) for debugging
- Notifications - Webhook/Slack/email alerts for update results
- History queries - Commands to inspect past update attempts
Flexibility & Extensibility
- Pluggable sources - Support GitLab, S3, OCI registries, generic HTTP
- Additional checksums - BLAKE2, BLAKE3, SHA-512 algorithm support
- Signature verification - Sigstore/cosign or GPG signature checks
- Custom extraction - Flexible archive handling and post-install hooks
- Systemd generation - Generate service/timer templates per app
Fleet & Orchestration
- Staggered updates - Coordinate batch updates across multiple hosts
- Control API - REST/gRPC daemon for remote management
Networking & Resilience
- Resumable downloads - Continue interrupted downloads of large artifacts
- Mirror support - Configure fallback sources for high availability
License
MIT
Dependencies
~35–57MB
~771K SLoC