Generate clean, verifiable Debian and Ubuntu APT sources — entirely in your browser.

DistroForge is a small, static web tool for composing Debian and Ubuntu apt sources directly in the browser.
It helps you build clean, correct sources.list or DEB822 .sources configurations by combining:
- official distribution repositories
- curated third-party sources
- derived distribution entries
No accounts, no backend, no tracking — just a single HTML/CSS/JS bundle served via GitHub Pages.
Live site: https://silentglasses.github.io/distro_forge/
- Avoid manual
sources.listerrors and outdated examples - Quickly assemble reproducible APT configurations
- Verify third-party repos with visible key fingerprints
- Stay in control, everything runs client-side, no hidden logic
Built for people who prefer simple, inspectable tools over opaque web apps.
| Path | What it does |
|---|---|
/ |
Emits a ready-to-use sources.list or DEB822 .sources. |
/third-party/ |
Curated catalog of third-party apt repos. |
/variants/ |
Sources for Debian and Ubuntu derived distros |
/help/ |
FAQ / troubleshooting |
- Progressive-disclosure UI: options unlock based on upstream selections; nothing is pre-selected.
- Correct Ubuntu architecture routing: non-amd64 architectures automatically use
ports.ubuntu.com/ubuntu-ports, including security updates. - Optional mirror selection with country-grouped lists for Debian and Ubuntu.
- Outputs both traditional
sources.listand DEB822.sourcesformats. - Copy-to-clipboard on all outputs; per-page reset to start clean.
- Light/dark theme with persistence via
localStorage. - Third-party entries include keyring paths and full GPG fingerprints for manual verification.
Pure static site with ES modules, testing locally:
cd distro_forge
python3 -m http.server 8080
# open http://localhost:8080Don't open index.html via file://, browsers block ES-module imports from that protocol.
Three datasets are tracked in the repo and refreshed automatically via scheduled GitHub Actions workflows. Every workflow opens a pull request rather than committing straight to main, so changes are reviewable.
- Source: the canonical
distro-info-dataCSVs for Debian and Ubuntu. - Script:
scripts/update-releases.mjsregenerates the file and writes a human-readable diff to.release-notes.md(added / removed / status-changed releases). - Workflow:
.github/workflows/update-releases.ymlruns every Monday at 06:00 UTC and viaworkflow_dispatch; opens a PR labelledrelease-datawith the diff as the body.
- Script:
scripts/update-mirrors.mjsHEADs every mirror URL and drops any that fail within 8 s. - Workflow:
.github/workflows/update-mirrors.ymlruns every Wednesday at 06:00 UTC; opens a PR labeledmirror-datawith the pruned list and the list of dropped mirrors. - Adding a new mirror is a manual PR edit, the pruner only removes.
- Script:
scripts/validate-third-party.mjschecks schema, HEADshomepage/uri/gpg.url, and verifies the declared GPG fingerprint against the actual key (requiresgpg; Actions runners have it). - Workflow:
.github/workflows/validate-third-party.ymlruns on every push/PR touching third-party data and weekly on Thursdays. Push/PR runs fail the build on any validation error; scheduled runs open or update an issue labeledthird-party-validationinstead.
node scripts/update-releases.mjs
node scripts/update-mirrors.mjs
node scripts/validate-third-party.mjsAll scripts need Node 18+ (for global fetch). The validator also shells out to gpg for fingerprint verification.
.github/workflows/pages.yml deploys the repo root to GitHub Pages on every push to main. Source set to GitHub Actions in Settings → Pages. The .nojekyll file keeps Pages from running Jekyll.
deb_sources/
├── index.html
├── help/index.html
├── third-party/
│ ├── index.html
│ └── app.js
├── variants/
│ ├── index.html
│ └── app.js
├── assets/
│ ├── styles.css
│ ├── app.js # main generator wiring
│ ├── data/
│ │ ├── releases.js # AUTO-GENERATED distro/release data
│ │ ├── mirrors-list.js # AUTO-PRUNED mirror list
│ │ └── variants.js # hand-curated variants data
│ └── lib/
│ ├── generate.js # pure generator for main page
│ ├── third-party.js # builder for /third-party/
│ ├── variant.js # builder for /variants/
│ └── ui.js # shared theme + active-nav helpers
├── data/third-party/
│ ├── repos.json # curated repos
│ └── index.txt # enabled repo IDs
├── scripts/
│ ├── update-releases.mjs
│ ├── update-mirrors.mjs
│ └── validate-third-party.mjs
├── .github/
│ ├── workflows/
│ │ ├── pages.yml
│ │ ├── update-releases.yml
│ │ ├── update-mirrors.yml
│ │ └── validate-third-party.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ ├── feature_request.yml
│ │ ├── third_party_request.yml
│ │ └── config.yml
│ └── PULL_REQUEST_TEMPLATE.md
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── .gitignore
├── .nojekyll
├── package.json
└── README.md
Contributions are welcome, especially:
- adding or verifying third-party repositories
- improving mirror coverage
- fixing edge cases in source generation
If you find this tool useful, consider:
- opening issues for gaps or inaccuracies
- submitting PRs for data updates or improvements
- sponsoring to support ongoing maintenance and data curation
See CONTRIBUTING.md for the full rundown of data formats, validation scripts, conventions, and what to check before opening a PR. Participation is subject to our CODE_OF_CONDUCT.md.
Issue templates are available for bug reports, feature requests, and new third-party repo requests. The third-party template asks for the upstream docs link and the full GPG fingerprint up-front.
MIT, see LICENSE.