Compare commits

..

12 Commits

Author SHA1 Message Date
Emily
0dc3e4f7eb testSignedPackages.shim-signed: init
This signs the shim with the same vendor certificate that gets embedded
in the shim, which is not what you want for supporting Microsoft Secure
Boot keys. The Microsoft signature will require different handling in
future work, and is blocked on compliance anyway, but this is still
useful for having a uniform bootloader chain and MOK handling.
2026-08-14 09:12:30 +01:00
Emily
cbfabf3690 testSignedPackages.systemd-boot-signed: init 2026-08-14 09:12:30 +01:00
Emily
b679c44d3c testSignedPackages.fwupd-efi-signed: init 2026-08-14 09:12:30 +01:00
Emily
b200783799 testSignedPackages: init 2026-08-14 09:12:30 +01:00
Emily
e96622b122 mkSignedPackages: init 2026-08-14 09:12:30 +01:00
Emily
6c62ab4d6b authenticodeCheckHook: init 2026-08-14 09:12:30 +01:00
Emily
dbbb241a34 fwupd-efi: add description 2026-08-14 09:12:29 +01:00
Emily
412750b3c7 fwupd-efi: inherit metadata from fwupd 2026-08-14 09:12:29 +01:00
Emily
7ee25ddbc3 fwupd-efi: add boot security team to maintainers 2026-08-14 09:12:29 +01:00
Emily
088c7d64cb shim-unsigned: add boot security team to maintainers 2026-08-14 09:12:29 +01:00
Emily
f3b80ee197 autopen: init at 0.2.0 2026-08-14 09:12:29 +01:00
Emily
9acceb309f maintainers/team-list: add boot security team 2026-08-14 09:12:29 +01:00
4347 changed files with 52229 additions and 65292 deletions

View File

@@ -23,15 +23,15 @@ insert_final_newline = false
# see https://nixos.org/nixpkgs/manual/#chap-conventions
[*.{bash,css,js,json,lock,md,nix,pl,pm,py,rb,sh,ts,xml}]
[*.{bash,css,js,json,lock,md,nix,pl,pm,py,rb,sh,xml}]
indent_style = space
# Match docbook files, set indent width of one
[*.xml]
indent_size = 1
# Match js/json/lockfiles/markdown/nix/ruby/ts files, set indent width of two
[*.{js,json,lock,md,nix,rb,ts}]
# Match json/lockfiles/markdown/nix/ruby files, set indent width of two
[*.{js,json,lock,md,nix,rb}]
indent_size = 2
# Match all the Bash code in Nix files, set indent width of two

View File

@@ -13,7 +13,7 @@ inputs:
runs:
using: composite
steps:
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
- uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
MERGED_SHA: ${{ inputs.merged-as-untrusted-at }}
TARGET_SHA: ${{ inputs.target-as-trusted-at }}

View File

@@ -1,9 +1,7 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directories:
- "/"
- ".github/actions/*/*"
directory: "/"
schedule:
interval: "weekly"
labels: []

20
.github/labeler.yml vendored
View File

@@ -43,6 +43,14 @@
- .github/**/*
- ci/**/*.*
"6.topic: coq":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/applications/science/logic/coq/**/*
- pkgs/development/coq-modules/**/*
- pkgs/top-level/coq-packages.nix
"6.topic: COSMIC":
- any:
- changed-files:
@@ -458,18 +466,6 @@
- any-glob-to-any-file:
- pkgs/development/rocm-modules/**/*
"6.topic: rocq":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/applications/science/logic/coq/**/*
- pkgs/applications/science/logic/rocq-core/**/*
- pkgs/build-support/coq/**/*
- pkgs/build-support/rocq/**/*
- pkgs/development/rocq-modules/**/*
- pkgs/top-level/coq-packages.nix
- pkgs/top-level/rocq-packages.nix
"6.topic: ruby":
- any:
- changed-files:

View File

@@ -375,7 +375,7 @@ jobs:
with:
github-token: ${{ steps.app-token.outputs.token || github.token }}
script: |
require('./nixpkgs/trusted/ci/github-script/check-target-branch.ts')({
require('./nixpkgs/trusted/ci/github-script/check-target-branch.js')({
github,
context,
core,

View File

@@ -77,7 +77,7 @@ jobs:
'.github/workflows/pull-request-target.yml',
'.github/workflows/test.yml',
'ci/github-script/bot.js',
'ci/github-script/check-target-branch.ts',
'ci/github-script/check-target-branch.js',
'ci/github-script/commits.js',
'ci/github-script/get-pr-commit-details.js',
'ci/github-script/lint-commits.js',

View File

@@ -466,8 +466,9 @@ nixos/tests/incus/ @adamcstephens
pkgs/by-name/in/incus/ @adamcstephens
pkgs/by-name/lx/lxc* @adamcstephens
# Flutter
# ExpidusOS, Flutter
/pkgs/development/compilers/flutter @RossComputerGuy
/pkgs/desktops/expidus @RossComputerGuy
# GNU Tar & Zip
/pkgs/by-name/gn/gnutar @RossComputerGuy
@@ -525,3 +526,7 @@ pkgs/by-name/wa/warp-terminal/ @emilytrau @imadnyc @4evy @johnrtitor
/nixos/lib/testing @NixOS/test-driver
/nixos/tests/nixos-test-driver @NixOS/test-driver
/nixos/modules/virtualisation/nspawn-container/run-nspawn @NixOS/test-driver
# Boot security
/pkgs/by-name/au/autopen @NixOS/boot-security
/pkgs/misc/signed-packages @NixOS/boot-security

View File

@@ -1,4 +1,2 @@
comparison
comparison.zip
node_modules
step-summary.md

View File

@@ -1,4 +1,3 @@
// @ts-nocheck
module.exports = async ({ github, context, core, dry }) => {
const path = require('node:path')
const { DefaultArtifactClient } = await import('@actions/artifact')

View File

@@ -1,6 +1,4 @@
import type * as actionsCore from '@actions/core'
import type { context as actionsContext } from '@actions/github'
import type { GitHub } from '@actions/github/lib/utils'
/// @ts-check
// TODO: should this be combined with the branch checks in prepare.js?
// They do seem quite similar, but this needs to run after eval,
@@ -11,47 +9,39 @@ const { readFile } = require('node:fs/promises')
const { postReview, dismissReviews } = require('./reviews.js')
const reviewKey = 'check-target-branch'
type ChangedPaths = {
attrdiff: {
added: string[]
changed: string[]
removed: string[]
}
attrdiffByKernel: Record<
string,
{
added: string[]
changed: string[]
removed: string[]
}
>
attrdiffByPlatform: Record<
string,
{
added: string[]
changed: string[]
removed: string[]
}
>
labels: Record<string, boolean>
rebuildCountByKernel: Record<string, number>
rebuildsByKernel: Record<string, string[]>
rebuildsByPlatform: Record<string, string[]>
}
async function checkTargetBranch({
github,
context,
core,
dry,
}: {
github: InstanceType<typeof GitHub>
context: typeof actionsContext
core: typeof actionsCore
dry: boolean
}) {
const changed: ChangedPaths = JSON.parse(
/**
* @param {{
* github: InstanceType<import('@actions/github/lib/utils').GitHub>,
* context: typeof import('@actions/github').context
* core: import('@actions/core')
* dry: boolean
* }} CheckTargetBranchProps
*/
async function checkTargetBranch({ github, context, core, dry }) {
/**
* @type {{
* attrdiff: {
* added: string[],
* changed: string[],
* removed: string[],
* },
* attrdiffByKernel: Record<string, {
* added: string[],
* changed: string[],
* removed: string[],
* }>,
* attrdiffByPlatform: Record<string, {
* added: string[],
* changed: string[],
* removed: string[],
* }>,
* labels: Record<string, boolean>,
* rebuildCountByKernel: Record<string, number>,
* rebuildsByKernel: Record<string, string[]>,
* rebuildsByPlatform: Record<string, string[]>,
* }}
*/
const changed = JSON.parse(
await readFile('comparison/changed-paths.json', 'utf-8'),
)
const pull_number = context.payload.pull_request?.number
@@ -165,7 +155,7 @@ async function checkTargetBranch({
reviewKey,
})
} else if (rebuildsAllTests && !isExemptKernelUpdate) {
let branchText: string
let branchText
if (base === 'master' && maxRebuildCount >= 500) {
branchText = '(probably either `staging-nixos` or `staging`)'
} else if (base === 'master') {

View File

@@ -1,4 +1,3 @@
// @ts-nocheck
module.exports = async ({ github, context, core, dry, cherryPicks }) => {
const { execFileSync } = require('node:child_process')
const { classify } = require('../supportedBranches.js')

View File

@@ -1,4 +1,4 @@
// @ts-nocheck
// @ts-check
const { promisify } = require('node:util')
const execFile = promisify(require('node:child_process').execFile)
@@ -16,7 +16,7 @@ const execFile = promisify(require('node:child_process').execFile)
/**
* @param {{
* args: string[]
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* quiet?: boolean,
* repoPath?: string,
* }} RunGitProps
@@ -40,7 +40,7 @@ async function runGit({ args, repoPath, core, quiet }) {
* of 250 commits and doesn't return the changed files.
*
* @param {{
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* pr: Awaited<ReturnType<InstanceType<import('@actions/github/lib/utils').GitHub>["rest"]["pulls"]["get"]>>["data"]
* repoPath?: string,
* }} GetCommitMessagesForPRProps

View File

@@ -1,4 +1,3 @@
// @ts-nocheck
const excludeTeams = [
/^voters.*$/,
/^nixpkgs-maintainers$/,

View File

@@ -1,3 +1,4 @@
// @ts-check
const { classify } = require('../supportedBranches.js')
const { getCommitDetailsForPR } = require('./get-pr-commit-details.js')
@@ -5,9 +6,9 @@ const { getCommitDetailsForPR } = require('./get-pr-commit-details.js')
/**
* @param {{
* github: InstanceType<typeof import('@actions/github/lib/utils').GitHub>,
* github: InstanceType<import('@actions/github/lib/utils').GitHub>,
* context: typeof import('@actions/github').context,
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* repoPath?: string,
* }} LintCommitsProps
*/
@@ -56,7 +57,7 @@ async function lintCommits({ github, context, core, repoPath }) {
/**
* @param {{
* commits: Commit[],
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* }} CheckCommitMessagesProps
*/
async function checkCommitMessages({ commits, core }) {
@@ -169,7 +170,7 @@ async function checkCommitMessages({ commits, core }) {
/**
* @param {{
* commits: Commit[],
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* }} CheckGitFieldsProps
*/
async function checkCommitMetadata({ commits, core }) {

View File

@@ -1,11 +1,12 @@
// @ts-check
const { classify } = require('../supportedBranches.js')
const { getCommitDetailsForPR } = require('./get-pr-commit-details')
/**
* @param {{
* github: InstanceType<typeof import('@actions/github/lib/utils').GitHub>,
* github: InstanceType<import('@actions/github/lib/utils').GitHub>,
* context: typeof import('@actions/github').context,
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* repoPath?: string,
* dry: boolean,
* }} CheckManualFileEditsProps

View File

@@ -1,4 +1,3 @@
// @ts-nocheck
const { classify } = require('../supportedBranches.js')
function runChecklist({

View File

@@ -10,11 +10,6 @@
"@actions/github": "9.1.0",
"bottleneck": "2.19.5",
"commander": "14.0.3"
},
"devDependencies": {
"@tsconfig/node24": "24.0.4",
"@types/node": "24.13.3",
"typescript": "7.0.2"
}
},
"node_modules/@actions/artifact": {
@@ -593,19 +588,6 @@
"protoc-gen-ts": "bin/protoc-gen-ts"
}
},
"node_modules/@protobuf-ts/plugin/node_modules/typescript": {
"version": "3.9.10",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/@protobuf-ts/protoc": {
"version": "2.11.1",
"resolved": "https://registry.npmjs.org/@protobuf-ts/protoc/-/protoc-2.11.1.tgz",
@@ -630,343 +612,6 @@
"@protobuf-ts/runtime": "^2.11.1"
}
},
"node_modules/@tsconfig/node24": {
"version": "24.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node24/-/node24-24.0.4.tgz",
"integrity": "sha512-2A933l5P5oCbv6qSxHs7ckKwobs8BDAe9SJ/Xr2Hy+nDlwmLE1GhFh/g/vXGRZWgxBg9nX/5piDtHR9Dkw/XuA==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.13.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz",
"integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.18.0"
}
},
"node_modules/@typescript/typescript-aix-ppc64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz",
"integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==",
"cpu": [
"ppc64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-darwin-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz",
"integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-darwin-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz",
"integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-freebsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz",
"integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-freebsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz",
"integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-arm": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz",
"integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==",
"cpu": [
"arm"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz",
"integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-loong64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz",
"integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==",
"cpu": [
"loong64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-mips64el": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz",
"integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==",
"cpu": [
"mips64el"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-ppc64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz",
"integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==",
"cpu": [
"ppc64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-riscv64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz",
"integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==",
"cpu": [
"riscv64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-s390x": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz",
"integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==",
"cpu": [
"s390x"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz",
"integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-netbsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz",
"integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-netbsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz",
"integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-openbsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz",
"integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-openbsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz",
"integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-sunos-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz",
"integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-win32-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz",
"integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-win32-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz",
"integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/vfs": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.1.tgz",
@@ -2012,37 +1657,16 @@
}
},
"node_modules/typescript": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz",
"integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==",
"version": "3.9.10",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc"
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=16.20.0"
},
"optionalDependencies": {
"@typescript/typescript-aix-ppc64": "7.0.2",
"@typescript/typescript-darwin-arm64": "7.0.2",
"@typescript/typescript-darwin-x64": "7.0.2",
"@typescript/typescript-freebsd-arm64": "7.0.2",
"@typescript/typescript-freebsd-x64": "7.0.2",
"@typescript/typescript-linux-arm": "7.0.2",
"@typescript/typescript-linux-arm64": "7.0.2",
"@typescript/typescript-linux-loong64": "7.0.2",
"@typescript/typescript-linux-mips64el": "7.0.2",
"@typescript/typescript-linux-ppc64": "7.0.2",
"@typescript/typescript-linux-riscv64": "7.0.2",
"@typescript/typescript-linux-s390x": "7.0.2",
"@typescript/typescript-linux-x64": "7.0.2",
"@typescript/typescript-netbsd-arm64": "7.0.2",
"@typescript/typescript-netbsd-x64": "7.0.2",
"@typescript/typescript-openbsd-arm64": "7.0.2",
"@typescript/typescript-openbsd-x64": "7.0.2",
"@typescript/typescript-sunos-x64": "7.0.2",
"@typescript/typescript-win32-arm64": "7.0.2",
"@typescript/typescript-win32-x64": "7.0.2"
"node": ">=4.2.0"
}
},
"node_modules/undici": {
@@ -2057,13 +1681,6 @@
"node": ">=14.0"
}
},
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"dev": true,
"license": "MIT"
},
"node_modules/universal-user-agent": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz",

View File

@@ -10,10 +10,5 @@
"@actions/github": "9.1.0",
"bottleneck": "2.19.5",
"commander": "14.0.3"
},
"devDependencies": {
"@tsconfig/node24": "24.0.4",
"@types/node": "24.13.3",
"typescript": "7.0.2"
}
}

View File

@@ -1,4 +1,3 @@
// @ts-nocheck
const { classify } = require('../supportedBranches.js')
const { postReview, dismissReviews } = require('./reviews.js')
const reviewKey = 'prepare'

View File

@@ -1,4 +1,3 @@
// @ts-nocheck
async function handleReviewers({
github,
context,

View File

@@ -1,3 +1,5 @@
// @ts-check
const eventToState = {
COMMENT: 'COMMENTED',
REQUEST_CHANGES: 'CHANGES_REQUESTED',
@@ -14,7 +16,7 @@ const reviewUsers = [
]
/**
* @typedef {InstanceType<typeof import('@actions/github/lib/utils').GitHub>} GitHub
* @typedef {InstanceType<import('@actions/github/lib/utils').GitHub>} GitHub
* @typedef {typeof import('@actions/github').context} Context
*
* @typedef {Awaited<ReturnType<GitHub['rest']['pulls']['listReviews']>>['data'][number]} Review
@@ -25,7 +27,7 @@ const reviewUsers = [
* @param {{
* github: GitHub,
* context: Context,
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* dry: boolean,
* reviewKey?: string,
* }} DismissReviewsProps
@@ -163,10 +165,10 @@ async function dismissReviews({ github, context, core, dry, reviewKey }) {
* @param {{
* github: GitHub,
* context: Context,
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* dry: boolean,
* body: string,
* event: keyof typeof eventToState,
* event: keyof eventToState,
* reviewKey: string,
* }} PostReviewProps
*/

View File

@@ -112,8 +112,8 @@ program
.argument('<repo>', 'Name of the GitHub repository to run on (Example: nixpkgs)')
.argument('<pr>', 'Number of the Pull Request to run on')
.action(async (owner, repo, pr, options) => {
const checkTargetBranch = (await import('./check-target-branch.ts')).default
await run(checkTargetBranch, owner, repo, pr, options)
const checkCommitMessages = (await import('./check-target-branch.js')).default
await run(checkCommitMessages, owner, repo, pr, options)
})
program

View File

@@ -1,4 +1,3 @@
// @ts-nocheck
module.exports = async ({ github, context, targetSha }) => {
const { content, encoding } = (
await github.rest.repos.getContent({

View File

@@ -1,26 +0,0 @@
{
"compilerOptions": {
"lib": [
"es2024",
"ESNext.Array",
"ESNext.Collection",
"ESNext.Error",
"ESNext.Iterator",
"ESNext.Promise"
],
"module": "nodenext",
"target": "es2024",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"moduleResolution": "node16",
"allowImportingTsExtensions": true,
"allowJs": true,
"checkJs": true,
"erasableSyntaxOnly": true,
"verbatimModuleSyntax": true,
"noEmit": true,
}
}

View File

@@ -1,4 +1,3 @@
// @ts-nocheck
module.exports = async ({ github, core, maxConcurrent = 1 }, callback) => {
const Bottleneck = require('bottleneck')

View File

@@ -2,7 +2,6 @@
/*
#!nix-shell -i node -p nodejs
*/
// @ts-nocheck
const typeConfig = {
master: ['development', 'primary'],

View File

@@ -14,12 +14,17 @@ Use **examples** first to show how to get something done. Keep **Explanation** l
Use our [styleguide](./styleguide.md) for more in depth guidance on writing good documentation.
Documentation about Nixpkgs belongs here, this includes 'getting-started'-guides and 'onboarding-guides' for *using* Nixpkgs and the language frameworks it ships.
This directory contains **guides** and **reference** documentation for Nixpkgs.
Write **guides** task-first: lead with a working example, then explain in prose.
Write **reference** as the specification of functions and attributes.
Borrowing from [Diátaxis framework](https://diataxis.fr/) what suits our needs:
We are actively working to generate reference documentation from the [doc-comments](https://github.com/NixOS/rfcs/blob/master/rfcs/0145-doc-strings.md) present in code, which also lets you view it locally with `:doc` in `nix repl`.
**Guides** are task-oriented. They can be tutorial-style walkthroughs or how-to sections.
Explanations appear as prose after examples.
**Reference** documentation is the specification of functions and attributes.
We are actively working to generate **all** reference documentation from the [doc-comments](https://github.com/NixOS/rfcs/blob/master/rfcs/0145-doc-strings.md) present in code.
This also provides the benefit of using `:doc` in the `nix repl` to view reference documentation locally on the fly.
See [Document structure](#document-structure) for a structural template.

View File

@@ -68,7 +68,7 @@ See [](#ex-portableService-hello) to understand how to use the output of `portab
: Allows you to override the package that provides {manpage}`mksquashfs(1)`, which is used internally by `portableService`.
_Default value:_ `pkgs.squashfs-tools`.
_Default value:_ `pkgs.squashfsTools`.
`squash-compression` (String; _optional_)

View File

@@ -1,49 +0,0 @@
# Dev environments {#dev-environments}
Create a `shell.nix` with the following:
```nix
# shell.nix
let
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz";
pkgs = import nixpkgs { };
in
pkgs.mkShell {
packages = [ pkgs.python3 ];
shellHook = ''
echo "Welcome in my nix shell"
'';
}
```
run
```sh
nix-shell
```
This activates your `shell.nix` and you should see:
```sh
unpacking 'https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz' into the Git cache...
Welcome in your nix shell
```
python3 is available
```sh
$ python3 --version
```
To leave the shell
```bash
ctrl+D
```
:::{.note}
You should use [pinned nixpkgs](https://nix.dev/guides/recipes/dependency-management.html).
The example used `unstable` here for demonstration purposes only
:::
For further information check out [nix-shell](https://nix.dev/manual/nix/stable/command-ref/nix-shell)

View File

@@ -1,6 +0,0 @@
# Getting started {#getting-started}
```{=include=} chapters
first-package.chapter.md
dev-environments.md
```

View File

@@ -116,7 +116,7 @@ options:
For each requested system image we can specify the following options:
* `systemImageTypes` specifies what kind of system images should be included.
Defaults to: `google_apis`, `google_apis_playstore`, `google_apis_ps16k` and `google_apis_playstore_ps16k`.
Defaults to: `default`.
* `abiVersions` specifies what kind of ABI version of each system image should
be included. Defaults to `armeabi-v7a` and `arm64-v8a`.

View File

@@ -206,7 +206,7 @@ Here is how your `default.nix` file would look for a Phoenix project.
# beam27Packages or beam29Packages is available if you need a particular version
beamPackages,
}:
beamPackages.mixRelease (finalAttrs: {
let
pname = "your_project";
version = "0.0.1";
@@ -215,6 +215,24 @@ beamPackages.mixRelease (finalAttrs: {
rev = "replace_with_your_commit";
};
# if using mix2nix you can use the mixNixDeps attribute
mixFodDeps = beamPackages.fetchMixDeps {
pname = "mix-deps-${pname}";
inherit src version;
# nix will complain and tell you the right value to replace this with
hash = lib.fakeHash;
mixEnv = ""; # default is "prod", when empty includes all dependencies, such as "dev", "test".
# if you have build time environment variables add them here
MY_ENV_VAR = "my_value";
};
in
beamPackages.mixRelease {
inherit
src
pname
version
mixFodDeps
;
# if you have build time environment variables add them here
MY_ENV_VAR = "my_value";
@@ -224,18 +242,7 @@ beamPackages.mixRelease (finalAttrs: {
mix do deps.loadpaths --no-deps-check, phx.digest
mix phx.digest --no-deps-check
'';
# if using mix2nix you can use the mixNixDeps attribute
mixFodDeps = beamPackages.fetchMixDeps {
pname = "mix-deps-${finalAttrs.pname}";
inherit (finalAttrs) src version;
# nix will complain and tell you the right value to replace this with
hash = lib.fakeHash;
mixEnv = ""; # default is "prod", when empty includes all dependencies, such as "dev", "test".
# if you have build time environment variables add them here
MY_ENV_VAR = "my_value";
};
})
}
```
Setup will require the following steps:

View File

@@ -59,9 +59,6 @@ Here is a simple package example.
- The library will be installed using the `angstrom.install` file that dune
generates.
- It also accepts an optional `dunePackages` argument, if there is more than one
dune package that needs to be built (see `zipperposition`)
```nix
{
lib,

View File

@@ -3,12 +3,11 @@
Note that "The Rocq Prover" (Rocq for short) is the new name of the
proof assistant formerly known as Coq. The `coq` and `coqPackages`
derivations currently remain for both older versions of Coq, but also
as compatibility aliases for some versions of Rocq. In both cases, the
`coq` and `rocq-core` attributes exist. In the case of Coq (< 9),
`rocq-core` is just an alias for `coq`, while in the case of Rocq (>= 9),
`rocq-core` is the main Rocq derivation, while `coq` provides
compatibility binaries (`coqc`, `coqtop`, etc.) for packages that still
depend on them.
some versions of Rocq during the renaming transition. In the latter
case, the `coq` derivation encompasses the compatibility binaries
(`coqtop`, `coqc`, etc.) in addition to the `rocq` binary. The packages
only in `coqPackages` are the ones which currently still depend on these
compatibility binaries.
## Rocq derivation: `rocq-core` {#rocq-derivation-rocq}
@@ -18,18 +17,18 @@ The Rocq derivation is overridable through the `rocq-core.override overrides`, w
* `customOCamlPackages` (optional, defaults to `null`, which lets Rocq choose a version automatically), which can be set to any of the ocaml packages attribute of `ocaml-ng` (such as `ocaml-ng.ocamlPackages_4_14` which is the default for Rocq 9.1 for example).
* `rocq-version` (optional, defaults to the short version e.g. "9.1"), is a version number of the form "x.y" that indicates which Rocq's version build behavior to mimic when using a source which is not a release. E.g. `rocq-core.override { version = "40be8435e132aab2231a79091f011ebc3e64a753"; rocq-version = "9.1"; }`.
## Creating custom Coq environments with `rocq-core.withPackages` {#coq-withPackages}
## Creating custom Coq environments with `coq.withPackages` {#coq-withPackages}
The `rocq-core.withPackages` function provides a convenient way to create a Rocq environment that includes additional Rocq packages. This is similar to how `python.withPackages` works for Python environments.
The `coq.withPackages` function provides a convenient way to create a Coq environment that includes additional Coq packages. This is similar to how `python.withPackages` works for Python environments.
The function takes a function that receives the Rocq package set and returns a list of packages. It returns a wrapped Rocq environment where the Rocq binaries (`rocq`, etc.) are configured with the appropriate environment variables to find the packages.
The function takes a function that receives the Coq package set and returns a list of packages. It returns a wrapped Coq environment where all Coq binaries (`coqtop`, `coqc`, `coqdep`, `coqchk`, `coqide`, etc.) are configured with the appropriate environment variables to find the packages.
### Usage {#coq-withPackages-usage}
Here is an example of creating a Rocq environment with specific packages.
Here is an example of creating a Coq environment with specific packages.
```nix
rocq-core.withPackages (
coq.withPackages (
ps: with ps; [
mathcomp
bignums
@@ -37,9 +36,7 @@ rocq-core.withPackages (
)
```
If you install the `vsrocq-language-server` or `rocq-lsp` server, make sure to list them as part of the above `rocq-core.withPackages` expression instead of installing them separately if you want them to find your Rocq packages.
For versions prior to Rocq 9.0, a similar `coq.withPackages` function is available.
If you install the `vsrocq-language-server` or `rocq-lsp` server, make sure to list them as part of the above `coq.withPackages` expression instead of installing them separately if you want them to find your Coq/Rocq packages.
## Rocq packages attribute sets: `rocqPackages` {#rocq-packages-attribute-sets-rocqpackages}
@@ -133,7 +130,7 @@ mkRocqDerivation {
mathcomp.boot
mathcomp.algebra
mathcomp-finmap
mathcomp.finite-group
mathcomp.fingroup
mathcomp-bigenough
];

View File

@@ -3,10 +3,10 @@
```{=include=} chapters
preface.chapter.md
first-package.chapter.md
```
```{=include=} parts
getting-started/getting-started.part.md
using-nixpkgs.md
lib.md
stdenv.md

View File

@@ -105,9 +105,6 @@
"cuda-writing-tests": [
"index.html#cuda-writing-tests"
],
"dev-environments": [
"index.html#dev-environments"
],
"ex-build-helpers-extendMkDerivation": [
"index.html#ex-build-helpers-extendMkDerivation"
],
@@ -152,9 +149,6 @@
"friction-graphics-wayland": [
"index.html#friction-graphics-wayland"
],
"getting-started": [
"index.html#getting-started"
],
"ghc-deprecation-policy": [
"index.html#ghc-deprecation-policy"
],

View File

@@ -82,8 +82,6 @@
- `nix-serve-ng` (and `haskellPackages.nix-serve-ng`) is now built against Lix instead of CppNix, following upstream which has switched to Lix as its supported Nix implementation.
- `buildPythonPackage` and `buildPythonApplication` now set `__structuredAttrs = true` by default. You can explicitly set `__structuredAttrs = false` in packages broken by this change.
- Linux kernel configuration has been moved out of the `linux-kernel` field of the platform structure into the kernel builders:
- `linux-kernel.name` has been removed.
- `linux-kernel.target` is available as the `target` parameter and passthru attribute on the kernel builders.
@@ -119,8 +117,6 @@
- `gh-actions-cache` has been removed since its functionality has been integrated directly into `gh` (`gh cache`). See [upstream readme](https://github.com/actions/gh-actions-cache).
- The OCaml-based Xen Store Daemon has been split off the `xen` package, and is now present in the `ocamlPackages.oxenstored` package.
- `requireFile` now sets `meta.license = lib.licenses.unfree` by default. Users of `requireFile`-based derivations that preserve this default will need to explicitly allow their evaluation as described in [](#sec-allow-unfree).
- `texlive.combine` is deprecated and scheduled for removal in 27.05. Please migrate to `texliveSmall.withPackages` (see [](#sec-language-texlive-user-guide)).
@@ -140,8 +136,6 @@
[pnpm `fetcherVersion` section](#javascript-pnpm-fetcherVersion) of the manual
for details.
- `makeSetupHook` now uses structured attributes and only makes substitutions based on the values of the `substitutions` argument - other derivation attributes are no longer considered.
- `rebuilderd` has been updated to 0.27.0 introducing breaking changes. See upstream changelog for details: [0.26.0](https://github.com/kpcyrd/rebuilderd/releases/tag/v0.26.0), [0.27.0](https://github.com/kpcyrd/rebuilderd/releases/tag/v0.27.0)
- Starting with v14, `flameshot` will primarily utilise xdg-desktop-portal calls for screenshotting. This will directly affect users on X11 window managers due to the lack of a compatible portal with Screenshot feature. See [upstream changelog](https://github.com/flameshot-org/flameshot/releases/tag/v14.0.0) or [NixOS Flameshot](https://wiki.nixos.org/wiki/Flameshot) wiki page for workarounds.
@@ -169,8 +163,6 @@
- The fwts efi-runtime kernel module was removed.
- `homebox` v0.26.0 introduced a new, required value to be set, `HBOX_AUTH_API_KEY_PEPPER`. If one is not provided the module will create one, it is recommended that you back this up as it is part of API Key generation and validation.
- Emacs loads the `early-default` library after `early-init.el`.
Users can add `early-init.el` via `emacs.pkgs.withPackages`
by packaging `early-init.el` into a library named `early-default`.

View File

@@ -465,8 +465,7 @@ div.appendix .variablelist .term {
font-display: swap;
}
div.chapter,
div.page {
.chapter {
content-visibility: auto;
}

View File

@@ -7,9 +7,6 @@ let
inherit (lib.lists)
filter
;
inherit (lib.attrsets)
catAttrs
;
inherit (lib.trivial)
showWarnings
;
@@ -195,7 +192,7 @@ rec {
checkAssertWarn =
assertions: warnings: val:
let
failedAssertions = catAttrs "message" (filter (x: !x.assertion) assertions);
failedAssertions = map (x: x.message) (filter (x: !x.assertion) assertions);
in
if failedAssertions != [ ] then
throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"

View File

@@ -2,7 +2,6 @@
let
inherit (builtins)
catAttrs
intersectAttrs
unsafeGetAttrPos
;
@@ -407,7 +406,7 @@ rec {
++ [
{
name = "all";
value = catAttrs "value" outputsList;
value = map (x: x.value) outputsList;
}
]
)

View File

@@ -241,7 +241,7 @@ let
# See https://github.com/NixOS/nixpkgs/pull/194391 for details.
closePropagationFast =
list:
builtins.catAttrs "val" (
map (x: x.val) (
builtins.genericClosure {
startSet = map (x: {
key = x.outPath;

View File

@@ -349,33 +349,24 @@ rec {
```
*/
_normaliseTreeFilter =
let
# Recurses into a tree that's already known to be a directory (either a "directory" or an attrset).
#
# Only directories need to be recursed into:
# Files are either null (excluded) or a file type string (included), which are already normalised.
#
# Checking this in the caller instead of here also avoids the thunk allocation for the path concatenation below.
recurse =
path: tree:
let
normalisedSubtrees = mapAttrs (
name: subtree:
if subtree == "directory" || isAttrs subtree then recurse (path + "/${name}") subtree else subtree
) (_directoryEntries path tree);
subtreeValues = attrValues normalisedSubtrees;
in
# This triggers either when all files in a directory are filtered out
# Or when the directory doesn't contain any files at all
if all isNull subtreeValues then
null
# Triggers when we have the same as a `readDir path`, so we can turn it back into an equivalent "directory".
else if all isString subtreeValues then
"directory"
else
normalisedSubtrees;
in
path: tree: if tree == "directory" || isAttrs tree then recurse path tree else tree;
path: tree:
if tree == "directory" || isAttrs tree then
let
entries = _directoryEntries path tree;
normalisedSubtrees = mapAttrs (name: _normaliseTreeFilter (path + "/${name}")) entries;
subtreeValues = attrValues normalisedSubtrees;
in
# This triggers either when all files in a directory are filtered out
# Or when the directory doesn't contain any files at all
if all isNull subtreeValues then
null
# Triggers when we have the same as a `readDir path`, so we can turn it back into an equivalent "directory".
else if all isString subtreeValues then
"directory"
else
normalisedSubtrees
else
tree;
/**
A minimal normalisation of a filesetTree, intended for pretty-printing:
@@ -535,9 +526,6 @@ rec {
else
"/" + concatStringsSep "/" fileset._internalBaseComponents + "/";
getBaseStringPrefix = substring 0 baseLength;
removeBaseStringPrefix = substring baseLength (-1);
baseLength = stringLength baseString;
# Check whether a list of path components under the base path exists in the tree.
@@ -563,12 +551,7 @@ rec {
# or a string ("directory" or "regular", etc.) in which case it's included
localTree != null;
in
# Start by recursing into the first element. This is guaranteed to be
# safe. components will never be empty (builtins.split can't make an
# empty list). Tree can be something other than an attrset, but if so,
# the isAttrs check will fail when being passed `or tree`, and the index
# being ahead doesn't matter.
recurse 2 (tree.${head components} or tree);
recurse 0 tree;
# Filter suited when there's no files
empty = _: _: false;
@@ -586,34 +569,25 @@ rec {
pathSlash = path + "/";
in
(
# Same as `hasPrefix baseString pathSlash`, but more efficient.
# The path is either the base itself or underneath it,
# but only on the few paths above it, so its checked first.
# With base /foo/bar this matches /foo/bar and /foo/bar/baz
# hasPrefix "/foo/bar/" "/foo/bar/baz/"
if getBaseStringPrefix pathSlash == baseString then
if pathSlash == baseString then
# The path is the base directory itself, which is always included
true
else
# Same as `removePrefix baseString path`, but more efficient.
# From the above code we know that hasPrefix baseString pathSlash holds, so this is safe.
# We don't use pathSlash here because we only needed the trailing slash for the prefix matching.
# With base /foo and path /foo/bar/baz this gives
# inTree (split "/" (removePrefix "/foo/" "/foo/bar/baz"))
# == inTree (split "/" "bar/baz")
# == inTree [ "bar" "baz" ]
inTree (split "/" (removeBaseStringPrefix path))
# Same as `hasPrefix pathSlash baseString`, but more efficient.
# The path is a proper ancestor of the base, which needs to be included for the base to be reachable:
# With base /foo/bar we need to include /foo:
# hasPrefix "/foo/" "/foo/bar/"
else if substring 0 (stringLength pathSlash) baseString == pathSlash then
if substring 0 (stringLength pathSlash) baseString == pathSlash then
true
else
# The path is unrelated to the base, so nothing from it is included
# With base /foo/bar this matches e.g. /baz
# Same as `! hasPrefix baseString pathSlash`, but more efficient.
# With base /foo/bar we need to exclude /baz
# ! hasPrefix "/baz/" "/foo/bar/"
else if substring 0 baseLength pathSlash != baseString then
false
else
# Same as `removePrefix baseString path`, but more efficient.
# From the above code we know that hasPrefix baseString pathSlash holds, so this is safe.
# We don't use pathSlash here because we only needed the trailing slash for the prefix matching.
# With base /foo and path /foo/bar/baz this gives
# inTree (split "/" (removePrefix "/foo/" "/foo/bar/baz"))
# == inTree (split "/" "bar/baz")
# == inTree [ "bar" "baz" ]
inTree (split "/" (substring baseLength (-1) path))
)
# This is a way have an additional check in case the above is true without any significant performance cost
&& (
@@ -828,34 +802,21 @@ rec {
*/
_unionTrees =
trees:
if length trees == 1 then
# The union of a single tree simply returns the first element
head trees
else
let
# Like lib.findFirstIndex but without indexing.
# This is a hot path so the indexing arithmetic adds up.
firstStr = foldl' (
found: tree:
if found != null then
found
else if isString tree then
tree
else
found # null
) null trees;
nonNulls = filter (tree: tree != null) trees;
in
let
stringIndex = findFirstIndex isString null trees;
withoutNull = filter (tree: tree != null) trees;
in
if stringIndex != null then
# If there's a string, it's always a fully included tree (dir or file),
# no need to look at other elements
if firstStr != null then
firstStr
else if nonNulls == [ ] then
null
else
# The non-null elements have to be attribute sets representing partial trees
# We need to recurse into those
zipAttrsWith (name: _unionTrees) nonNulls;
elemAt trees stringIndex
else if withoutNull == [ ] then
# If all trees are null, then the resulting tree is also null
null
else
# The non-null elements have to be attribute sets representing partial trees
# We need to recurse into those
zipAttrsWith (name: _unionTrees) withoutNull;
/**
Computes the intersection of two filesets.

View File

@@ -14,7 +14,6 @@
let
inherit (lib)
catAttrs
concatMapStringsSep
concatStrings
escape
@@ -410,7 +409,7 @@ rec {
elems:
let
gvarElems = map mkValue elems;
tupleType = type.tupleOf (catAttrs "type" gvarElems);
tupleType = type.tupleOf (map (e: e.type) gvarElems);
in
mkPrimitive tupleType gvarElems
// {

View File

@@ -203,11 +203,6 @@ lib.mapAttrs mkLicense (
fullName = " BitTorrent Open Source License v1.1";
};
blessing = {
spdxId = "blessing";
fullName = "SQLite Blessing";
};
boehmGC = {
spdxId = "Boehm-GC";
fullName = "Boehm-Demers-Weiser GC License";
@@ -1622,13 +1617,6 @@ lib.mapAttrs mkLicense (
fullName = "Universal Permissive License";
};
valveSDK = {
fullName = "Valve Corporation Steamworks SDK Access Agreement";
url = "https://partner.steamgames.com/documentation/sdk_access_agreement";
free = false;
redistributable = true;
};
vim = {
spdxId = "Vim";
fullName = "Vim License";

View File

@@ -16,7 +16,6 @@ let
any
attrNames
attrValues
catAttrs
concatMap
isFunction
isBool
@@ -142,10 +141,10 @@ lib.fix (self: {
assert all isTypeDef types;
let
# Store a list of functions so we don't have to pay the cost of attrset lookups at runtime.
funcs = catAttrs "verify" types;
funcs = map (t: t.verify) types;
in
{
name = "union<${concatStringsSep "," (catAttrs "name" types)}>";
name = "union<${concatStringsSep "," (map (t: t.name) types)}>";
verify = v: any (func: func v) funcs;
};
@@ -154,10 +153,10 @@ lib.fix (self: {
assert all isTypeDef types;
let
# Store a list of functions so we don't have to pay the cost of attrset lookups at runtime.
funcs = catAttrs "verify" types;
funcs = map (t: t.verify) types;
in
{
name = "intersection<${concatStringsSep "," (catAttrs "name" types)}>";
name = "intersection<${concatStringsSep "," (map (t: t.name) types)}>";
verify = v: all (func: func v) funcs;
};

View File

@@ -566,7 +566,7 @@ let
let
keyFilter = filter (attrs: !isDisabled modulesPath disabled attrs);
in
catAttrs "module" (genericClosure {
map (attrs: attrs.module) (genericClosure {
startSet = keyFilter modules;
operator = attrs: keyFilter attrs.modules;
});
@@ -1148,8 +1148,8 @@ let
// {
value = addErrorContext "while evaluating the option `${showOption loc}':" value;
inherit (res.defsFinal') highestPrio;
definitions = catAttrs "value" res.defsFinal;
files = catAttrs "file" res.defsFinal;
definitions = map (def: def.value) res.defsFinal;
files = map (def: def.file) res.defsFinal;
definitionsWithLocations = res.defsFinal;
inherit (res) isDefined;
inherit (res.checkedAndMerged) valueMeta;

View File

@@ -29,7 +29,6 @@ let
;
inherit (lib.attrsets)
attrByPath
catAttrs
optionalAttrs
showAttrPath
;
@@ -540,7 +539,7 @@ rec {
:::
*/
getValues = catAttrs "value";
getValues = map (x: x.value);
/**
Extracts values of all `file` keys of the given list
@@ -562,7 +561,7 @@ rec {
:::
*/
getFiles = catAttrs "file";
getFiles = map (x: x.file);
# Generate documentation template from the list of option declaration like
# the set generated with filterOptionSets.

View File

@@ -151,24 +151,7 @@ let
);
# Derived meta-data
useLLVM =
final.isFreeBSD
|| final.isOpenBSD
|| final.isUefi
|| final.isMsvc
||
# because GCC does not support this platform yet
(with final; isWindows && isAarch64);
# Use the split GCC package set (`gccNGPackages`) instead of the
# monolithic `gcc`. No platform selects it yet; it is opt-in, set
# explicitly on a platform spec, so that the split set can be exercised
# before anything depends on it.
#
# I (@Ericson2314) plan on making obscure low-tier platforms (e.g.
# NetBSD) use it soon, so we can dogfood GCC NG and thereby iron out its
# bugs.
useGccNG = false;
useLLVM = final.isFreeBSD || final.isOpenBSD;
libc =
if final.isDarwin then
@@ -193,7 +176,9 @@ let
"uclibc"
else if final.isAndroid then
"bionic"
else if final.isLinux then
else if
final.isLinux # default
then
"glibc"
else if final.isFreeBSD then
"fblibc"
@@ -205,8 +190,6 @@ let
"avrlibc"
else if final.isGhcjs then
null
else if final.isUefi then
null
else if final.isNone then
"newlib"
# TODO(@Ericson2314) think more about other operating systems

View File

@@ -93,6 +93,7 @@ rec {
config = "aarch64-unknown-linux-android";
androidSdkVersion = "35";
androidNdkVersion = "27";
libc = "bionic";
useAndroidPrebuilt = false;
useLLVM = true;
};
@@ -168,18 +169,22 @@ rec {
riscv64-embedded = {
config = "riscv64-none-elf";
libc = "newlib";
};
riscv32-embedded = {
config = "riscv32-none-elf";
libc = "newlib";
};
mips64-embedded = {
config = "mips64-none-elf";
libc = "newlib";
};
mips-embedded = {
config = "mips-none-elf";
libc = "newlib";
};
# https://github.com/loongson/la-softdev-convention/blob/master/la-softdev-convention.adoc#10-operating-system-package-build-requirements
@@ -196,17 +201,17 @@ rec {
mmix = {
config = "mmix-unknown-mmixware";
# Not `isNone`: the OS here is `mmixware`, so the bare-metal default does
# not apply.
libc = "newlib";
};
rx-embedded = {
config = "rx-none-elf";
libc = "newlib";
};
msp430 = {
config = "msp430-elf";
libc = "newlib";
};
avr = {
@@ -215,10 +220,12 @@ rec {
vc4 = {
config = "vc4-elf";
libc = "newlib";
};
or1k = {
config = "or1k-elf";
libc = "newlib";
};
m68k = {
@@ -243,6 +250,7 @@ rec {
arm-embedded = {
config = "arm-none-eabi";
libc = "newlib";
};
arm-embedded-nano = {
config = "arm-none-eabi";
@@ -250,6 +258,7 @@ rec {
};
armhf-embedded = {
config = "arm-none-eabihf";
libc = "newlib";
# GCC8+ does not build without this
# (https://www.mail-archive.com/gcc-bugs@gcc.gnu.org/msg552339.html):
gcc = {
@@ -260,31 +269,38 @@ rec {
aarch64-embedded = {
config = "aarch64-none-elf";
libc = "newlib";
rust.rustcTarget = "aarch64-unknown-none";
};
aarch64be-embedded = {
config = "aarch64_be-none-elf";
libc = "newlib";
};
ppc-embedded = {
config = "powerpc-none-eabi";
libc = "newlib";
};
ppcle-embedded = {
config = "powerpcle-none-eabi";
libc = "newlib";
};
i686-embedded = {
config = "i686-elf";
libc = "newlib";
};
x86_64-embedded = {
config = "x86_64-elf";
libc = "newlib";
};
microblaze-embedded = {
config = "microblazeel-none-elf";
libc = "newlib";
};
#
@@ -322,10 +338,16 @@ rec {
x86_64-unknown-uefi = {
config = "x86_64-unknown-uefi";
libc = null;
useLLVM = true;
linker = "lld";
};
aarch64-unknown-uefi = {
config = "aarch64-unknown-uefi";
libc = null;
useLLVM = true;
linker = "lld";
};
#
@@ -360,11 +382,12 @@ rec {
};
# mingw-w64 with ucrt for Aarch64, default compiler (which is LLVM
# see ./default.nix).
# because GCC does not support this platform yet).
mingw-ucrt-aarch64 = {
config = "aarch64-w64-mingw32";
libc = "ucrt";
rust.rustcTarget = "aarch64-pc-windows-gnullvm";
useLLVM = true;
};
# mingw-64 back compat
@@ -377,10 +400,12 @@ rec {
# Target the MSVC ABI
x86_64-windows = {
config = "x86_64-pc-windows-msvc";
useLLVM = true;
};
aarch64-windows = {
config = "aarch64-pc-windows-msvc";
useLLVM = true;
};
x86_64-cygwin = {
@@ -391,10 +416,12 @@ rec {
aarch64-freebsd = {
config = "aarch64-unknown-freebsd";
useLLVM = true;
};
x86_64-freebsd = {
config = "x86_64-unknown-freebsd";
useLLVM = true;
};
x86_64-netbsd = {

View File

@@ -608,7 +608,7 @@ rec {
description = "fileset";
descriptionClass = "noun";
check = isFileset;
merge = loc: defs: unions (getValues defs);
merge = loc: defs: unions (map (x: x.value) defs);
emptyValue.value = empty;
};

View File

@@ -2,10 +2,11 @@
"acme": {
"description": "Maintain ACME-related packages and modules.",
"id": 3806126,
"maintainers": {},
"maintainers": {
"emilazy": 18535642
},
"members": {
"arianvp": 628387,
"emilazy": 18535642,
"m1cr0man": 3044438
},
"name": "ACME"
@@ -59,6 +60,7 @@
"adamcstephens": 2071575,
"ankhers": 750786,
"gleber": 33185,
"minijackson": 1200507,
"yurrriq": 1866448
},
"name": "Beam"
@@ -66,11 +68,12 @@
"boot-security": {
"description": "Maintain support for boot security technologies like Secure Boot",
"id": 18686947,
"maintainers": {},
"members": {
"ElvishJerricco": 1365692,
"maintainers": {
"emilazy": 18535642
},
"members": {
"ElvishJerricco": 1365692
},
"name": "Boot security"
},
"bootstrapping": {
@@ -95,8 +98,8 @@
"fgaz": 8182846,
"natsukium": 25083790,
"philiptaron": 43863,
"tomodachi94": 68489118,
"tr3foil": 29682759
"pyrotelekinetic": 29682759,
"tomodachi94": 68489118
},
"members": {},
"name": "Categorization"
@@ -181,6 +184,7 @@
"description": "Improve Darwin-support across Nixpkgs and help maintainers without access to Darwin hardware. Apply to join through https://github.com/NixOS/nixpkgs/issues/323144 to keep the process transparent.",
"id": 2385202,
"maintainers": {
"emilazy": 18535642,
"toonn": 1486805
},
"members": {
@@ -207,12 +211,10 @@
"cideM": 4246921,
"cidkidnix": 67574902,
"copumpkin": 2623,
"delafthi": 50531499,
"devusb": 4951663,
"domenkozar": 126339,
"dwt": 57199,
"eclairevoyant": 848000,
"emilazy": 18535642,
"ethancedwards8": 60861925,
"fiddlerwoaroof": 808745,
"fulsomenko": 14945057,
@@ -578,11 +580,11 @@
"id": 9955829,
"maintainers": {
"RossComputerGuy": 19699320,
"alyssais": 2768870
"alyssais": 2768870,
"emilazy": 18535642
},
"members": {
"Ericson2314": 1055245,
"emilazy": 18535642,
"peterwaller-arm": 52030119,
"rrbutani": 7833358
},
@@ -754,6 +756,16 @@
},
"name": "Nixpkgs CI"
},
"nixpkgs-core": {
"description": "Provides leadership for and has authority over Nixpkgs.",
"id": 14317027,
"maintainers": {
"alyssais": 2768870,
"emilazy": 18535642
},
"members": {},
"name": "Nixpkgs core"
},
"nixpkgs-merge-bot": {
"description": "This team exists as a target for triggering the nixpkgs merge bot.",
"id": 13926892,
@@ -989,11 +1001,11 @@
"id": 11265412,
"maintainers": {
"RossComputerGuy": 19699320,
"emilazy": 18535642,
"philiptaron": 43863
},
"members": {
"Ericson2314": 1055245,
"emilazy": 18535642,
"reckenrode": 7413633
},
"name": "stdenv"

View File

@@ -63,12 +63,6 @@
{
# keep-sorted start case=no numeric=no block=yes
"3mp3ri0r" = {
email = "christoforus@xendit.co";
github = "3mp3ri0r";
githubId = 3140815;
name = "Christoforus Surjoputro";
};
_0b11stan = {
name = "Tristan Auvinet Pinaudeau";
email = "tristan@tic.sh";
@@ -295,11 +289,6 @@
name = "6543";
keys = [ { fingerprint = "8722 B61D 7234 1082 553B 201C B8BE 6D61 0E61 C862"; } ];
};
_66HEX = {
name = "Marek Jóźwiak";
github = "66HEX";
githubId = 168720167;
};
_6AA4FD = {
email = "f6442954@gmail.com";
github = "6AA4FD";
@@ -627,11 +616,6 @@
{ fingerprint = "CE85 54F7 B9BC AC0D D648 5661 AB5F C04C 3C94 443F"; }
];
};
ad-si = {
name = "Adrian Sieber";
github = "ad-si";
githubId = 36796532;
};
ad030 = {
name = "Alex Dam";
github = "ad030";
@@ -891,12 +875,6 @@
githubId = 6055037;
name = "Alexander Hirner";
};
AhmedAmr = {
email = "ahmedamr24680@gmail.com";
github = "AhmedAmrNabil";
githubId = 43810060;
name = "Ahmed Amr";
};
ahoneybun = {
email = "aaronhoneycutt@proton.me";
github = "ahoneybun";
@@ -1450,11 +1428,6 @@
githubId = 30437811;
name = "Alex Andrews";
};
alikaansun = {
github = "alikaansun";
githubId = 77810345;
name = "Ali Kaan Sunnetcioglu";
};
alikindsys = {
email = "alice@blocovermelho.org";
github = "alikindsys";
@@ -1993,13 +1966,6 @@
githubId = 143312793;
name = "Annin";
};
annoyingrains = {
email = "avali@avali.zone";
matrix = "@avali:avali.zone";
github = "AnnoyingRain5";
githubId = 35289650;
name = "AnnoyingRains";
};
anntnzrb = {
github = "anntnzrb";
githubId = 51257127;
@@ -2220,12 +2186,6 @@
githubId = 8436007;
name = "Aria Edmonds";
};
ar4m1s = {
name = "Aramis";
github = "Ar4m1s";
githubId = 59250656;
matrix = "@vegardbm:matrix.org";
};
arbel-arad = {
email = "arbel@spacetime.technology";
github = "arbel-arad";
@@ -2352,12 +2312,6 @@
githubId = 8049011;
name = "Arik Grahl";
};
arison = {
email = "arison@duck.com";
github = "ArisoN-ext";
githubId = 181835726;
name = "ArisoN";
};
ariutta = {
email = "anders.riutta@gmail.com";
github = "ariutta";
@@ -5188,11 +5142,6 @@
githubId = 1103294;
name = "Christopher Rosset";
};
christo-auer = {
name = "Christopher Auer";
github = "christo-auer";
githubId = 15138131;
};
christoph-heiss = {
email = "christoph@c8h4.io";
github = "christoph-heiss";
@@ -6903,12 +6852,6 @@
githubId = 27348469;
name = "Cat";
};
denzonl = {
email = "dennis@bogers.xyz";
github = "DenzoNL";
githubId = 7504556;
name = "Dennis Bogers";
};
derchris = {
email = "derchris@me.com";
github = "derchrisuk";
@@ -7161,12 +7104,6 @@
githubId = 15774340;
name = "Thomas Depierre";
};
dibenzepin = {
name = "Fumnanya";
email = "fmowete@outlook.com";
github = "dibenzepin";
githubId = 87488715;
};
DictXiong = {
email = "me@beardic.cn";
github = "DictXiong";
@@ -7608,6 +7545,12 @@
githubId = 81854406;
name = "Chew Cheng Hong";
};
drew-dirac = {
email = "drew@diracinc.com";
github = "drew-dirac";
githubId = 187309685;
name = "Drew Council";
};
drperceptron = {
github = "drperceptron";
githubId = 92106371;
@@ -7787,8 +7730,7 @@
matrix = "@dvdznf:gitter.im";
};
dvn0 = {
email = "devan@informatics.coop";
keys = [ { fingerprint = "E0F4 87C6 6298 7353 A7D0 E997 8203 BD5C 41D8 29DF"; } ];
email = "git@dvn.me";
github = "dvn0";
githubId = 10859387;
name = "Devan Carpenter";
@@ -8023,12 +7965,6 @@
github = "edlimerkaj";
githubId = 71988351;
};
edoars = {
name = "Edoardo Signorini";
email = "mail@edoars.me";
github = "edoars";
githubId = 44139791;
};
edrex = {
email = "ericdrex@gmail.com";
github = "edrex";
@@ -8151,13 +8087,6 @@
githubId = 7494394;
name = "Karim Elatov";
};
eldios = {
email = "emanuele.lele.calo@gmail.com";
github = "eldios";
githubId = 483767;
name = "Emanuele 'Lele' Calo";
keys = [ { fingerprint = "AA6B C774 3F8F 9AD8 4BBA 15C7 2CCB F4B7 1EFF DD46"; } ];
};
eleanor = {
email = "dejan@proteansec.com";
github = "proteansec";
@@ -8316,12 +8245,6 @@
githubId = 1365692;
name = "Will Fancher";
};
elzorrorebelde = {
name = "Jorge Javier Araya Navarro";
email = "jorge@esavara.cr";
github = "elzorrorebelde";
githubId = 1055216;
};
emaiax = {
email = "github@emaiax.dev";
github = "emaiax";
@@ -8804,12 +8727,6 @@
githubId = 330292;
name = "Evan Richter";
};
evanwporter = {
email = "evanwporter@gmail.com";
github = "evanwporter";
githubId = 115374841;
name = "Evan Porter";
};
evax = {
email = "nixos@evax.fr";
github = "evax";
@@ -10132,11 +10049,6 @@
name = "Kirill Samoylenkov";
keys = [ { fingerprint = "955B 97C5 78A3 DF03 D818 25EB 8E40 5DD2 CF84 CCE0"; } ];
};
gefla = {
name = "Gerd Flaig";
github = "gefla";
githubId = 56790;
};
genga898 = {
email = "genga898@gmail.com";
github = "genga898";
@@ -10183,12 +10095,7 @@
github = "gepbird";
githubId = 29818440;
name = "Gutyina Gergő";
matrix = "@gepbird:matrix.org";
keys = [
{ fingerprint = "hEzYpII9pUMfbhhr1LbUaLoGKGKX7UJQ1i9QU5SIssQ"; }
{ fingerprint = "MnieeyZ1Y02OB4PMrkM5xrk3ZXq3XTahcSocDyqzmFg"; }
{ fingerprint = "YfsHXlTvwc3HmLzQPi4g9nn4bKCj/mV/xgg9dxxxdnU"; }
{ fingerprint = "2NGbD6uF4OYtqjaYvN4foZFooT7XTAHODUaNxGVuJdk"; }
{ fingerprint = "RoAfvqa6w1l8Vdm3W60TDXurYwJ6h03VEGD+wDNGEwc"; }
{ fingerprint = "MP2UpIRtJpbFFqyucP431H/FPCfn58UhEUTro4lXtRs"; }
];
@@ -11335,6 +11242,11 @@
githubId = 58676303;
name = "hhydraa";
};
hibiday = {
name = "Katsumi Takeuchi";
github = "hibiday";
githubId = 137286929;
};
higebu = {
name = "Yuya Kusakabe";
email = "yuya.kusakabe@gmail.com";
@@ -11346,11 +11258,6 @@
github = "HigherOrderLogic";
githubId = 73709188;
};
highghlow = {
name = "Alex Kravchenko";
github = "unhighghlow";
githubId = 132668972;
};
hirenashah = {
email = "hiren@hiren.io";
github = "hirenashah";
@@ -12520,13 +12427,6 @@
githubId = 7558482;
name = "Jack Gerrits";
};
jackoe = {
name = "Jack Wines";
email = "nixos@winesj.com";
github = "jackoe";
githubId = 3060163;
matrix = "@noiobeforebedtime:winesj.com";
};
jackr = {
name = "Jack Rosenberg";
email = "nixos@jackr.eu";
@@ -13646,12 +13546,6 @@
githubId = 32305209;
name = "John Children";
};
johnhamelink = {
email = "me@johnhame.link";
github = "johnhamelink";
githubId = 101739;
name = "John Hamelink";
};
johnjohnstone = {
email = "jjohnstone@riseup.net";
github = "johnjohnstone";
@@ -14093,12 +13987,6 @@
name = "John Soo";
githubId = 10039785;
};
jsqu4re = {
email = "johannes.jeising@gmail.com";
github = "jsqu4re";
githubId = 35706792;
name = "Johannes Jeising";
};
jsusk = {
email = "joshua@suskalo.org";
github = "IGJoshua";
@@ -16192,11 +16080,7 @@
};
liamthexpl0rer = {
name = "Liam";
matrix = "@liamthexpl0rer:l14mx.de";
keys = [
{ fingerprint = "3C0A 0FC8 E406 E602 50F3 FCFD 7633 7F2C A1CB 537D"; }
{ fingerprint = "CC53 895B 3CC7 7B29 AA46 55EF 6DF0 2F41 092A 9B30"; }
];
matrix = "@liamthexpl0rer:matrix.org";
github = "liamthexpl0rer";
githubId = 119797945;
};
@@ -17000,13 +16884,6 @@
}
];
};
lunkentuss = {
email = "peter.hansson17@gmail.com";
matrix = "@lunkentuss:matrix.org";
github = "lunkentuss";
githubId = 9850798;
name = "Peter Hansson";
};
LunNova = {
email = "nixpkgs-maintainer@lunnova.dev";
github = "LunNova";
@@ -17044,17 +16921,6 @@
matrix = "@lux:ontheblueplanet.com";
name = "Lux";
};
luytan = {
email = "luytan@khora.me";
github = "luytan";
githubId = 221864923;
name = "Luytan";
keys = [
{
fingerprint = "E7B7 215C 0DFB 3D8C 17EE 95E0 E0AD 187A 4F2B 41EF";
}
];
};
luz = {
email = "luz666@daum.net";
github = "Luz";
@@ -18949,12 +18815,6 @@
githubId = 54669781;
keys = [ { fingerprint = "293B 93D8 A471 059F 85D7 16A6 5BA9 2099 D9BE 2DAA"; } ];
};
mishushakov = {
email = "mish@e2b.dev";
github = "mishushakov";
githubId = 10400064;
name = "Mish Ushakov";
};
misilelab = {
name = "misilelab";
email = "misileminecord@gmail.com";
@@ -19321,13 +19181,6 @@
matrix = "@motiejus:jakstys.lt";
name = "Motiejus Jakštys";
};
Mowerick = {
email = "oliverhagenauer@gmail.com";
github = "Mowerick";
githubId = 102822250;
keys = [ { fingerprint = "6472 901A F0E7 F983 4893 042F 5F76 361C 2EF9 C95F"; } ];
name = "Oliver Hagenauer";
};
mpcsh = {
email = "m@mpc.sh";
github = "mpcsh";
@@ -20615,12 +20468,6 @@
githubId = 70602908;
github = "nikolaizombie1";
};
nikp123 = {
name = "nikp123";
email = "nikp123@e.email";
github = "nikp123";
githubId = 4696350;
};
nikstur = {
email = "nikstur@outlook.com";
name = "nikstur";
@@ -21098,12 +20945,6 @@
githubId = 1839979;
name = "Niklas Thörne";
};
ntsk = {
email = "ntsk@ntsk.jp";
github = "ntsk";
githubId = 5681281;
name = "ntsk";
};
nudelsalat = {
email = "nudelsalat@clouz.de";
name = "Fabian Dreßler";
@@ -21889,12 +21730,6 @@
githubId = 4908217;
name = "Paho Lurie-Gregg";
};
paige = {
email = "paigely@tuta.io";
github = "ssalggnikool";
githubId = 235818692;
name = "paige";
};
pakhfn = {
email = "pakhfn@gmail.com";
github = "pakhfn";
@@ -22924,6 +22759,12 @@
githubId = 4201956;
name = "pongo1231";
};
poopsicles = {
name = "Fumnanya";
email = "fmowete@outlook.com";
github = "dibenzepin";
githubId = 87488715;
};
PopeRigby = {
name = "PopeRigby";
github = "poperigby";
@@ -23652,13 +23493,6 @@
github = "rachalaraj";
githubId = 124191100;
};
rachitvrma = {
name = "Rachit Kumar Verma";
email = "rachitverma1122+nixpkgs@gmail.com";
matrix = "@rachitvrma:matrix.org";
github = "rachitvrma";
githubId = 155641117;
};
RadxaYuntian = {
# This is the work account for @MakiseKurisu
name = "ZHANG Yuntian";
@@ -23967,12 +23801,6 @@
name = "Roland Conybeare";
keys = [ { fingerprint = "bw5Cr/4ul1C2UvxopphbZbFI1i5PCSnOmPID7mJ/Ogo"; } ];
};
rdk31 = {
email = "nixpkgs@rdk31.com";
github = "rdk31";
githubId = 16737959;
name = "rdk31";
};
rdnetto = {
email = "rdnetto@gmail.com";
github = "rdnetto";
@@ -23996,12 +23824,6 @@
{ fingerprint = "01D7 5486 3A6D 64EA AC77 0D26 FBF1 9A98 2CCE 0048"; }
];
};
recutita = {
name = "Katsumi Takeuchi";
email = "contact@recutita.com";
github = "recutita";
githubId = 137286929;
};
redfish64 = {
email = "engler@gmail.com";
github = "redfish64";
@@ -24299,12 +24121,6 @@
githubId = 6047658;
name = "Ryan Horiguchi";
};
rhousand = {
email = "rhousand@gmail.com";
github = "rhousand";
githubId = 6124540;
name = "Ryan Housand";
};
rhydianjenkins = {
name = "Rhydian Jenkins";
github = "RhydianJenkins";
@@ -26116,6 +25932,12 @@
githubId = 5512096;
name = "Sébastien Guimmara";
};
shackra = {
name = "Jorge Javier Araya Navarro";
email = "jorge@esavara.cr";
github = "shackra";
githubId = 1055216;
};
shadaj = {
github = "shadaj";
githubId = 543055;
@@ -26668,12 +26490,6 @@
githubId = 848812;
name = "Stephan Jau";
};
sjcobb = {
email = "sjcobb2003@gmail.com";
github = "sjcobb2022";
githubId = 68509699;
name = "sjcobb";
};
sjfloat = {
email = "steve+nixpkgs@jonescape.com";
github = "sjfloat";
@@ -26693,12 +26509,6 @@
githubId = 617130;
keys = [ { fingerprint = "C4F7 46C7 B560 38D8 210F 0288 5877 DEE9 7428 557F"; } ];
};
skirlez = {
name = "skirlez";
email = "skirlez3@gmail.com";
github = "skirlez";
githubId = 17904548;
};
skohtv = {
name = "Skoh";
email = "contact@skoh.dev";
@@ -31070,13 +30880,6 @@
githubId = 1595132;
name = "Kranium Gikos Mendoza";
};
WOnder93 = {
email = "omosnacek@gmail.com";
github = "WOnder93";
githubId = 3041388;
matrix = "@omos:fedora.im";
name = "Ondrej Mosnáček";
};
workflow = {
email = "4farlion@gmail.com";
github = "workflow";
@@ -31388,12 +31191,6 @@
githubId = 3028542;
name = "Guillermo NWDD";
};
xoconoch = {
email = "github@cordovault.com";
github = "xoconoch";
githubId = 93692082;
name = "Xoconoch";
};
xokdvium = {
email = "sergei@zimmerman.foo";
github = "xokdvium";
@@ -32012,12 +31809,6 @@
githubId = 3449926;
name = "David Costa";
};
ZariTen = {
email = "ZaritenProt@proton.me";
github = "ZariTen";
githubId = 48529745;
name = "ZariTen";
};
zatm8 = {
email = "maxis1191@gmail.com";
github = "mourogurt";

View File

@@ -23,7 +23,6 @@ digestif,,,,,5.3,
dkjson,,,,,,
enet,,,,,,ulysseszhan
etlua,,,,,,ulysseszhan
fallo,,,,,,mrcjkb
fennel,,,,,,misterio77
fidget.nvim,,,,,5.1,mrcjkb
fifo,,,,,,
1 name rockspec ref server version luaversion maintainers
23 dkjson
24 enet ulysseszhan
25 etlua ulysseszhan
fallo mrcjkb
26 fennel misterio77
27 fidget.nvim 5.1 mrcjkb
28 fifo

View File

@@ -10,9 +10,6 @@ stdenv.mkDerivation {
pname = "nixpkgs-lint";
version = "1";
__structuredAttrs = true;
strictDeps = true;
nativeBuildInputs = [ makeWrapper ];
buildInputs = [
perl
@@ -23,20 +20,16 @@ stdenv.mkDerivation {
dontBuild = true;
installPhase = ''
runHook preInstall
mkdir -p $out/bin
cp ${./nixpkgs-lint.pl} $out/bin/nixpkgs-lint
# make the built version hermetic
substituteInPlace $out/bin/nixpkgs-lint \
--replace-fail "#! /usr/bin/env nix-shell" "#! ${lib.getExe perl}"
wrapProgram $out/bin/nixpkgs-lint --set PERL5LIB $PERL5LIB
runHook postInstall
'';
meta = {
description = "Utility for Nixpkgs contributors to check Nixpkgs for common errors";
description = "A utility for Nixpkgs contributors to check Nixpkgs for common errors";
mainProgram = "nixpkgs-lint";
platforms = lib.platforms.unix;
};

View File

@@ -91,6 +91,10 @@ with lib.maintainers;
shortName = "Blockchains";
};
boot-security = {
github = "boot-security";
};
budgie = {
members = [
bobby285271
@@ -402,7 +406,6 @@ with lib.maintainers;
GaetanLepage
natsukium
thomasjm
haansn08
];
scope = "Maintain Jupyter and related packages.";
shortName = "Jupyter";
@@ -711,6 +714,7 @@ with lib.maintainers;
sage = {
members = [
timokau
raskin
collares
];

View File

@@ -395,7 +395,7 @@ have a predefined type and string generator already declared under
`mkRaw pythonCode`
: Outputs the given string as raw Python code. Note that the final result will be stripped of any comments.
: Outputs the given string as raw Python code
`_imports`

View File

@@ -1,57 +0,0 @@
# State revision {#sec-state-revision}
NixOS includes a {option}`system.stateVersion` option, used by some modules for a
variety of reasons related to non-backward-compatible changes to software or
the module itself.
Module authors are discouraged from adding new uses of
{option}`system.stateVersion` to their module.
However, when the alternatives are impractical, modules that wish to consume
{option}`system.stateVersion` should instead define their own `stateRevision`
option using `utils.mkStateRevisionOption`.
There should be no uses of `config.system.stateVersion` directly in the module.
(Note the name difference: the {option}`system.stateVersion` option, with a V,
takes a value that looks like "YY.MM".
A `stateRevision` option, with an R, takes a non-negative integer value.)
Modules should also add the value of their `stateRevision` option to
`system.moduleStateRevisions."your.module.stateRevision"`, when the module is
enabled.
This is a purely informative option that exists to help describe the effects of
changing {option}`system.stateVersion`.
Example:
```nix
{
lib,
config,
utils,
...
}:
let
cfg = config.services.whatever;
in
{
options.services.whatever = {
enable = lib.mkEnableOption "whatever, a service that does whatever";
stateRevision = utils.mkStateRevisionOption {
descriptionName = "the whatever service";
migrations = {
"26.05" = "Rename `/var/lib/old_name` to `/var/lib/new_name`.";
};
};
};
config = lib.mkIf cfg.enable {
systemd.services.whatever = {
# ...
serviceConfig.StateDirectory = if cfg.stateRevision < 1 then "old_name" else "new_name";
};
# Important: this is inside the `lib.mkIf cfg.enable`
system.moduleStateRevisions."services.whatever.stateRevision" = cfg.stateRevision;
};
}
```

View File

@@ -220,5 +220,4 @@ importing-modules.section.md
replace-modules.section.md
freeform-modules.section.md
settings-options.section.md
state-revision.section.md
```

View File

@@ -41,22 +41,8 @@ supported stable release.
When you first install NixOS, you're automatically subscribed to the
NixOS channel that corresponds to your installation source. For
instance, if you installed from a 26.05 ISO, you will be subscribed to
the `nixos-26.05` channel.
Commands below are prefixed with `#` and have to be run as root in a
login shell:
```ShellSession
$ sudo -i
```
Without `sudo`:
```ShellSession
$ su -
```
To see which NixOS channel you're subscribed to, run:
the `nixos-26.05` channel. To see which NixOS channel you're subscribed
to, run the following as root:
```ShellSession
# nix-channel --list | grep nixos
@@ -98,15 +84,9 @@ by running
which is equivalent to the more verbose `nix-channel --update nixos; nixos-rebuild switch`.
::: {.note}
Channels are set per user. `nix-channel` reads and writes
`$HOME/.nix-channels`, so it acts on the channels of whoever owns the
current `$HOME`. A login shell sets `$HOME` to `/root`, which is why the
commands above act on root's channels — the ones
`/etc/nixos/configuration.nix` uses.
Plain `sudo` and `su` keep your own `$HOME`. `nix-channel --list` then
lists your own channels, and prints nothing when you have none.
`nix-channel --add` adds the channel for your user alone.
Channels are set per user. This means that running `nix-channel --add`
as a non root user (or without sudo) will not affect
configuration in `/etc/nixos/configuration.nix`
:::
::: {.warning}

View File

@@ -7,5 +7,5 @@ Additional information regarding the Nix package manager and the Nixpkgs project
If you encounter problems, please report them on the [`Discourse`](https://discourse.nixos.org), the [Matrix room](https://matrix.to/#/%23nix:nixos.org), or on the [`#nixos` channel on Libera.Chat](irc://irc.libera.chat/#nixos). Alternatively, consider [contributing to this manual](#chap-contributing). Bugs should be reported in [NixOS GitHub issue tracker](https://github.com/NixOS/nixpkgs/issues).
::: {.note}
Commands prefixed with `#` have to be run as root.
Commands prefixed with `#` have to be run as root, either requiring to login as root user or temporarily switching to it using `sudo` for example.
:::

View File

@@ -253,9 +253,6 @@
"sec-override-nixos-test": [
"index.html#sec-override-nixos-test"
],
"sec-state-revision": [
"index.html#sec-state-revision"
],
"sec-wireless-declarative": [
"index.html#sec-wireless-declarative"
],

View File

@@ -28,18 +28,10 @@
firewall, is available through
[services.portmaster](#opt-services.portmaster.enable).
- [btrfs-heatmap](https://github.com/knorrie/btrfs-heatmap), setcap wrapper for `btrfs-heatmap` package, a visualizer of how a btrfs filesystem is using the underlying disk space of the block devices. Available as [programs.btrfs-heatmap](#opt-programs.btrfs-heatmap.enable)
- [compsize](https://github.com/kilobyte/compsize), setcap wrapper for `compsize` package, a cli utility to to inspect compression type/ratio on BTRFS filesystems. Available as [programs.compsize](#opt-programs.compsize.enable)
- [tranquil](https://tangled.org/tranquil.farm/tranquil-pds) is an ATProto PDS (personal data server) implementation in Rust. A featureful, spec conscious and community driven alternative to the Bluesky reference implementation PDS. Available as [services.tranquil-pds](#opt-services.tranquil-pds.enable).
- [Cardwire](https://github.com/OpenGamingCollective/cardwire), a GPU manager for Linux that uses eBPF+LSM hooks to control GPUs. Available as [services.cardwired](#opt-services.cardwired.enable).
- [Moonlight Qt](https://moonlight-stream.org/), a client for playing your PC games on almost any device. Available as [programs.moonlight-qt](#opt-programs.moonlight-qt.enable).
- [RomM](https://romm.app/), a self-hosted ROM manager and player. Available as [services.romm](#opt-services.romm.enable).
- [scx_loader](https://github.com/sched-ext/scx-loader), a system daemon and DBus-based loader for sched_ext schedulers. `scxctl` is the command-line client for interacting with the loader, allowing users to switch schedulers, modes, and arguments dynamically. Available as [services.scx-loader](#opt-services.scx-loader.enable)
- [tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap), an ATProtocol firehose synchronisation utility. Available as [services.tap](#opt-services.tap.enable).
@@ -58,20 +50,14 @@
- [Stump](https://www.stumpapp.dev/), a free and open source comics, manga and digital book server with OPDS support. Available as [services.stump](#opt-services.stump.enable).
- [P2Pool](https://github.com/SChernykh/p2pool), a decentralized mining pool for Monero. Available as [services.p2pool](#opt-services.p2pool.enable).
- [Freescout](https://freescout.net/), a free, open source Helpdesk and shared mailbox. Available as [services.freescout](#opt-services.freescout.enable).
- [Lix TOML remote builders](https://docs.lix.systems/manual/lix/stable/advanced-topics/distributed-builds.html#using-a-toml-configuration), remote builder configuration using lix's TOML format. Available as [lix.buildMachines](#opt-lix.buildMachines). Note: incompatible with `nix.buildMachines`.
- [Forgejo Runner](https://forgejo.org/docs/latest/admin/actions/), a daemon for Forgejo Actions. Available as [services.forgejo-runner](#opt-services.forgejo-runner.instances).
- [Koito](https://koito.io/), a modern, themeable scrobbler that you can use with any program that scrobbles to a custom ListenBrainz URL. Available as [services.koito](#opt-services.koito.enable).
- [Zapret2](https://github.com/bol-van/zapret2), an extensible DPI bypass program. Available as [services.zapret2](#opt-services.zapret2.enable).
- [Solaar](https://github.com/pwr-Solaar/Solaar), a program to control logitech devices.
- [FlapAlerted](https://github.com/Kioubit/FlapAlerted), detects BGP flapping events and provides statistics based on BGP update messages. Available as [services.flap-alerted](#opt-services.flap-alerted.enable).
- [gocron](https://github.com/flohoss/gocron), a task scheduler with web interface. Available as [services.gocron](#opt-services.gocron.enable).
@@ -82,8 +68,6 @@
- [Matrix Authentication Service](https://github.com/element-hq/matrix-authentication-service) is an OAuth2.0 and OpenID Connect provider for Matrix homeservers (such as Synapse). It replaces standard password authentication with modern OpenID Connect flows, and can delegate authentication to upstream OIDC providers. Available as [services.matrix-authentication-service](#opt-services.matrix-authentication-service.enable).
- [Krill](https://nlnetlabs.nl/projects/krill/about), RPKI CA and Publication Server written in Rust. Available as [services.krill](#opt-services.krill.enable).
- [stash-clipboard](https://github.com/NotAShelf/stash), a Wayland clipboard "manager" with fast persistent history and multi-media support. Available as [services.stash-clipboard](#opt-services.stash-clipboard.enable).
- [OO7](https://github.com/linux-credentials/oo7) is a desktop-agnostic Secret Service provider. Available as [services.oo7](#opt-services.oo7.enable)
@@ -96,10 +80,6 @@
- [Entropy](https://github.com/ergohaven/entropy), a configurator for programmable keyboards and input devices running Vial-QMK/RMK firmware. Available as [programs.entropy](#opt-programs.entropy.enable).
- [Kvrocks](https://kvrocks.apache.org/), a distributed key value NoSQL database compatible with the Redis protocol. Available as [services.kvrocks](#opt-services.kvrocks.enable).
- [kvrocks_exporter](https://github.com/RocksLabs/kvrocks_exporter), a Prometheus exporter for Kvrocks metrics. Available as [services.prometheus.exporters.kvrocks](#opt-services.prometheus.exporters.kvrocks.enable).
## Backward Incompatibilities {#sec-release-26.11-incompatibilities}
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
@@ -134,8 +114,6 @@
- Rustical migrates from `settings.http.host` and `settings.http.port` to `settings.http.bind` to support UNIX domain sockets as well as TCP sockets in one setting.
- The `jetty_11` package has been removed as it reached end of life. Use `jetty_12` instead.
- The Mullvad VPN service now has a separate toggle to enable the Mullvad VPN graphical user interface. If you have previously used Mullvad on a desktop by setting `services.mullvad-vpn.package` to `pkgs.mullvad-vpn`, you should now **unset that option**, and enable `services.mullvad-vpn.gui.enable`. The VPN will not work if `services.mullvad-vpn.package` is set to `pkgs.mullvad-vpn`, as `pkgs.mullvad-vpn` no longer contains the Mullvad Daemon; please ensure that `services.mullvad-vpn.package` is set to `pkgs.mullvad`, regardless if you plan to enable the graphical user interface or not.
- A number of options for `services.llama-cpp` have been removed in favor of the structured [](#opt-services.llama-cpp.settings) option, attributes from which are used as arguments to `llama-server` executable, you can see all available options by running `llama-server --help`. Configuring model presets using Nix attribute set via `services.llama-cpp.modelsPreset` is no longer supported, please use `services.llama-cpp.settings.models-preset` with a path to an INI file containing desired options.
@@ -162,12 +140,8 @@
- String values passed to `services.phpfpm.settings`, `services.phpfpm.pools.<name>.phpEnv`, and `services.phpfpm.pools.<name>.settings` are now properly quoted and escaped, except for the `${}` syntax that is left as-is. If you are manually escaping these values, please adjust accordingly.
- GitLab has been updated from 18.x to 19.x and requires PostgreSQL >= 17, as stated in the [documentation](https://docs.gitlab.com/19.1/install/requirements/#postgresql). Check the [upgrade guide](#module-services-postgres-upgrading) in the NixOS manual on how to upgrade your PostgreSQL installation.
- `services.gitlab.registry` has been modified so that the GitLab container registry runs in the `gitlab-container-registry` system user. This behavior can be modified with the `services.gitlab.registry.user` option.
- `fail2ban` has been updated to 1.1.1, which has a few breaking changes compared to 1.1.0 ([changelog](https://github.com/fail2ban/fail2ban/blob/1.1.1/ChangeLog))
- `systemd.user.extraConfig` has been removed in favor of the structured [](#opt-systemd.user.settings.Manager) option. Use `systemd.user.settings.Manager` to set any `systemd-user.conf(5)` option directly. For example, replace `systemd.user.extraConfig = "DefaultTimeoutStartSec=60";` with `systemd.user.settings.Manager.DefaultTimeoutStartSec = 60;`.
- `matrix-appservice-discord` was removed from nixpkgs along with its NixOS module (`services.matrix-appservice-discord`) as it is no longer actively maintained upstream. Use the actively-maintained puppeting bridge [`mautrix-discord`](#opt-services.mautrix-discord.enable) instead.
@@ -201,8 +175,6 @@
- `temporal` has been updated to the 1.31 release line. Always consult the [upstream upgrade
notes](https://docs.temporal.io/self-hosted-guide/upgrade-server) before upgrading between versions.
- The Xen Project Hypervisor has been [updated to version 4.22](https://wiki.xenproject.org/wiki/Xen_Project_4.22_Release_Notes), after [version 4.21](https://wiki.xenproject.org/wiki/Xen_Project_4.21_Release_Notes) was skipped in 26.05. The module now has a separate option to customise the OCaml-based Xen Store Daemon package, `virtualisation.xen.store.package`.
- The `shell_interact()` function on interactive runs of NixOS VM tests has been deprecated. Use the SSH backdoor instead.
- NixOS VM tests now prefer to express durations and timeouts as `datetime.timedelta` values instead of bare numbers. Methods such as `machine.wait_until_succeeds`, `machine.sleep`, `retry`, and `polling_condition` now accept a `timedelta` (e.g., `machine.wait_for_unit("sshd.service", timeout=datetime.timedelta(minutes=1))`). Passing an `int`/`float` as seconds still works but now emits a deprecation warning. Argument names that explicitly defined units were preserved but have had `timedelta` equivalents introduced (`timeout_seconds` → `timeout`, `secs` → `duration`, `seconds_interval` → `interval`).
@@ -237,8 +209,6 @@
- `boot.supportedFilesystems.ntfs` installs `ntfsprogs-plus` instead of `ntfs3g` on kernel version 7.1 and later, unless `boot.supportedFilesystems.ntfs-3g` is explicitly enabled.
- `services.i2pd` has been refactored to take [RFC42](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md)-compliant `settings`. In order to migrate, you will need to move existing config under `settings` and rename them in accordance with the [upstream config format](https://docs.i2pd.website/en/latest/user-guide/configuration/#available-options). In addition, `inTunnels` and `outTunnels` needs to be renamed to `serverTunnels` and `clientTunnels` respectively.
- The `programs.fuse` module, which provides the `fusermount3` executable and the `/etc/fuse.conf` config file, is now opt-in. The obligation to enable it has been shifted to its various consumers (e.g. gvfs, flatpak, appimage, sshfs). This can break fuse consumers at runtime, that don't explicitly declare that dependency with a module, e.g the mounting functionality in various backup tools (borg, restic, rclone, ...).
- `services.plausible` can now again seed an initial admin user declaratively via [`services.plausible.adminUser.email`](#opt-services.plausible.adminUser.email).
@@ -247,8 +217,6 @@
- `services.gitlab.registry` now uses PostgreSQL as database storage for new installations and supports old installations that use the filesystem as metadata storage. It creates the required PostgreSQL database and user. Users can manually migrate their filesystem based metadata storage. See [GitLab Container Registry Migration to database metadata store](#module-services-gitlab-registry-database-migration).
- Enabling [`services.userborn`](#opt-services.userborn.enable) on a system that was previously managed by the default `update-users-groups.pl` script now imports the legacy state from `/var/lib/nixos/` on the first switch. Locked stub entries are added to `/etc/passwd` and `/etc/group` for every name recorded in `uid-map`/`gid-map` that no longer has a live entry, so a previously-used UID/GID cannot be reassigned to a different user. If the import fails, userborn does not start and the user database is left untouched. Inspect `journalctl -u userborn-import-legacy.service`, fix or remove the legacy state, and switch again. The import can be skipped entirely with [`services.userborn.importLegacyState`](#opt-services.userborn.importLegacyState)` = false`.
- The `newuidmap` and `newgidmap` security wrappers are now installed with `cap_setuid`/`cap_setgid` file capabilities instead of the setuid-root bit, matching shadow's `--with-fcaps` install mode and other major distributions. Rootless containers (podman, docker-rootless, unprivileged user namespaces) are unaffected. The only behavioural change is that mapping host uid 0 via `/etc/subuid` (which NixOS never configures by default) additionally requires `cap_setfcap`; users who explicitly grant uid 0 in a subuid range can restore the previous behaviour with `security.wrappers.newuidmap.capabilities = lib.mkForce "cap_setuid,cap_setfcap+ep";`.
- The `authelia` module now uses systemd's `LoadCredential` to load all files defined in `secrets`. As such, these files no longer need to be readable by the authelia user and group: they can for example be set to be only readable by the root user.
@@ -265,5 +233,3 @@
- `trilium-desktop` and `trilium-server` have been updated to 0.104.0. This release includes security hardening fixes that may break functionality. [See upstream release note for details](https://github.com/TriliumNext/Trilium/releases/tag/v0.104.0).
- `nix` now supports running in "daemonless" mode by setting `nix.daemon.enable = false`. Under this mode all store operations must go through the [local store type](https://nix.dev/manual/nix/latest/store/types/local-store), which typically requires root permissions.
- [Hister](https://github.com/asciimoo/hister), a web history service offering blazing fast, content-based search across visited websites. Available as [services.hister](#opt-services.hister.enable).

View File

@@ -6,7 +6,7 @@
xorriso,
syslinux,
libossp_uuid,
squashfs-tools,
squashfsTools,
# The file name of the resulting ISO image.
isoName ? "cd.iso",

View File

@@ -1,7 +1,7 @@
{
lib,
stdenv,
squashfs-tools,
squashfsTools,
closureInfo,
fileName ? "squashfs",
@@ -31,7 +31,7 @@ stdenv.mkDerivation {
# to the closure that was used to build it
unsafeDiscardReferences.out = true;
nativeBuildInputs = [ squashfs-tools ];
nativeBuildInputs = [ squashfsTools ];
buildCommand = ''
closureInfo=${closureInfo { rootPaths = storeContents; }}

View File

@@ -60,7 +60,7 @@ buildPythonApplication {
util-linux
vde2
]
++ lib.optionals stdenv.hostPlatform.isLinux [
++ lib.optionals stdenv.isLinux [
vhost-device-vsock
]
++ lib.optionals enableNspawn [

View File

@@ -8,12 +8,12 @@ testModuleArgs@{
}:
let
inherit (lib) mkOption types;
inherit (types) either lines functionTo;
inherit (types) either str functionTo;
in
{
options = {
testScript = mkOption {
type = either lines (functionTo lines);
type = either str (functionTo str);
apply =
v:
if lib.isFunction v then
@@ -27,7 +27,7 @@ in
'';
};
testScriptString = mkOption {
type = lines;
type = str;
readOnly = true;
internal = true;
};

View File

@@ -6,10 +6,8 @@
let
inherit (lib)
all
any
attrNames
concatImapStringsSep
concatMapStringsSep
concatStringsSep
elem
@@ -29,11 +27,8 @@ let
isList
isPath
isString
length
listToAttrs
literalMD
mapAttrs
mkOption
nameValuePair
optionalString
removePrefix
@@ -41,10 +36,8 @@ let
splitString
stringToCharacters
types
versionOlder
;
inherit (lib.lists) findFirstIndex;
inherit (lib.strings) toJSON escapeC;
in
@@ -611,122 +604,6 @@ let
lib.listToAttrs
];
};
/**
Creates a per-module `stateRevision` option that takes an int value, with a
default that is derived from `system.stateVersion`.
# Inputs
`descriptionName`
: A human-friendly name for your module, used for the description of the
created option.
`migrations`
: Attribute set that maps from values of `system.stateVersion`
(representing the breakpoints at which the default value of this option
will change) to Markdown instructions to users for manually migrating
their data to this breakpoint. The migration instructions will be
included in the NixOS documentation for this option. (These instructions
must only contain Markdown inlines, because they will be rendered as
items in an ordered list. In particular, nested lists will not render
correctly.)
`migrations` will also be exposed as an attribute on the result.
# Examples
:::{.example}
## `lib.options.mkStateRevisionOption` usage example
```nix
exampleModule =
{ lib, config, utils, ... }:
{
options.services.whatever = {
stateRevision = utils.mkStateRevisionOption {
descriptionName = "the whatever service";
migrations = {
"26.05" = "Rename `/var/lib/old_name` to `/var/lib/new_name`.";
"26.11" = "Run the `upgrade_whatever` utility.";
};
};
};
};
}
(pkgs.nixos [
exampleModule
{ system.stateVersion = "25.11"; }
]).config.services.whatever.stateRevision # => 0
(pkgs.nixos [
exampleModule
{ system.stateVersion = "26.05"; }
]).config.services.whatever.stateRevision # => 1
(pkgs.nixos [
exampleModule
{ system.stateVersion = "27.05"; }
]).config.services.whatever.stateRevision # => 2
```
:::
Modules should use this function when they change how data managed by the
module is persisted on the system between NixOS releases.
The default value of the option will be the number of attributes in the
`migrations` parameter with name less than or equal to the value of
`system.stateVersion`.
When using this function, don't forget to add the option's value to
`system.moduleStateRevisions."your.module.stateRevision"` when your module is
enabled.
*/
mkStateRevisionOption =
{
descriptionName,
migrations,
}:
let
versions = attrNames migrations;
maxVal = length versions;
in
assert all (v: builtins.match "[0-9]{2}\\.[0-9]{2}" v != null) versions;
mkOption {
type = types.ints.between 0 maxVal;
description = ''
This option versions the format of state persisted by
${descriptionName}. Its default value depends on the value of
{option}`system.stateVersion`.
Users who wish to increment this option will need to take manual
migration steps to preserve their data. **If you perform these
migrations, rolling back to an older generation will require also
reversing the migrations to the state expected by that generation.**
The migrations needed to advance to each value of this option are as
follows (perform all instructions after the row for the current
`stateRevision`, up to and including the row for the new
`stateRevision`):
0. (none)
${concatImapStringsSep "\n" (
v: sv: "${toString v}. ${replaceStrings [ "\n" ] [ " " ] migrations.${sv}}"
) versions}
Note that you do **not** need to change {option}`system.stateVersion`
in order to update this option. {option}`system.stateVersion` only
determines the default value of this option. Most users should not
change {option}`system.stateVersion` at all.
'';
default = findFirstIndex (versionOlder config.system.stateVersion) maxVal versions;
defaultText = literalMD ''
If {option}`system.stateVersion` is:
${concatImapStringsSep "\n" (v: sv: "* &lt;${sv}: ${toString (v - 1)}") versions}
* otherwise: ${toString maxVal}
'';
}
// {
inherit migrations;
};
};
in
utils

View File

@@ -109,10 +109,6 @@ in
"pata_qdi"
"pata_winbond"
]
++ lib.optionals (lib.versionAtLeast config.boot.kernelPackages.kernel.version "7.2") [
# xhci-pci defers AMD 800-series chipset controllers to this driver.
"xhci_pci_prom21"
]
++ lib.optionals platform.isx86 [ "vmw_balloon" ]
++ lib.optionals (pkgs.stdenv.hostPlatform.isi686 || pkgs.stdenv.hostPlatform.isx86_64) [
"vmw_vmci"

View File

@@ -19,8 +19,8 @@ in
[ "hardware" "logitech" "wireless" "enable" ]
)
(lib.mkRenamedOptionModule
[ "hardware" "logitech" "enableGraphical" ]
[ "hardware" "logitech" "wireless" "enableGraphical" ]
[ "programs" "solaar" "enable" ]
)
];
@@ -56,11 +56,20 @@ in
wireless = {
enable = lib.mkEnableOption "support for Logitech Wireless Devices";
enableGraphical = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Enable graphical support applications.";
};
};
};
config = lib.mkIf (cfg.wireless.enable || cfg.lcd.enable) {
environment.systemPackages = lib.optional cfg.wireless.enable pkgs.ltunify;
environment.systemPackages =
[ ]
++ lib.optional cfg.wireless.enable pkgs.ltunify
++ lib.optional cfg.wireless.enableGraphical pkgs.solaar;
services.udev = {
# ltunifi and solaar both provide udev rules but the most up-to-date have been split

View File

@@ -482,7 +482,7 @@ in
combineIcdPkgs =
icd: pkgs:
pkgs.symlinkJoin {
name = "nvidia-egl-external-platforms${lib.optionalString pkgs.stdenv.hostPlatform.is32bit "-x32"}";
name = "nvidia-egl-external-platforms${lib.optionalString pkgs.stdenv.is32bit "-x32"}";
paths = lib.attrVals icd pkgs;
# Remediate reversed priorities in pre-595 drivers,
# https://github.com/NixOS/nixpkgs/pull/497342#issuecomment-4034876793

View File

@@ -17,7 +17,7 @@
dosfstools,
mtools,
e2fsprogs,
squashfs-tools,
squashfsTools,
erofs-utils,
btrfs-progs,
xfsprogs,
@@ -104,7 +104,7 @@ let
mtools
];
"ext4" = [ e2fsprogs.bin ];
"squashfs" = [ squashfs-tools ];
"squashfs" = [ squashfsTools ];
"erofs" = [ erofs-utils ];
"btrfs" = [ btrfs-progs ];
"xfs" = [ xfsprogs ];

View File

@@ -400,7 +400,7 @@ in
# Figure out device names for the boot device and root filesystem.
rootPart=$(${lib.getExe' pkgs.util-linux "findmnt"} -n -o SOURCE /)
bootDevice=$(${lib.getExe' pkgs.util-linux "lsblk"} -npo PKNAME $rootPart)
partNum=$(${lib.getExe' pkgs.util-linux "lsblk"} -npo PARTN $rootPart)
partNum=$(${lib.getExe' pkgs.util-linux "lsblk"} -npo MAJ:MIN $rootPart | ${lib.getExe pkgs.gawk} -F: '{print $2}')
# Resize the root partition and the filesystem to fit the disk
echo ",+," | ${lib.getExe' pkgs.util-linux "sfdisk"} -N$partNum --no-reread $bootDevice

View File

@@ -206,10 +206,10 @@ sub pciCheck {
$device eq "0x4222" || $device eq "0x4227");
# Intel NPU driver
# list taken from linux(v7.1): drivers/accel/ivpu/ivpu_drv.h
# list taken from linux(v6.18): drivers/accel/ivpu/ivpu_drv.h
if ($vendor eq "0x8086" &&
($device eq "0x7d1d" || $device eq "0xad1d" || $device eq "0x643e" ||
$device eq "0xb03e" || $device eq "0xfd3e" || $device eq "0xd71d"))
($device eq "0xfd3e" || $device eq "0x7d1d" || $device eq "0xad1d" ||
$device eq "0x643e" || $device eq "0xb03e"))
{
push @attrs, "hardware.cpu.intel.npu.enable = true;";
}

View File

@@ -194,7 +194,7 @@ in
redmine = 147;
#seeks = 148; # removed 2020-06-21
prosody = 149;
# i2pd = 150; # dynamically allocated as of 2026-08-07
i2pd = 150;
systemd-coredump = 151;
systemd-network = 152;
systemd-resolve = 153;
@@ -534,7 +534,7 @@ in
redmine = 147;
#seeks = 148; # removed 2020-06-21
prosody = 149;
# i2pd = 150; # dynamically allocated as of 2026-08-07
i2pd = 150;
systemd-network = 152;
systemd-resolve = 153;
systemd-timesync = 154;

View File

@@ -2,51 +2,12 @@
config,
options,
lib,
pkgs,
...
}:
let
cfg = config.nixpkgs;
opt = options.nixpkgs;
isConfig = x: builtins.isAttrs x || lib.isFunction x;
optCall = f: x: if lib.isFunction f then f x else f;
mergeConfig =
lhs_: rhs_:
let
lhs = optCall lhs_ { inherit lib pkgs; };
rhs = optCall rhs_ { inherit lib pkgs; };
in
lib.recursiveUpdate lhs rhs
// lib.optionalAttrs (lhs ? allowUnfreePackages) {
allowUnfreePackages = lhs.allowUnfreePackages ++ (lib.attrByPath [ "allowUnfreePackages" ] [ ] rhs);
}
// lib.optionalAttrs (lhs ? packageOverrides) {
packageOverrides =
pkgs:
optCall lhs.packageOverrides pkgs // optCall (lib.attrByPath [ "packageOverrides" ] { } rhs) pkgs;
}
// lib.optionalAttrs (lhs ? perlPackageOverrides) {
perlPackageOverrides =
pkgs:
optCall lhs.perlPackageOverrides pkgs
// optCall (lib.attrByPath [ "perlPackageOverrides" ] { } rhs) pkgs;
};
configType = lib.mkOptionType {
name = "nixpkgs-config";
description = "nixpkgs config";
check =
x:
let
traceXIfNot = c: if c x then true else lib.traceSeqN 1 x false;
in
traceXIfNot isConfig;
merge = args: lib.foldr (def: mergeConfig def.value) { };
};
overlayType = lib.mkOptionType {
name = "nixpkgs-overlay";
description = "nixpkgs overlay";
@@ -73,6 +34,8 @@ let
++ lib.optional (opt.localSystem.highestPrio < (lib.mkOptionDefault { }).priority) opt.localSystem
++ lib.optional (opt.crossSystem.highestPrio < (lib.mkOptionDefault { }).priority) opt.crossSystem;
_configDefinitions = opt.config.definitionsWithLocations;
defaultPkgs =
if opt.hostPlatform.isDefined then
let
@@ -90,14 +53,21 @@ let
in
import ../../.. (
{
inherit (cfg) config overlays;
inherit _configDefinitions;
inherit (cfg) overlays;
# Explicitly set config to prevent impure.nix from filling it
# from the NIXPKGS_CONFIG environment variable.
config = { };
}
// systemArgs
)
else
import ../../.. {
inherit _configDefinitions;
# Explicitly set config to prevent impure.nix from filling it
# from the NIXPKGS_CONFIG environment variable.
config = { };
inherit (cfg)
config
overlays
localSystem
crossSystem
@@ -165,7 +135,15 @@ in
example = lib.literalExpression ''
{ allowBroken = true; allowUnfree = true; }
'';
type = configType;
type = lib.types.deferredModuleWith {
staticModules = [
{ _module.args.docPrefix = "https://nixos.org/manual/nixpkgs/unstable/"; }
../../../pkgs/top-level/config.nix
];
};
# Returns pkgs.config instead of nixpkgs.config
# This shadows the deferredModule to make it look like a submodule
apply = _: finalPkgs.config;
description = ''
Global configuration for Nixpkgs.
The complete list of [Nixpkgs configuration options](https://nixos.org/manual/nixpkgs/unstable/#sec-config-options-reference) is in the [Nixpkgs manual section on global configuration](https://nixos.org/manual/nixpkgs/unstable/#chap-packageconfig).
@@ -406,7 +384,7 @@ in
'';
}
{
assertion = opt.pkgs.isDefined -> cfg.config == { };
assertion = opt.pkgs.isDefined -> opt.config.highestPrio == (lib.mkOptionDefault null).priority;
message = ''
Your system configures nixpkgs with an externally created instance.
`nixpkgs.config` options should be passed when creating the instance instead.

View File

@@ -254,30 +254,6 @@ in
'';
};
moduleStateRevisions = mkOption {
type =
let
baseType = types.attrsOf types.ints.unsigned;
isStateRevisionOption = x: lib.isOption x && x ? migrations;
in
types.addCheck baseType (
attrs:
builtins.all (
attrPath: isStateRevisionOption (lib.attrByPath (lib.splitString "." attrPath) null options)
) (builtins.attrNames attrs)
)
// {
description = "${baseType.description}, in which every attribute name is the path to an option created with mkStateRevisionOption";
};
default = { };
internal = true;
description = ''
NixOS modules should set attributes on this option. Users should leave
it alone. Future tooling may use it to determine the consequences of
updating {option}`system.stateVersion`.
'';
};
configurationRevision = mkOption {
type = types.nullOr types.str;
default = null;

View File

@@ -185,7 +185,6 @@
./programs/bcc.nix
./programs/benchexec.nix
./programs/browserpass.nix
./programs/btrfs-heatmap.nix
./programs/calls.nix
./programs/captive-browser.nix
./programs/ccache.nix
@@ -197,7 +196,6 @@
./programs/cnping.nix
./programs/comma.nix
./programs/command-not-found/command-not-found.nix
./programs/compsize.nix
./programs/coolercontrol.nix
./programs/corefreq.nix
./programs/cpu-energy-meter.nix
@@ -295,7 +293,6 @@
./programs/npm.nix
./programs/ns-usbloader.nix
./programs/nushell.nix
./programs/nvrs.nix
./programs/nxdumpclient.nix
./programs/oblogout.nix
./programs/obs-studio.nix
@@ -328,7 +325,6 @@
./programs/skim.nix
./programs/slock.nix
./programs/sniffnet.nix
./programs/solaar.nix
./programs/soundmodem.nix
./programs/ssh.nix
./programs/starship.nix
@@ -350,7 +346,6 @@
./programs/tsm-client.nix
./programs/turbovnc.nix
./programs/udevil.nix
./programs/upki.nix
./programs/usbtop.nix
./programs/vim.nix
./programs/virt-manager.nix
@@ -523,7 +518,6 @@
./services/continuous-integration/buildbot/master.nix
./services/continuous-integration/buildbot/worker.nix
./services/continuous-integration/buildkite-agents.nix
./services/continuous-integration/forgejo-runner.nix
./services/continuous-integration/gitea-actions-runner.nix
./services/continuous-integration/github-runners.nix
./services/continuous-integration/gitlab-runner/runner.nix
@@ -553,7 +547,6 @@
./services/databases/hbase-standalone.nix
./services/databases/influxdb2.nix
./services/databases/influxdb.nix
./services/databases/kvrocks.nix
./services/databases/lldap.nix
./services/databases/memcached.nix
./services/databases/monetdb.nix
@@ -645,7 +638,6 @@
./services/display-managers/greetd.nix
./services/display-managers/lemurs.nix
./services/display-managers/ly.nix
./services/display-managers/noctalia-greeter.nix
./services/display-managers/plasma-login-manager.nix
./services/display-managers/regreet.nix
./services/display-managers/sddm.nix
@@ -685,7 +677,6 @@
./services/hardware/bolt.nix
./services/hardware/brltty.nix
./services/hardware/buffyboard.nix
./services/hardware/cardwired.nix
./services/hardware/ddccontrol.nix
./services/hardware/deepcool-digital-linux.nix
./services/hardware/dell-bios-fan-control.nix
@@ -1295,7 +1286,6 @@
./services/networking/knot-resolver.nix
./services/networking/knot.nix
./services/networking/kresd.nix
./services/networking/krill.nix
./services/networking/lambdabot.nix
./services/networking/legit.nix
./services/networking/libreswan.nix
@@ -1381,7 +1371,6 @@
./services/networking/opkssh/opkssh.nix
./services/networking/ostinato.nix
./services/networking/owamp.nix
./services/networking/p2pool.nix
./services/networking/pangolin.nix
./services/networking/pdns-recursor.nix
./services/networking/pdnsd.nix
@@ -1719,7 +1708,6 @@
./services/web-apps/haven.nix
./services/web-apps/healthchecks.nix
./services/web-apps/hedgedoc.nix
./services/web-apps/hister.nix
./services/web-apps/hledger-web.nix
./services/web-apps/homebox.nix
./services/web-apps/homer.nix
@@ -1817,7 +1805,6 @@
./services/web-apps/remark42.nix
./services/web-apps/reposilite.nix
./services/web-apps/rimgo.nix
./services/web-apps/romm.nix
./services/web-apps/rss-bridge.nix
./services/web-apps/rsshub.nix
./services/web-apps/rustical.nix

View File

@@ -1,32 +0,0 @@
{
config,
pkgs,
lib,
...
}:
{
meta.maintainers = with lib.maintainers; [ sandarukasa ];
options = {
programs.btrfs-heatmap = {
enable = lib.mkEnableOption "btrfs-heatmap + setcap wrapper";
package = lib.mkPackageOption pkgs "btrfs-heatmap" { };
};
};
config =
let
cfg = config.programs.btrfs-heatmap;
in
lib.mkIf cfg.enable {
# for the man page
environment.systemPackages = [ cfg.package ];
security.wrappers.btrfs-heatmap = {
owner = config.users.users.root.name;
group = config.users.users.root.group;
capabilities = "cap_sys_admin+p";
source = lib.getExe cfg.package;
};
};
}

View File

@@ -85,32 +85,7 @@ in
extraOpts = lib.mkOption {
type = lib.types.attrs;
description = ''
Extra chromium policy options. These settings are locked and the user cannot change them in the browser later.
A list of available policies
can be found in the Chrome Enterprise documentation:
<https://cloud.google.com/docs/chrome-enterprise/policies/>
Make sure the selected policy is supported on Linux and your browser version.
'';
default = { };
example = lib.literalExpression ''
{
"BrowserSignin" = 0;
"SyncDisabled" = true;
"PasswordManagerEnabled" = false;
"SpellcheckEnabled" = true;
"SpellcheckLanguage" = [
"de"
"en-US"
];
}
'';
};
extraOptsRecommended = lib.mkOption {
type = lib.types.attrs;
description = ''
Extra chromium policy options in recommended. These are default settings. The user can change them in the browser later if they want to.
A list of available policies
Extra chromium policy options. A list of available policies
can be found in the Chrome Enterprise documentation:
<https://cloud.google.com/docs/chrome-enterprise/policies/>
Make sure the selected policy is supported on Linux and your browser version.
@@ -166,9 +141,6 @@ in
"chromium/policies/managed/extra.json" = lib.mkIf (cfg.extraOpts != { }) {
text = builtins.toJSON cfg.extraOpts;
};
"chromium/policies/recommended/extra.json" = lib.mkIf (cfg.extraOptsRecommended != { }) {
text = builtins.toJSON cfg.extraOptsRecommended;
};
"chromium/initial_preferences" = lib.mkIf (cfg.initialPrefs != { }) {
text = builtins.toJSON cfg.initialPrefs;
};
@@ -184,9 +156,6 @@ in
"opt/chrome/policies/managed/extra.json" = lib.mkIf (cfg.extraOpts != { }) {
text = builtins.toJSON cfg.extraOpts;
};
"opt/chrome/policies/recommended/extra.json" = lib.mkIf (cfg.extraOptsRecommended != { }) {
text = builtins.toJSON cfg.extraOptsRecommended;
};
# for brave
"brave/policies/managed/default.json" = lib.mkIf (defaultProfile != { }) {
text = builtins.toJSON defaultProfile;
@@ -194,9 +163,6 @@ in
"brave/policies/managed/extra.json" = lib.mkIf (cfg.extraOpts != { }) {
text = builtins.toJSON cfg.extraOpts;
};
"brave/policies/recommended/extra.json" = lib.mkIf (cfg.extraOptsRecommended != { }) {
text = builtins.toJSON cfg.extraOptsRecommended;
};
};
};
}

View File

@@ -1,32 +0,0 @@
{
config,
pkgs,
lib,
...
}:
{
meta.maintainers = with lib.maintainers; [ sandarukasa ];
options = {
programs.compsize = {
enable = lib.mkEnableOption "compsize + setcap wrapper";
package = lib.mkPackageOption pkgs "compsize" { };
};
};
config =
let
cfg = config.programs.compsize;
in
lib.mkIf cfg.enable {
# for the man page
environment.systemPackages = [ cfg.package ];
security.wrappers.compsize = {
owner = config.users.users.root.name;
group = config.users.users.root.group;
capabilities = "cap_sys_admin+p";
source = lib.getExe cfg.package;
};
};
}

View File

@@ -92,11 +92,6 @@ in
]
);
restartTriggers = [
cfg.package
config.environment.etc."gamemode.ini".source
];
serviceConfig.ExecStart = lib.mkIf cfg.enableRenice [
"" # Tell systemd to clear the existing ExecStart list, to prevent appending to it.
"${config.security.wrapperDir}/gamemoded"

View File

@@ -10,11 +10,6 @@ let
package = cfg.package.override {
inherit (config.security) wrapperDir;
};
uiPackage = cfg.ui.package.override {
gpu-screen-recorder = package;
inherit (config.security) wrapperDir;
};
in
{
options = {
@@ -29,47 +24,19 @@ in
wrappers for promptless recording.
'';
};
ui = {
enable = lib.mkEnableOption "the GPU Screen Recorder overlay UI";
package = lib.mkPackageOption pkgs "gpu-screen-recorder-ui" { };
notifPackage = lib.mkPackageOption pkgs "gpu-screen-recorder-notification" { };
};
};
};
config = lib.mkIf cfg.enable (
lib.mkMerge [
{
environment.systemPackages = [ cfg.package ];
config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
security.wrappers."gsr-kms-server" = {
owner = "root";
group = "root";
capabilities = "cap_sys_admin+ep";
source = lib.getExe' package "gsr-kms-server";
};
}
security.wrappers."gsr-kms-server" = {
owner = "root";
group = "root";
capabilities = "cap_sys_admin+ep";
source = lib.getExe' package "gsr-kms-server";
};
};
(lib.mkIf cfg.ui.enable {
environment.systemPackages = [
cfg.ui.package
cfg.ui.notifPackage
];
security.wrappers."gsr-global-hotkeys" = {
owner = "root";
group = "root";
capabilities = "cap_setuid+ep";
source = lib.getExe' uiPackage "gsr-global-hotkeys";
};
})
]
);
meta.maintainers = with lib.maintainers; [
timschumi
AhmedAmr
keenanweaver
];
meta.maintainers = with lib.maintainers; [ timschumi ];
}

View File

@@ -27,7 +27,7 @@ let
paths = [ cfg.package ];
nativeBuildInputs = [ pkgs.makeWrapper ];
postBuild = ''
wrapProgram "$out/bin/ioquake3" --add-flags "+set fs_basepath ${cfg.baseq3} +set fs_cdpath ${fsBasepath} +exec settings.cfg"
wrapProgram "$out/bin/ioquake3" --add-flags "+set fs_basepath ${fsBasepath} +exec settings.cfg"
'';
};
in
@@ -37,32 +37,6 @@ in
package = lib.mkPackageOption pkgs "ioquake3" { };
baseq3 = lib.mkOption {
type = with lib.types; (either package path);
default = pkgs.symlinkJoin {
name = "quake3-demo-content";
paths = [
pkgs.quake3demodata
pkgs.quake3pointrelease
];
};
defaultText = "Freely redistributable Quake 3 demo data (`pak0`) plus the 1.32 point release files (`pak1`-`pak8`), merged together.";
example = "/var/lib/quake3";
description = ''
Path to the directory containing the baseq3 files (pak*.pk3).
Defaults to the freely redistributable demo data (pak0) merged
with the 1.32 point release files (pak1-pak8), so the game runs
out of the box without owning a retail copy.
This value is passed directly as fs_basepath, so pak files are
searched for in `''${baseq3}/baseq3/`, e.g. a value of
`/var/lib/quake3` expects `/var/lib/quake3/baseq3/pak0.pk3` and
so on. To use a full retail install instead, point this at the
directory containing its `baseq3` folder.
'';
};
settings = lib.mkOption {
type = lib.types.attrsOf (
lib.types.oneOf [

View File

@@ -1,93 +0,0 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.programs.solaar;
inherit (lib)
mkEnableOption
mkIf
mkOption
types
maintainers
mkPackageOption
;
in
{
options.programs.solaar = {
enable = mkEnableOption "Solaar, the open source driver for Logitech devices.";
package = mkPackageOption pkgs "solaar" { };
userService = {
enable = mkEnableOption "Enable the solaar systemd service for each user.";
window = mkOption {
type = types.enum [
"show"
"hide"
"only"
];
default = "hide";
description = ''
Start with window showing / hidden / only (no tray icon).
'';
};
batteryIcons = mkOption {
type = types.enum [
"regular"
"symbolic"
"solaar"
];
default = "regular";
description = ''
Prefer regular battery / symbolic battery / solaar icons.
'';
};
extraArgs = mkOption {
type = types.listOf types.str;
default = [ ];
example = [ "--restart-on-wake-up" ];
description = ''
Extra arguments to pass to Solaar.
'';
};
};
};
config = mkIf cfg.enable {
hardware.logitech.wireless.enable = lib.mkDefault true;
environment.systemPackages = [ cfg.package ];
systemd.user.services.solaar = mkIf cfg.userService.enable {
description = "Solaar, the open source driver for Logitech devices";
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
after = [ "dbus.service" ];
serviceConfig = {
Type = "simple";
ExecStart = lib.escapeShellArgs (
[
(lib.getExe cfg.package)
"--window"
cfg.userService.window
"--battery-icons"
cfg.userService.batteryIcons
]
++ cfg.userService.extraArgs
);
Restart = "on-failure";
RestartSec = "5";
};
};
};
meta = {
maintainers = [ maintainers.Svenum ];
};
}

View File

@@ -71,7 +71,7 @@ let
{
freeformType = attrsOf (either scalarType (listOf scalarType));
# Client system-options file directives are explained here:
# https://www.ibm.com/docs/en/storage-protect/8.2.2?topic=utilities-processing-options
# https://www.ibm.com/docs/en/storage-protect/8.2.1?topic=utilities-processing-options
options.servername = mkOption {
type = servernameType;
default = name;

View File

@@ -1,97 +0,0 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.upki;
format = pkgs.formats.toml { };
configFile = format.generate "upki.toml" cfg.settings;
in
{
options.services.upki = {
enable = lib.mkEnableOption "upki certificate infrastructure cache updates";
package = lib.mkPackageOption pkgs "upki" { };
interval = lib.mkOption {
type = lib.types.str;
default = "2h";
example = "1h";
description = "How often to update the upki cache.";
};
settings = lib.mkOption {
inherit (format) type;
default = { };
description = "Settings written to the upki config file.";
example = lib.literalExpression ''
{
cache-dir = "/var/cache/upki";
revocation.fetch-url = "https://upki.rustls.dev/";
}
'';
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
services.upki.settings = {
cache-dir = lib.mkDefault "/var/cache/upki";
revocation.fetch-url = lib.mkDefault "https://upki.rustls.dev/";
};
users.users.upki = {
isSystemUser = true;
group = "upki";
};
users.groups.upki = { };
systemd.services.upki-fetch = {
description = "Update the upki cache";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${lib.getExe cfg.package} --config-file ${configFile} fetch";
User = "upki";
Group = "upki";
CacheDirectory = "upki";
CacheDirectoryMode = "0755";
UMask = "0022";
# Hardening
LockPersonality = true;
MemoryDenyWriteExecute = true;
NoNewPrivileges = true;
PrivateTmp = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectSystem = "strict";
RestrictAddressFamilies = [
"AF_UNIX"
"AF_INET"
"AF_INET6"
];
RestrictRealtime = true;
SystemCallArchitectures = "native";
SystemCallErrorNumber = "EPERM";
SystemCallFilter = "@system-service";
};
};
systemd.timers.upki-fetch = {
description = "Update the upki cache every ${cfg.interval}";
wantedBy = [ "timers.target" ];
timerConfig = {
OnActiveSec = "0";
OnUnitActiveSec = cfg.interval;
};
};
};
}

View File

@@ -6,7 +6,7 @@
}:
let
inherit (lib.options) mkEnableOption mkPackageOption mkOption;
inherit (lib.modules) mkIf mkAfter;
inherit (lib.modules) mkIf;
inherit (lib.meta) getExe;
inherit (lib.types) listOf str;
inherit (lib.strings) concatStringsSep;
@@ -52,15 +52,15 @@ in
environment.systemPackages = [ cfg.package ];
programs = {
zsh.interactiveShellInit = mkIf cfg.enableZshIntegration (mkAfter ''
zsh.interactiveShellInit = mkIf cfg.enableZshIntegration ''
eval "$(${getExe cfg.package} init zsh ${cfgFlags} )"
'');
bash.interactiveShellInit = mkIf cfg.enableBashIntegration (mkAfter ''
'';
bash.interactiveShellInit = mkIf cfg.enableBashIntegration ''
eval "$(${getExe cfg.package} init bash ${cfgFlags} )"
'');
fish.interactiveShellInit = mkIf cfg.enableFishIntegration (mkAfter ''
'';
fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
${getExe cfg.package} init fish ${cfgFlags} | source
'');
'';
xonsh.config = ''
execx($(${getExe cfg.package} init xonsh ${cfgFlags}), 'exec', __xonsh__.ctx, filename='zoxide')
'';

View File

@@ -58,8 +58,6 @@ in
type = lib.types.bool;
};
package = lib.mkPackageOption pkgs "zsh" { };
shellAliases = lib.mkOption {
default = { };
description = ''
@@ -197,7 +195,7 @@ in
. ${config.system.build.setEnvironment}
fi
HELPDIR="${cfg.package}/share/zsh/$ZSH_VERSION/help"
HELPDIR="${pkgs.zsh}/share/zsh/$ZSH_VERSION/help"
# Tell zsh how to find installed completions.
for p in ''${(z)NIX_PROFILES}; do
@@ -309,7 +307,7 @@ in
environment.etc.zinputrc.text = builtins.readFile ./zinputrc;
environment.systemPackages = [
cfg.package
pkgs.zsh
]
++ lib.optional cfg.enableCompletion pkgs.nix-zsh-completions;
@@ -319,7 +317,7 @@ in
environment.shells = [
"/run/current-system/sw/bin/zsh"
"${cfg.package}/bin/zsh"
"${pkgs.zsh}/bin/zsh"
];
};

View File

@@ -79,7 +79,7 @@ in
};
firstUid = mkOption {
type = types.ints.between 1000 65533;
type = types.numbers.between 1000 65533;
default = 60000;
description = ''
Start of block of UIDs reserved for sandboxes.
@@ -87,7 +87,7 @@ in
};
firstGid = mkOption {
type = types.ints.between 1000 65533;
type = types.numbers.between 1000 65533;
default = 60000;
description = ''
Start of block of GIDs reserved for sandboxes.
@@ -95,7 +95,7 @@ in
};
numBoxes = mkOption {
type = types.ints.between 1000 65533;
type = types.numbers.between 1000 65533;
default = 1000;
description = ''
Number of UIDs and GIDs to reserve, starting from

View File

@@ -84,10 +84,12 @@ let
}
}
'';
__structuredAttrs = true;
passAsFile = [
"expectScript"
];
};
checkPhase = ''
printf "%s" "$expectScript" | ${lib.getExe pkgs.buildPackages.expect} -f -
${lib.getExe pkgs.buildPackages.expect} -f "$expectScriptPath"
'';
};

View File

@@ -108,7 +108,7 @@ in
DynamicUser = true;
ExecStart = lib.getExe cfg.package;
LockPersonality = true;
MemoryDenyWriteExecute = false; # pcre2 jit
MemoryDenyWriteExecute = true;
PrivateDevices = true;
ProtectClock = true;
ProtectControlGroups = true;

View File

@@ -1,529 +0,0 @@
{
config,
lib,
pkgs,
utils,
...
}:
let
inherit (lib)
foldlAttrs
literalExpression
literalMD
mkEnableOption
mkIf
mkOption
mkPackageOption
mkRemovedOptionModule
mkRenamedOptionModule
nameValuePair
optionals
types
;
cfg = config.services.forgejo-runner;
settingsFormat = pkgs.formats.yaml { };
config' = config;
# An option type for cfg.secrets that is like cfg.settings (free-form yaml), but limited
# to just path and attrsOf path. It uses the same implementation primivites as
# pkgs.formats.yaml (serializableValueWith).
# The alternative would be something like types.any, which is too weak, or a hard-coded
# max-depth by chaining multiple types.oneOf and types.attrsOf together, which is both
# longer in code and less future-proof.
secretsTypeBase = types.oneOf [
types.externalPath
(types.attrsOf secretsTypeBase)
];
secretsType = secretsTypeBase // {
description = "nested attribute set of ${types.externalPath.description}";
};
labels =
instance:
instance.settings.runner.labels
++ (lib.flatten (
lib.mapAttrsToList (_: value: value.labels or [ ]) instance.settings.server.connections
));
in
{
meta.maintainers = pkgs.forgejo-runner.meta.maintainers;
options.services.forgejo-runner = {
package = mkPackageOption pkgs "forgejo-runner" { };
instances = mkOption {
default = { };
description = ''
Forgejo Runner instances.
'';
type = types.attrsOf (
types.submodule (
{
options,
config,
name,
...
}:
{
imports = [
../../misc/assertions.nix
# compat for users coming from nixos/gitea-actions-runner
(mkRenamedOptionModule [ "url" ] [ "settings" "server" "connections" "default" "url" ])
(mkRenamedOptionModule [ "labels" ] [ "settings" "runner" "labels" ])
(mkRemovedOptionModule [ "name" ] ''
The option `${options.name}' has been removed, because it has no longer
any effect, as runners no longer self-report their name to Forgejo.
'')
(mkRemovedOptionModule [ "token" ] ''
The option `${options.token}' has been renamed to
`${options.settings}.server.connections.default.token'
but additional attention is required.
Assuming you are migrating from `services.gitea-actions-runner', you will need to:
1. Find the old `.runner' file of your previously registered runner. You will need
to extract two values from it. Given the instance name of "${name}", you should
be able to find it at `/var/lib/gitea-runner/${name}/.runner'.
2. Read the contents of it, for example using `cat /var/lib/gitea-runner/native/.runner'.
3. Take note of the "uuid" and set the option `${options.settings}.server.connections.default.uuid'
to that value. For example "c9e50be9-a7c3-4aee-ba35-624c4ff8c519".
4. Take note of the "token" and set the option `${options.settings}.server.connections.default.token'
to that value. For example "6634bb58be0db23cc013a2e72dd1828ae0257cf".
5. Remove option `${options.token}'.
'')
(mkRemovedOptionModule [ "tokenFile" ] ''
The option `${options.tokenFile}' has been renamed to
`${options.secrets}.server.connections.default.token_url'
but additional attention is required.
Assuming you are migrating from `services.gitea-actions-runner', you will need to:
1. Find the old `.runner' file of your previously registered runner. You will need
to extract two values from it. Given the instance name of "${name}", you should
be able to find it at `/var/lib/gitea-runner/${name}/.runner'.
2. Read the contents of it, for example using `cat /var/lib/gitea-runner/native/.runner'.
3. Take note of the "uuid" and set the option `${options.settings}.server.connections.default.uuid'
to that value. For example "c9e50be9-a7c3-4aee-ba35-624c4ff8c519".
4. Take note of the "token" and replace the contents of your existing token file with it.
You no longer need to prefix the token with `TOKEN='. Put just the token in that file
and nothing else.
5. Rename `${options.tokenFile}' to `${options.secrets}.server.connections.default.token_url'.
'')
];
config = mkIf config.enable {
assertions = [
{
assertion =
lib.any (label: lib.hasInfix ":docker" label) (labels config)
-> (
config.runtimes.docker
|| config.runtimes.podman
# Mute assertion as an escape hatch for end-users
# that override our options.runtimes default.
|| options.runtimes.docker.highestPrio < (lib.mkOptionDefault { }).priority
|| options.runtimes.podman.highestPrio < (lib.mkOptionDefault { }).priority
);
message = ''
The option `${options.settings}' has at least one label of
type `docker' configured, but no compatible container runtime enabled.
You need to enable either
`config.virtualisation.docker.enable' or
`config.virtualisation.podman.enable'.
If you are absolutely sure what you are doing
and are certain this is wrong, you can set
`${options.runtimes.docker}' or
`${options.runtimes.podman}' to dismiss this assertion.
'';
}
{
assertion = config.settings.server.connections != { };
message = ''
The option `${options.settings}.server.connections' requires at least one connection.
'';
}
]
++ (foldlAttrs (
assertions: _: connection:
assertions ++ connection.assertions
) [ ] config.settings.server.connections);
};
options = {
enable = mkEnableOption "this Forgejo Runner instance";
settings = mkOption {
default = { };
description = ''
Free-form settings written directly to the {file}`config.yaml` file.
Refer to [`config.example.yaml`] or run {command}`forgejo-runner generation-config` for supported values.
[`config.example.yaml`]: https://code.forgejo.org/forgejo/runner/src/branch/main/internal/pkg/config/config.example.yaml
'';
type = types.submodule {
freeformType = settingsFormat.type;
config = lib.mapAttrsRecursive (
path: _: "file:$CREDENTIALS_DIRECTORY/${lib.join "__" path}"
) config.secrets;
options = {
runner = {
labels = mkOption {
# TODO: Support new attrset format (yaml map)
# https://code.forgejo.org/forgejo/runner/pulls/1571
type = types.listOf types.str;
example = literalExpression ''
[
# provide a debian base with nodejs for actions
"debian-latest:docker://node:current"
# fake the ubuntu name, because node provides no ubuntu builds
"ubuntu-latest:docker://node:current"
# provide native execution on the host
#"native:host"
]
'';
description = ''
Labels used to map jobs to their runtime environment.
Many common actions require {command}`bash`, {command}`git` and {command}`node`,
as well as a filesystem that follows the filesystem hierarchy standard.
If you specify a label of type `docker`, the resulting runner service
will be automatically added to the *Podman* or *Docker* group.
See <https://forgejo.org/docs/latest/admin/actions/configuration/#choosing-labels>.
::: {.note}
Labels of type [`lxc`] are currently not supported.
:::
[`lxc`]: https://forgejo.org/docs/latest/admin/actions/configuration/#lxc
'';
};
};
server = {
connections = mkOption {
default = { };
description = ''
One or more connections to Forgejo instances, each with a UUID and Token pair.
See <https://forgejo.org/docs/latest/admin/actions/registration/>.
::: {.note}
Ephemeral runner mode is not yet supported by this module.
:::
'';
example = literalExpression ''
{
default = {
url = "https://example.com/";
uuid = "c9e50be9-a7c3-4aee-ba35-624c4ff8c519";
# Also see ${options.secrets}.server.connections.<name>.token_url
token = "6634bb58be0db23cc013a2e72dd1828ae0257cf";
};
}
'';
type = types.attrsOf (
types.submodule (
{ name, config, ... }:
{
freeformType = settingsFormat.type;
imports = [
../../misc/assertions.nix
];
config = {
assertions = [
{
assertion =
(config.token == null && config ? token_url && config.token_url != null)
|| (config.token != null && config ? token_url && config.token_url == null)
|| (config.token != null && !config ? token_url);
message = ''
The option `${options.settings}' needs to have exactly one of
`server.connections.${name}.token_url': ${
if config ? token_url then lib.toJSON config.token_url else "<not set>"
} or
`server.connections.${name}.token': ${lib.toJSON config.token}
that is *not* null.
Hint:
`${options.secrets}.server.connections.${name}.token_url' will set
`${options.settings}.server.connections.${name}.token_url' for you.
'';
}
];
};
options = {
url = mkOption {
type = types.str;
example = "https://example.com/";
description = ''
Base URL of your Forgejo instance.
'';
};
uuid = mkOption {
type = types.str;
example = "c9e50be9-a7c3-4aee-ba35-624c4ff8c519";
description = ''
UUID of this runner.
See <https://forgejo.org/docs/latest/admin/actions/registration/>.
'';
};
token = mkOption {
type = types.nullOr types.str;
example = "6634bb58be0db23cc013a2e72dd1828ae0257cf";
description = ''
Token of this runner.
See <https://forgejo.org/docs/latest/admin/actions/registration/>.
::: {.note}
The deprecated "Registration Token" is not supported.
You need a UUID and Token pair.
:::
::: {.warning}
The value will be stored unencrypted in the world-readable Nix store.
To store the secret securely, see {option}`${options.secrets}.server.connections.<name>.token_url`.
:::
'';
};
};
}
)
);
};
};
};
};
};
secrets = mkOption {
type = secretsType;
default = { };
description = ''
This follows the same structure as {option}`${options.settings}`
but the value of each key is a path.
The specified secret path is then read by systemd via [`LoadCredential=`]
and templated into {option}`${options.settings}` for you.
[`LoadCredential=`]: https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Credentials
'';
example = literalExpression ''
{
server.connections.example = {
token_url = "/run/keys/forgejo-runner_token";
};
cache = {
secret_url = "/run/keys/forgejo-runner_cache-secret";
};
}
'';
};
hostPackages = mkOption {
type = types.listOf types.package;
default = with pkgs; [
bash
coreutils
curl
gawk
gnused
nodejs
wget
];
defaultText = literalExpression ''
with pkgs; [
bash
coreutils
curl
gawk
gnused
nodejs
wget
]
'';
description = ''
List of packages that are available to your workflow and actions when the
runner is configured with a label of type `host` ({option}`${options.runtimes.host}`).
::: {.note}
{command}`gitMinimal` is always part of the environment because {command}`forgejo-runner`
depends on it. If you need a different variant of {command}`git`, e.g. {command}`gitFull`,
add it here. Your package will take priority over {command}`gitMinimal`.
:::
'';
};
runtimes = {
host = mkOption {
type = types.bool;
default = lib.any (label: lib.hasSuffix ":host" label) (labels config);
defaultText = literalMD "Whether this instance has at least one label with suffix `:host`.";
description = ''
Whether to configure the systemd service for jobs with the backend of type `host`.
::: {.warning}
Setting this will override the automatic detection and safeguards.
:::
'';
};
docker = mkOption {
type = types.bool;
default =
lib.any (label: lib.hasInfix ":docker" label) (labels config)
&& config'.virtualisation.docker.enable;
defaultText = literalMD ''
Whether this instance has at least one label with infix `:docker`
and {option}`config.virtualisation.docker.enable` set to `true`.
'';
description = ''
Whether to configure the systemd service to work with Docker.
::: {.warning}
Setting this will override the automatic detection and safeguards.
:::
'';
};
podman = mkOption {
type = types.bool;
default =
lib.any (label: lib.hasInfix ":docker" label) (labels config)
&& config'.virtualisation.podman.enable;
defaultText = literalMD ''
Whether this instance has at least one label with infix `:docker`
and {option}`config.virtualisation.podman.enable` set to `true`.
'';
description = ''
Whether to configure the systemd service to work with Podman.
::: {.warning}
Setting this will override the automatic detection and safeguards.
:::
'';
};
};
configFile = mkOption {
internal = true;
readOnly = true;
type = types.path;
default = settingsFormat.generate "config.yaml" (
# Filter out remains of ../misc/assertions.nix.
# Note: This is for optics only, as forgejo-runner simply ignores settings it does not know.
lib.filterAttrsRecursive (n: _: n != "assertions" && n != "warnings") config.settings
);
description = ''
Implementation detail for use in {file}`nixos/tests/forgejo.nix`.
FIXME: Offload into top-level config once upstream supports {var}`uuid_url`.
'';
};
};
}
)
);
};
};
config = mkIf (cfg.instances != { }) {
assertions = (
foldlAttrs (
assertions: _: instance:
assertions ++ instance.assertions
) [ ] cfg.instances
);
warnings = (
foldlAttrs (
warnings: _: instance:
warnings ++ instance.warnings
) [ ] cfg.instances
);
systemd.services = lib.mapAttrs' (
name: instance:
nameValuePair "forgejo-runner-${utils.escapeSystemdPath name}" {
inherit (instance) enable;
description = "Forgejo Runner";
wants = [ "network-online.target" ];
after = [
"network-online.target"
]
++ optionals instance.runtimes.docker [
"docker.service"
]
++ optionals instance.runtimes.podman [
# TODO: Add support for rootless Podman
"podman.service"
];
wantedBy = [
"multi-user.target"
];
environment = {
HOME = "/var/lib/forgejo-runner/${name}";
};
path = optionals instance.runtimes.host instance.hostPackages ++ [ pkgs.gitMinimal ];
serviceConfig = {
DynamicUser = true;
StateDirectory = "forgejo-runner/${name}";
WorkingDirectory = "/var/lib/forgejo-runner/${name}";
# DynamicUser will try to use id-mapped mounts for exec directories,
# which has the side-effect of setting nosuid and noexec as mount option.
# Users of host runners expect to be able to execute scripts in their
# pipeline, so we override the noexec mount option by setting ExecPaths.
ExecPaths = optionals instance.runtimes.host [ "/var/lib/forgejo-runner/${name}" ];
ExecStart = toString [
(lib.getExe cfg.package)
"daemon"
"--config"
instance.configFile
];
Restart = "on-failure";
RestartSec = 10;
LoadCredential = lib.mapAttrsToListRecursive (
path: value: "${lib.join "__" path}:${value}"
) instance.secrets;
SupplementaryGroups =
optionals instance.runtimes.docker [
"docker"
]
++ optionals instance.runtimes.podman [
"podman"
];
};
}
) cfg.instances;
};
}

View File

@@ -1,88 +0,0 @@
# shellcheck shell=bash
# Request an installation access token for a GitHub App.
#
# Adapted from https://github.com/myoung34/docker-github-actions-runner (MIT,
# Copyright (c) 2020 Marcus Young), see:
# https://github.com/orgs/community/discussions/24743#discussioncomment-3245300
#
# Expects the following environment variables:
# * APP_ID the GitHub App's ID
# * APP_PRIVATE_KEY the GitHub App's PEM-encoded private key (contents)
# * APP_LOGIN the org/user login the App is installed on
# * GITHUB_HOST optional, defaults to github.com (set for GHES)
#
# Prints the installation access token (prefixed with `ghs_`) to stdout.
_GITHUB_HOST=${GITHUB_HOST:="github.com"}
# If the host is not github.com, use the GitHub Enterprise Server API endpoint.
if [[ ${_GITHUB_HOST} == "github.com" ]]; then
URI="https://api.${_GITHUB_HOST}"
else
URI="https://${_GITHUB_HOST}/api/v3"
fi
API_VERSION=v3
API_HEADER="Accept: application/vnd.github.${API_VERSION}+json"
CONTENT_LENGTH_HEADER="Content-Length: 0"
APP_INSTALLATIONS_URI="${URI}/app/installations"
# JWT token issuance and expiration parameters, see:
# https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app
JWT_IAT_DRIFT=60
JWT_EXP_DELTA=600
JWT_JOSE_HEADER='{
"alg": "RS256",
"typ": "JWT"
}'
build_jwt_payload() {
now=$(date +%s)
iat=$((now - JWT_IAT_DRIFT))
jq -c \
--arg iat_str "${iat}" \
--arg exp_delta_str "${JWT_EXP_DELTA}" \
--arg app_id_str "${APP_ID}" \
'
($iat_str | tonumber) as $iat
| ($exp_delta_str | tonumber) as $exp_delta
| ($app_id_str | tonumber) as $app_id
| .iat = $iat
| .exp = ($iat + $exp_delta)
| .iss = $app_id
' <<<"{}" | tr -d '\n'
}
base64url() {
base64 | tr '+/' '-_' | tr -d '=\n'
}
rs256_sign() {
openssl dgst -binary -sha256 -sign <(echo "$1")
}
request_access_token() {
jwt_payload=$(build_jwt_payload)
encoded_jwt_parts=$(base64url <<<"${JWT_JOSE_HEADER}").$(base64url <<<"${jwt_payload}")
encoded_mac=$(echo -n "${encoded_jwt_parts}" | rs256_sign "${APP_PRIVATE_KEY}" | base64url)
generated_jwt="${encoded_jwt_parts}.${encoded_mac}"
auth_header="Authorization: Bearer ${generated_jwt}"
app_installations_response=$(
curl -fsSX GET \
-H "${auth_header}" \
-H "${API_HEADER}" \
"${APP_INSTALLATIONS_URI}"
)
access_token_url=$(echo "${app_installations_response}" | jq --raw-output '.[] | select (.account.login == "'"${APP_LOGIN}"'" and .app_id == '"${APP_ID}"') .access_tokens_url')
curl -fsSX POST \
-H "${CONTENT_LENGTH_HEADER}" \
-H "${auth_header}" \
-H "${API_HEADER}" \
"${access_token_url}" |
jq --raw-output .token
}
request_access_token

View File

@@ -42,8 +42,7 @@
};
url = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
type = lib.types.str;
description = ''
Repository to add the runner to.
@@ -56,16 +55,12 @@
Otherwise, you are going to get a `404 NotFound`
from `POST https://api.github.com/actions/runner-registration`
in the configure script.
Mandatory unless `orgs` is used, in which case the URL is taken
from each `orgs.<name>.url` instead and this option is ignored.
'';
example = "https://github.com/nixos/nixpkgs";
};
tokenFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
type = lib.types.path;
description = ''
The full path to a file which contains either
@@ -73,10 +68,6 @@
* a classic PAT
* or a runner registration token
Exactly one of `tokenFile` and `githubApp` must be set. Use
`githubApp` to authenticate via a GitHub App installation instead
of a token file.
Changing this option or the `tokenFile`s content triggers a new runner registration.
We suggest using the fine-grained PATs. A runner registration token is valid
@@ -135,71 +126,6 @@
default = "auto";
};
githubApp = lib.mkOption {
default = null;
description = ''
Authenticate the runner using a GitHub App installation instead
of a `tokenFile`. Exactly one of `tokenFile` and `githubApp` must
be set.
On every start the service derives a short-lived installation
access token from the App's private key, uses it to fetch a fresh
runner registration token and registers the runner with it. This
avoids storing a long-lived personal access token on the host and
pairs well with `ephemeral` runners.
The App needs read and write access to the
"self-hosted runners" administration of the organisation (or
repository) given in `url`, and must be installed on the `login`
below.
'';
example = lib.literalExpression ''
{
id = 123456;
login = "my-org";
privateKeyFile = "/run/secrets/github-app.pem";
}
'';
type = lib.types.nullOr (
lib.types.submodule {
options = {
id = lib.mkOption {
type = lib.types.int;
description = "The GitHub App's ID (the numeric `App ID`, not the client ID).";
example = 123456;
};
login = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
The organisation (or user) login the GitHub App is
installed on. Used to look up the App installation and,
for organisation-wide runners, as the registration scope.
Mandatory unless `orgs` is used, in which case the login
is taken from each `orgs.<name>.login` instead and this
option is ignored.
Changing this option triggers a new runner registration.
'';
example = "my-org";
};
privateKeyFile = lib.mkOption {
type = lib.types.path;
description = ''
The full path to a file containing the GitHub App's
PEM-encoded private key. The file should be deployed as a
secret and is never copied into the Nix store.
'';
example = "/run/secrets/github-app.pem";
};
};
}
);
};
name = lib.mkOption {
type = lib.types.nullOr lib.types.str;
description = ''
@@ -211,107 +137,6 @@
default = name;
};
count = lib.mkOption {
type = lib.types.ints.positive;
default = 1;
example = 4;
description = ''
Number of identical runner instances to create.
Without `orgs`, this fans the single entry (using the
entry-level `url`) out into `count` runner services:
`github-runner-<name>` for `count == 1` (unchanged) and
`github-runner-<name>-<n>` for `count > 1`. Each instance
registers under a distinct runner name.
With `orgs`, this is the default replica count for every org
that does not set its own; see `orgs.<name>.count`.
Pairs well with `ephemeral`.
'';
};
orgs = lib.mkOption {
default = { };
description = ''
Organisations (or repositories) to serve from this entry.
When set, the entry fans out into one systemd service per runner
named `github-runner-<name>-<org>-<n>`, where `<org>` is the
attribute name and `<n>` ranges over the per-org `count`. The
entry-level `githubApp`/`tokenFile` is shared across every org;
only the App `login` changes per org (defaulting to the
attribute name), so a single GitHub App installed on multiple
orgs serves all of them.
Leaving this empty (the default) keeps the single-runner
behaviour: the entry-level `url`, `name` and auth, fanned out by
the entry-level `count`.
'';
example = lib.literalExpression ''
{
org-a.count = 12;
org-b = {
count = 2;
extraLabels = [ "org-b" ];
};
}
'';
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
url = lib.mkOption {
type = lib.types.str;
default = "https://github.com/${name}";
defaultText = lib.literalExpression ''"https://github.com/''${name}"'';
description = ''
URL of the organisation (or repository) to connect to.
Defaults to the GitHub URL derived from the attribute name.
'';
};
login = lib.mkOption {
type = lib.types.str;
default = name;
defaultText = lib.literalExpression "\${name}";
description = ''
GitHub login (org or user) the shared `githubApp` is
installed on. Defaults to the attribute name. Ignored
when authenticating via `tokenFile`.
'';
};
count = lib.mkOption {
type = lib.types.ints.positive;
default = config.count;
defaultText = lib.literalMD "the entry-level `count`";
example = 4;
description = ''
Number of identical runner instances to create for this
org. Defaults to the entry-level `count`. Each gets its
own systemd service named `github-runner-<name>-<org>-<n>`
and registers under a distinct runner name. Pairs well
with `ephemeral`.
'';
};
extraLabels = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = lib.literalExpression ''[ "org-a" ]'';
description = ''
Extra labels added, on top of the entry-level `extraLabels`,
only to this org's runners.
'';
};
};
}
)
);
};
runnerGroup = lib.mkOption {
type = lib.types.nullOr lib.types.str;
description = ''

View File

@@ -1,58 +0,0 @@
# shellcheck shell=bash
# Fetch a self-hosted runner registration token from the GitHub API.
#
# Adapted from https://github.com/myoung34/docker-github-actions-runner (MIT,
# Copyright (c) 2020 Marcus Young).
#
# Expects the following environment variables:
# * ACCESS_TOKEN a token authorized to manage self-hosted runners
# (a GitHub App installation token or a suitable PAT)
# * RUNNER_SCOPE one of `org`, `ent` or `repo`
# * ORG_NAME the org login (for `org` scope)
# * ENTERPRISE_NAME the enterprise slug (for `ent` scope)
# * REPO_URL the repository URL (for `repo` scope)
# * GITHUB_HOST optional, defaults to github.com (set for GHES)
#
# Prints `{"token": ..., "full_url": ...}` to stdout.
_GITHUB_HOST=${GITHUB_HOST:="github.com"}
# If the host is not github.com, use the GitHub Enterprise Server API endpoint.
if [[ ${_GITHUB_HOST} == "github.com" ]]; then
URI="https://api.${_GITHUB_HOST}"
else
URI="https://${_GITHUB_HOST}/api/v3"
fi
API_VERSION=v3
API_HEADER="Accept: application/vnd.github.${API_VERSION}+json"
AUTH_HEADER="Authorization: token ${ACCESS_TOKEN}"
CONTENT_LENGTH_HEADER="Content-Length: 0"
case ${RUNNER_SCOPE} in
org*)
_FULL_URL="${URI}/orgs/${ORG_NAME}/actions/runners/registration-token"
;;
ent*)
_FULL_URL="${URI}/enterprises/${ENTERPRISE_NAME}/actions/runners/registration-token"
;;
*)
_PROTO="https://"
_URL="${REPO_URL/${_PROTO}/}"
_PATH="$(echo "${_URL}" | grep / | cut -d/ -f2-)"
_ACCOUNT="$(echo "${_PATH}" | cut -d/ -f1)"
_REPO="$(echo "${_PATH}" | cut -d/ -f2)"
_FULL_URL="${URI}/repos/${_ACCOUNT}/${_REPO}/actions/runners/registration-token"
;;
esac
RUNNER_TOKEN="$(curl -fsSX POST \
-H "${CONTENT_LENGTH_HEADER}" \
-H "${AUTH_HEADER}" \
-H "${API_HEADER}" \
"${_FULL_URL}" |
jq -r '.token')"
echo "{\"token\": \"${RUNNER_TOKEN}\", \"full_url\": \"${_FULL_URL}\"}"

View File

@@ -1,71 +0,0 @@
# shellcheck shell=bash
# Force-remove a previously registered, offline self-hosted runner via the
# GitHub API. Used before re-registering to avoid orphaned runners piling up in
# the GitHub Actions UI.
#
# Adapted from https://github.com/myoung34/docker-github-actions-runner (MIT,
# Copyright (c) 2020 Marcus Young).
#
# Expects the following environment variables:
# * ACCESS_TOKEN a token authorized to manage self-hosted runners
# * RUNNER_NAME the name of the runner to remove
# * RUNNER_SCOPE one of `org`, `ent` or `repo`
# * ORG_NAME the org login (for `org` scope)
# * ENTERPRISE_NAME the enterprise slug (for `ent` scope)
# * REPO_URL the repository URL (for `repo` scope)
# * GITHUB_HOST optional, defaults to github.com (set for GHES)
_GITHUB_HOST=${GITHUB_HOST:="github.com"}
# If the host is not github.com, use the GitHub Enterprise Server API endpoint.
if [[ ${_GITHUB_HOST} == "github.com" ]]; then
URI="https://api.${_GITHUB_HOST}"
else
URI="https://${_GITHUB_HOST}/api/v3"
fi
API_HEADER="Accept: application/vnd.github+json"
AUTH_HEADER="Authorization: token ${ACCESS_TOKEN}"
CONTENT_LENGTH_HEADER="Content-Length: 0"
runners_url() {
case ${RUNNER_SCOPE} in
org*)
echo "${URI}/orgs/${ORG_NAME}/actions/runners"
;;
ent*)
echo "${URI}/enterprises/${ENTERPRISE_NAME}/actions/runners"
;;
*)
_PROTO="https://"
_URL="${REPO_URL/${_PROTO}/}"
_PATH="$(echo "${_URL}" | grep / | cut -d/ -f2-)"
_ACCOUNT="$(echo "${_PATH}" | cut -d/ -f1)"
_REPO="$(echo "${_PATH}" | cut -d/ -f2)"
echo "${URI}/repos/${_ACCOUNT}/${_REPO}/actions/runners"
;;
esac
}
_RUNNERS_URL="$(runners_url)"
RUNNERS="$(curl -fsSX GET \
-H "${CONTENT_LENGTH_HEADER}" \
-H "${AUTH_HEADER}" \
-H "${API_HEADER}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"${_RUNNERS_URL}")"
RUNNER_ID=$(echo "$RUNNERS" | jq -r '.runners[] | select( (.name == env.RUNNER_NAME) and (.status == "offline") ) | .id')
if [[ $RUNNER_ID == "" ]]; then
echo "Runner ${RUNNER_NAME} doesn't exist or is online. Nothing to unregister."
exit 0
fi
echo "${RUNNER_NAME} is still registered and offline. Forcing removal..."
curl -fsSX DELETE \
-H "${CONTENT_LENGTH_HEADER}" \
-H "${AUTH_HEADER}" \
-H "${API_HEADER}" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"${_RUNNERS_URL}/${RUNNER_ID}"

View File

@@ -9,22 +9,6 @@
lib.flip lib.mapAttrsToList config.services.github-runners (
name: cfg:
map (lib.mkIf cfg.enable) [
{
assertion = (cfg.tokenFile == null) != (cfg.githubApp == null);
message = "`services.github-runners.${name}`: Exactly one of `tokenFile` and `githubApp` must be set";
}
{
assertion = cfg.orgs != { } || cfg.url != null;
message = "`services.github-runners.${name}`: `url` must be set unless `orgs` is used";
}
{
assertion = cfg.orgs != { } || cfg.githubApp == null || cfg.githubApp.login != null;
message = "`services.github-runners.${name}`: `githubApp.login` must be set unless `orgs` is used (the login is then derived per org)";
}
{
assertion = cfg.orgs != { } || cfg.count == 1 || cfg.name != null;
message = "`services.github-runners.${name}`: `name` must not be null when `count > 1` (each replica needs a distinct registration name)";
}
{
assertion = !cfg.noDefaultLabels || (cfg.extraLabels != [ ]);
message = "`services.github-runners.${name}`: The `extraLabels` option is mandatory if `noDefaultLabels` is set";
@@ -40,49 +24,8 @@
config.systemd.services =
let
enabledRunners = lib.filterAttrs (_: cfg: cfg.enable) config.services.github-runners;
runnerInstances = lib.concatMapAttrs (
name: cfg:
if cfg.orgs == { } then
# Single org/repo (entry-level `url`), fanned out by `count`. For
# `count == 1` the service keeps the bare `github-runner-<name>` name
# for backwards compatibility; `count > 1` suffixes `-<n>`.
let
suffixes = if cfg.count == 1 then [ "" ] else map (n: "-${toString n}") (lib.range 1 cfg.count);
in
lib.listToAttrs (
map (
suffix:
lib.nameValuePair "${name}${suffix}" (
cfg // { name = if cfg.name == null then null else "${cfg.name}${suffix}"; }
)
) suffixes
)
else
lib.listToAttrs (
lib.concatLists (
lib.flip lib.mapAttrsToList cfg.orgs (
orgName: org:
map (
n:
let
key = "${name}-${orgName}-${toString n}";
in
lib.nameValuePair key (
cfg
// {
url = org.url;
name = key;
extraLabels = cfg.extraLabels ++ org.extraLabels;
githubApp = if cfg.githubApp == null then null else cfg.githubApp // { login = org.login; };
}
)
) (lib.range 1 org.count)
)
)
)
) enabledRunners;
in
(lib.flip lib.mapAttrs' runnerInstances (
(lib.flip lib.mapAttrs' enabledRunners (
name: cfg:
let
svcName = "github-runner-${name}";
@@ -98,66 +41,6 @@
currentConfigTokenFilename = ".current-token";
workDir = if cfg.workDir == null then runtimeDir else cfg.workDir;
newConfigTokenPath = "$STATE_DIRECTORY/.new-token";
currentConfigTokenPath = "$STATE_DIRECTORY/${currentConfigTokenFilename}";
# Wrapper script which expects the full path of the state, working and logs
# directory as arguments. Overrides the respective systemd variables to provide
# unambiguous directory names. This becomes relevant, for example, if the
# caller overrides any of the StateDirectory=, RuntimeDirectory= or LogDirectory=
# to contain more than one directory. This causes systemd to set the respective
# environment variables with the path of all of the given directories, separated
# by a colon.
writeScript =
scriptName: lines:
pkgs.writeShellScript "${svcName}-${scriptName}.sh" ''
set -euo pipefail
STATE_DIRECTORY="$1"
WORK_DIRECTORY="$2"
LOGS_DIRECTORY="$3"
${lines}
'';
ghUrlPath = lib.removePrefix "https://github.com/" cfg.url;
ghUrlSegments = lib.filter (s: s != "") (lib.splitString "/" ghUrlPath);
runnerScope = if lib.length ghUrlSegments >= 2 then "repo" else "org";
appHelper =
helperName: scriptFile:
pkgs.writeShellApplication {
name = helperName;
runtimeInputs = with pkgs; [
jq
curl
openssl
coreutils
];
excludeShellChecks = [
"SC2154"
"SC2116"
];
text = builtins.readFile scriptFile;
};
fetchAccessToken = appHelper "github-app-access-token" ./app-token.sh;
fetchRegistrationToken = appHelper "github-runner-registration-token" ./registration-token.sh;
removeRunner = appHelper "github-runner-remove" ./remove-runner.sh;
appEnv = lib.optionalString (cfg.githubApp != null) ''
export APP_ID=${toString cfg.githubApp.id}
export APP_LOGIN=${lib.escapeShellArg cfg.githubApp.login}
APP_PRIVATE_KEY="$(cat ${lib.escapeShellArg cfg.githubApp.privateKeyFile})"
export APP_PRIVATE_KEY
export RUNNER_SCOPE=${runnerScope}
export ORG_NAME=${lib.escapeShellArg cfg.githubApp.login}
export REPO_URL=${lib.escapeShellArg cfg.url}
${
if cfg.name != null then
"export RUNNER_NAME=${lib.escapeShellArg cfg.name}"
else
''export RUNNER_NAME="$(uname -n)"''
}
'';
in
lib.nameValuePair svcName {
description = "GitHub Actions runner";
@@ -201,6 +84,24 @@
# - Set up the directory structure by creating the necessary symlinks.
ExecStartPre =
let
# Wrapper script which expects the full path of the state, working and logs
# directory as arguments. Overrides the respective systemd variables to provide
# unambiguous directory names. This becomes relevant, for example, if the
# caller overrides any of the StateDirectory=, RuntimeDirectory= or LogDirectory=
# to contain more than one directory. This causes systemd to set the respective
# environment variables with the path of all of the given directories, separated
# by a colon.
writeScript =
name: lines:
pkgs.writeShellScript "${svcName}-${name}.sh" ''
set -euo pipefail
STATE_DIRECTORY="$1"
WORK_DIRECTORY="$2"
LOGS_DIRECTORY="$3"
${lines}
'';
runnerRegistrationConfig = lib.getAttrs [
"ephemeral"
"extraLabels"
@@ -213,6 +114,8 @@
] cfg;
newConfigPath = builtins.toFile "${svcName}-config.json" (builtins.toJSON runnerRegistrationConfig);
currentConfigPath = "$STATE_DIRECTORY/.nixos-current-config.json";
newConfigTokenPath = "$STATE_DIRECTORY/.new-token";
currentConfigTokenPath = "$STATE_DIRECTORY/${currentConfigTokenFilename}";
runnerCredFiles = [
".credentials"
@@ -261,23 +164,6 @@
# Always clean workDir
find -H "$WORK_DIRECTORY" -mindepth 1 -delete
'';
unconfigureRunnerGitHubApp = writeScript "unconfigure-github-app" ''
${appEnv}
ACCESS_TOKEN="$(${lib.getExe' fetchAccessToken "github-app-access-token"})"
export ACCESS_TOKEN
${lib.getExe' removeRunner "github-runner-remove"} || true
find "$STATE_DIRECTORY/" -mindepth 1 -delete
umask 000
${lib.getExe' fetchRegistrationToken "github-runner-registration-token"} \
| ${pkgs.jq}/bin/jq -r '.token' > "${newConfigTokenPath}"
install --mode=600 "${newConfigTokenPath}" "${currentConfigTokenPath}"
# Always clean workDir
find -H "$WORK_DIRECTORY" -mindepth 1 -delete
'';
configureRunner =
writeScript "configure" # bash
''
@@ -299,33 +185,24 @@
${lib.optionalString cfg.noDefaultLabels "--no-default-labels"}
)
token=$(<"${newConfigTokenPath}")
${
if cfg.githubApp != null then
''
args+=(--token "$token")
''
case ${cfg.tokenType} in
access)
args+=(--pat "$token")
;;
registration)
args+=(--token "$token")
;;
auto)
# If the token file contains a PAT (i.e., it starts with "ghp_" or "github_pat_"),
# we have to use the --pat option, if it is not a PAT, we assume it contains a
# registration token and use the --token option
if [[ "$token" =~ ^gh[a-z]+_* ]] || [[ "$token" =~ ^github_pat_* ]]; then
args+=(--pat "$token")
else
''
case ${cfg.tokenType} in
access)
args+=(--pat "$token")
;;
registration)
args+=(--token "$token")
;;
auto)
# If the token file contains a PAT (i.e., it starts with "ghp_" or "github_pat_"),
# we have to use the --pat option, if it is not a PAT, we assume it contains a
# registration token and use the --token option
if [[ "$token" =~ ^gh[a-z]+_* ]] || [[ "$token" =~ ^github_pat_* ]]; then
args+=(--pat "$token")
else
args+=(--token "$token")
fi
;;
esac
''
}
args+=(--token "$token")
fi
;;
esac
${cfg.package}/bin/Runner.Listener configure "''${args[@]}"
# Move the automatically created _diag dir to the logs dir
mkdir -p "$STATE_DIRECTORY/_diag"
@@ -357,33 +234,11 @@
}"
)
[
# runs as root
"+${if cfg.githubApp != null then unconfigureRunnerGitHubApp else unconfigureRunner}"
"+${unconfigureRunner}" # runs as root
configureRunner
setupWorkDir
];
ExecStopPost = lib.optionals (cfg.githubApp != null) (
let
unregister = writeScript "unregister-github-app" ''
${appEnv}
ACCESS_TOKEN="$(${lib.getExe' fetchAccessToken "github-app-access-token"})"
export ACCESS_TOKEN
${lib.getExe' removeRunner "github-runner-remove"} || true
'';
in
map (
x:
"${x} ${
lib.escapeShellArgs [
stateDir
workDir
logsDir
]
}"
) [ "-+${unregister}" ] # runs as root
);
# If running in ephemeral mode, restart the service on-exit (i.e., successful de-registration of the runner)
# to trigger a fresh registration.
Restart = if cfg.ephemeral then "on-success" else "no";
@@ -401,12 +256,11 @@
WorkingDirectory = workDir;
InaccessiblePaths = [
# Token file path given in the configuration, if visible to the service
"-${cfg.tokenFile}"
# Token file in the state directory
"${stateDir}/${currentConfigTokenFilename}"
]
# Token file path given in the configuration, if visible to the service
++ lib.optional (cfg.tokenFile != null) "-${cfg.tokenFile}"
++ lib.optional (cfg.githubApp != null) "-${cfg.githubApp.privateKeyFile}";
];
KillSignal = "SIGINT";

View File

@@ -1,279 +0,0 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.kvrocks;
format = pkgs.formats.keyValue {
# Emit list values as repeated keys (e.g. rename-command), matching MultiStringField.
listsAsDuplicateKeys = true;
mkKeyValue = lib.generators.mkKeyValueDefault {
mkValueString = v: if lib.isBool v then lib.boolToYesNo v else toString v;
} " ";
};
defaultDir = "/var/lib/kvrocks";
dataDir = cfg.settings.dir;
isDefaultDir = dataDir == defaultDir;
# Defaults match upstream Config field defaults (config.cc).
# freeformType uses listsAsDuplicateKeys, so set values are singleton lists.
workers = lib.head (cfg.settings.workers or [ 8 ]);
maxBackgroundJobs = lib.head (cfg.settings."rocksdb.max_background_jobs" or [ 4 ]);
maxclients = lib.head (cfg.settings.maxclients or [ 10240 ]);
maxOpenFiles = lib.head (cfg.settings."rocksdb.max_open_files" or [ 8096 ]);
# Thread inventory from server.cc ("Kvrocks threads list") + Server::Start:
# always-on: main, workers, task-runner (1), server-cron, compact-check,
# rocksdb background (bounded by max_background_jobs)
# optional: master-repl (+ ≤4 parallel fetch via std::async on full sync),
# feed-slave per replica, slot-migrate (cluster)
alwaysOnThreads = 1 + workers + 1 + 1 + 1 + maxBackgroundJobs;
# 1 master-repl + 4 fetch + 1 slot-migrate + ~16 replicas + misc (jemalloc, …)
dynamicThreadMargin = 32;
# From Server::AdjustOpenFilesLimit:
# max_files = maxclients + rocksdb.max_open_files + min_reserved_fds
# min_reserved_fds = 128 (listen sockets, logs, persistence, misc)
openFilesReserved = 128;
hasUnixSocket = cfg.settings.unixsocket != "";
hasTcp = lib.length cfg.settings.bind > 0;
configFile = format.generate "kvrocks.conf" (
{
daemonize = "no";
supervised = "systemd";
}
// (builtins.removeAttrs cfg.settings [
"bind"
"unixsocket"
])
// lib.optionalAttrs (hasTcp && !cfg.socketActivation) {
bind = lib.concatStringsSep " " cfg.settings.bind;
}
// lib.optionalAttrs hasUnixSocket {
unixsocket = cfg.settings.unixsocket;
}
// lib.optionalAttrs cfg.socketActivation {
socket-fd = 3;
}
);
in
{
meta.maintainers = pkgs.kvrocks.meta.maintainers;
options = {
services.kvrocks = {
enable = lib.mkEnableOption "the Kvrocks server";
package = lib.mkPackageOption pkgs "kvrocks" { };
user = lib.mkOption {
type = lib.types.str;
default = "kvrocks";
description = "User account under which Kvrocks runs.";
};
group = lib.mkOption {
type = lib.types.str;
default = "kvrocks";
description = "Group under which Kvrocks runs.";
};
socketActivation = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Enable systemd socket activation for TCP.
Requires exactly one address in {option}`services.kvrocks.settings.bind`.
'';
};
settings = lib.mkOption {
type = lib.types.submodule {
freeformType = format.type;
options = {
bind = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [
"127.0.0.1"
"::1"
];
description = "The addresses to bind to.";
};
port = lib.mkOption {
type = lib.types.port;
default = 6666;
description = "Accept connections on the specified port.";
};
unixsocket = lib.mkOption {
type = lib.types.str;
default = "";
example = "/run/kvrocks/kvrocks.sock";
description = "Unix socket path.";
};
dir = lib.mkOption {
type = lib.types.str;
default = defaultDir;
description = "Directory for database files.";
};
};
};
default = { };
example = {
workers = 8;
maxclients = 10000;
rename-command = [
"KEYS \"\""
"FLUSHDB \"\""
];
};
description = ''
Configuration for kvrocks.
See <https://github.com/apache/kvrocks/blob/unstable/kvrocks.conf> for supported options.
List values are emitted as repeated keys (for example `rename-command`),
except {option}`services.kvrocks.settings.bind` which is space-separated
on a single line.
'';
};
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether to open the firewall for the kvrocks port.";
};
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = hasTcp || hasUnixSocket;
message = "services.kvrocks: set settings.bind and/or settings.unixsocket.";
}
{
assertion = cfg.socketActivation -> builtins.length cfg.settings.bind == 1;
message = "services.kvrocks.socketActivation requires exactly one settings.bind address.";
}
];
networking.firewall.allowedTCPPorts = lib.mkIf (cfg.openFirewall && hasTcp) [
cfg.settings.port
];
systemd.tmpfiles.settings."10-kvrocks" = lib.mkIf (!isDefaultDir) {
${dataDir}.d = {
user = cfg.user;
group = cfg.group;
mode = "0700";
};
};
systemd.sockets.kvrocks = lib.mkIf cfg.socketActivation {
description = "Kvrocks socket";
wantedBy = [ "sockets.target" ];
listenStreams =
let
addr = builtins.head cfg.settings.bind;
port = toString cfg.settings.port;
listenStream = if lib.hasInfix ":" addr then "[${addr}]:${port}" else "${addr}:${port}";
in
lib.singleton listenStream;
socketConfig = {
Accept = false;
SocketUser = cfg.user;
SocketGroup = cfg.group;
};
};
systemd.services.kvrocks = {
description = "Kvrocks - Distributed key value database";
documentation = [ "https://kvrocks.apache.org/" ];
wantedBy = lib.mkIf (!cfg.socketActivation) [ "multi-user.target" ];
after = [ "network.target" ] ++ lib.optionals cfg.socketActivation [ "kvrocks.socket" ];
requires = lib.optionals cfg.socketActivation [ "kvrocks.socket" ];
serviceConfig = {
Type = "notify";
ExecStart = "${lib.getExe cfg.package} -c ${configFile}";
Restart = "on-failure";
RestartSec = "10s";
User = cfg.user;
Group = cfg.group;
StateDirectory = lib.mkIf isDefaultDir "kvrocks";
StateDirectoryMode = "0700";
RuntimeDirectory = "kvrocks";
RuntimeDirectoryMode = "0755";
BindPaths = lib.mkIf (!isDefaultDir) [ dataDir ];
LimitNPROC = lib.mkDefault (alwaysOnThreads + dynamicThreadMargin);
# When rocksdb.max_open_files is -1 (unlimited), fall back to a high limit.
LimitNOFILE = lib.mkDefault (
if maxOpenFiles < 0 then 1048576 else maxclients + maxOpenFiles + openFilesReserved
);
TimeoutSec = 300;
NonBlocking = lib.mkIf cfg.socketActivation true;
# Capabilities
CapabilityBoundingSet = "";
# Security
NoNewPrivileges = true;
# Sandboxing
TemporaryFileSystem = [ "/:ro" ];
BindReadOnlyPaths = [
builtins.storeDir
"/etc"
];
ProtectSystem = "strict";
ProtectHome = true;
PrivateTmp = true;
PrivateDevices = true;
PrivateUsers = true;
ProtectClock = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectControlGroups = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_UNIX"
];
RestrictNamespaces = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
PrivateMounts = true;
SocketBindDeny = [ "any" ];
SocketBindAllow = lib.optionals (hasTcp && !cfg.socketActivation) [
"tcp:${toString cfg.settings.port}"
];
# System Call Filtering
SystemCallArchitectures = "native";
SystemCallFilter = "~@cpu-emulation @debug @keyring @memlock @mount @obsolete @privileged @resources @setuid";
};
};
users = {
users = lib.mkIf (cfg.user == "kvrocks") {
kvrocks = {
isSystemUser = true;
group = cfg.group;
description = "Kvrocks daemon user";
};
};
groups = lib.mkIf (cfg.group == "kvrocks") {
kvrocks = { };
};
};
};
}

View File

@@ -752,7 +752,7 @@ in
"AF_INET6"
];
LockPersonality = true;
MemoryDenyWriteExecute = false; # pcre2 jit
MemoryDenyWriteExecute = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
PrivateMounts = true;

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