nikstur/lon
{ "createdAt": "2024-08-09T17:21:27Z", "defaultBranch": "main", "description": "Lock & update Nix dependencies", "fullName": "nikstur/lon", "homepage": "", "language": "Rust", "name": "lon", "pushedAt": "2026-05-02T13:38:23Z", "stargazersCount": 89, "topics": [ "nix", "package-manager", "updates", "versioning" ], "updatedAt": "2026-06-03T17:43:48Z", "url": "https://github.com/nikstur/lon"}Lock & update Nix dependencies.
Features
Section titled “Features”- Only uses SRI hashes
- Supports fixed outputs of
builtins.fetchGitby using an SRI hash and thus enables caching for these sources in the Nix Store - Allows overriding dependencies via an environment variable for local development
- Leverages modern Nix features (concretely this means Nix >= 2.4 is required)
- Built-in bot to automate dependency updates for GitHub, GitLab, and Forgejo
- Supports the Lockable HTTP Tarball Protocol
Installation
Section titled “Installation”The easiest way to use Lon is directly from Nixpkgs. It is currently available
in the nixos-unstable branch and will be included in NixOS releases starting
from 25.05.
You can also invoke it via nix run github:nikstur/lon.
$ lonUsage: lon [OPTIONS] <COMMAND>
Commands: init Initialize lon.{nix,lock} add Add a new source update Update an existing source to the newest revision modify Modify an existing source remove Remove an existing source freeze Freeze an existing source unfreeze Unfreeze an existing source bot Bot that opens PRs for updates help Print this message or the help of the given subcommand(s)
Options: -q, --quiet Silence all output -v, --verbose... Verbose mode (-v, -vv, etc.) -d, --directory <DIRECTORY> The directory containing lon.{nix,lock} -h, --help Print help -V, --version Print versionInitialize Lon:
$ lon initWriting lon.nix...Writing empty lon.lock...Initialize from an existing Niv lock file:
$ lon init --from niv --source nix/sources.jsonWriting lon.nix...Initializing lon.lock from "nix/sources.json"Converting bombon...Locked revision: 2c7df3b0877337b9ce4825ffbaa6e5148b96acb4Locked hash: sha256-EiV+QA0RZqzt+lrYdsao7p1LhHB+fICjT4do4L+lIdM=Converting nixpkgs...Locked revision: 292fa7d4f6519c074f0a50394dbbe69859bb6043Locked hash: sha256-GaOZntlJ6gPPbbkTLjbd8BMWaDYafhuuYRNrxCGnPJw=Add a new GitHub source:
$ lon add github nixos/nixpkgs masterAdding nixpkgs...Locked revision: 543931cdbf2b2313479c391d956edb5347362744Locked hash: sha256-8pTC0OIYD47alDVf2mwSytwARCwoH6IqnUfpyshyQX8=Add a new Git source:
$ lon add git snix https://git.snix.dev/snix/snix.git canonAdding snix...Locked revision: e33040a3e1a500e73dd8a4c2b9e793d7cb85384fLocked hash: sha256-TpWEIhAgzGIupKARl+a3btrBaV9wQGYyxzN42Cnmu14=Locked lastModified: 1761157523Git sources also support fetching submodules. Enable it by supplying
--submodules to Lon.
Add a new (Lockable) Tarball source:
Adding lix...Locked immutable URL: https://git.lix.systems/api/v1/repos/lix-project/lix/archive/18efc848fe7b79c84a2e4311ac9ce3492b7aaa82.tar.gz?rev=18efc848fe7b79c84a2e4311ac9ce3492b7aaa82Locked revision: 18efc848fe7b79c84a2e4311ac9ce3492b7aaa82Locked hash: sha256-B4TrQgd/3pm0SvnCkYkvLuldhrO+9QRB/mKa6JrItNo=If the provided URL doesn’t point to a lockable tarball, it pins the provided
URL directly. You can change the URL of a non-lockable tarball by calling
lon modify $name --url $new_url.
You can now access these sources via lon.nix:
let sources = import ./lon.nix; pkgs = import sources.nixpkgs { }; lix = import sources.lix;in { nix = pkgs.nix; lix = lix.packages.x86_64-linux.default; }You can update individual sources via lon update nixpkgs or all sources via
lon update. You can even let Lon create a commit for the updates it performs
via lon update --commit. The commit message will list all the updates
performed similar to the way nix flake update --commit-lock-file does.
Overriding a Source for Local Development
Section titled “Overriding a Source for Local Development”You can use environment variables that follow the scheme LON_OVERRIDE_${name}
to override a source for local development. Lon will use the path this variable
points to instead of the fetching the locked source from lon.lock.
Note that no sanitizing of names is performed by Lon. That’s why you should give your sources names that only contain alphanumeric names.
With the subcommand bot <forge>, you can automatically update your sources. Lon
iterates over each source and if an update is available, performs it and opens
a PR.
Currently, GitLab (gitlab), GitHub (github) and Forgejo (forgejo) are supported.
Bot that opens PRs for updates
Usage: lon bot <COMMAND>
Commands: gitlab Run the bot for GitLab github Run the bot for GitHub forgejo Run the bot for Forgejo help Print this message or the help of the given subcommand(s)
Options: -h, --help Print helpGitLab Usage
Section titled “GitLab Usage”- Create a [Project Access Token] with the role
Developer, and theapiandwrite_repositoryscope. You can also create a [Group Access Token] so that the entire group can use the bot. - Store the token in a CI/CD variable called
PROJECT_ACCESS_TOKEN. - Configure a [Scheduled Pipeline].
- Extend your
.gitlab-ci.ymlwith the following snippet. Make sure to setLON_PUSH_URLincluding the token stored inPROJECT_ACCESS_TOKEN.
stages: - update
lon: stage: update rules: # Only run on a schedule and only on the main branch. - if: $CI_PIPELINE_SOURCE == "schedule" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH variables: LON_TOKEN: "$PROJECT_ACCESS_TOKEN" LON_PUSH_URL: "https://token:${LON_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" LON_LABELS: "bot,lon" script: - lon bot gitlab[Project Access Token] !: https://docs.gitlab.com/user/project/settings/project_access_tokens/ [Group Access Token] !: https://docs.gitlab.com/user/group/settings/group_access_tokens/ [Scheduled Pipeline] !: https://docs.gitlab.com/ci/pipelines/schedules/
GitHub Usage
Section titled “GitHub Usage”- Allow GitHub Actions to create Pull Requests
- Add a workflow for updates (e.g.
.github/workflows/update.yml). Use the following snippet to create a functioning workflow. Note specifically the permissions and environment variables.
jobs: update: runs-on: ubuntu-latest permissions: contents: write pull-requests: write issues: write steps: - uses: actions/checkout@v4 - env: LON_TOKEN: ${{ secrets.GITHUB_TOKEN }} LON_LABELS: "lon,bot" run: lon bot githubForgejo Usage
Section titled “Forgejo Usage”Basic usage
Section titled “Basic usage”Add a workflow for updates (e.g. .forgejo/workflows/update.yml). Use the
following snippet to create a functioning workflow.
jobs: update: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - env: LON_TOKEN: ${{ secrets.FORGEJO_TOKEN }} LON_LABELS: "lon,bot" run: lon bot forgejoNote, however, that the pull requests opened via this actions will not trigger workflows due to how the automatic token is designed.
With an Access Token
Section titled “With an Access Token”To alleviate the previous problem, it is possible to create a personal access token to use instead of the automatic one.
- Create an [Access Token] with the
write:repositoryscope - Add the token to the actions secret variables
The next snippet creates such a workflow.
jobs: update: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: token: ${{ secrets.ACCESS_TOKEN }} - env: LON_TOKEN: ${{ secrets.ACCESS_TOKEN }} LON_LABELS: "lon,bot" run: lon bot forgejo[Access Token] !: https://docs.codeberg.org/advanced/access-token/
Config
Section titled “Config”The bot is configured exclusively via environment variables.
Required
Section titled “Required”LON_TOKEN: The token to access the forge API and push to the repository.
Optional
Section titled “Optional”LON_USER_NAME: The Git user name under which the changes are made.LON_USER_EMAIL: The Git user email under which the changes are made.LON_LABELS: The labels to set on the Pull Request as a comma separated string (e.g."lon,bot").LON_PUSH_URL: The URL to use to push to the repository. This can be used to set a token in the URL. For GitLab, this is required.LON_LIST_COMMITS: The number of commits to list in the commit message that occurred between the old revision and the updated revision. If this is unset, none are listed.
GitLab Specific (Required)
Section titled “GitLab Specific (Required)”These are predefined in GitLab CI/CD.
CI_API_V4_URLCI_PROJECT_IDCI_DEFAULT_BRANCH
GitHub Specific (Required)
Section titled “GitHub Specific (Required)”These are predefined in GitHub Actions.
GITHUB_REPOSITORY
Contributing
Section titled “Contributing”Contributions are welcome!
Lon has a growing test suite that consists of two parts:
- normal Rust unit/integration tests
- VM tests
The VM tests are also written in Rust but are ignored when you call cargo test. They are designed to only run inside a VM because they access resources
mocked by another VM. You can call these VM tests via nix build .#checks.x86_64-linux.lon.
You can add another VM test by creating one in inside the ignored module of
the Rust integration tests.
All the tests are included in the flake checks. You can run all of them via
nix flake check.
Invariants
Section titled “Invariants”- Support only few repository hosters: Lon does not aim to support all possible repository hosters. It will focus on the most important ones and will as much as possible rely on generic protocols (e.g. Git) to find and lock updates. GitHub is already an exception to this rule, but because of its ubiquity and importance, it is unavoidable.
- No tracking besides Git branches. You can still lock e.g. a specific revision, but you will have to update it manually.
On the Shoulders of Giants
Section titled “On the Shoulders of Giants”Lon is heavily inspired by niv and npins and builds on their success.