Merge 1efa528e94 into haskell-updates

This commit is contained in:
nixpkgs-ci[bot]
2026-01-21 00:24:28 +00:00
committed by GitHub
332 changed files with 17392 additions and 17526 deletions
+38 -8
View File
@@ -7,6 +7,8 @@ inputs:
description: "Whether and which SHA to checkout for the merge commit in the ./nixpkgs/untrusted folder."
target-as-trusted-at:
description: "Whether and which SHA to checkout for the target commit in the ./nixpkgs/trusted folder."
untrusted-pin-bump:
description: "Commit that bumps ci/pinned.json; when set, ./nixpkgs/untrusted and ./nixpkgs/untrusted-pinned are derived from this commit."
runs:
using: composite
@@ -15,6 +17,7 @@ runs:
env:
MERGED_SHA: ${{ inputs.merged-as-untrusted-at }}
TARGET_SHA: ${{ inputs.target-as-trusted-at }}
PIN_BUMP_SHA: ${{ inputs.untrusted-pin-bump }}
with:
script: |
const { spawn } = require('node:child_process')
@@ -52,13 +55,18 @@ runs:
return pinned.pins.nixpkgs.revision
}
const pin_bump_sha = process.env.PIN_BUMP_SHA
// When dealing with a pin bump commit, we need `--depth=2` to view & apply its diff
const depth = pin_bump_sha ? 2 : 1
const commits = [
{
sha: process.env.MERGED_SHA,
path: 'untrusted',
},
{
sha: await getPinnedSha(process.env.MERGED_SHA),
sha: await getPinnedSha(pin_bump_sha || process.env.MERGED_SHA),
path: 'untrusted-pinned'
},
{
@@ -68,14 +76,17 @@ runs:
{
sha: await getPinnedSha(process.env.TARGET_SHA),
path: 'trusted-pinned'
},
{
sha: pin_bump_sha
}
].filter(({ sha }) => Boolean(sha))
console.log('Checking out the following commits:', commits)
console.log('Fetching the following commits:', commits)
// Fetching all commits at once is much faster than doing multiple checkouts.
// This would fail without --refetch, because the we had a partial clone before, but changed it above.
await run('git', 'fetch', '--depth=1', '--refetch', 'origin', ...(commits.map(({ sha }) => sha)))
await run('git', 'fetch', `--depth=${depth}`, '--refetch', 'origin', ...(commits.map(({ sha }) => sha)))
// Checking out onto tmpfs takes 1s and is faster by at least factor 10x.
await run('mkdir', 'nixpkgs')
@@ -89,8 +100,27 @@ runs:
}
// Create all worktrees in parallel.
await Promise.all(commits.map(async ({ sha, path }) => {
await run('git', 'worktree', 'add', join('nixpkgs', path), sha, '--no-checkout')
await run('git', '-C', join('nixpkgs', path), 'sparse-checkout', 'disable')
await run('git', '-C', join('nixpkgs', path), 'checkout', '--progress')
}))
await Promise.all(
commits
.filter(({ path }) => Boolean(path))
.map(async ({ sha, path }) => {
await run('git', 'worktree', 'add', join('nixpkgs', path), sha, '--no-checkout')
await run('git', '-C', join('nixpkgs', path), 'sparse-checkout', 'disable')
await run('git', '-C', join('nixpkgs', path), 'checkout', '--progress')
})
)
// Apply pin bump to untrusted worktree
if (pin_bump_sha) {
console.log('Applying untrusted ci/pinned.json bump:', pin_bump_sha)
try {
await run('git', '-C', join('nixpkgs', 'untrusted'), 'cherry-pick', '--no-commit', pin_bump_sha)
} catch {
core.setFailed([
`Failed to apply ci/pinned.json bump commit ${pin_bump_sha}.`,
`This commit does not apply cleanly onto the untrusted base ${process.env.MERGED_SHA}.`,
`Please rebase the PR or ensure the pin bump is standalone.`
].join(' '))
return
}
}
+2 -6
View File
@@ -41,7 +41,7 @@ jobs:
- runner: ubuntu-24.04-arm
name: aarch64-linux
systems: aarch64-linux
builds: [shell, manual-nixos, manual-nixpkgs, manual-nixpkgs-tests]
builds: [shell, manual-nixos, manual-nixpkgs]
desc: shell, docs
- runner: macos-14
name: darwin
@@ -90,11 +90,7 @@ jobs:
- name: Build Nixpkgs manual
if: contains(matrix.builds, 'manual-nixpkgs') && !cancelled()
run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A manual-nixpkgs -A manual-nixpkgs-tests
- name: Build Nixpkgs manual tests
if: contains(matrix.builds, 'manual-nixpkgs-tests') && !cancelled()
run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A manual-nixpkgs-tests
run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A manual-nixpkgs
- name: Build lib tests
if: contains(matrix.builds, 'lib-tests') && !cancelled()
+90 -3
View File
@@ -9,7 +9,11 @@ on:
mergedSha:
required: true
type: string
headSha:
required: false # only required when testVersions is true
type: string
targetSha:
required: true
type: string
systems:
required: true
@@ -36,6 +40,8 @@ jobs:
runs-on: ubuntu-slim
outputs:
versions: ${{ steps.versions.outputs.versions }}
ciPinBumpCommit: ${{ steps.find-pinned-commit.outputs.ciPinBumpCommit }}
ciPinBumpCommitShort: ${{ steps.find-pinned-commit.outputs.ciPinBumpCommitShort }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
@@ -53,6 +59,78 @@ jobs:
sparse-checkout: |
ci/pinned.json
- name: Find commit that touched ci/pinned.json
id: find-pinned-commit
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
TARGET_SHA: ${{ inputs.targetSha }}
HEAD_SHA: ${{ inputs.headSha }}
with:
script: |
const targetSha = process.env.TARGET_SHA
const headSha = process.env.HEAD_SHA
if (!targetSha || !headSha) {
core.setFailed('Error: Both targetSha and headSha inputs are required when testVersions is true.')
return
}
// Compare the two commits to get the list of commits in between
const comparison = await github.rest.repos.compareCommitsWithBasehead({
...context.repo,
basehead: `${targetSha}...${headSha}`,
})
if(comparison.data.commits.length > 50) {
core.setFailed('Error: Too many commits in comparison, cannot reliably find pinned.json change.')
return
}
const logRateLimit = async (label) => {
const { data } = await github.rest.rateLimit.get()
const { remaining, limit, used } = data.rate
core.info(`[Rate Limit ${label}] ${remaining}/${limit} remaining (${used} used)`)
}
await logRateLimit('before commit filtering')
// Filter commits that modified ci/pinned.json
const commitsModifyingPinned = (
await Promise.all(
comparison.data.commits.map(async (commit) => {
const commitDetails = await github.rest.repos.getCommit({
...context.repo,
ref: commit.sha,
})
const modifiesPinned = commitDetails.data.files?.some(
(file) => file.filename === "ci/pinned.json"
)
return modifiesPinned ? commit.sha : null
})
)
).filter((sha) => sha !== null)
await logRateLimit('after commit filtering')
if (commitsModifyingPinned.length === 0) {
// This should not happen as testVersions should only be true
// when ci/pinned.json was modified in the PR.
core.setFailed("Error: ci/pinned.json was not modified in this PR")
return
} else if (commitsModifyingPinned.length > 1) {
core.setFailed([
"Error: Multiple commits touch ci/pinned.json in this PR:",
...commitsModifyingPinned,
"Please ensure only a single commit modifies ci/pinned.json for accurate version matrix evaluation."
].join("\n"))
return
}
const ciPinBumpCommit = commitsModifyingPinned[0]
core.setOutput("ciPinBumpCommit", ciPinBumpCommit)
core.setOutput("ciPinBumpCommitShort", ciPinBumpCommit.substring(0, 7))
core.info(`Found pinned.json commit: ${ciPinBumpCommit}`)
- name: Install Nix
uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
@@ -75,7 +153,7 @@ jobs:
# Failures for versioned Evals will be collected in a separate job below
# to not interrupt main Eval's compare step.
continue-on-error: ${{ matrix.version != '' }}
name: ${{ matrix.system }}${{ matrix.version && format(' @ {0}', matrix.version) || '' }}
name: ${{ matrix.system }}${{ matrix.version && format(' @ {0} ({1})', matrix.version, needs.versions.outputs.ciPinBumpCommitShort) || '' }}
timeout-minutes: 15
steps:
# This is not supposed to be used and just acts as a fallback.
@@ -96,7 +174,9 @@ jobs:
- name: Check out the PR at merged and target commits
uses: ./.github/actions/checkout
with:
merged-as-untrusted-at: ${{ inputs.mergedSha }}
# For versioned evals, use the target as the untrusted base and apply the pin-bump commit
merged-as-untrusted-at: ${{ matrix.version && inputs.targetSha || inputs.mergedSha }}
untrusted-pin-bump: ${{ matrix.version && needs.versions.outputs.ciPinBumpCommit }}
target-as-trusted-at: ${{ inputs.targetSha }}
- name: Install Nix
@@ -284,6 +364,7 @@ jobs:
ARTIFACT_PREFIX: ${{ inputs.artifact-prefix }}
SYSTEMS: ${{ inputs.systems }}
VERSIONS: ${{ needs.versions.outputs.versions }}
CI_PIN_BUMP_COMMIT: ${{ needs.versions.outputs.ciPinBumpCommit }}
with:
script: |
const { readFileSync } = require('node:fs')
@@ -292,8 +373,10 @@ jobs:
const prefix = process.env.ARTIFACT_PREFIX
const systems = JSON.parse(process.env.SYSTEMS)
const versions = JSON.parse(process.env.VERSIONS)
const ciPinBumpCommit = process.env.CI_PIN_BUMP_COMMIT
core.summary.addHeading('Lix/Nix version comparison')
core.summary.addRaw(`\n*Evaluated at commit: \`${ciPinBumpCommit}\` (commit that modified ci/pinned.json)*\n`, true)
core.summary.addTable(
[].concat(
[
@@ -324,7 +407,11 @@ jobs:
.filter((attr) => attr.split('.').length > 1)
if (attrs.length > 0) {
core.setFailed(
`${version} on ${system} has changed outpaths!\nNote: Please make sure to update ci/pinned.json separately from changes to other packages.`,
`${version} on ${system} has changed outpaths!\n` +
`Note: This indicates that commit ${ciPinBumpCommit} ` +
`(which modified ci/pinned.json) also contains other ` +
`changes affecting package outputs. ` +
`Please ensure ci/pinned.json is updated in a standalone commit.`
)
return { data: ':x:' }
}
@@ -86,6 +86,7 @@ jobs:
with:
artifact-prefix: ${{ inputs.artifact-prefix }}
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
headSha: ${{ github.event.pull_request.head.sha }}
targetSha: ${{ needs.prepare.outputs.targetSha }}
systems: ${{ needs.prepare.outputs.systems }}
testVersions: ${{ contains(fromJSON(needs.prepare.outputs.touched), 'pinned') && !contains(fromJSON(needs.prepare.outputs.headBranch).type, 'development') }}
-1
View File
@@ -172,7 +172,6 @@ rec {
lib-tests = import ../lib/tests/release.nix { inherit pkgs; };
manual-nixos = (import ../nixos/release.nix { }).manual.${system} or null;
manual-nixpkgs = (import ../doc { inherit pkgs; });
manual-nixpkgs-tests = (import ../doc { inherit pkgs; }).tests;
nixpkgs-vet = pkgs.callPackage ./nixpkgs-vet.nix {
nix = pkgs.nixVersions.latest;
};
+5 -12
View File
@@ -133,6 +133,11 @@ module.exports = async ({ github, context, core, dry }) => {
id,
})
.then((resp) => resp.data)
.catch((e) => {
// User may have deleted their account
if (e.status === 404) return null
throw e
})
}
return users[id]
@@ -145,22 +150,10 @@ module.exports = async ({ github, context, core, dry }) => {
// This API request is important for the merge-conflict label, because it triggers the
// creation of a new test merge commit. This is needed to actually determine the state of a PR.
//
// NOTE (2025-12-15): Temporarily skipping mergeability checks here
// on GitHubs request to measure the impact of the resulting ref
// writes on their internal metrics; merge conflicts resulting from
// changes to target branches will not have labels applied for the
// duration. The label should still be updated on pushes.
//
// TODO: Restore mergeability checks in some form after a few days
// or when we hear back from GitHub.
const pull_request = (
await github.rest.pulls.get({
...context.repo,
pull_number,
// Undocumented parameter (as of 2025-12-15), added by GitHub
// for us; stability unclear.
skip_mergeability_checks: true,
})
).data
+9 -3
View File
@@ -42,9 +42,15 @@ async function handleReviewers({
}
const users = new Set([
...(await Promise.all(
maintainers.map(async (id) => (await getUser(id)).login.toLowerCase()),
)),
...(
await Promise.all(
maintainers.map(async (id) => {
const user = await getUser(id)
// User may have deleted their account
return user?.login?.toLowerCase()
}),
)
).filter(Boolean),
...owners
.filter((handle) => handle && !handle.includes('/'))
.map((handle) => handle.toLowerCase()),
+1
View File
@@ -168,6 +168,7 @@ stdenvNoCC.mkDerivation (
};
tests = {
# Don't run this in CI because it's not reproducible
manpage-urls = callPackage ../tests/manpage-urls.nix { };
};
};
+2
View File
@@ -61,6 +61,8 @@
- `spoof` has been removed, as there are many issues upstream with it working on modern OS versions, and it appears to be unmaintained.
- `nodePackages.wavedrom-cli` has been removed, as it was unmaintained within nixpkgs.
- `kanata` now requires `karabiner-dk` version 6.0+ or later.
The package has been updated to use the new `karabiner-dk` package and the `darwinDriver` output stays at the version defined in the package.
+24 -4
View File
@@ -58,12 +58,19 @@ logFailure() {
evalConfig() {
local attr=$1
shift
local script="import ./default.nix { modules = [ $* ];}"
local nix_args=()
if [ "${ABORT_ON_WARN-0}" = "1" ]; then
local-nix-instantiate --option abort-on-warn true -E "$script" -A "$attr"
else
local-nix-instantiate -E "$script" -A "$attr"
nix_args+=(--option abort-on-warn true)
fi
if [ "${STRICT_EVAL-0}" = "1" ]; then
nix_args+=(--strict)
fi
local script="import ./default.nix { modules = [ $* ];}"
local-nix-instantiate "${nix_args[@]}" -E "$script" -A "$attr"
}
reportFailure() {
@@ -247,6 +254,19 @@ checkConfigError 'A definition for option .* is not of type .fileset.. Definitio
checkConfigError 'A definition for option .* is not of type .fileset.. Definition values:\n.*' config.filesetCardinal.err3 ./fileset.nix
checkConfigError 'A definition for option .* is not of type .fileset.. Definition values:\n.*' config.filesetCardinal.err4 ./fileset.nix
# types.serializableValueWith
checkConfigOutput '^null$' config.nullableValue.null ./types.nix
checkConfigOutput '^true$' config.nullableValue.bool ./types.nix
checkConfigOutput '^1$' config.nullableValue.int ./types.nix
checkConfigOutput '^1.1$' config.nullableValue.float ./types.nix
checkConfigOutput '^"foo"$' config.nullableValue.str ./types.nix
checkConfigOutput '^".*/store.*"$' config.nullableValue.path ./types.nix
STRICT_EVAL=1 checkConfigOutput '^\{"foo":1\}$' config.nullableValue.attrs ./types.nix
STRICT_EVAL=1 checkConfigOutput '^\[\{"bar":\[1\]\}\]$' config.nullableValue.list ./types.nix
checkConfigError 'A definition for option .* is not of type .VAL value.. .*' config.nullableValue.lambda ./types.nix
checkConfigError 'A definition for option .* is not of type .VAL value.. .*' config.structuredValue.null ./types.nix
# Check boolean option.
checkConfigOutput '^false$' config.enable ./declare-enable.nix
checkConfigError 'The option .* does not exist. Definition values:\n\s*- In .*: true' config.enable ./define-enable.nix
+32
View File
@@ -16,6 +16,19 @@ in
options = {
pathInStore = mkOption { type = types.lazyAttrsOf types.pathInStore; };
externalPath = mkOption { type = types.lazyAttrsOf types.externalPath; };
# serializableValueWith
nullableValue = mkOption {
type = types.attrsOf (types.serializableValueWith { typeName = "VAL"; });
};
structuredValue = mkOption {
type = types.attrsOf (
types.serializableValueWith {
typeName = "VAL";
nullable = false;
}
);
};
assertions = mkOption { };
};
config = {
@@ -35,6 +48,22 @@ in
externalPath.ok1 = "/foo/bar";
externalPath.ok2 = "/";
# serializableValueWith { nullable = true; }
nullableValue.null = null; # null
nullableValue.bool = true; # bool
nullableValue.int = 1; # int
nullableValue.float = 1.1; # float
nullableValue.str = "foo"; # str
nullableValue.path = ./.; # path
nullableValue.attrs = {
foo = 1;
};
nullableValue.list = [ { bar = [ 1 ]; } ]; # list
nullableValue.lambda = x: x; # Error
# serializableValueWith { nullable = false; }
structuredValue.null = null; # Error
assertions =
with lib.types;
@@ -486,6 +515,9 @@ in
assert (unique { message = "custom"; } (listOf str)).description == "list of string";
assert (unique { message = "test"; } (either int str)).description == "signed integer or string";
assert (unique { message = "test"; } (listOf str)).description == "list of string";
# json & toml
assert json.description == "JSON value";
assert toml.description == "TOML value";
# done
"ok";
};
+39
View File
@@ -1437,6 +1437,45 @@ rec {
};
};
/**
Creates a value type suitable for serialization formats.
Parameters:
- typeName: String describing the format (e.g. "JSON", "YAML", "XML")
- nullable: Whether the structured value type allows `null` values.
Returns a type suitable for structured data formats that supports:
- Basic types: boolean, integer, float, string, path
- Complex types: attribute sets and lists
*/
serializableValueWith =
{
typeName,
nullable ? true,
}:
let
baseType = oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
];
valueType = (if nullable then nullOr baseType else baseType) // {
description = "${typeName} value";
};
in
valueType;
json = serializableValueWith { typeName = "JSON"; };
toml = serializableValueWith {
typeName = "TOML";
nullable = false;
};
# Either value of type `t1` or `t2`.
either =
t1: t2:
@@ -497,6 +497,20 @@ Composed types are types that take a type as parameter. `listOf
value of type *`to`*. Can be used to preserve backwards compatibility
of an option if its type was changed.
`types.json`
: A type representing JSON-compatible values. This includes `null`, booleans,
integers, floats, strings, paths, attribute sets, and lists.
Attribute sets and lists can be arbitrarily nested and contain any JSON-compatible
values.
`types.toml`
: A type representing TOML-compatible values. This includes booleans,
integers, floats, strings, paths, attribute sets, and lists.
Attribute sets and lists can be arbitrarily nested and contain any TOML-compatible
values.
## Submodule {#section-option-types-submodule}
`submodule` is a very powerful type that defines a set of sub-options
+3
View File
@@ -109,6 +109,9 @@
"modular-services": [
"index.html#modular-services"
],
"module-services-amule": [
"index.html#module-services-amule"
],
"module-services-anubis": [
"index.html#module-services-anubis"
],
+5 -11
View File
@@ -32,14 +32,8 @@ let
let
qemu-common = import ../qemu-common.nix { inherit (pkgs) lib stdenv; };
# Convert legacy VLANs to named interfaces and merge with explicit interfaces.
vlansNumbered = forEach (zipLists config.virtualisation.vlans (range 1 255)) (v: {
name = "eth${toString v.snd}";
vlan = v.fst;
assignIP = true;
});
explicitInterfaces = lib.mapAttrsToList (n: v: v // { name = n; }) config.virtualisation.interfaces;
interfaces = vlansNumbered ++ explicitInterfaces;
interfaces = lib.attrValues config.virtualisation.allInterfaces;
interfacesNumbered = zipLists interfaces (range 1 255);
# Automatically assign IP addresses to requested interfaces.
@@ -67,10 +61,10 @@ let
{ fst, snd }: qemu-common.qemuNICFlags snd fst.vlan config.virtualisation.test.nodeNumber
)
);
udevRules = forEach interfacesNumbered (
{ fst, snd }:
udevRules = forEach interfaces (
interface:
# MAC Addresses for QEMU network devices are lowercase, and udev string comparison is case-sensitive.
''SUBSYSTEM=="net",ACTION=="add",ATTR{address}=="${toLower (qemu-common.qemuNicMac fst.vlan config.virtualisation.test.nodeNumber)}",NAME="${fst.name}"''
''SUBSYSTEM=="net",ACTION=="add",ATTR{address}=="${toLower (qemu-common.qemuNicMac interface.vlan config.virtualisation.test.nodeNumber)}",NAME="${interface.name}"''
);
networkConfig = {
+10 -1
View File
@@ -77,6 +77,15 @@ in
example = false;
};
extraCompletionPackages = lib.mkOption {
type = lib.types.listOf lib.types.package;
default = [ ];
example = lib.literalExpression "config.users.users.alice.packages";
description = ''
Additional packages to generate completions from, if {option}`programs.fish.generateCompletions` is enabled.
'';
};
vendor.config.enable = lib.mkOption {
type = lib.types.bool;
default = true;
@@ -295,7 +304,7 @@ in
pkgs.buildEnv {
name = "system_fish-completions";
ignoreCollisions = true;
paths = map generateCompletions config.environment.systemPackages;
paths = map generateCompletions (config.environment.systemPackages ++ cfg.extraCompletionPackages);
};
})
+1 -1
View File
@@ -377,7 +377,7 @@ systemd-tmpfiles --create
systemctl start acme-example.com.service
```
## Ensuring dependencies for services that need to be reloaded when a certificate challenges {#module-security-acme-reload-dependencies}
## Ensuring dependencies for services that need to be reloaded when a certificate changes {#module-security-acme-reload-dependencies}
Services that depend on ACME certificates and need to be reloaded can use one of two approaches to reload upon successfull certificate acquisition or renewal:
@@ -3,6 +3,8 @@
device-name-strategy,
discovery-mode,
mounts,
disable-hooks,
enable-hooks,
glibc,
jq,
lib,
@@ -37,7 +39,8 @@ writeScriptBin "nvidia-cdi-generator" ''
}
--discovery-mode ${discovery-mode} \
--device-name-strategy ${device-name-strategy} \
--disable-hook create-symlinks \
${lib.concatMapStringsSep " \\\n" (hook: "--disable-hook ${hook}") disable-hooks} \
${lib.concatMapStringsSep " \\\n" (hook: "--enable-hook ${hook}") enable-hooks} \
--ldconfig-path ${lib.getExe' glibc "ldconfig"} \
--library-search-path ${lib.getLib nvidia-driver}/lib \
--nvidia-cdi-hook-path ${lib.getOutput "tools" nvidia-container-toolkit}/bin/nvidia-cdi-hook \
@@ -120,6 +120,26 @@
package = lib.mkPackageOption pkgs "nvidia-container-toolkit" { };
disable-hooks = lib.mkOption {
type = lib.types.listOf lib.types.nonEmptyStr;
default = [ "create-symlinks" ];
description = ''
List of hooks to disable when generating the CDI specification.
Each hook name will be passed as `--disable-hook <hook-name>` to nvidia-ctk.
Set to an empty list to disable no hooks.
'';
};
enable-hooks = lib.mkOption {
type = lib.types.listOf lib.types.nonEmptyStr;
default = [ ];
description = ''
List of hooks to enable when generating the CDI specification.
Each hook name will be passed as `--enable-hook <hook-name>` to nvidia-ctk.
Set to an empty list to enable no hooks.
'';
};
extraArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
@@ -306,6 +326,8 @@
device-name-strategy
discovery-mode
mounts
disable-hooks
enable-hooks
extraArgs
;
nvidia-container-toolkit = config.hardware.nvidia-container-toolkit.package;
@@ -0,0 +1,30 @@
# aMule {#module-services-amule}
[aMule](https://www.amule.org/) is a free and open-source peer-to-peer file sharing client that supports the eD2k and Kad networks.
It allows users to search for, download, and share files with others on these networks.
The `amuled` daemon is the command-line version of aMule, designed to run as a background service without a graphical user interface, making it suitable for servers or headless systems.
It handles finding sources, managing download and upload queues, and interacting with the eD2k servers and Kad network.
Here an example which also enables the web server and sets custom paths for the downloads:
```nix
{
services.amule = {
enable = true;
openPeerPorts = true;
openWebServerPort = true;
ExternalConnectPasswordFile = "/run/secrets/amule-password";
WebServerPasswordFile = "/run/secrets/amule-web/password";
settings = {
eMule = {
IncomingDir = "/mnt/hd/amule";
TempDir = "/mnt/hd/amule/Temp";
};
WebServer.Enabled = 1;
};
};
}
```
You can connect using `amulegui` and choosing the host, port (`4712` by default) and password, the username is always `amule`.
Otherwise, if you enabled the web server, connect using the browser (port `4711` by default).
+284 -50
View File
@@ -1,89 +1,323 @@
{
config,
lib,
options,
utils,
pkgs,
...
}:
let
cfg = config.services.amule;
opt = options.services.amule;
user = if cfg.user != null then cfg.user else "amule";
in
{
settingsFormat = pkgs.formats.ini { };
###### interface
inherit (lib)
mkOption
mkEnableOption
mkPackageOption
types
optionalAttrs
mkIf
mkMerge
literalExpression
optionalString
optionals
getExe
;
options = {
services.amule = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
settingsOptions = {
eMule = {
Port = mkOption {
type = types.port;
default = 4662;
description = ''
Whether to run the AMule daemon. You need to manually run "amuled --ec-config" to configure the service for the first time.
TCP port for eD2k connections.
Required for connecting to servers and achieving a High ID.
'';
};
dataDir = lib.mkOption {
type = lib.types.str;
default = "/home/${user}/";
defaultText = lib.literalExpression ''
"/home/''${config.${opt.user}}/"
'';
UDPPort = mkOption {
type = types.port;
default = 4672;
description = ''
The directory holding configuration, incoming and temporary files.
UDP port for eD2k traffic (searches, source exchange) and all Kad network communication.
Essential for a High ID on both networks and proper Kad functioning.
'';
};
user = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
TempDir = mkOption {
type = types.path;
default = "${cfg.dataDir}/Temp";
defaultText = literalExpression "\${config.services.amule.dataDir}/Temp";
description = ''
The user the AMule daemon should run as.
Directory where aMule stores incomplete downloads (.part/.part.met files).
'';
};
IncomingDir = mkOption {
type = types.path;
default = "${cfg.dataDir}/Incoming";
defaultText = literalExpression "\${config.services.amule.dataDir}/Incoming";
description = ''
Directory where aMule moves completed downloads.
Files in this directory are automatically shared.
Ensure the aMule service has write permissions
'';
};
OSDirectory = mkOption {
type = types.path;
default = cfg.dataDir;
defaultText = literalExpression "\${config.services.amule.dataDir}";
description = "On-disk state directory, probably you don't want to change this";
internal = true;
};
};
ExternalConnect = {
AcceptExternalConnections = mkOption {
type = types.enum [
0
1
];
default = 1;
description = "Whether to accept external connections, if disabled amuled refuses to start";
internal = true;
};
ECPort = mkOption {
type = types.port;
default = 4712;
description = "TCP port for external connections, like remote control via amule-gui";
};
ECPassword = mkOption {
type = types.str;
default = "";
description = ''
MD5 hash of the password, obtainaible with `echo "<password>" | md5sum | cut -d ' ' -f 1`
'';
};
};
WebServer = {
Enabled = lib.mkOption {
type = types.enum [
0
1
];
default = 0;
description = "Set to 1 to enable the web server";
};
Password = mkOption {
type = types.str;
default = "";
description = ''
MD5 hash of the password, obtainaible with `echo "<password>" | md5sum | cut -d ' ' -f 1`
'';
};
Port = mkOption {
type = types.port;
default = 4711;
description = "Web server port";
};
};
};
###### implementation
webServerEnabled = cfg.settings.WebServer.Enabled == 1;
in
{
options.services.amule = {
enable = mkEnableOption "aMule daemon";
config = lib.mkIf cfg.enable {
package = mkPackageOption pkgs "amule-daemon" { };
users.users = lib.mkIf (cfg.user == null) [
amuleWebPackage = mkPackageOption pkgs "amule-web" { };
extraArgs = mkOption {
type = types.listOf types.str;
default = [ ];
description = "Additional passed arguments";
};
dataDir = mkOption {
type = types.path;
default = "/var/lib/amuled";
description = "Directory holding configuration and by default also incoming and temporary files";
};
user = mkOption {
type = types.str;
default = "amule";
description = "The user the aMule daemon should run as";
};
group = mkOption {
type = types.str;
default = "amule";
description = "Group under which amule runs";
};
openPeerPorts = mkEnableOption "open the peer port(s) in the firewall";
openExternalConnectPort = mkEnableOption "open the external connect port";
openWebServerPort = mkEnableOption "open the web server port";
ExternalConnectPasswordFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
File containing the password for connecting with amule-gui,
set this only if you didn't set `settings.ExternalConnect.ECPassword`
'';
};
WebServerPasswordFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
File containing the password for connecting to the web server,
set this only if you didn't set `settings.ExternalConnect.ECPassword`
'';
};
settings = mkOption {
type = types.submodule {
freeformType = settingsFormat.type;
options = settingsOptions;
};
description = ''
Free form attribute set for aMule settings.
The final configuration file is generated merging the default settings with these options.
'';
example = literalExpression ''
{
eMule = {
IncomingDir = "/mnt/hd/amule/Incoming";
TempDir = "/mnt/hd/amule/Temp";
};
WebServer.Enabled = 1;
}
'';
default = { };
};
};
config = mkIf cfg.enable {
assertions = [
{
name = "amule";
description = "AMule daemon";
group = "amule";
assertion = isNull cfg.ExternalConnectPasswordFile -> cfg.settings.ExternalConnect.ECPassword != "";
message = "Set only one between `ExternalConnectPasswordFile` and `settings.ExternalConnect.ECPassword`";
}
]
++ optionals webServerEnabled [
{
assertion = isNull cfg.WebServerPasswordFile -> cfg.settings.WebServer.Password != "";
message = "Set only one between `ExternalWebServerFile` `settings.WebServer.Password`";
}
];
users.users = optionalAttrs (cfg.user == "amule") {
amule = {
group = cfg.group;
description = "aMule user";
isSystemUser = true;
uid = config.ids.uids.amule;
}
];
};
};
users.groups = lib.mkIf (cfg.user == null) [
{
name = "amule";
gid = config.ids.gids.amule;
}
];
users.groups = optionalAttrs (cfg.group == "amule") {
amule.gid = config.ids.gids.amule;
};
systemd.tmpfiles.settings."10-amuled".${cfg.dataDir}.d = {
inherit (cfg) user group;
mode = "0755";
};
services.amule.settings = {
eMule.AppVersion = lib.getVersion cfg.package;
};
systemd.services.amuled = {
description = "AMule daemon";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
path = [ pkgs.crudini ];
preStart = ''
mkdir -p ${cfg.dataDir}
chown ${user} ${cfg.dataDir}
AMULE_CONF="${cfg.dataDir}/amule.conf"
if [ ! -f "$AMULE_CONF" ]; then
echo "First run detected: starting aMule to generate default configuration..."
echo "aMule will fail with an error - this is expected and normal"
rm -f ${cfg.dataDir}/lastversion
set +e
${getExe cfg.package} --config-dir ${cfg.dataDir}
set -e
fi
''
+ (lib.concatMapAttrsStringSep "" (
section:
lib.concatMapAttrsStringSep "" (
param: value: ''
crudini --inplace --set "$AMULE_CONF" "${section}" "${param}" "${builtins.toString value}"
''
)
) cfg.settings)
+ optionalString (!isNull cfg.ExternalConnectPasswordFile) ''
EC_PASSWORD=$(cat ${cfg.ExternalConnectPasswordFile} | md5sum | cut -d ' ' -f 1)
crudini --inplace --set "$AMULE_CONF" "ExternalConnect" "ECPassword" "$EC_PASSWORD"
''
+ optionalString (!isNull cfg.WebServerPasswordFile) ''
WEB_PASSWORD=$(cat ${cfg.WebServerPasswordFile} | md5sum | cut -d ' ' -f 1)
crudini --inplace --set "$AMULE_CONF" "WebServer" "Password" "$WEB_PASSWORD"
'';
script = ''
${pkgs.su}/bin/su -s ${pkgs.runtimeShell} ${user} \
-c 'HOME="${cfg.dataDir}" ${pkgs.amule-daemon}/bin/amuled'
'';
serviceConfig = {
User = cfg.user;
Group = cfg.group;
ExecStart = utils.escapeSystemdExecArgs (
[
(getExe cfg.package)
"--config-dir"
cfg.dataDir
]
++ optionals webServerEnabled [ "--use-amuleweb=${getExe cfg.amuleWebPackage}" ]
++ cfg.extraArgs
);
Restart = "on-failure";
RestartSec = "5s";
# Hardening
NoNewPrivileges = true;
PrivateTmp = true;
PrivateDevices = true;
DevicePolicy = "closed";
ProtectSystem = "strict";
ProtectControlGroups = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ReadWritePaths = [
cfg.dataDir
cfg.settings.eMule.TempDir
cfg.settings.eMule.IncomingDir
];
RestrictAddressFamilies = "AF_INET";
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
LockPersonality = true;
};
};
networking.firewall = mkMerge [
(mkIf cfg.openPeerPorts {
allowedTCPPorts = [ cfg.settings.eMule.Port ];
allowedUDPPorts = [ cfg.settings.eMule.UDPPort ];
})
(mkIf cfg.openWebServerPort {
allowedTCPPorts = [ cfg.settings.WebServer.Port ];
})
];
};
meta = {
maintainers = with lib.maintainers; [ aciceri ];
doc = ./amuled.md;
};
}
+49 -7
View File
@@ -78,15 +78,57 @@ It is possible to configure default settings for all instances of Anubis, via {o
```nix
{
services.anubis.defaultOptions = {
botPolicy = {
dnsbl = false;
};
settings.DIFFICULTY = 3;
};
}
```
Note that at the moment, a custom bot policy is not merged with the baked-in one. That means to only override a setting
like `dnsbl`, copying the entire bot policy is required. Check
[the upstream repository](https://github.com/TecharoHQ/anubis/blob/1509b06cb921aff842e71fbb6636646be6ed5b46/cmd/anubis/botPolicies.json)
for the policy.
By default, this module uses Anubis's built-in policy (`botPolicies.yaml`), which includes sensible defaults for bot
rules, thresholds, status codes, and storage backend. A custom policy file is only generated when you explicitly
customize the policy via {option}`services.anubis.instances.<name>.policy`.
To add custom bot rules while keeping the defaults:
```nix
{
services.anubis.instances.default = {
settings.TARGET = "http://localhost:8000";
policy.extraBots = [
{
name = "my-allowed-bot";
user_agent_regex = "MyBot/.*";
action = "ALLOW";
}
];
};
}
```
To opt out of the default bot rules entirely and define your own:
```nix
{
services.anubis.instances.default = {
settings.TARGET = "http://localhost:8000";
policy = {
useDefaultBotRules = false;
extraBots = [
{
name = "my-rule";
path_regex = ".*";
action = "CHALLENGE";
}
];
};
};
}
```
::: {.note}
When you customize the policy, a custom policy file is generated. This file imports the default bot rules via
`(data)/meta/default-config.yaml` when {option}`services.anubis.instances.<name>.policy.useDefaultBotRules` is enabled,
but uses Anubis's simpler legacy threshold instead of the 5-tier thresholds from `botPolicies.yaml`. If you need custom
thresholds, specify them in {option}`services.anubis.instances.<name>.policy.settings`.
:::
See [the upstream documentation](https://anubis.techaro.lol/docs/admin/policies) for all available policy options.
+94 -13
View File
@@ -12,6 +12,32 @@ let
enabledInstances = lib.filterAttrs (_: conf: conf.enable) cfg.instances;
instanceName = name: if name == "" then "anubis" else "anubis-${name}";
# Only generates a custom policy file when the user has explicitly customized
# something (extraBots, settings, or disabled default bot rules). When nothing
# is customized, returns null so Anubis uses its built-in botPolicies.yaml
# which includes sensible defaults for thresholds, status_codes, store, etc.
mkPolicyFile =
name: instance:
let
hasCustomization =
!instance.policy.useDefaultBotRules
|| instance.policy.extraBots != [ ]
|| instance.policy.settings != { };
bots =
(lib.optional instance.policy.useDefaultBotRules {
import = "(data)/meta/default-config.yaml";
})
++ instance.policy.extraBots;
policyContent = {
inherit bots;
}
// instance.policy.settings;
in
if hasCustomization then
jsonFormat.generate "${instanceName name}-policy.json" policyContent
else
null;
unixAddr = network: addr: lib.strings.optionalString (network == "unix") addr;
unixSocketAddrs =
settings:
@@ -40,6 +66,10 @@ let
in
{ name, ... }:
{
imports = [
(lib.mkRenamedOptionModule [ "botPolicy" ] [ "policy" "settings" ])
];
options = {
enable = lib.mkEnableOption "this instance of Anubis" // {
default = true;
@@ -65,18 +95,71 @@ let
type = types.str;
};
botPolicy = mkDefaultOption "botPolicy" {
default = null;
policy = lib.mkOption {
default = { };
description = ''
Anubis policy configuration in Nix syntax. Set to `null` to use the baked-in policy which should be
sufficient for most use-cases.
This option has no effect if `settings.POLICY_FNAME` is set to a different value, which is useful for
importing an existing configuration.
Anubis policy configuration.
See [the documentation](https://anubis.techaro.lol/docs/admin/policies) for details.
'';
type = types.nullOr jsonFormat.type;
type = types.submodule {
options = {
useDefaultBotRules = mkDefaultOption "policy.useDefaultBotRules" {
type = types.bool;
default = true;
description = ''
Whether to include Anubis's default bot detection rules via the
`(data)/meta/default-config.yaml` import.
Set to `false` to define your own bot rules from scratch using
{option}`extraBots`.
'';
};
extraBots = mkDefaultOption "policy.extraBots" {
type = types.listOf jsonFormat.type;
default = [ ];
example = lib.literalExpression ''
[
{
name = "my-bot";
user_agent_regex = "MyBot/.*";
action = "ALLOW";
}
]
'';
description = ''
Additional bot rules appended to the policy.
When {option}`useDefaultBotRules` is `true`, these rules are added after
Anubis's default rules. When `false`, only these rules are used.
'';
};
settings = mkDefaultOption "policy.settings" {
type = jsonFormat.type;
default = { };
example = lib.literalExpression ''
{
dnsbl = false;
store = {
backend = "bbolt";
parameters.path = "/var/lib/anubis/data.bdb";
};
}
'';
description = ''
Additional policy settings merged into the policy file.
Common settings include `dnsbl`, `store`, `logging`, `thresholds`,
`impressum`, `openGraph`, and `statusCodes`.
See [the documentation](https://anubis.techaro.lol/docs/admin/policies) for
available options.
'';
};
};
};
};
extraFlags = mkDefaultOption "extraFlags" {
@@ -175,8 +258,8 @@ let
POLICY_FNAME = mkDefaultOption "settings.POLICY_FNAME" {
default = null;
description = ''
The bot policy file to use. Leave this as `null` to respect the value set in
{option}`services.anubis.instances.<name>.botPolicy`.
The policy file to use. Leave this as `null` to use the policy generated from
{option}`services.anubis.instances.<name>.policy`.
'';
type = types.nullOr types.path;
};
@@ -306,10 +389,8 @@ in
POLICY_FNAME =
if instance.settings.POLICY_FNAME != null then
instance.settings.POLICY_FNAME
else if instance.botPolicy != null then
jsonFormat.generate "${instanceName name}-botPolicy.json" instance.botPolicy
else
null;
mkPolicyFile name instance;
}
)
);
@@ -19,8 +19,6 @@ let
};
settingsFormat = pkgs.formats.yaml { };
configFile = settingsFormat.generate "headscale.yaml" cfg.settings;
cliConfigFile = settingsFormat.generate "headscale.yaml" cliConfig;
assertRemovedOption = option: message: {
assertion = !lib.hasAttrByPath option cfg;
@@ -35,6 +33,16 @@ in
package = lib.mkPackageOption pkgs "headscale" { };
configFile = lib.mkOption {
type = lib.types.path;
readOnly = true;
default = settingsFormat.generate "headscale.yaml" cfg.settings;
defaultText = lib.literalExpression ''(pkgs.formats.yaml { }).generate "headscale.yaml" config.services.headscale.settings'';
description = ''
Path to the configuration file of headscale.
'';
};
user = lib.mkOption {
default = "headscale";
type = lib.types.str;
@@ -621,7 +629,7 @@ in
environment = {
# Headscale CLI needs a minimal config to be able to locate the unix socket
# to talk to the server instance.
etc."headscale/config.yaml".source = cliConfigFile;
etc."headscale/config.yaml".source = settingsFormat.generate "headscale.yaml" cliConfig;
systemPackages = [ cfg.package ];
};
@@ -646,7 +654,7 @@ in
export HEADSCALE_DATABASE_POSTGRES_PASS="$(head -n1 ${lib.escapeShellArg cfg.settings.database.postgres.password_file})"
''}
exec ${lib.getExe cfg.package} serve --config ${configFile}
exec ${lib.getExe cfg.package} serve --config ${cfg.configFile}
'';
serviceConfig =
@@ -13,7 +13,6 @@ let
bool
listOf
str
attrs
submodule
;
cfg = config.services.yggdrasil;
@@ -69,7 +68,7 @@ in
settings = mkOption {
type = submodule {
freeformType = attrs;
freeformType = (pkgs.formats.json { }).type;
options = {
PrivateKeyPath = mkOption {
type = nullOr path;
+1 -1
View File
@@ -76,7 +76,7 @@ in
example = lib.literalExpression ''
{
enableACME = true;
forceHttps = true;
forceSSL = true;
}
'';
};
+1 -1
View File
@@ -140,7 +140,7 @@ in
"pics.''${config.networking.domain}"
];
enableACME = true;
forceHttps = true;
forceSSL = true;
}
'';
description = ''
+1 -1
View File
@@ -45,7 +45,7 @@ in
example = lib.literalExpression ''
{
enableACME = true;
forceHttps = true;
forceSSL = true;
}
'';
description = ''
@@ -10,13 +10,7 @@ let
runTests = stdenv.mkDerivation {
name = "tests-activation-lib";
src = fileset.toSource {
root = ./.;
fileset = fileset.unions [
./lib.sh
./test.sh
];
};
src = ./lib;
buildPhase = ":";
doCheck = true;
postUnpack = ''
+8 -2
View File
@@ -6,7 +6,7 @@
}:
let
node-forbiddenDependencies-fail = nixos (
{ ... }:
{ config, ... }:
{
system.forbiddenDependenciesRegexes = [ "-dev$" ];
environment.etc."dev-dependency" = {
@@ -15,16 +15,22 @@ let
documentation.enable = false;
fileSystems."/".device = "ignore-root-device";
boot.loader.grub.enable = false;
# Don't do this in an actual config
system.stateVersion = config.system.nixos.release;
}
);
node-forbiddenDependencies-succeed = nixos (
{ ... }:
{ config, ... }:
{
system.forbiddenDependenciesRegexes = [ "-dev$" ];
system.extraDependencies = [ expect.dev ];
documentation.enable = false;
fileSystems."/".device = "ignore-root-device";
boot.loader.grub.enable = false;
# Don't do this in an actual config
system.stateVersion = config.system.nixos.release;
}
);
in
@@ -0,0 +1,138 @@
# This module defines networking options for virtual machines and containers.
# It is intended to be used with systemd-nspawn containers and QEMU virtual machines.
{ config, lib, ... }:
let
inherit (lib) types;
interfaceType = types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
type = types.str;
default = name;
description = ''
Interface name
'';
};
vlan = lib.mkOption {
type = types.ints.unsigned;
description = ''
VLAN to which the network interface is connected.
'';
};
assignIP = lib.mkOption {
type = types.bool;
default = false;
description = ''
Automatically assign an IP address to the network interface using the same scheme as
virtualisation.vlans.
'';
};
};
}
);
cfg = config.virtualisation;
# Convert legacy VLANs to named interfaces.
vlansNumbered = lib.listToAttrs (
lib.forEach (lib.zipLists cfg.vlans (lib.range 1 255)) (
v:
let
name = "eth${toString v.snd}";
in
lib.nameValuePair name {
inherit name;
vlan = v.fst;
assignIP = true;
}
)
);
in
{
options = {
networking.primaryIPAddress = lib.mkOption {
type = types.str;
default = "";
internal = true;
description = "Primary IP address used in /etc/hosts.";
};
networking.primaryIPv6Address = lib.mkOption {
type = types.str;
default = "";
internal = true;
description = "Primary IPv6 address used in /etc/hosts.";
};
virtualisation.vlans = lib.mkOption {
type = types.listOf types.ints.unsigned;
default = if cfg.interfaces == { } then [ 1 ] else [ ];
defaultText = lib.literalExpression ''if cfg.interfaces == {} then [ 1 ] else [ ]'';
example = [
1
2
];
description = ''
Virtual networks to which the container or VM is connected. Each number «N» in
this list causes the container to have a virtual Ethernet interface
attached to a separate virtual network on which it will be assigned IP
address `192.168.«N».«M»`, where «M» is the index of this container in
the list of containers.
'';
};
virtualisation.interfaces = lib.mkOption {
default = { };
example = {
enp1s0.vlan = 1;
};
description = ''
Extra network interfaces to add to the container or VM in addition to the ones
created by {option}`virtualisation.vlans`.
'';
type = types.attrsOf interfaceType;
};
virtualisation.allInterfaces = lib.mkOption {
type = types.attrsOf interfaceType;
readOnly = true;
description = ''
All network interfaces for the container or VM. Combines
{option}`virtualisation.vlans` and {option}`virtualisation.interfaces`.
'';
default = vlansNumbered // cfg.interfaces;
};
};
config = {
assertions = [
(
let
conflictingKeys = lib.intersectAttrs vlansNumbered cfg.interfaces;
in
{
assertion = conflictingKeys == { };
message = ''
`virtualisation.vlans` and `virtualisation.interfaces` have conflicting keys: ${lib.concatStringsSep "," (lib.attrNames conflictingKeys)}
'';
}
)
(
let
allInterfaceNames =
(lib.mapAttrsToList (k: i: i.name) vlansNumbered)
++ (lib.mapAttrsToList (k: i: i.name) cfg.interfaces);
in
{
assertion = lib.allUnique allInterfaceNames;
message = ''
`virtualisation.vlans` and `virtualisation.interfaces` have conflicting interface names: ${lib.concatStringsSep "," allInterfaceNames}
'';
}
)
];
};
}
@@ -0,0 +1,114 @@
# This module creates a lightweight "container" from the NixOS configuration.
# Building the `config.system.build.nspawn` attribute gives you a command
# that starts a systemd-nspawn container running the NixOS configuration
# defined in `config`. By default, the Nix store is shared read-only with the
# host, which makes (re)building very efficient.
# This shares a lot in common with
# `nixos/modules/virtualisation/nixos-containers.nix`, but doesn't use systemd
# units.
# The networking options here match the options in
# `nixos/modules/virtualisation/nixos-containers.nix` which allows using these
# lightweight containers for nixos integration tests.
{
config,
pkgs,
lib,
...
}:
let
inherit (lib) types;
cfg = config.virtualisation;
in
{
imports = [ ../guest-networking-options.nix ];
options = {
virtualisation.cmdline = lib.mkOption {
type = types.listOf types.str;
default = [ ];
example = [
"systemd.unit=rescue.target"
"systemd.log_level=debug"
"systemd.log_target=console"
];
description = ''
Command line arguments to pass to the init process (likely systemd).
Useful for debugging.
'';
};
virtualisation.rootDir = lib.mkOption {
type = types.str;
default = "./${config.system.name}-root";
defaultText = lib.literalExpression ''"./''${config.system.name}-root"'';
description = ''
Path to a directory for the root filesystem for the container.
The directory will be created on startup if it does not
exist.
'';
};
virtualisation.systemd-nspawn = {
package = lib.mkPackageOption pkgs "systemd" { };
options = lib.mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--bind=/home:/home" ];
description = ''
Options passed to systemd-nspawn.
See [systemd-nspawn docs](https://www.freedesktop.org/software/systemd/man/latest/systemd-nspawn.html) for a complete list.
'';
};
};
};
config = {
boot.isNspawnContainer = true;
# TODO(arianvp): Remove after https://github.com/NixOS/nixpkgs/pull/480686 is merged
console.enable = true;
virtualisation.systemd-nspawn.options = [
"--private-network"
"--machine=${config.system.name}"
"--bind-ro=/nix/store:/nix/store"
# systemd-nspawn does some cleverness to mount a procfs and sysfs in an
# unprivileged container, see
# <https://github.com/systemd/systemd/blob/v258.2/src/nspawn/nspawn.c#L4341-L4349>.
# Unfortunately, this doesn't work in the Nix build sandbox as we do not
# have permission to mount filesystems of type `sysfs` nor `procfs`.
# Fortunately, the build sandbox does provide a `/proc` and `/sys` that
# we can just forward onto the container.
"--private-users=no"
"--bind=/proc:/run/host/proc"
"--bind=/sys:/run/host/sys"
# From `man systemd-nspawn`:
# > Use --keep-unit and --register=no in combination to disable any
# > kind of unit allocation or registration with systemd-machined.
"--keep-unit"
"--register=no"
];
system.build.nspawn =
let
run-nspawn = pkgs.callPackage ./run-nspawn { };
commandLineOptions = lib.cli.toCommandLineShellGNU { } {
container-name = config.system.name;
root-dir = cfg.rootDir;
interfaces-json = builtins.toJSON (lib.attrValues cfg.allInterfaces);
init = "${config.system.build.toplevel}/init";
cmdline-json = builtins.toJSON cfg.cmdline;
};
in
pkgs.writers.writeDashBin "run-${config.system.name}-nspawn" ''
exec ${lib.getExe run-nspawn} ${commandLineOptions} ${lib.escapeShellArgs config.virtualisation.systemd-nspawn.options} "$@"
'';
};
}
@@ -0,0 +1,6 @@
{ python3Packages, systemd }:
python3Packages.callPackage ./package.nix {
# We want `pkgs.systemd`, *not* `python3Packages.systemd`.
inherit systemd;
}
@@ -0,0 +1,54 @@
{
buildPythonApplication,
e2fsprogs,
iproute2,
lib,
mypy,
ruff,
setuptools,
systemd,
}:
buildPythonApplication {
pname = "run-nspawn";
version = "1.0";
pyproject = true;
src = ./src;
postPatch = ''
substituteInPlace run_nspawn/__init__.py \
--replace-fail "@ip@" "${lib.getExe' iproute2 "ip"}" \
--replace-fail "@systemd-nspawn@" "${lib.getExe' systemd "systemd-nspawn"}" \
--replace-fail "@chattr@" "${lib.getExe' e2fsprogs "chattr"}"
'';
build-system = [
setuptools
];
propagatedBuildInputs = [
systemd
iproute2
];
doCheck = true;
nativeCheckInputs = [
mypy
ruff
];
checkPhase = ''
echo -e "\x1b[32m## run mypy\x1b[0m"
mypy run_nspawn
echo -e "\x1b[32m## run ruff check\x1b[0m"
ruff check .
echo -e "\x1b[32m## run ruff format\x1b[0m"
ruff format --check --diff .
'';
meta = {
mainProgram = "run-nspawn";
};
}
@@ -0,0 +1,4 @@
{
pkgs ? import ../../../../.. { },
}:
pkgs.callPackage ./default.nix { }
@@ -0,0 +1,13 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "run-nspawn"
version = "1.0"
[project.scripts]
run-nspawn = "run_nspawn:main"
[tool.setuptools.packages]
find = {}
@@ -0,0 +1,250 @@
import contextlib
import dataclasses
import fcntl
import logging
import os
import signal
import subprocess
import sys
import typing
from pathlib import Path
logger = logging.getLogger()
# Install a SIGTERM handler so all our context managers get a chance to
# clean up.
signal.signal(signal.SIGTERM, lambda _signum, _frame: sys.exit(0))
@dataclasses.dataclass
class Netns:
name: str
path: Path
def run_ip(*args: str) -> None:
subprocess.run(
["@ip@", *args],
check=True,
)
@contextlib.contextmanager
def mk_netns(name: str) -> typing.Generator[Netns, None, None]:
logger.info("creating netns %s", name)
run_ip("netns", "add", name)
try:
yield Netns(name=name, path=Path("/run/netns") / name)
finally:
logger.info("deleting netns %s", name)
run_ip("netns", "delete", name)
@contextlib.contextmanager
def vlan_lock(vlan: int) -> typing.Generator[None, None, None]:
lockfile = Path(f"/run/nixos-nspawn/vlan-{vlan}.lock")
lockfile.parent.mkdir(parents=True, exist_ok=True)
with lockfile.open("w") as f:
# Grab an exclusive lock.
fcntl.flock(f, fcntl.LOCK_EX)
try:
yield
finally:
# Release the exclusive lock.
fcntl.flock(f, fcntl.LOCK_UN)
@contextlib.contextmanager
def ensure_vlan_bridge(vlan: int) -> typing.Generator[str, None, None]:
"""
Ensure a bridge for the given vlan exists, and create one if it does not.
Note that this bridge may get used by other containers, so we're careful
to not delete it unless we're sure nobody else is using it.
"""
# These IP addresses correspond to the static IP assignment logic in
# <nixos/lib/testing/network.nix>.
ipv4_addr = f"192.168.{vlan}.254/24"
ipv6_addr = f"2001:db8:{vlan}::fe/64"
bridge_name = f"br{vlan}"
bridge_path = Path("/sys/class/net") / bridge_name
try:
# To avoid racing against other nspawn containers that also
# need this vlan, grab an exclusive lock.
with vlan_lock(vlan):
if not bridge_path.exists():
logger.info("creating bridge %s", bridge_name)
run_ip("link", "add", bridge_name, "type", "bridge")
run_ip("link", "set", bridge_name, "up")
run_ip("addr", "add", ipv4_addr, "dev", bridge_name)
run_ip("addr", "add", ipv6_addr, "dev", bridge_name)
yield bridge_name
finally:
# To avoid racing against other nspawn containers that also
# releasing this vlan, grab an exclusive lock.
with vlan_lock(vlan):
if bridge_path.exists():
child_intf_count = len(list((bridge_path / "brif").iterdir()))
if child_intf_count == 0:
logger.info("deleting bridge %s", bridge_name)
run_ip("link", "delete", bridge_name)
@contextlib.contextmanager
def mk_veth(
container_name: str,
netns: Netns,
container_intf_name: str,
vlan: int,
) -> typing.Generator[None, None, None]:
host_intf_name = f"{container_name}-{container_intf_name}"
with ensure_vlan_bridge(vlan) as bridge_name:
logger.info("creating interface %s", host_intf_name)
run_ip(
"link",
"add",
host_intf_name,
"type",
"veth",
"peer",
"name",
container_intf_name,
"netns",
netns.name,
)
try:
run_ip("link", "set", host_intf_name, "master", bridge_name)
run_ip("link", "set", host_intf_name, "up")
yield
finally:
logger.info("deleting interface %s", host_intf_name)
run_ip("link", "delete", host_intf_name)
def run(
container_name: str,
root_dir_str: str,
interfaces: dict,
nspawn_options: list[str],
init: str,
cmdline: list[str],
) -> None:
logging.basicConfig(
format=f"nixos-nspawn({container_name}): %(message)s",
level=logging.WARNING,
)
assert os.geteuid() == 0, (
f"systemd-nspawn requires root to work. You are {os.geteuid()}"
)
root_dir = Path(root_dir_str)
root_dir.mkdir(parents=True, exist_ok=True)
root_dir.chmod(0o755)
with (
mk_netns(f"nixos-nspawn-{container_name}") as netns,
contextlib.ExitStack() as stack,
):
for interface in interfaces:
stack.enter_context(
mk_veth(
container_name=container_name,
netns=netns,
container_intf_name=interface["name"],
vlan=interface["vlan"],
)
)
def print_pid() -> None:
print(
f"systemd-nspawn's PID is {os.getpid()}",
# Need to flush stdout before systemd-nspawn gets exec-ed.
flush=True,
)
cp = subprocess.Popen(
[
"@systemd-nspawn@",
*nspawn_options,
f"--directory={root_dir}",
f"--network-namespace-path={netns.path}",
init,
*cmdline,
],
preexec_fn=print_pid,
)
try:
exit_code = cp.wait()
finally:
# If we get interrupted for any reason (most likely a SIGTERM),
# be sure to kill our child process.
cp.terminate()
# NixOS creates `/var/empty` with the immutable filesystem attribute [0].
# This makes it difficult to clean up the machine's root directory
# (which the test driver does to ensure tests start fresh).
# We unset that bit here so others are less likely to run into this issue.
# Note: this may cause issues on filesystems that don't support
# "Linux file attributes". Please improve this if you run into this!
#
# [0]: https://github.com/NixOS/nixpkgs/blob/d1eff395720e1fe15838263642a2bc1dca1eea32/nixos/modules/system/activation/activation-script.nix#L281
subprocess.run(
[
"@chattr@",
"-i",
root_dir / "var/empty",
],
check=True,
)
sys.exit(exit_code)
def main():
import argparse
import json
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument(
"--container-name", required=True, help="Name of the container"
)
arg_parser.add_argument(
"--root-dir",
required=True,
help="Path to container root directory (overridable with RUN_NSPAWN_ROOT_DIR)",
)
arg_parser.add_argument(
"--interfaces-json",
dest="interfaces",
type=json.loads,
required=True,
help="JSON-encoded list of interfaces, each with 'name' and 'vlan' fields",
)
arg_parser.add_argument("--init", required=True, help="Path to init binary")
arg_parser.add_argument(
"--cmdline-json",
dest="cmdline",
type=json.loads,
default=[],
help="JSON-encoded list of command line arguments to pass to init",
)
# Parse only known args to allow for extra args to be passed to systemd-nspawn.
args, nspawn_options = arg_parser.parse_known_args()
run(
container_name=args.container_name,
root_dir_str=os.getenv("RUN_NSPAWN_ROOT_DIR", default=args.root_dir),
interfaces=args.interfaces,
nspawn_options=nspawn_options,
init=args.init,
cmdline=args.cmdline,
)
if __name__ == "__main__":
main()
+1 -65
View File
@@ -365,6 +365,7 @@ in
imports = [
../profiles/qemu-guest.nix
./disk-size-option.nix
./guest-networking-options.nix
(mkRenamedOptionModule
[
"virtualisation"
@@ -679,57 +680,6 @@ in
'';
};
virtualisation.vlans = mkOption {
type = types.listOf types.ints.unsigned;
default = if config.virtualisation.interfaces == { } then [ 1 ] else [ ];
defaultText = lib.literalExpression ''if config.virtualisation.interfaces == {} then [ 1 ] else [ ]'';
example = [
1
2
];
description = ''
Virtual networks to which the VM is connected. Each
number «N» in this list causes
the VM to have a virtual Ethernet interface attached to a
separate virtual network on which it will be assigned IP
address
`192.168.«N».«M»`,
where «M» is the index of this VM
in the list of VMs.
'';
};
virtualisation.interfaces = mkOption {
default = { };
example = {
enp1s0.vlan = 1;
};
description = ''
Network interfaces to add to the VM.
'';
type =
with types;
attrsOf (submodule {
options = {
vlan = mkOption {
type = types.ints.unsigned;
description = ''
VLAN to which the network interface is connected.
'';
};
assignIP = mkOption {
type = types.bool;
default = false;
description = ''
Automatically assign an IP address to the network interface using the same scheme as
virtualisation.vlans.
'';
};
};
});
};
virtualisation.writableStore = mkOption {
type = types.bool;
default = cfg.mountHostNixStore;
@@ -752,20 +702,6 @@ in
'';
};
networking.primaryIPAddress = mkOption {
type = types.str;
default = "";
internal = true;
description = "Primary IP address used in /etc/hosts.";
};
networking.primaryIPv6Address = mkOption {
type = types.str;
default = "";
internal = true;
description = "Primary IPv6 address used in /etc/hosts.";
};
virtualisation.host.pkgs = mkOption {
type = options.nixpkgs.pkgs.type;
default = pkgs;
-1
View File
@@ -99,7 +99,6 @@ rec {
(onFullSupported "nixos.tests.firewall")
(onFullSupported "nixos.tests.fontconfig-default-fonts")
(onFullSupported "nixos.tests.gitlab.gitlab")
(onFullSupported "nixos.tests.gitlab.runner")
(onFullSupported "nixos.tests.gnome")
(onSystems [ "x86_64-linux" ] "nixos.tests.hibernate")
(onFullSupported "nixos.tests.i3wm")
+1 -1
View File
@@ -200,7 +200,7 @@ in
activation-bashless-image = runTest ./activation/bashless-image.nix;
activation-etc-overlay-immutable = runTest ./activation/etc-overlay-immutable.nix;
activation-etc-overlay-mutable = runTest ./activation/etc-overlay-mutable.nix;
activation-lib = pkgs.callPackage ../modules/system/activation/lib/test.nix { };
activation-lib = pkgs.callPackage ../modules/system/activation/lib-test.nix { };
activation-nix-channel = runTest ./activation/nix-channel.nix;
activation-nixos-init = runTest ./activation/nixos-init.nix;
activation-perlless = runTest ./activation/perlless.nix;
+23 -40
View File
@@ -1,36 +1,4 @@
{ lib, ... }:
let
legacyBotPolicyJSON = ''
{
"bots": [
{
"import": "(data)/bots/_deny-pathological.yaml"
},
{
"import": "(data)/meta/ai-block-aggressive.yaml"
},
{
"import": "(data)/crawlers/_allow-good.yaml"
},
{
"import": "(data)/bots/aggressive-brazilian-scrapers.yaml"
},
{
"import": "(data)/common/keep-internet-working.yaml"
},
{
"name": "generic-browser",
"user_agent_regex": "Mozilla|Opera",
"action": "CHALLENGE"
}
],
"dnsbl": false,
"status_codes": {
"CHALLENGE": 200,
"DENY": 200
}
}'';
in
{
name = "anubis";
meta.maintainers = with lib.maintainers; [
@@ -54,7 +22,6 @@ in
services.anubis = {
defaultOptions = {
botPolicy = builtins.fromJSON legacyBotPolicyJSON;
settings = {
DIFFICULTY = 3;
USER_DEFINED_DEFAULT = true;
@@ -92,14 +59,29 @@ in
};
};
instances."botPolicy-default" = {
botPolicy = null;
instances."policy-default" = {
settings = {
TARGET = "http://localhost:8080";
};
};
instances."botPolicy-file" = {
instances."policy-custom" = {
policy = {
extraBots = [
{
name = "custom-allow";
user_agent_regex = "CustomBot/.*";
action = "ALLOW";
}
];
settings.dnsbl = false;
};
settings = {
TARGET = "http://localhost:8080";
};
};
instances."policy-file" = {
settings = {
TARGET = "http://localhost:8080";
POLICY_FNAME = "/etc/anubis-botPolicy.json";
@@ -191,9 +173,10 @@ in
machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "DIFFICULTY=5"')
machine.succeed('cat /run/current-system/etc/systemd/system/anubis-tcp.service | grep "DIFFICULTY=3"')
# Check correct BotPolicy settings are applied
machine.succeed('cat /run/current-system/etc/systemd/system/anubis.service | grep "POLICY_FNAME=/nix/store"')
machine.fail('cat /run/current-system/etc/systemd/system/anubis-botPolicy-default.service | grep "POLICY_FNAME="')
machine.succeed('cat /run/current-system/etc/systemd/system/anubis-botPolicy-file.service | grep "POLICY_FNAME=/etc/anubis-botPolicy.json"')
# Check correct policy settings are applied.
machine.fail('cat /run/current-system/etc/systemd/system/anubis.service | grep "POLICY_FNAME="')
machine.fail('cat /run/current-system/etc/systemd/system/anubis-policy-default.service | grep "POLICY_FNAME="')
machine.succeed('cat /run/current-system/etc/systemd/system/anubis-policy-custom.service | grep "POLICY_FNAME=/nix/store"')
machine.succeed('cat /run/current-system/etc/systemd/system/anubis-policy-file.service | grep "POLICY_FNAME=/etc/anubis-botPolicy.json"')
'';
}
+1 -1
View File
@@ -18,7 +18,7 @@ in
name = "kanidm-provisioning-${kanidmPackage.version}";
meta.maintainers = with pkgs.lib.maintainers; [ oddlama ];
_module.args.kanidmPackage = pkgs.lib.mkDefault pkgs.kanidmWithSecretProvisioning;
_module.args.kanidmPackage = pkgs.lib.mkDefault pkgs.kanidmWithSecretProvisioning_1_7;
nodes.provision =
{ pkgs, lib, ... }:
+1 -1
View File
@@ -21,7 +21,7 @@ in
oddlama
];
_module.args.kanidmPackage = pkgs.lib.mkDefault pkgs.kanidm;
_module.args.kanidmPackage = pkgs.lib.mkDefault pkgs.kanidm_1_7;
nodes.server =
{ pkgs, ... }:
+2 -1
View File
@@ -6,12 +6,13 @@ let
evalConfig = import ../lib/eval-config.nix;
nixos = evalConfig {
system = null;
modules = [
{
system.stateVersion = "25.05";
fileSystems."/".device = "/dev/null";
boot.loader.grub.device = "nodev";
nixpkgs.hostPlatform = pkgs.system;
nixpkgs.hostPlatform = pkgs.stdenv.hostPlatform.system;
virtualisation.vmVariant.networking.hostName = "vm";
virtualisation.vmVariantWithBootLoader.networking.hostName = "vm-w-bl";
}
@@ -6,11 +6,11 @@
melpaBuild rec {
pname = "ebuild-mode";
version = "1.80";
version = "1.81";
src = fetchzip {
url = "https://gitweb.gentoo.org/proj/ebuild-mode.git/snapshot/ebuild-mode-${version}.tar.bz2";
hash = "sha256-pQ177zp0UTk9Koq+yhgaGIeFziV7KFng+Z6sAZs7qzY=";
hash = "sha256-b+59Ec+NOHvFgbFOmnsvGjnq392VR1JCsPx/ORSdffo=";
};
meta = {
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,3 +1,4 @@
import bisect
import os
from pathlib import Path
from tempfile import TemporaryDirectory
@@ -30,7 +31,7 @@ def add_entries(sources, targets, hashes):
if path == target["@url"]:
raise ValueError(f"Unexpected target path {path}")
hashes.append({"url": url, "hash": artefact["sha256sum"], "path": path})
bisect.insort(hashes, {"url": url, "hash": artefact["sha256sum"], "path": path}, key=lambda e: e["url"])
def add_libraries(
@@ -12,12 +12,12 @@
pkgs,
}:
let
version = "0.0.27-unstable-2026-01-09";
version = "0.0.27-unstable-2026-01-20";
src = fetchFromGitHub {
owner = "yetone";
repo = "avante.nvim";
rev = "e89eb79abf5754645e20aa6074da10ed20bba33c";
hash = "sha256-jxbDBvaVtgC0L/MSyoZjGjBxvRUdNofRsiUHwntab7c=";
rev = "08b202a5c5dc93959bfe7dc276adfcba84ecc5be";
hash = "sha256-YDlxwAOimaTFo7mTICQBdb7EQCp8vrBnwjWwxmBImis=";
};
avante-nvim-lib = rustPlatform.buildRustPackage {
pname = "avante-nvim-lib";
@@ -8,13 +8,13 @@
}:
mkLibretroCore {
core = "flycast";
version = "0-unstable-2025-12-29";
version = "0-unstable-2026-01-19";
src = fetchFromGitHub {
owner = "flyinghead";
repo = "flycast";
rev = "4886dcb1c20cd4a85627cc4970d9d01cdf1c2d7d";
hash = "sha256-Lp0MCf8MbqfeSdp6qrWi+q1xgatKl+8HDbTSd5xuzLM=";
rev = "f86e195017fb1595c2622bca3c95e88198194784";
hash = "sha256-Cd3vFpB66Bymv/Zjzd4XO3qJn5vaSnkWV1i5IxtaXXc=";
fetchSubmodules = true;
};
@@ -5,13 +5,13 @@
}:
mkLibretroCore {
core = "genesis-plus-gx";
version = "0-unstable-2025-12-21";
version = "0-unstable-2026-01-16";
src = fetchFromGitHub {
owner = "libretro";
repo = "Genesis-Plus-GX";
rev = "7c5819b7bd0b84c3265ee7dfcd7b90210ed7d687";
hash = "sha256-3YrRWxKk6Uci5MKS5lQYU+edrLdsFYIAR6pTPXwiy8c=";
rev = "3f0f44787b3c9f51eaad3abfbeb86f345d6d8fb1";
hash = "sha256-ZrJIZqkJC39vreiNPeEm764vDW42uv6kZb0rFo4bAXw=";
};
meta = {
+4 -2
View File
@@ -8,6 +8,7 @@
qtmultimedia,
qtscript,
qtserialport,
qtwebsockets,
alsa-lib,
ola,
libftdi1,
@@ -19,13 +20,13 @@
mkDerivation rec {
pname = "qlcplus";
version = "4.13.1";
version = "5.0.0";
src = fetchFromGitHub {
owner = "mcallegari";
repo = "qlcplus";
rev = "QLC+_${version}";
sha256 = "sha256-AKmPxHOlMtea3q0NDULp3XfJ0JnYeF/iFUJw0dDOiio=";
hash = "sha256-gEwcTIJhY78Ts0lUn4MVciV7sPIBkqlxPMa9I1nTHO0=";
};
nativeBuildInputs = [
@@ -38,6 +39,7 @@ mkDerivation rec {
qtmultimedia
qtscript
qtserialport
qtwebsockets
alsa-lib
ola
libftdi1
@@ -833,13 +833,13 @@
"vendorHash": "sha256-duHOqjy8AthXuDX63GO3myJ9TJmV0Ts1a8OsbSOGZWI="
},
"launchdarkly_launchdarkly": {
"hash": "sha256-4vOAkZac3dpYdzZDk+vvqmr/S37q/Gl0HmOAFuDKyag=",
"hash": "sha256-95dvJa6yyBiBVa2/SIUD7vb5jUgKZ2lPhsoBouvswVg=",
"homepage": "https://registry.terraform.io/providers/launchdarkly/launchdarkly",
"owner": "launchdarkly",
"repo": "terraform-provider-launchdarkly",
"rev": "v2.26.0",
"rev": "v2.26.1",
"spdx": "MPL-2.0",
"vendorHash": "sha256-Y1L1nIOubhBN5vNIXY7miQgR9OzoTCS7QA55DEMwDSA="
"vendorHash": "sha256-JRqLG+lM7emw8F0J2mVt4xHKvLG/TC/FNZiiXd0dKZY="
},
"linode_linode": {
"hash": "sha256-/igrYgWTM4vujH2PFzXijVhHw0gQzLUwFZJd+RM0hSQ=",
@@ -1,8 +1,8 @@
{
"linux-canary": {
"hash": "sha256-2o0SBMbtozibAIL7lHDJ2LfNjbDKY578PvcNdFs/AC4=",
"url": "https://canary.dl2.discordapp.net/apps/linux/0.0.844/discord-canary-0.0.844.tar.gz",
"version": "0.0.844"
"hash": "sha256-jomLXlIr+ajJspmh/seNb48alPSuCw8ybYkfc0uAziE=",
"url": "https://canary.dl2.discordapp.net/apps/linux/0.0.852/discord-canary-0.0.852.tar.gz",
"version": "0.0.852"
},
"linux-development": {
"hash": "sha256-EVkjWoqWl9Z+iHCLPOLu4PIUb2wC3HVcPVjOVz++IVw=",
@@ -15,19 +15,19 @@
"version": "0.0.172"
},
"linux-stable": {
"hash": "sha256-/NfgHBXsUWYoDEVGz13GBU1ISpSdB5OmrjhSN25SBMg=",
"url": "https://stable.dl2.discordapp.net/apps/linux/0.0.119/discord-0.0.119.tar.gz",
"version": "0.0.119"
"hash": "sha256-4rJ0l0zSoOz7L65sy3Gegcsb/nJGGFu6h5TGAb0fqUI=",
"url": "https://stable.dl2.discordapp.net/apps/linux/0.0.120/discord-0.0.120.tar.gz",
"version": "0.0.120"
},
"osx-canary": {
"hash": "sha256-qh5+hCEQXivdugj5jzS+i1ftmyh6l2YEE63oS+qV2Go=",
"url": "https://canary.dl2.discordapp.net/apps/osx/0.0.948/DiscordCanary.dmg",
"version": "0.0.948"
"hash": "sha256-ZzqakVB2Rkcq5zME2WnSCw1CLzpD3VDM/pu4nQ7rRNs=",
"url": "https://canary.dl2.discordapp.net/apps/osx/0.0.956/DiscordCanary.dmg",
"version": "0.0.956"
},
"osx-development": {
"hash": "sha256-y840b3WlWnSK+22l7AoasQbDmbB+2LOzbxA13yJxrPA=",
"url": "https://development.dl2.discordapp.net/apps/osx/0.0.106/DiscordDevelopment.dmg",
"version": "0.0.106"
"hash": "sha256-B1//zMlTv2+RWHfWZSaaU8ubVOwWob+EYjNdtFRwlgg=",
"url": "https://development.dl2.discordapp.net/apps/osx/0.0.107/DiscordDevelopment.dmg",
"version": "0.0.107"
},
"osx-ptb": {
"hash": "sha256-tjWbvWOvSinVZDvJYFFcbmr+y7W5PmIr/alrS82ECBo=",
@@ -35,8 +35,8 @@
"version": "0.0.204"
},
"osx-stable": {
"hash": "sha256-OjHYJNZlM/cOLM61qvoauzNl3f/GVPdJMsnM+kxc/38=",
"url": "https://stable.dl2.discordapp.net/apps/osx/0.0.371/Discord.dmg",
"version": "0.0.371"
"hash": "sha256-PkZU/1GxPmfxq2qP/5gGU85EFYPI1V42iHfoy9x9fKI=",
"url": "https://stable.dl2.discordapp.net/apps/osx/0.0.372/Discord.dmg",
"version": "0.0.372"
}
}
@@ -435,14 +435,14 @@ in
docker_29 =
let
version = "29.1.3";
version = "29.1.5";
in
callPackage dockerGen {
inherit version;
cliRev = "v${version}";
cliHash = "sha256-8VpFDYn9mRFv7BnHek2+HvIu6jNPYNC1asozJvRX/A4=";
cliHash = "sha256-fg18lmJsMoy7lpL4hGkIhM0LKnhEY5nl5f0YuW8yg0A=";
mobyRev = "docker-v${version}";
mobyHash = "sha256-yB6FF4tzi6R+wH6U0JS8PMZGVRl1gWCY2Cjb/JR+62w=";
mobyHash = "sha256-iUoqJT0lIiVh5WaHzlw71QXxc3sEsSpQpADb0KveXNQ=";
runcRev = "v1.3.4";
runcHash = "sha256-1IfY08sBoDpbLrwz1AKBRSTuCZyOgQzYPHTDUI6fOZ8=";
containerdRev = "v2.2.0";
@@ -53,6 +53,12 @@
buildInputs = [ alsa-lib ];
};
# Force using the cmake backend. At least on Darwin, the build else gets confused and fails.
aws-lc-sys = prev: {
nativeBuildInputs = [ cmake ];
env.AWS_LC_SYS_CMAKE_BUILDER = 1;
};
cairo-rs = attrs: {
buildInputs = [ cairo ];
};
+5 -5
View File
@@ -29,15 +29,15 @@
},
"beta": {
"linux": {
"version": "8.11.22-26.BETA",
"version": "8.12.0-11.BETA",
"sources": {
"x86_64": {
"url": "https://downloads.1password.com/linux/tar/beta/x86_64/1password-8.11.22-26.BETA.x64.tar.gz",
"hash": "sha256-lkQypBqr1VX/+8yz5PhUULKG9ZpuXjeS/ZNLL1Qzdcs="
"url": "https://downloads.1password.com/linux/tar/beta/x86_64/1password-8.12.0-11.BETA.x64.tar.gz",
"hash": "sha256-0PDkZAqlY/afocvc/rcly/nwZeSSbXdRyXH57aVPUoQ="
},
"aarch64": {
"url": "https://downloads.1password.com/linux/tar/beta/aarch64/1password-8.11.22-26.BETA.arm64.tar.gz",
"hash": "sha256-1PrkmOWBenPvQIiHlq4RAKzItYLVj5DkGD38eGFDlHM="
"url": "https://downloads.1password.com/linux/tar/beta/aarch64/1password-8.12.0-11.BETA.arm64.tar.gz",
"hash": "sha256-0YDJKexCdOeU0/KPsJzI5rBUlbDEFW5N33LFXtDo3tg="
}
}
},
+3 -3
View File
@@ -7,16 +7,16 @@
buildGoModule rec {
pname = "ali";
version = "0.7.5";
version = "0.8.0";
src = fetchFromGitHub {
owner = "nakabonne";
repo = "ali";
tag = "v${version}";
hash = "sha256-/pdHlI20IzSTX2pnsbxPiJiWmOCbp13eJWLi0Tcsueg=";
hash = "sha256-iwuvWqDaaf/U8f4KDeq1gs+FlDoC11uDs+l2Z7Npd6M=";
};
vendorHash = "sha256-YWx9K04kTMaI0FXebwRQVCt0nxIwZ6xlbtI2lk3qp0M=";
vendorHash = "sha256-pRxkRY0MkQGnNhA/3CtT0ohKAPNx8QeyuD6bcacYHGI=";
meta = {
description = "Generate HTTP load and plot the results in real-time";
+3 -2
View File
@@ -3,6 +3,7 @@
enableDaemon ? false, # build amule daemon
httpServer ? false, # build web interface for the daemon
client ? false, # build amule remote gui
mainProgram ? "amule",
fetchFromGitHub,
fetchpatch,
stdenv,
@@ -103,10 +104,10 @@ stdenv.mkDerivation rec {
no adware or spyware as is often found in proprietary P2P
applications.
'';
homepage = "https://github.com/amule-project/amule";
license = lib.licenses.gpl2Plus;
maintainers = [ ];
maintainers = with lib.maintainers; [ aciceri ];
inherit mainProgram;
platforms = lib.platforms.unix;
# Undefined symbols for architecture arm64: "_FSFindFolder"
broken = stdenv.hostPlatform.isDarwin;
+1 -1
View File
@@ -95,7 +95,7 @@ let
(with pkgs; [
xorg.libxkbfile
xorg.libxshmfence
xcb-util-cursor-HEAD
libxcb-cursor
krb5
zstd
]);
+3 -3
View File
@@ -13,13 +13,13 @@ let
pkg = buildGoModule (finalAttrs: {
pname = "arduino-cli";
version = "1.4.0";
version = "1.4.1";
src = fetchFromGitHub {
owner = "arduino";
repo = "arduino-cli";
tag = "v${finalAttrs.version}";
hash = "sha256-H7vccxDzJt0e/91PIV6Qg8nRD0beb/3g7AZ4uk2ebXU=";
hash = "sha256-2m0V7yj6C7Lvlu9RaM54pbGKSwrek6WYuwH1yqYHdB0=";
};
nativeBuildInputs = [
@@ -31,7 +31,7 @@ let
subPackages = [ "." ];
vendorHash = "sha256-GPZLvEgL/2Ekfj58d8dsbc6e2hHB2zUapvFdIT43hhQ=";
vendorHash = "sha256-5bkaHEzQ2gLV1epkScbCf1qv5XeuewLwqNcpPCSdbh4=";
postPatch =
let
+8 -7
View File
@@ -12,7 +12,7 @@
rustPlatform.buildRustPackage (finalAttrs: {
pname = "arti";
version = "1.7.0";
version = "1.9.0";
src = fetchFromGitLab {
domain = "gitlab.torproject.org";
@@ -20,10 +20,10 @@ rustPlatform.buildRustPackage (finalAttrs: {
owner = "core";
repo = "arti";
tag = "arti-v${finalAttrs.version}";
hash = "sha256-4Vx5ATVdE8AoMWjDKKkwGOFVOwI0Qhyfr8MiAo+7MNw=";
hash = "sha256-b5DWu38/iKwKcmp4BNgkeE5F522YRZZiev9gUZ/Rb1E=";
};
cargoHash = "sha256-x1Pws9XbvwZqxJTJmPHQd6qbNLgkHxCK3YIZbRylk2M=";
cargoHash = "sha256-SGxSZaY8//FHhySbarfgleafF5YEWJW/fUAwo3576NI=";
nativeBuildInputs = lib.optionals stdenv.hostPlatform.isLinux [ pkg-config ];
@@ -54,12 +54,13 @@ rustPlatform.buildRustPackage (finalAttrs: {
checkFlags = [
# problematic test that hangs the build
"--skip=reload_cfg::test::watch_single_file"
# some of the cli tests attempt to validate that the filesystem and build
# is securely configured, which is somewhat broken by the nix build sandbox
"--skip=cli_tests"
];
# some of the CLI tests attempt to validate that the filesystem and runtime
# environment are securely configured, which breaks inside the nix build
# sandbox. this does NOT affect downstream users of Arti.
env.ARTI_FS_DISABLE_PERMISSION_CHECKS = 1;
nativeInstallCheckInputs = [
versionCheckHook
];
+3 -3
View File
@@ -18,16 +18,16 @@
}:
rustPlatform.buildRustPackage rec {
pname = "asusctl";
version = "6.2.0";
version = "6.3.1";
src = fetchFromGitLab {
owner = "asus-linux";
repo = "asusctl";
tag = version;
hash = "sha256-frQbfCdK7bD6IAUa+MAOaRLhMrbdFRdHocQ0Z1tzsqE=";
hash = "sha256-x3WKxjYrWYaLWDi52b3uQSYnr/Qunf6JYu4ikt4ajls=";
};
cargoHash = "sha256-Z3JFp/qH3mD3Hy/kqSONOZ+syulgr+t0ZzFRvNN+Ayg=";
cargoHash = "sha256-FyVbeHzwMr8UJ2OoVYVekXJFhus/ab7KwfGK4eaua6A=";
postPatch = ''
files="
+5 -2
View File
@@ -13,7 +13,7 @@
stdenv.mkDerivation (finalAttrs: {
pname = "babl";
version = "0.1.116";
version = "0.1.120";
outputs = [
"out"
@@ -23,7 +23,7 @@ stdenv.mkDerivation (finalAttrs: {
src = fetchurl {
url = "https://download.gimp.org/pub/babl/${lib.versions.majorMinor finalAttrs.version}/babl-${finalAttrs.version}.tar.xz";
hash = "sha256-UPrgaYZ8et4SWYiP8ePbhf7IbXCCUuU4W1pPOaeOxIM=";
hash = "sha256-9HatFSAftO0MkMF0xSSx5CcczWmjdyQtamn834fOrMI=";
};
patches = [
@@ -46,6 +46,9 @@ stdenv.mkDerivation (finalAttrs: {
mesonFlags = [
"-Dprefix-dev=${placeholder "dev"}"
# On Linux, this would be disabled by default but we have -Dauto_features=enabled.
# Disable it on other platforms too, since I cannot test it there.
"-Drelocatable=disabled"
]
++ lib.optionals (stdenv.buildPlatform != stdenv.hostPlatform) [
# Docs are opt-out in native but opt-in in cross builds.
+3 -3
View File
@@ -5,13 +5,13 @@
}:
stdenv.mkDerivation (finalAttrs: {
pname = "base16-schemes";
version = "0-unstable-2025-11-08";
version = "0-unstable-2026-01-15";
src = fetchFromGitHub {
owner = "tinted-theming";
repo = "schemes";
rev = "4ac26dc99141c1b2a26eb7fefe46e22e07eec77c";
hash = "sha256-pr+RtDs+3qo0v7ZXfcSdtP0PoDDPU9EHw2Oe5EUwWtQ=";
rev = "43dd14f6466a782bd57419fdfb5f398c74d6ac53";
hash = "sha256-AWTIYZ1tZab0YwAQwgt5yO4ucqZoc4iXX002Byy7pRY=";
};
installPhase = ''
+6 -3
View File
@@ -2,6 +2,7 @@
lib,
rustPlatform,
fetchFromGitHub,
nix-update-script,
stdenv,
pkg-config,
makeWrapper,
@@ -13,16 +14,16 @@
}:
rustPlatform.buildRustPackage (finalAttrs: {
pname = "bilibili-tui";
version = "1.0.6";
version = "1.0.9";
src = fetchFromGitHub {
owner = "MareDevi";
repo = "bilibili-tui";
tag = "v${finalAttrs.version}";
hash = "sha256-nWUFcKQgUNaiVU0zgSB8LTdvUruc8fovCAembQz5w3I=";
hash = "sha256-LACNDpVhlYEgT3fN+Ff2MVipblUqPlqwOUpTLaXSCbk=";
};
cargoHash = "sha256-KvJpMQuvZM/s3b4/Pzmeucb95KeuuUx4bz3sJsKyLc8=";
cargoHash = "sha256-q3jRjmzQA64sZjVShoEmu1x2CFOAgBGgZYyTq7Lg4is=";
nativeBuildInputs = [ makeWrapper ] ++ lib.optionals (!stdenv.hostPlatform.isDarwin) [ pkg-config ];
@@ -41,6 +42,8 @@ rustPlatform.buildRustPackage (finalAttrs: {
}
'';
passthru.updateScript = nix-update-script { };
meta = {
description = "Terminal user interface (TUI) client for Bilibili";
homepage = "https://maredevi.moe/projects/bilibili-tui/";
+2 -2
View File
@@ -6,13 +6,13 @@
buildGoModule rec {
pname = "butane";
version = "0.25.1";
version = "0.26.0";
src = fetchFromGitHub {
owner = "coreos";
repo = "butane";
rev = "v${version}";
hash = "sha256-HrLnXkaayCmMrvW79NSYrmI0ujfHtRwWmonkbvTXEXY=";
hash = "sha256-htD/FecmBVUp0bmzDJpUNw8rVr9mheFwagUISFu8lJM=";
};
vendorHash = null;
+4 -2
View File
@@ -13,7 +13,7 @@ rustPlatform.buildRustPackage rec {
src = fetchFromGitHub {
owner = "nextest-rs";
repo = "nextest";
rev = "cargo-nextest-${version}";
tag = "cargo-nextest-${version}";
hash = "sha256-Ff9GibY6pm7+NbgAB8iNO+uj+uK1sxU+UkaiIS5BLEk=";
};
@@ -33,7 +33,9 @@ rustPlatform.buildRustPackage rec {
"cargo-nextest"
];
passthru.updateScript = nix-update-script { };
passthru.updateScript = nix-update-script {
extraArgs = [ "--version-regex=^cargo-nextest-([0-9.]+)$" ];
};
meta = {
description = "Next-generation test runner for Rust projects";
+18 -8
View File
@@ -4,7 +4,7 @@
fetchurl,
libX11,
bison,
ksh,
mksh,
perl,
libXinerama,
libXt,
@@ -33,15 +33,18 @@
flex,
libXpm,
rpcsvc-proto,
sessreg,
pkg-config,
lmdb,
}:
stdenv.mkDerivation rec {
stdenv.mkDerivation (finalAttrs: {
pname = "cde";
version = "2.5.1";
version = "2.5.3";
src = fetchurl {
url = "mirror://sourceforge/cdesktopenv/cde-${version}.tar.gz";
hash = "sha256-caslezz2kbljwApv5igDPH345PK2YqQUTi1YZgvM1Dw=";
url = "mirror://sourceforge/cdesktopenv/cde-${finalAttrs.version}.tar.gz";
hash = "sha256-K1jAjr8Ka7nUoyGRzSXiBPXYy6gbzKo2/HL1xKqXmFQ=";
};
postPatch = ''
@@ -62,7 +65,7 @@ stdenv.mkDerivation rec {
done
substituteInPlace configure.ac \
--replace "-I/usr/include/tirpc" "-I${libtirpc.dev}/include/tirpc"
--replace-warn "-I/usr/include/tirpc" "-I${libtirpc.dev}/include/tirpc"
patchShebangs autogen.sh config.rpath contrib programs
'';
@@ -82,9 +85,11 @@ stdenv.mkDerivation rec {
libXScrnSaver
tcl
libXaw
ksh
mksh
libxcrypt
libXpm
sessreg
lmdb
];
nativeBuildInputs = [
bison
@@ -100,10 +105,15 @@ stdenv.mkDerivation rec {
perl
flex
rpcsvc-proto
pkg-config
];
enableParallelBuilding = true;
# Can probably remove after next release
# https://sourceforge.net/p/cdesktopenv/code/ci/f0154141b1f1501490bac8e0235214bf8f00f715/
env.NIX_CFLAGS_COMPILE = "-std=gnu17";
preConfigure = ''
export LOCALE_ARCHIVE="${glibcLocales}/lib/locale/locale-archive"
'';
@@ -123,4 +133,4 @@ stdenv.mkDerivation rec {
maintainers = [ ];
platforms = lib.platforms.linux;
};
}
})
+2 -2
View File
@@ -8,13 +8,13 @@
stdenv.mkDerivation (finalAttrs: {
pname = "cgif";
version = "0.5.0";
version = "0.5.1";
src = fetchFromGitHub {
owner = "dloebl";
repo = "cgif";
tag = "v${finalAttrs.version}";
hash = "sha256-i8xngmVhRCGkczY3NzomLkXj+iqPb81lvLn6dXsByYs=";
hash = "sha256-Vnm0YIMoU6gJCxSP28mqBtqZnfhmhmvaSp5DvZJqW/A=";
};
nativeBuildInputs = [
+17 -4
View File
@@ -1,33 +1,46 @@
{
stdenv,
lib,
fetchFromGitHub,
rustPlatform,
openssl,
pkg-config,
alsa-lib,
nix-update-script,
}:
rustPlatform.buildRustPackage (finalAttrs: {
pname = "chess-tui";
version = "2.0.0";
version = "2.3.0";
src = fetchFromGitHub {
owner = "thomas-mauran";
repo = "chess-tui";
tag = finalAttrs.version;
hash = "sha256-SIQoi/pnbS1TyX6iA8azo0nVfsCQd6ntn9VZCz/Zkgw=";
hash = "sha256-g+rKib+ZoBa2ssYKgS0tg0xngurY1z3DbBZZEn/LJU4=";
};
cargoHash = "sha256-aWj8ruu/Y/VCgvhAkWVfDDztmVzHsZix88JUAOYttmg=";
cargoHash = "sha256-Brj+9AS0ZR/b188jkJa84WRHk0HtiKpMlyMUSLmzBfA=";
checkFlags = [
# assertion failed: result.is_ok()
"--skip=tests::test_config_create"
];
buildInputs = [ openssl ];
buildInputs = [
openssl
]
# alsa-lib is required for the alsa-sys. alsa-lib does not compile on darwin
++ lib.optionals stdenv.hostPlatform.isLinux [ alsa-lib ]
# bindgenHook is required for coreaudio-sys on darwin
++ lib.optionals stdenv.hostPlatform.isDarwin [ rustPlatform.bindgenHook ];
nativeBuildInputs = [ pkg-config ];
PKG_CONFIG_PATH = "${openssl.dev}/lib/pkgconfig";
passthru.updateScript = nix-update-script { };
meta = {
description = "Chess TUI implementation in rust";
homepage = "https://github.com/thomas-mauran/chess-tui";
+3 -3
View File
@@ -8,16 +8,16 @@
buildGoModule rec {
pname = "cirrus-cli";
version = "0.159.1";
version = "0.160.0";
src = fetchFromGitHub {
owner = "cirruslabs";
repo = "cirrus-cli";
rev = "v${version}";
hash = "sha256-Zf7muVwJQzye5YEeQtRbHQ2SmFFap7BMze9YuJv1ABU=";
hash = "sha256-odD2ap2Z+Wsrz3XIDJrGyxbsrMvZBp3kQJ64LhIpc74=";
};
vendorHash = "sha256-n2Bmx4EJ+L6+rlvfG/2FD4Ua9bG9GVcnvD+QPfQg/HE=";
vendorHash = "sha256-zW0xX4E2Wr/liL2RMGiU1wpwFbeiuex1owWisysHJsc=";
ldflags = [
"-X github.com/cirruslabs/cirrus-cli/internal/version.Version=v${version}"
+3 -3
View File
@@ -6,18 +6,18 @@
buildGoModule rec {
pname = "cnquery";
version = "12.18.0";
version = "12.19.0";
src = fetchFromGitHub {
owner = "mondoohq";
repo = "cnquery";
tag = "v${version}";
hash = "sha256-aDpWVujFSKTRDZW764LzNmqJkb61tfdLPN/JT81NrZs=";
hash = "sha256-lFnXkBPokDO/eduWhg/lSqqjRhC8/5tGqkS/RZHhZnU=";
};
subPackages = [ "apps/cnquery" ];
vendorHash = "sha256-OliliGBpFPPJnYZ3wQ2q7t+9bsiN5ik0FJrNGlVxivo=";
vendorHash = "sha256-WnUCDiDfIC2Cl1LEpkZlT5tGFMaWb5htX8VFmJBEjbI=";
ldflags = [
"-w"
+3 -3
View File
@@ -9,17 +9,17 @@
}:
rustPlatform.buildRustPackage rec {
pname = "codeberg-cli";
version = "0.5.1";
version = "0.5.4";
src = fetchFromGitea {
domain = "codeberg.org";
owner = "Aviac";
repo = "codeberg-cli";
rev = "v${version}";
hash = "sha256-81435dgw7fy4igUN3TYNjRans8uRZ/6TQWBxu0benwU=";
hash = "sha256-o+Jf9JKDGsnSVV8sJcJddZG+9DBn6DB4HfaxLxxwa+U=";
};
cargoHash = "sha256-1E7UuDbJKrnhMQI6trk7nHkeywCPFg1021pQhRcb4kQ=";
cargoHash = "sha256-HBVswxako/Djv8ayhEfgGVaFWblNn6ngtbQh9jNaxcQ=";
nativeBuildInputs = [
pkg-config
installShellFiles
+4 -4
View File
@@ -5,7 +5,7 @@
"packages": {
"": {
"dependencies": {
"codebuff": "^1.0.581"
"codebuff": "^1.0.589"
}
},
"node_modules/chownr": {
@@ -18,9 +18,9 @@
}
},
"node_modules/codebuff": {
"version": "1.0.581",
"resolved": "https://registry.npmjs.org/codebuff/-/codebuff-1.0.581.tgz",
"integrity": "sha512-3lMaeo/TqALXwPWwPvwaIGaVlJcz7cXisEvEGqG4qjOUIFPd+mpiZBw1nF64U67fSxkjvll1/JNKk/mZTEAVng==",
"version": "1.0.589",
"resolved": "https://registry.npmjs.org/codebuff/-/codebuff-1.0.589.tgz",
"integrity": "sha512-e6Fxe49DgX9qx8itMEM7HBro73MhZZXUUYkbQh4+NBHQs9711bja1DN9PzqzKpluFJ3BmU/e67CG70uBrxmavA==",
"cpu": [
"x64",
"arm64"
+3 -3
View File
@@ -6,14 +6,14 @@
buildNpmPackage rec {
pname = "codebuff";
version = "1.0.581";
version = "1.0.589";
src = fetchzip {
url = "https://registry.npmjs.org/codebuff/-/codebuff-${version}.tgz";
hash = "sha256-A5sEqkw9nm9ijyq7FT0vVNegbDl1LXQHI62dfdP/0WI=";
hash = "sha256-kW8I+Aw87O21g56Gy5Z8R+Snuxqr78fHVTckuIp31hQ=";
};
npmDepsHash = "sha256-CEoacNXow99r4i9cF2BUA5dNcgU1dCBc4dq0n0p7CBU=";
npmDepsHash = "sha256-8+u7/1oQ19ZnA1EZrAgrwppliOZWPb+PJ22xHr6WFKE=";
postPatch = ''
cp ${./package-lock.json} package-lock.json
+4 -4
View File
@@ -5,6 +5,7 @@
cmake,
pkg-config,
boxed-cpp,
cairo,
freetype,
fontconfig,
libunicode,
@@ -28,13 +29,13 @@
stdenv.mkDerivation (finalAttrs: {
pname = "contour";
version = "0.6.1.7494";
version = "0.6.2.8008";
src = fetchFromGitHub {
owner = "contour-terminal";
repo = "contour";
tag = "v${finalAttrs.version}";
hash = "sha256-jgasZhdcJ+UF3VIl8HLcxBayvbA/dkaOG8UtANRgeP4=";
hash = "sha256-xbJxV1q7+ddhnH0jDYzqVHwARCD0EyVh3POFRkl4d1Q=";
};
patches = lib.optionals stdenv.hostPlatform.isDarwin [
@@ -59,6 +60,7 @@ stdenv.mkDerivation (finalAttrs: {
buildInputs = [
boxed-cpp
cairo
fontconfig
freetype
libunicode
@@ -79,8 +81,6 @@ stdenv.mkDerivation (finalAttrs: {
darwin.libutil
];
cmakeFlags = [ "-DCONTOUR_QT_VERSION=6" ];
postInstall = ''
mkdir -p $out/nix-support $terminfo/share
''
+1 -1
View File
@@ -60,7 +60,7 @@ stdenv.mkDerivation (finalAttrs: {
meta = {
description = "Schrodinger-developed 2D Coordinate Generation";
homepage = "https://github.com/schrodinger/coordgenlibs";
changelog = "https://github.com/schrodinger/coordgenlibs/releases/tag/${finalAttrs.version}";
changelog = "https://github.com/schrodinger/coordgenlibs/releases/tag/v${finalAttrs.version}";
maintainers = [ lib.maintainers.rmcgibbo ];
license = lib.licenses.bsd3;
};
@@ -7,16 +7,16 @@
buildGoModule rec {
pname = "coroot-node-agent";
version = "1.27.2";
version = "1.27.3";
src = fetchFromGitHub {
owner = "coroot";
repo = "coroot-node-agent";
rev = "v${version}";
hash = "sha256-bA23qnC94hrmyQWR5kAKR27wzs55AJPC3Ix/l/9YCEY=";
hash = "sha256-uIj74Su2ICB5v/khMgCJXps+HQUT67U6kI06QzNs+nc=";
};
vendorHash = "sha256-jMR/ylMEgNDOn5mDkJU38h9h2rinCX7/jtOyjDos5Qc=";
vendorHash = "sha256-adrXNMdR20K+DLexLebvjgcQFV9XLqYdHZW5hg/Zk8w=";
buildInputs = [ systemdLibs ];
+1 -1
View File
@@ -49,7 +49,7 @@ stdenv.mkDerivation (finalAttrs: {
};
meta = {
changelog = "https://github.com/cowsql/cowsql/releases/tag/${finalAttrs.version}";
changelog = "https://github.com/cowsql/cowsql/releases/tag/v${finalAttrs.version}";
description = "Embeddable, replicated and fault tolerant SQL engine";
homepage = "https://github.com/cowsql/cowsql";
license = lib.licenses.lgpl3Only;
+13 -19
View File
@@ -8,23 +8,25 @@
nix-update-script,
withServer ? true,
}:
let
rustPlatform.buildRustPackage (finalAttrs: {
pname = "cup-docker";
version = "3.4.3";
version = "3.5.1";
src = fetchFromGitHub {
owner = "sergi0g";
repo = "cup";
tag = "v${version}";
hash = "sha256-RRhUSL9TR7qr93F5+fyhGW7j6VTs+yVvpni/JHmC5os=";
tag = "v${finalAttrs.version}";
hash = "sha256-l7TQwCzQNwrsM+xRcRcQaxIsnd8SVzrqEMwIoZGVBR0=";
};
web = stdenvNoCC.mkDerivation (finalAttrs: {
pname = "${pname}-web";
inherit version src;
web = stdenvNoCC.mkDerivation (finalAttrsWeb: {
pname = "${finalAttrs.pname}-web";
inherit (finalAttrs) version src;
impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [
"GIT_PROXY_COMMAND"
"SOCKS_SERVER"
];
sourceRoot = "${finalAttrs.src.name}/web";
sourceRoot = "${finalAttrsWeb.src.name}/web";
nativeBuildInputs = [
bun
nodejs-slim_latest
@@ -47,17 +49,10 @@ let
cp -R ./dist $out
runHook postInstall
'';
outputHash = "sha256-Ac1PJYmTQv9XrmhmF1p77vdXh8252hz0CUKxJA+VQR4=";
outputHash = "sha256-uLsWppRabaI7JSHYf3YsEvf0Y36kU/iuNXnDXd+6AXY=";
outputHashAlgo = "sha256";
outputHashMode = "recursive";
});
in
rustPlatform.buildRustPackage {
inherit
src
version
pname
;
cargoHash = "sha256-1VSbv6lDRRLZIu7hYrAqzQmvxcuhnPU0rcWfg7Upcm4=";
@@ -70,11 +65,10 @@ rustPlatform.buildRustPackage {
];
preConfigure = lib.optionalString withServer ''
cp -r ${web}/dist src/static
cp -r ${finalAttrs.web}/dist src/static
'';
passthru = {
inherit web;
updateScript = nix-update-script {
extraArgs = [
"--subpackage"
@@ -94,4 +88,4 @@ rustPlatform.buildRustPackage {
kuflierl
];
};
}
})
+21 -8
View File
@@ -2,28 +2,41 @@
lib,
buildGoModule,
fetchFromGitHub,
nix-update-script,
# testing
sqlite,
}:
buildGoModule rec {
buildGoModule (finalAttrs: {
pname = "dbmate";
version = "2.28.0";
version = "2.29.3";
src = fetchFromGitHub {
owner = "amacneil";
repo = "dbmate";
tag = "v${version}";
hash = "sha256-DQTeLqlZmzfTQoJBTFTX8x3iplkmrl1cplDQQcCGCZM=";
tag = "v${finalAttrs.version}";
hash = "sha256-H/HBDM2uBRrlgetU2S9ZS1c6//Le+DlrYlnnJpTs3XM=";
};
vendorHash = "sha256-Js0hiRt6l3ur7+pfeYa35C17gr77NHvapaSrgF9cP8c=";
vendorHash = "sha256-wfcVb8fqnpT8smKuL6SPANAK86tLXglhQPZCA4G8P9E=";
doCheck = false;
tags = [ "fts5" ];
nativeCheckInputs = [
sqlite
];
passthru.updateScript = nix-update-script { };
meta = {
description = "Database migration tool";
mainProgram = "dbmate";
homepage = "https://github.com/amacneil/dbmate";
changelog = "https://github.com/amacneil/dbmate/releases/tag/v${version}";
changelog = "https://github.com/amacneil/dbmate/releases/tag/${finalAttrs.src.tag}";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [
sarahec
];
};
}
})
+15 -3
View File
@@ -3,16 +3,17 @@
buildGoModule,
fetchFromGitHub,
stdenv,
nix-update-script,
}:
buildGoModule rec {
buildGoModule (finalAttrs: {
pname = "delve";
version = "1.26.0";
src = fetchFromGitHub {
owner = "go-delve";
repo = "delve";
rev = "v${version}";
tag = "v${finalAttrs.version}";
hash = "sha256-tFd8g866nRSNUVNz+6SM6YLl4ys3AUP3c8eT1kWbjKY=";
};
@@ -24,6 +25,11 @@ buildGoModule rec {
subPackages = [ "cmd/dlv" ];
ldflags = [
"-s"
"-w"
];
hardeningDisable = [ "fortify" ];
preCheck = ''
@@ -44,11 +50,17 @@ buildGoModule rec {
ln $out/bin/dlv $out/bin/dlv-dap
'';
# delve doesn't support --version
doInstallCheck = false;
passthru.updateScript = nix-update-script { };
meta = {
description = "Debugger for the Go programming language";
homepage = "https://github.com/go-delve/delve";
changelog = "https://github.com/go-delve/delve/blob/v${finalAttrs.version}/CHANGELOG.md";
maintainers = with lib.maintainers; [ vdemeester ];
license = lib.licenses.mit;
mainProgram = "dlv";
};
}
})
+3 -3
View File
@@ -9,16 +9,16 @@
buildGoModule (finalAttrs: {
pname = "dnscontrol";
version = "4.30.0";
version = "4.31.0";
src = fetchFromGitHub {
owner = "StackExchange";
repo = "dnscontrol";
tag = "v${finalAttrs.version}";
hash = "sha256-SLcOG42Pd0RgDT98qNgceovDYbBvF0N7/ItkjBlEtLY=";
hash = "sha256-8Pb/njUjiyUQZA3UnZ+4INJBnmXCo+F7+BhCDt1hJGQ=";
};
vendorHash = "sha256-OsBVyWCPoVKBXmE/NH3r7KUH4TFCNkKu3LGJlW7dNqI=";
vendorHash = "sha256-GMzLaV3LQNa4K111P6DLG28KAAgj9AHyPua4XSih14k=";
nativeBuildInputs = [ installShellFiles ];
+2 -2
View File
@@ -30,11 +30,11 @@ let
in
stdenv.mkDerivation rec {
pname = "dnsmasq";
version = "2.91";
version = "2.92";
src = fetchurl {
url = "https://www.thekelleys.org.uk/dnsmasq/${pname}-${version}.tar.xz";
hash = "sha256-9iJoKEizNnetsratCCZGGKKuCgHaSGqT/YzZEYaz0VM=";
hash = "sha256-S/UMLBAY+fvCYDffUbkOzqDLc9RhYoRnY7kt8NbDpFg=";
};
postPatch = lib.optionalString stdenv.hostPlatform.isLinux ''
-29
View File
@@ -1,29 +0,0 @@
{
lib,
stdenv,
buildGoModule,
fetchFromGitHub,
}:
buildGoModule rec {
pname = "docui";
version = "2.0.4";
src = fetchFromGitHub {
owner = "skanehira";
repo = "docui";
rev = version;
hash = "sha256-tHv1caNGiWC9Dc/qR4ij9xGM1lotT0KyrpJpdBsHyks=";
};
vendorHash = "sha256-5xQ5MmGpyzVh4gXZAhCY16iVw8zbCMzMA5IOsPdn7b0=";
meta = {
description = "TUI Client for Docker";
homepage = "https://github.com/skanehira/docui";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ aethelz ];
broken = stdenv.hostPlatform.isDarwin;
mainProgram = "docui";
};
}
+3 -3
View File
@@ -8,18 +8,18 @@
php.buildComposerProject2 (finalAttrs: {
pname = "drupal";
version = "11.3.1";
version = "11.3.2";
src = fetchFromGitLab {
domain = "git.drupalcode.org";
owner = "project";
repo = "drupal";
tag = finalAttrs.version;
hash = "sha256-dVCDIKqLbYHlVwv5wveXG0oHc2g3Zl6J6LG1/e8IIZw=";
hash = "sha256-RrBnVDjB6aKW6btmX604saXfPKo18oRka+SdlNmFqUo=";
};
composerNoPlugins = false;
vendorHash = "sha256-7FwwkPTKc/miStdHv1wfLoZhV4Gku1KwNgSlWdpPG8g=";
vendorHash = "sha256-c3pqPnyeuSqpMhh1an1NAnDC+IyeRVUT+dCN19/nrMQ=";
passthru = {
tests = {
+2 -2
View File
@@ -5,7 +5,7 @@
}:
let
pname = "e1s";
version = "1.0.52";
version = "1.0.53";
in
buildGoModule {
inherit pname version;
@@ -14,7 +14,7 @@ buildGoModule {
owner = "keidarcy";
repo = "e1s";
tag = "v${version}";
hash = "sha256-ObqCd27gMG1WWqAObZZP1rGLJuh8weCdC0zrLfoPwMo=";
hash = "sha256-Cy/aZVO6xM1oCeyT6x1O+otbUZ5lS90fl3iZzkf02QM=";
};
vendorHash = "sha256-8z2RVT2W8TLXdZBAmi/2fu63pijVgzqSvF9xpGexlQ0=";
+3 -3
View File
@@ -10,18 +10,18 @@
}:
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "eas-cli";
version = "16.23.1";
version = "16.28.0";
src = fetchFromGitHub {
owner = "expo";
repo = "eas-cli";
rev = "v${finalAttrs.version}";
hash = "sha256-hMUDtl5lMAZzlvPdzO7J3JTw0B5/fjssuqQlg1MUO3w=";
hash = "sha256-/1E26CDD+vXR6/v9zOFOcJEuU/evUSVovQwnuyoV4SA=";
};
yarnOfflineCache = fetchYarnDeps {
yarnLock = finalAttrs.src + "/yarn.lock"; # Point to the root lockfile
hash = "sha256-ybctj6TgW9JluDIsSaNm18wUXSBPuIT45te5HoQuz5s=";
hash = "sha256-W2FuU4J28/qtXUa+eqirpc7bjRdL1fk6mgGxR50icYI=";
};
nativeBuildInputs = [
@@ -63,7 +63,7 @@ stdenv.mkDerivation (finalAttrs: {
meta = {
description = "Fast and effective C++ file optimizer";
homepage = "https://github.com/fhanau/Efficient-Compression-Tool";
changelog = "https://github.com/fhanau/Efficient-Compression-Tool/releases/tag/${finalAttrs.version}";
changelog = "https://github.com/fhanau/Efficient-Compression-Tool/releases/tag/v${finalAttrs.version}";
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [
jwillikers
+2 -2
View File
@@ -28,13 +28,13 @@ assert blas.isILP64 == scalapack.isILP64;
stdenv.mkDerivation rec {
pname = "elpa";
version = "2025.06.001";
version = "2025.06.002";
passthru = { inherit (blas) isILP64; };
src = fetchurl {
url = "https://elpa.mpcdf.mpg.de/software/tarball-archive/Releases/${version}/elpa-${version}.tar.gz";
sha256 = "sha256-/usf6hq0qGcLjTJAdl7wragoBi737JtzXuy6KEhRXJQ=";
sha256 = "sha256-3jGAwG4rDbtWk56ErRpf0WhEZb04rSGWeS0PQCiTf9o=";
};
patches = [
+2 -2
View File
@@ -20,13 +20,13 @@
}:
stdenv.mkDerivation (finalAttrs: {
pname = "embellish";
version = "0.5.1";
version = "0.6.0";
src = fetchFromGitHub {
owner = "getnf";
repo = "embellish";
tag = "v${finalAttrs.version}";
hash = "sha256-Db7/vo9LVE7IeFFHx/BKs+qxzsvuB+6ZLRb7A1NHrxQ=";
hash = "sha256-2WPOXrEhnFP3NHE+MksREYlIoGN8AJE7Y2aw3ObVHeM=";
};
nativeBuildInputs = [
+2 -2
View File
@@ -18,13 +18,13 @@
stdenv.mkDerivation rec {
pname = "fheroes2";
version = "1.1.11";
version = "1.1.13";
src = fetchFromGitHub {
owner = "ihhub";
repo = "fheroes2";
rev = version;
hash = "sha256-U8iJAhubMHGPXNph+kWhMzRDbh3e4bikgQKbPPeKqV8=";
hash = "sha256-ct58Rkc6ORXldINQZVzMuObMl0BMk6QG88oU4tT0WcE=";
};
nativeBuildInputs = [ imagemagick ];
+3 -3
View File
@@ -10,16 +10,16 @@
rustPlatform.buildRustPackage rec {
pname = "flake-edit";
version = "0.3.1";
version = "0.3.3";
src = fetchFromGitHub {
owner = "a-kenji";
repo = "flake-edit";
rev = "v${version}";
hash = "sha256-Ptg/Wt8H6vOvk/V6juDmFd6Vzu/F3LzxDIGObuwySLA=";
hash = "sha256-CDz7iDOPearlxsqLuAuG+cmKneFavxJmdCbnWwEIvcU=";
};
cargoHash = "sha256-5i3wll3CdrRbwN8zsD4MQg62hvsMPESMW4YrtjPeySw=";
cargoHash = "sha256-IvBrJBSAMLfqefyUnS3Ex+JvHJAWJtVtkBVp2kFvA4s=";
nativeBuildInputs = [
installShellFiles
@@ -7,16 +7,16 @@
}:
rustPlatform.buildRustPackage (finalAttrs: {
pname = "framework-tool-tui";
version = "0.7.3";
version = "0.7.6";
src = fetchFromGitHub {
owner = "grouzen";
repo = "framework-tool-tui";
tag = "v${finalAttrs.version}";
hash = "sha256-+m92Q5rfINS/TDAXpHDpwJPyV8kGrdS4y72DWw9NLe0=";
hash = "sha256-reIsJK2bGuMf83SmjCVu9PdUrd4zilCxpvbZllnU6vo=";
};
cargoHash = "sha256-feA+Jn3ldq6pJe/xFqBAaemNcT0Kjfl61IWIXKHHp9o=";
cargoHash = "sha256-E2lVpu+sI/Bf1YwqCbwg3pr15kfo4DUddwI+5/Dwh40=";
nativeBuildInputs = [ pkg-config ];
buildInputs = [ udev ];
+2 -2
View File
@@ -70,13 +70,13 @@
stdenv.mkDerivation (finalAttrs: {
pname = "freerdp";
version = "3.20.2";
version = "3.21.0";
src = fetchFromGitHub {
owner = "FreeRDP";
repo = "FreeRDP";
rev = finalAttrs.version;
hash = "sha256-IcEWlNh0AI3Vkqf2FzQYOIq64J6iWJxWlUfYkcBpGUU=";
hash = "sha256-oIws2HO2usOCtVDe6OTIdIDHYgb9tBIEctvCW6/Woxc=";
};
postPatch = ''
+4 -5
View File
@@ -20,14 +20,13 @@ let
in
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "freetube";
version = "0.23.12-unstable-2026-01-15";
version = "0.23.13";
src = fetchFromGitHub {
owner = "FreeTubeApp";
repo = "FreeTube";
# tag = "v${finalAttrs.version}-beta";
rev = "e110a4b603e0f5f275d210aea005698a0d4b26ad";
hash = "sha256-kq6twf7ce2987iHtwikPzolzzbxr1xcoirqUGpPG4V8=";
tag = "v${finalAttrs.version}-beta";
hash = "sha256-vnqrl/2hxL0RQbLHkgRntyTRSWmhMM7hOi31r4pKCgs=";
};
# Darwin requires writable Electron dist
@@ -50,7 +49,7 @@ stdenvNoCC.mkDerivation (finalAttrs: {
yarnOfflineCache = fetchYarnDeps {
yarnLock = "${finalAttrs.src}/yarn.lock";
hash = "sha256-E6D2Uo06MAcnOKy00e5JoLdKQOeGVr7y7Lu6rZ1F82M=";
hash = "sha256-sM9CkDnATSEUf/uuUyT4JuRmjzwa1WzIyNYEw69MPtU=";
};
nativeBuildInputs = [
@@ -1,13 +1,13 @@
diff --git a/_scripts/ebuilder.config.mjs b/_scripts/ebuilder.config.mjs
index 55e72b227..d218f5ac4 100644
--- a/_scripts/ebuilder.config.mjs
+++ b/_scripts/ebuilder.config.mjs
@@ -2,6 +2,8 @@ import packageDetails from '../package.json' with { type: 'json' }
diff --git a/_scripts/ebuilder.config.js b/_scripts/ebuilder.config.js
index 14d0d9df1..c5fc569c8 100644
--- a/_scripts/ebuilder.config.js
+++ b/_scripts/ebuilder.config.js
@@ -1,6 +1,8 @@
const { name, productName } = require('../package.json')
/** @type {import('electron-builder').Configuration} */
export default {
const config = {
+ electronVersion: "@electron-version@",
+ electronDist: "electron-dist",
appId: `io.freetubeapp.${packageDetails.name}`,
appId: `io.freetubeapp.${name}`,
copyright: 'Copyleft © 2020-2025 freetubeapp@protonmail.com',
// asar: false,
+2 -2
View File
@@ -8,7 +8,7 @@
let
pname = "gallery-dl";
version = "1.31.2";
version = "1.31.3";
in
python3Packages.buildPythonApplication {
inherit pname version;
@@ -18,7 +18,7 @@ python3Packages.buildPythonApplication {
owner = "mikf";
repo = "gallery-dl";
tag = "v${version}";
hash = "sha256-cKgfIJFSlUmZa3ovInI98Yw29QurXNAy7J1dUSPAUfQ=";
hash = "sha256-vheQA67lPeYt7wly/4AbiReDx9ZlUbgqxT5YTxI0gVo=";
};
build-system = [ python3Packages.setuptools ];
+8 -8
View File
@@ -68,7 +68,7 @@
pkg-config,
poppler,
proj,
python3,
python3Packages,
qhull,
rav1e,
sqlite,
@@ -98,8 +98,8 @@ stdenv.mkDerivation (finalAttrs: {
doxygen
graphviz
pkg-config
python3.pkgs.setuptools
python3.pkgs.wrapPython
python3Packages.setuptools
python3Packages.wrapPython
swig
]
++ lib.optionals useJava [
@@ -202,8 +202,8 @@ stdenv.mkDerivation (finalAttrs: {
libwebp
zlib
zstd
python3
python3.pkgs.numpy
python3Packages.python
python3Packages.numpy
]
++ tileDbDeps
++ libAvifDeps
@@ -219,7 +219,7 @@ stdenv.mkDerivation (finalAttrs: {
++ darwinDeps
++ nonDarwinDeps;
pythonPath = [ python3.pkgs.numpy ];
pythonPath = [ python3Packages.numpy ];
postInstall = ''
wrapPythonProgramsIn "$out/bin" "$out $pythonPath"
''
@@ -238,14 +238,14 @@ stdenv.mkDerivation (finalAttrs: {
pushd autotest
export HOME=$(mktemp -d)
export PYTHONPATH="$out/${python3.sitePackages}:$PYTHONPATH"
export PYTHONPATH="$out/${python3Packages.python.sitePackages}:$PYTHONPATH"
export GDAL_DOWNLOAD_TEST_DATA=OFF
# allows to skip tests that fail because of file handle leak
# the issue was not investigated
# https://github.com/OSGeo/gdal/blob/v3.9.0/autotest/gdrivers/bag.py#L54
export CI=1
'';
nativeInstallCheckInputs = with python3.pkgs; [
nativeInstallCheckInputs = with python3Packages; [
pytestCheckHook
pytest-benchmark
pytest-env

Some files were not shown because too many files have changed in this diff Show More