mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-07-23 17:12:27 +00:00
Compare commits
3 Commits
lib-types-
...
treewide-f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1235b95827 | ||
|
|
6f52e21fbc | ||
|
|
0d8595a4e8 |
2
.github/workflows/backport.yml
vendored
2
.github/workflows/backport.yml
vendored
@@ -14,7 +14,7 @@ permissions: {}
|
||||
jobs:
|
||||
backport:
|
||||
name: Backport Pull Request
|
||||
if: vars.NIXPKGS_CI_APP_ID && github.event.pull_request.merged == true && (github.event.action != 'labeled' || startsWith(github.event.label.name, 'backport'))
|
||||
if: github.repository_owner == 'NixOS' && github.event.pull_request.merged == true && (github.event.action != 'labeled' || startsWith(github.event.label.name, 'backport'))
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
# Use a GitHub App to create the PR so that CI gets triggered
|
||||
|
||||
4
.github/workflows/check-cherry-picks.yml
vendored
4
.github/workflows/check-cherry-picks.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: "Check cherry-picks"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/check-cherry-picks.yml
|
||||
pull_request_target:
|
||||
branches:
|
||||
- 'release-**'
|
||||
@@ -16,6 +13,7 @@ jobs:
|
||||
check:
|
||||
name: cherry-pick-check
|
||||
runs-on: ubuntu-24.04-arm
|
||||
if: github.repository_owner == 'NixOS'
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
|
||||
3
.github/workflows/check-format.yml
vendored
3
.github/workflows/check-format.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: Check that files are formatted
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/check-format.yml
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened, edited]
|
||||
|
||||
|
||||
3
.github/workflows/check-shell.yml
vendored
3
.github/workflows/check-shell.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: "Check shell"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/check-shell.yml
|
||||
pull_request_target:
|
||||
paths:
|
||||
- 'shell.nix'
|
||||
|
||||
7
.github/workflows/codeowners-v2.yml
vendored
7
.github/workflows/codeowners-v2.yml
vendored
@@ -23,9 +23,6 @@
|
||||
name: Codeowners v2
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/codeowners-v2.yml
|
||||
pull_request_target:
|
||||
types: [opened, ready_for_review, synchronize, reopened, edited]
|
||||
|
||||
@@ -67,7 +64,6 @@ jobs:
|
||||
run: nix-build base/ci -A codeownersValidator
|
||||
|
||||
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
||||
if: vars.OWNER_RO_APP_ID
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.OWNER_RO_APP_ID }}
|
||||
@@ -81,7 +77,6 @@ jobs:
|
||||
path: pr
|
||||
|
||||
- name: Validate codeowners
|
||||
if: steps.app-token.outputs.token
|
||||
run: result/bin/codeowners-validator
|
||||
env:
|
||||
OWNERS_FILE: pr/${{ env.OWNERS_FILE }}
|
||||
@@ -104,7 +99,6 @@ jobs:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
||||
if: vars.OWNER_APP_ID
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.OWNER_APP_ID }}
|
||||
@@ -117,7 +111,6 @@ jobs:
|
||||
run: nix-build ci -A requestReviews
|
||||
|
||||
- name: Request reviews
|
||||
if: steps.app-token.outputs.token
|
||||
run: result/bin/request-code-owner-reviews.sh ${{ github.repository }} ${{ github.event.number }} "$OWNERS_FILE"
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
5
.github/workflows/eval-aliases.yml
vendored
5
.github/workflows/eval-aliases.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: Eval aliases
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/eval-aliases.yml
|
||||
pull_request_target:
|
||||
|
||||
permissions: {}
|
||||
@@ -29,7 +26,7 @@ jobs:
|
||||
extra_nix_config: sandbox = true
|
||||
|
||||
- name: Ensure flake outputs on all systems still evaluate
|
||||
run: nix flake check --all-systems --no-build ./nixpkgs
|
||||
run: nix --experimental-features 'nix-command flakes' flake check --all-systems --no-build ./nixpkgs
|
||||
|
||||
- name: Query nixpkgs with aliases enabled to check for basic syntax errors
|
||||
run: |
|
||||
|
||||
10
.github/workflows/eval.yml
vendored
10
.github/workflows/eval.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: Eval
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/eval.yml
|
||||
pull_request_target:
|
||||
types: [opened, ready_for_review, synchronize, reopened]
|
||||
push:
|
||||
@@ -169,7 +166,7 @@ jobs:
|
||||
tag:
|
||||
name: Tag
|
||||
runs-on: ubuntu-24.04-arm
|
||||
needs: [ get-merge-commit, process ]
|
||||
needs: [ process ]
|
||||
if: needs.process.outputs.targetRunId
|
||||
permissions:
|
||||
pull-requests: write
|
||||
@@ -178,7 +175,6 @@ jobs:
|
||||
# See ./codeowners-v2.yml, reuse the same App because we need the same permissions
|
||||
# Can't use the token received from permissions above, because it can't get enough permissions
|
||||
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
||||
if: vars.OWNER_APP_ID
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.OWNER_APP_ID }}
|
||||
@@ -209,7 +205,6 @@ jobs:
|
||||
run: nix-build base/ci -A requestReviews
|
||||
|
||||
- name: Labelling pull request
|
||||
if: ${{ github.event_name == 'pull_request_target' && github.repository_owner == 'NixOS' }}
|
||||
run: |
|
||||
# Get all currently set rebuild labels
|
||||
gh api \
|
||||
@@ -244,7 +239,7 @@ jobs:
|
||||
NUMBER: ${{ github.event.number }}
|
||||
|
||||
- name: Add eval summary to commit statuses
|
||||
if: ${{ github.event_name == 'pull_request_target' && github.repository_owner == 'NixOS' }}
|
||||
if: ${{ github.event_name == 'pull_request_target' }}
|
||||
run: |
|
||||
description=$(jq -r '
|
||||
"Package: added " + (.attrdiff.added | length | tostring) +
|
||||
@@ -264,7 +259,6 @@ jobs:
|
||||
NUMBER: ${{ github.event.number }}
|
||||
|
||||
- name: Requesting maintainer reviews
|
||||
if: ${{ steps.app-token.outputs.token && github.repository_owner == 'NixOS' }}
|
||||
run: |
|
||||
# maintainers.json contains GitHub IDs. Look up handles to request reviews from.
|
||||
# There appears to be no API to request reviews based on GitHub IDs
|
||||
|
||||
7
.github/workflows/get-merge-commit.yml
vendored
7
.github/workflows/get-merge-commit.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: Get merge commit
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/get-merge-commit.yml
|
||||
workflow_call:
|
||||
outputs:
|
||||
mergedSha:
|
||||
@@ -41,9 +38,9 @@ jobs:
|
||||
push)
|
||||
echo "mergedSha=${{ github.sha }}" >> "$GITHUB_OUTPUT"
|
||||
;;
|
||||
pull_request*)
|
||||
pull_request_target)
|
||||
if commits=$(base/ci/get-merge-commit.sh ${{ github.repository }} ${{ github.event.number }}); then
|
||||
echo -e "Checking the commits:\n$commits"
|
||||
echo "Checking the commits:\n$commits"
|
||||
echo "$commits" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
# Skipping so that no notifications are sent
|
||||
|
||||
3
.github/workflows/lib-tests.yml
vendored
3
.github/workflows/lib-tests.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: "Building Nixpkgs lib-tests"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/lib-tests.yml
|
||||
pull_request_target:
|
||||
paths:
|
||||
- 'lib/**'
|
||||
|
||||
4
.github/workflows/manual-nixos-v2.yml
vendored
4
.github/workflows/manual-nixos-v2.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: "Build NixOS manual v2"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/manual-nixos-v2.yml
|
||||
pull_request_target:
|
||||
branches:
|
||||
- master
|
||||
@@ -41,6 +38,7 @@ jobs:
|
||||
extra_nix_config: sandbox = true
|
||||
|
||||
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
|
||||
if: github.repository_owner == 'NixOS'
|
||||
with:
|
||||
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
|
||||
name: nixpkgs-ci
|
||||
|
||||
4
.github/workflows/manual-nixpkgs-v2.yml
vendored
4
.github/workflows/manual-nixpkgs-v2.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: "Build Nixpkgs manual v2"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/manual-nixpkgs-v2.yml
|
||||
pull_request_target:
|
||||
branches:
|
||||
- master
|
||||
@@ -28,6 +25,7 @@ jobs:
|
||||
extra_nix_config: sandbox = true
|
||||
|
||||
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
|
||||
if: github.repository_owner == 'NixOS'
|
||||
with:
|
||||
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
|
||||
name: nixpkgs-ci
|
||||
|
||||
3
.github/workflows/nix-parse-v2.yml
vendored
3
.github/workflows/nix-parse-v2.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: "Check whether nix files are parseable v2"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/nix-parse-v2.yml
|
||||
pull_request_target:
|
||||
|
||||
permissions: {}
|
||||
|
||||
3
.github/workflows/nixpkgs-vet.yml
vendored
3
.github/workflows/nixpkgs-vet.yml
vendored
@@ -6,9 +6,6 @@
|
||||
name: Vet nixpkgs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/nixpkgs-vet.yml
|
||||
pull_request_target:
|
||||
# This workflow depends on the base branch of the PR, but changing the base branch is not included in the default trigger events, which would be `opened`, `synchronize` or `reopened`.
|
||||
# Instead it causes an `edited` event, so we need to add it explicitly here.
|
||||
|
||||
3
.github/workflows/no-channel.yml
vendored
3
.github/workflows/no-channel.yml
vendored
@@ -1,9 +1,6 @@
|
||||
name: "No channel PR"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/no-channel.yml
|
||||
pull_request_target:
|
||||
# Re-run should be triggered when the base branch is updated, instead of silently failing
|
||||
types: [opened, synchronize, reopened, edited]
|
||||
|
||||
4
.github/workflows/periodic-merge-24h.yml
vendored
4
.github/workflows/periodic-merge-24h.yml
vendored
@@ -31,10 +31,6 @@ jobs:
|
||||
into: staging-next-24.11
|
||||
- from: staging-next-24.11
|
||||
into: staging-24.11
|
||||
- from: master
|
||||
into: staging-next-25.05
|
||||
- from: staging-next-25.05
|
||||
into: staging-25.05
|
||||
- from: master staging
|
||||
into: haskell-updates
|
||||
uses: ./.github/workflows/periodic-merge.yml
|
||||
|
||||
15
ci/OWNERS
15
ci/OWNERS
@@ -171,11 +171,6 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobeza
|
||||
/pkgs/top-level/python-packages.nix @natsukium
|
||||
/pkgs/top-level/release-python.nix @natsukium
|
||||
|
||||
# CUDA
|
||||
/pkgs/top-level/cuda-packages.nix @NixOS/cuda-maintainers
|
||||
/pkgs/top-level/release-cuda.nix @NixOS/cuda-maintainers
|
||||
/pkgs/development/cuda-modules @NixOS/cuda-maintainers
|
||||
|
||||
# Haskell
|
||||
/doc/languages-frameworks/haskell.section.md @sternenseemann @maralorn @wolfgangwalther
|
||||
/maintainers/scripts/haskell @sternenseemann @maralorn @wolfgangwalther
|
||||
@@ -309,8 +304,8 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
|
||||
/pkgs/build-support/dlang @jtbx @TomaSajt
|
||||
|
||||
# Dhall
|
||||
/pkgs/development/dhall-modules @Gabriella439 @Profpatsch
|
||||
/pkgs/development/interpreters/dhall @Gabriella439 @Profpatsch
|
||||
/pkgs/development/dhall-modules @Gabriella439 @Profpatsch @ehmry
|
||||
/pkgs/development/interpreters/dhall @Gabriella439 @Profpatsch @ehmry
|
||||
|
||||
# Idris
|
||||
/pkgs/development/idris-modules @Infinisil
|
||||
@@ -384,6 +379,12 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
|
||||
# Xfce
|
||||
/doc/hooks/xfce4-dev-tools.section.md @NixOS/xfce
|
||||
|
||||
# nim
|
||||
/doc/languages-frameworks/nim.section.md @ehmry
|
||||
/pkgs/build-support/build-nim-package.nix @ehmry
|
||||
/pkgs/build-support/build-nim-sbom.nix @ehmry
|
||||
/pkgs/top-level/nim-overrides.nix @ehmry
|
||||
|
||||
# terraform providers
|
||||
/pkgs/applications/networking/cluster/terraform-providers @zowoq
|
||||
|
||||
|
||||
@@ -63,7 +63,10 @@ let
|
||||
fs = pkgs.lib.fileset;
|
||||
nixFilesSrc = fs.toSource {
|
||||
root = ../.;
|
||||
fileset = fs.difference ../. (fs.maybeMissing ../.git);
|
||||
fileset = fs.difference (fs.unions [
|
||||
(fs.fileFilter (file: file.hasExt "nix") ../.)
|
||||
../.git-blame-ignore-revs
|
||||
]) (fs.maybeMissing ../.git);
|
||||
};
|
||||
in
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"rev": "eaeed9530c76ce5f1d2d8232e08bec5e26f18ec1",
|
||||
"sha256": "132nimgi1g88fbhddk4b8b1qk68jly494x2mnphyk3xa1d2wy9q7"
|
||||
"rev": "573c650e8a14b2faa0041645ab18aed7e60f0c9a",
|
||||
"sha256": "0qg99zj0gb0pc6sjlkmwhk1c1xz14qxmk6gamgfmcxpsfdp5vn72"
|
||||
}
|
||||
|
||||
@@ -99,12 +99,17 @@ failure. To prevent this, guard the completion generation commands.
|
||||
```nix
|
||||
{
|
||||
nativeBuildInputs = [ installShellFiles ];
|
||||
postInstall = lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
|
||||
# using named fd
|
||||
installShellCompletion --cmd foobar \
|
||||
--bash <($out/bin/foobar --bash-completion) \
|
||||
--fish <($out/bin/foobar --fish-completion) \
|
||||
--zsh <($out/bin/foobar --zsh-completion)
|
||||
'';
|
||||
postInstall = lib.optionalString (stdenv.hostPlatform.emulatorAvailable buildPackages) (
|
||||
let
|
||||
emulator = stdenv.hostPlatform.emulator buildPackages;
|
||||
in
|
||||
''
|
||||
# using named fd
|
||||
installShellCompletion --cmd foobar \
|
||||
--bash <(${emulator} $out/bin/foobar --bash-completion) \
|
||||
--fish <(${emulator} $out/bin/foobar --fish-completion) \
|
||||
--zsh <(${emulator} $out/bin/foobar --zsh-completion)
|
||||
''
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -779,7 +779,7 @@ that depend on that library, you may want to use:
|
||||
|
||||
```nix
|
||||
haskellPackages.haskell-ci.overrideScope (self: super: {
|
||||
Cabal = self.Cabal_3_14_2_0;
|
||||
Cabal = self.Cabal_3_14_1_1;
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# Nixpkgs 25.11 (2025.11/??) {#sec-nixpkgs-release-25.11}
|
||||
|
||||
## Highlights {#sec-nixpkgs-release-25.11-highlights}
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
|
||||
## Backward Incompatibilities {#sec-nixpkgs-release-25.11-incompatibilities}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
|
||||
## Other Notable Changes {#sec-nixpkgs-release-25.11-notable-changes}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
|
||||
## Nixpkgs Library {#sec-nixpkgs-release-25.11-lib}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
### Breaking changes {#sec-nixpkgs-release-25.11-lib-breaking}
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
|
||||
|
||||
### Deprecations {#sec-nixpkgs-release-25.11-lib-deprecations}
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
|
||||
|
||||
### Additions and Improvements {#sec-nixpkgs-release-25.11-lib-additions-improvements}
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
|
||||
@@ -1141,15 +1141,12 @@ They cannot be overridden without rebuilding the package.
|
||||
|
||||
If dependencies should be resolved at runtime, use `--suffix` to append fallback values to `PATH`.
|
||||
|
||||
There’s many more kinds of arguments, they are documented in `nixpkgs/pkgs/build-support/setup-hooks/make-wrapper.sh` for the `makeWrapper` implementation and in `nixpkgs/pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh` for the `makeBinaryWrapper` implementation.
|
||||
There’s many more kinds of arguments, they are documented in `nixpkgs/pkgs/build-support/setup-hooks/make-wrapper.sh` for the `makeWrapper` implementation and in `nixpkgs/pkgs/build-support/setup-hooks/make-binary-wrapper/make-binary-wrapper.sh` for the `makeBinaryWrapper` implementation.
|
||||
|
||||
`wrapProgram` is a convenience function you probably want to use most of the time, implemented by both `makeWrapper` and `makeBinaryWrapper`.
|
||||
|
||||
Using the `makeBinaryWrapper` implementation is usually preferred, as it creates a tiny _compiled_ wrapper executable, that can be used as a shebang interpreter. This is needed mostly on Darwin, where shebangs cannot point to scripts, [due to a limitation with the `execve`-syscall](https://stackoverflow.com/questions/67100831/macos-shebang-with-absolute-path-not-working). Compiled wrappers generated by `makeBinaryWrapper` can be inspected with `less <path-to-wrapper>` - by scrolling past the binary data you should be able to see the shell command that generated the executable and there see the environment variables that were injected into the wrapper.
|
||||
|
||||
However, `makeWrapper` is more flexible and implements more arguments.
|
||||
Use `makeWrapper` if you need the wrapper to use shell features (e.g. look up environment variables) at runtime.
|
||||
|
||||
### `remove-references-to -t` \<storepath\> [ `-t` \<storepath\> ... ] \<file\> ... {#fun-remove-references-to}
|
||||
|
||||
Removes the references of the specified files to the specified store files. This is done without changing the size of the file by replacing the hash by `eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee`, and should work on compiled executables. This is meant to be used to remove the dependency of the output on inputs that are known to be unnecessary at runtime. Of course, reckless usage will break the patched programs.
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
{ lib }:
|
||||
|
||||
let
|
||||
inherit (lib.strings)
|
||||
concatStringsSep
|
||||
;
|
||||
inherit (lib.lists)
|
||||
filter
|
||||
;
|
||||
inherit (lib.trivial)
|
||||
showWarnings
|
||||
;
|
||||
in
|
||||
rec {
|
||||
|
||||
/**
|
||||
@@ -142,61 +131,4 @@ rec {
|
||||
"each element in ${name} must be one of ${lib.generators.toPretty { } xs}, but is: ${
|
||||
lib.generators.toPretty { } vals
|
||||
}";
|
||||
|
||||
/**
|
||||
Wrap a value with logic that throws an error when assertions
|
||||
fail and emits any warnings.
|
||||
|
||||
# Inputs
|
||||
|
||||
`assertions`
|
||||
|
||||
: A list of assertions. If any of their `assertion` attrs is `false`, their `message` attrs will be emitted in a `throw`.
|
||||
|
||||
`warnings`
|
||||
|
||||
: A list of strings to emit as warnings. This function does no filtering on this list.
|
||||
|
||||
`val`
|
||||
|
||||
: A value to return, wrapped in `warn`, if a `throw` is not necessary.
|
||||
|
||||
# Type
|
||||
|
||||
```
|
||||
checkAssertWarn :: [ { assertion :: Bool; message :: String } ] -> [ String ] -> Any -> Any
|
||||
```
|
||||
|
||||
# Examples
|
||||
:::{.example}
|
||||
## `lib.asserts.checkAssertWarn` usage example
|
||||
```nix
|
||||
checkAssertWarn
|
||||
[ { assertion = false; message = "Will fail"; } ]
|
||||
[ ]
|
||||
null
|
||||
stderr> error:
|
||||
stderr> Failed assertions:
|
||||
stderr> - Will fail
|
||||
|
||||
checkAssertWarn
|
||||
[ { assertion = true; message = "Will not fail"; } ]
|
||||
[ "Will warn" ]
|
||||
null
|
||||
stderr> evaluation warning: Will warn
|
||||
null
|
||||
```
|
||||
|
||||
:::
|
||||
*/
|
||||
checkAssertWarn =
|
||||
assertions: warnings: val:
|
||||
let
|
||||
failedAssertions = map (x: x.message) (filter (x: !x.assertion) assertions);
|
||||
in
|
||||
if failedAssertions != [ ] then
|
||||
throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
|
||||
else
|
||||
showWarnings warnings val;
|
||||
|
||||
}
|
||||
|
||||
@@ -651,11 +651,6 @@ lib.mapAttrs mkLicense (
|
||||
url = "https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception";
|
||||
};
|
||||
|
||||
gpl2UBDLPlus = {
|
||||
fullName = "GNU General Public License v3.0 or later (with UBDL exception)";
|
||||
url = "https://spdx.org/licenses/UBDL-exception.html";
|
||||
};
|
||||
|
||||
gpl2Oss = {
|
||||
fullName = "GNU General Public License version 2 only (with OSI approved licenses linking exception)";
|
||||
url = "https://www.mysql.com/about/legal/licensing/foss-exception";
|
||||
|
||||
@@ -382,7 +382,7 @@ in
|
||||
(splitRoot p).root
|
||||
(splitRoot p).subpath
|
||||
|
||||
- Trying to get the parent directory of `root` using [`dirOf`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-dirOf) returns `root` itself:
|
||||
- Trying to get the parent directory of `root` using [`readDir`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-readDir) returns `root` itself:
|
||||
|
||||
dirOf (splitRoot p).root == (splitRoot p).root
|
||||
|
||||
|
||||
@@ -352,9 +352,21 @@ let
|
||||
else
|
||||
null;
|
||||
|
||||
# Handle Android SDK and NDK versions.
|
||||
androidSdkVersion = args.androidSdkVersion or null;
|
||||
androidNdkVersion = args.androidNdkVersion or null;
|
||||
# Remove before 25.05
|
||||
androidSdkVersion =
|
||||
if (args ? sdkVer && !args ? androidSdkVersion) then
|
||||
throw "For android `sdkVer` has been renamed to `androidSdkVersion`"
|
||||
else if (args ? androidSdkVersion) then
|
||||
args.androidSdkVersion
|
||||
else
|
||||
null;
|
||||
androidNdkVersion =
|
||||
if (args ? ndkVer && !args ? androidNdkVersion) then
|
||||
throw "For android `ndkVer` has been renamed to `androidNdkVersion`"
|
||||
else if (args ? androidSdkVersion) then
|
||||
args.androidNdkVersion
|
||||
else
|
||||
null;
|
||||
}
|
||||
// (
|
||||
let
|
||||
|
||||
@@ -146,10 +146,6 @@ rec {
|
||||
riscv64 = riscv "64";
|
||||
riscv32 = riscv "32";
|
||||
|
||||
riscv64-musl = {
|
||||
config = "riscv64-unknown-linux-musl";
|
||||
};
|
||||
|
||||
riscv64-embedded = {
|
||||
config = "riscv64-none-elf";
|
||||
libc = "newlib";
|
||||
|
||||
@@ -160,9 +160,6 @@ checkConfigError 'A definition for option .intStrings\.badTagTypeError\.left. is
|
||||
checkConfigError 'A definition for option .nested\.right\.left. is not of type .signed integer.' config.nested.right.left ./types-attrTag.nix
|
||||
checkConfigError 'In attrTag, each tag value must be an option, but tag int was a bare type, not wrapped in mkOption.' config.opt.int ./types-attrTag-wrong-decl.nix
|
||||
|
||||
# types.nix assertions
|
||||
checkConfigOutput '"ok"' config.check ./types.nix
|
||||
|
||||
# types.pathInStore
|
||||
checkConfigOutput '".*/store/0lz9p8xhf89kb1c1kk6jxrzskaiygnlh-bash-5.2-p15.drv"' config.pathInStore.ok1 ./types.nix
|
||||
checkConfigOutput '".*/store/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15"' config.pathInStore.ok2 ./types.nix
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ config, lib, ... }:
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (builtins)
|
||||
storeDir
|
||||
@@ -7,24 +7,10 @@ let
|
||||
types
|
||||
mkOption
|
||||
;
|
||||
|
||||
m = {
|
||||
options = {
|
||||
enableQux = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
check = mkOption { };
|
||||
# NB: types are tested in multiple places, so this list is far from exhaustive
|
||||
pathInStore = mkOption { type = types.lazyAttrsOf types.pathInStore; };
|
||||
attrNamesToTrue = mkOption { type = types.lazyAttrsOf types.attrNamesToTrue; };
|
||||
attrNamesToSet = mkOption { type = types.lazyAttrsOf types.attrNamesToSet; };
|
||||
attrNamesToSubmodules = mkOption { type = types.lazyAttrsOf (types.attrNamesToSubmodules m); };
|
||||
};
|
||||
config = {
|
||||
pathInStore.ok1 = "${storeDir}/0lz9p8xhf89kb1c1kk6jxrzskaiygnlh-bash-5.2-p15.drv";
|
||||
@@ -35,112 +21,5 @@ in
|
||||
pathInStore.bad3 = "${storeDir}/";
|
||||
pathInStore.bad4 = "${storeDir}/.links"; # technically true, but not reasonable
|
||||
pathInStore.bad5 = "/foo/bar";
|
||||
attrNamesToTrue.justNames = [
|
||||
"a"
|
||||
"b"
|
||||
"c"
|
||||
];
|
||||
attrNamesToTrue.mixed = lib.mkMerge [
|
||||
{
|
||||
a = true;
|
||||
b = false;
|
||||
}
|
||||
[ "c" ]
|
||||
];
|
||||
attrNamesToTrue.trivial = {
|
||||
a = true;
|
||||
b = false;
|
||||
c = true;
|
||||
};
|
||||
attrNamesToSet.justNames = [
|
||||
"a"
|
||||
"b"
|
||||
"c"
|
||||
];
|
||||
attrNamesToSet.mixed = lib.mkMerge [
|
||||
{
|
||||
a = { };
|
||||
b = { };
|
||||
}
|
||||
[ "c" ]
|
||||
];
|
||||
attrNamesToSet.trivial = {
|
||||
a = { };
|
||||
b = { };
|
||||
c = { };
|
||||
};
|
||||
attrNamesToSubmodules.justNames = [
|
||||
"a"
|
||||
"b"
|
||||
"c"
|
||||
];
|
||||
attrNamesToSubmodules.mixed = lib.mkMerge [
|
||||
{
|
||||
a = { };
|
||||
b.enableQux = true;
|
||||
}
|
||||
[ "c" ]
|
||||
];
|
||||
attrNamesToSubmodules.trivial = {
|
||||
a = { };
|
||||
b.enableQux = true;
|
||||
c = { };
|
||||
};
|
||||
check =
|
||||
assert
|
||||
config.attrNamesToTrue.justNames == {
|
||||
a = true;
|
||||
b = true;
|
||||
c = true;
|
||||
};
|
||||
assert
|
||||
config.attrNamesToTrue.mixed == {
|
||||
a = true;
|
||||
b = false;
|
||||
c = true;
|
||||
};
|
||||
assert
|
||||
config.attrNamesToTrue.trivial == {
|
||||
a = true;
|
||||
b = false;
|
||||
c = true;
|
||||
};
|
||||
assert
|
||||
config.attrNamesToSet.justNames == {
|
||||
a = { };
|
||||
b = { };
|
||||
c = { };
|
||||
};
|
||||
assert
|
||||
config.attrNamesToSet.mixed == {
|
||||
a = { };
|
||||
b = { };
|
||||
c = { };
|
||||
};
|
||||
assert
|
||||
config.attrNamesToSet.trivial == {
|
||||
a = { };
|
||||
b = { };
|
||||
c = { };
|
||||
};
|
||||
assert
|
||||
config.attrNamesToSubmodules.justNames == {
|
||||
a.enableQux = false;
|
||||
b.enableQux = false;
|
||||
c.enableQux = false;
|
||||
};
|
||||
assert
|
||||
config.attrNamesToSubmodules.mixed == {
|
||||
a.enableQux = false;
|
||||
b.enableQux = true;
|
||||
c.enableQux = false;
|
||||
};
|
||||
assert
|
||||
config.attrNamesToSubmodules.trivial == {
|
||||
a.enableQux = false;
|
||||
b.enableQux = true;
|
||||
c.enableQux = false;
|
||||
};
|
||||
"ok";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1456,23 +1456,6 @@ let
|
||||
nestedTypes.finalType = finalType;
|
||||
};
|
||||
|
||||
# Tests: lib/tests/modules/types.nix
|
||||
# Docs: nixos/doc/manual/development/option-types.section.md
|
||||
# Docs: https://nixos.org/manual/nixos/unstable/#sec-option-types-basic
|
||||
attrNamesToTrue = coercedTo (types.listOf types.str) (
|
||||
enabledList: lib.genAttrs enabledList (_attrName: true)
|
||||
) (types.attrsOf types.bool);
|
||||
|
||||
# Tests: lib/tests/modules.sh, lib/tests/modules/types.nix
|
||||
# Docs: nixos/doc/manual/development/option-types.section.md
|
||||
# Docs: https://nixos.org/manual/nixos/unstable/#sec-option-types-basic
|
||||
attrNamesToSet = attrNamesToSubmodules { };
|
||||
attrNamesToSubmodules =
|
||||
m:
|
||||
coercedTo (types.listOf types.str) (enabledList: lib.genAttrs enabledList (_attrName: { })) (
|
||||
types.attrsOf (types.submodule m)
|
||||
);
|
||||
|
||||
# Augment the given type with an additional type check function.
|
||||
addCheck = elemType: check: elemType // { check = x: elemType.check x && check x; };
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
More fields may be added in the future, however, in order to comply with GDPR this file should stay as minimal as possible.
|
||||
|
||||
When editing this file:
|
||||
* keep the list alphabetically sorted
|
||||
* keep the list alphabetically sorted, check with:
|
||||
nix-instantiate --eval maintainers/scripts/check-maintainers-sorted.nix
|
||||
* test the validity of the format with:
|
||||
nix-build lib/tests/maintainers.nix
|
||||
|
||||
@@ -536,12 +537,6 @@
|
||||
}
|
||||
];
|
||||
};
|
||||
Acconut = {
|
||||
email = "marius@transloadit.com";
|
||||
github = "Acconut";
|
||||
githubId = 1375043;
|
||||
name = "Marius Kleidl";
|
||||
};
|
||||
acesyde = {
|
||||
name = "Pierre-Emmanuel Mercier";
|
||||
email = "acesyde@gmail.com";
|
||||
@@ -1859,12 +1854,6 @@
|
||||
name = "Austin Lund";
|
||||
keys = [ { fingerprint = "7083 E268 4BFD 845F 2B84 9E74 B695 8918 ED23 32CE"; } ];
|
||||
};
|
||||
appleboblin = {
|
||||
email = "github@appleboblin.com";
|
||||
github = "appleboblin";
|
||||
githubId = 16847957;
|
||||
name = "Po-Hui Lin";
|
||||
};
|
||||
applejag = {
|
||||
email = "applejag.luminance905@passmail.com";
|
||||
github = "applejag";
|
||||
@@ -5813,7 +5802,7 @@
|
||||
email = "me@dblsaiko.net";
|
||||
github = "2xsaiko";
|
||||
githubId = 3987560;
|
||||
name = "Katalin Rebhan";
|
||||
name = "Marco Rebhan";
|
||||
};
|
||||
dbohdan = {
|
||||
email = "dbohdan@dbohdan.com";
|
||||
@@ -5852,11 +5841,6 @@
|
||||
githubId = 39909293;
|
||||
name = "Dominic Delabruere";
|
||||
};
|
||||
ddogfoodd = {
|
||||
github = "ddogfoodd";
|
||||
githubId = 58050402;
|
||||
name = "Jost Alemann";
|
||||
};
|
||||
dduan = {
|
||||
email = "daniel@duan.ca";
|
||||
github = "dduan";
|
||||
@@ -8564,12 +8548,6 @@
|
||||
githubId = 21362942;
|
||||
name = "Fugi";
|
||||
};
|
||||
fullmetalsheep = {
|
||||
email = "fullmetalsheep@proton.me";
|
||||
github = "fullmetalsheep";
|
||||
githubId = 23723926;
|
||||
name = "Dash R";
|
||||
};
|
||||
funkeleinhorn = {
|
||||
email = "git@funkeleinhorn.com";
|
||||
github = "funkeleinhorn";
|
||||
@@ -11369,13 +11347,6 @@
|
||||
githubId = 19669567;
|
||||
name = "Willy";
|
||||
};
|
||||
jennifgcrl = {
|
||||
email = "jennifer@jezh.me";
|
||||
github = "jennifgcrl";
|
||||
githubId = 110419915;
|
||||
matrix = "@fgcrl:matrix.org";
|
||||
name = "Jennifer Zhou";
|
||||
};
|
||||
jensbin = {
|
||||
email = "jensbin+git@pm.me";
|
||||
github = "jensbin";
|
||||
@@ -11420,17 +11391,6 @@
|
||||
githubId = 10786794;
|
||||
name = "Markus Hihn";
|
||||
};
|
||||
jess = {
|
||||
name = "Jessica";
|
||||
email = "jess+nix@jessie.cafe";
|
||||
github = "ttrssreal";
|
||||
githubId = 43591752;
|
||||
keys = [
|
||||
{
|
||||
fingerprint = "8092 3BD1 ECD0 E436 671D C8E9 BA33 5068 6C91 8606";
|
||||
}
|
||||
];
|
||||
};
|
||||
jessemoore = {
|
||||
email = "jesse@jessemoore.dev";
|
||||
github = "jesseDMoore1994";
|
||||
@@ -11622,12 +11582,6 @@
|
||||
githubId = 9866621;
|
||||
name = "Jack";
|
||||
};
|
||||
jkachmar = {
|
||||
email = "git@jkachmar.com";
|
||||
github = "jkachmar";
|
||||
githubId = 8461423;
|
||||
name = "jkachmar";
|
||||
};
|
||||
jkarlson = {
|
||||
email = "jekarlson@gmail.com";
|
||||
github = "ethorsoe";
|
||||
@@ -12715,12 +12669,6 @@
|
||||
githubId = 37185887;
|
||||
name = "Calvin Kim";
|
||||
};
|
||||
keegancsmith = {
|
||||
email = "keegan.csmith@gmail.com";
|
||||
name = "Keegan Carruthers-Smith";
|
||||
github = "keegancsmith";
|
||||
githubId = 187831;
|
||||
};
|
||||
keenanweaver = {
|
||||
email = "keenanweaver@protonmail.com";
|
||||
name = "Keenan Weaver";
|
||||
@@ -13469,12 +13417,6 @@
|
||||
githubId = 58425080;
|
||||
name = "Viktor Pocedulić";
|
||||
};
|
||||
kvz = {
|
||||
email = "kevin@transloadit.com";
|
||||
github = "kvz";
|
||||
githubId = 26752;
|
||||
name = "Kevin van Zonneveld";
|
||||
};
|
||||
kwaa = {
|
||||
name = "藍+85CD";
|
||||
email = "kwa@kwaa.dev";
|
||||
@@ -18544,12 +18486,6 @@
|
||||
github = "ovlach";
|
||||
githubId = 4405107;
|
||||
};
|
||||
owickstrom = {
|
||||
email = "oskar@wickstrom.tech";
|
||||
name = "Oskar Wickström";
|
||||
github = "owickstrom";
|
||||
githubId = 1464328;
|
||||
};
|
||||
oxalica = {
|
||||
email = "oxalicc@pm.me";
|
||||
github = "oxalica";
|
||||
@@ -24134,12 +24070,6 @@
|
||||
github = "tebriel";
|
||||
githubId = 821688;
|
||||
};
|
||||
tebro = {
|
||||
email = "git@tebro.simplelogin.com";
|
||||
name = "Richard Weber";
|
||||
github = "Tebro";
|
||||
githubId = 3861339;
|
||||
};
|
||||
techknowlogick = {
|
||||
email = "techknowlogick@gitea.com";
|
||||
github = "techknowlogick";
|
||||
@@ -26908,12 +26838,6 @@
|
||||
githubId = 15948162;
|
||||
name = "Yanni Papandreou";
|
||||
};
|
||||
yarekt = {
|
||||
name = "Yarek T";
|
||||
email = "yarekt+nixpkgs@gmail.com";
|
||||
github = "yarektyshchenko";
|
||||
githubId = 185304;
|
||||
};
|
||||
yarny = {
|
||||
github = "Yarny0";
|
||||
githubId = 41838844;
|
||||
|
||||
@@ -106,6 +106,7 @@ luazip,,,,,,
|
||||
lusc_luv,,,,,,
|
||||
lush.nvim,,,https://luarocks.org/dev,,,teto
|
||||
luuid,,,,20120509-2,,
|
||||
luv,,,,1.48.0-2,,
|
||||
lyaml,,,,,,lblasc
|
||||
lz.n,,,,,,mrcjkb
|
||||
lze,,,,,,birdee
|
||||
|
||||
|
@@ -843,7 +843,6 @@ with lib.maintainers;
|
||||
Gabriella439
|
||||
curran
|
||||
lf-
|
||||
jkachmar
|
||||
];
|
||||
scope = "Group registry for packages maintained by Mercury";
|
||||
shortName = "Mercury Employees";
|
||||
|
||||
@@ -135,79 +135,6 @@ merging is handled.
|
||||
problems.
|
||||
:::
|
||||
|
||||
`types.attrNamesToTrue`
|
||||
|
||||
: Either a list of attribute names, or an attribute set of
|
||||
booleans. A list will be coerced into an attribute set with those
|
||||
names, whose values are set to `true`. This is useful when it is
|
||||
convenient to be able to write definitions as a simple list, but
|
||||
still need to be able to override and disable individual values.
|
||||
|
||||
If configurability of the items is needed or `false` is not a
|
||||
desirable value, prefer `types.attrNamesToSubmodule` or `types.attrNamesToSet`.
|
||||
|
||||
::: {#ex-types-attrNamesToTrue .example}
|
||||
### `types.attrNamesToTrue`
|
||||
```
|
||||
{
|
||||
foo = [ "bar" ];
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
{
|
||||
foo.bar = true;
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
`types.attrNamesToSet`
|
||||
|
||||
: Either a list of attribute names, or an attribute set of `{ }`.
|
||||
This is similar to `types.attrNamesToTrue`, but `false` is not a permitted
|
||||
value. This is useful when that's not an expected value, and by using this
|
||||
type, you have the option to upgrade the type to `types.attrNamesToSubmodule`
|
||||
without breaking anything.
|
||||
|
||||
::: {#ex-types-attrNamesToSet .example}
|
||||
### `types.attrNamesToSet`
|
||||
```
|
||||
{
|
||||
foo = [ "bar" ];
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
{
|
||||
foo.bar = { };
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
`types.attrNamesToSubmodule` *`submodule`*
|
||||
|
||||
: Either a list of attribute names, or an attribute set of submodules.
|
||||
This is similar to `types.attrNamesToSet`, but the values are submodules
|
||||
instead of empty sets. This is useful when the values of this type are
|
||||
optionally configurable.
|
||||
|
||||
::: {#ex-types-attrNamesToSubmodule .example}
|
||||
### `types.attrNamesToSubmodule`
|
||||
```
|
||||
{
|
||||
foo = [ "bar" ];
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
{
|
||||
foo.bar = { };
|
||||
foo.baz.enableQux = true;
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
|
||||
`types.pkgs`
|
||||
|
||||
: A type for the top level Nixpkgs package set.
|
||||
|
||||
@@ -71,19 +71,10 @@ An SSH-based backdoor to log into machines can be enabled with
|
||||
{
|
||||
name = "…";
|
||||
nodes.machines = { /* … */ };
|
||||
interactive.sshBackdoor.enable = true;
|
||||
sshBackdoor.enable = true;
|
||||
}
|
||||
```
|
||||
|
||||
::: {.warning}
|
||||
Make sure to only enable the backdoor for interactive tests
|
||||
(i.e. by using `interactive.sshBackdoor.enable`)! This is the only
|
||||
supported configuration.
|
||||
|
||||
Running a test in a sandbox with this will fail because `/dev/vhost-vsock` isn't available
|
||||
in the sandbox.
|
||||
:::
|
||||
|
||||
This creates a [vsock socket](https://man7.org/linux/man-pages/man7/vsock.7.html)
|
||||
for each VM to log in with SSH. This configures root login with an empty password.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ up a VirtualBox guest, follow these instructions:
|
||||
|
||||
1. Base Memory Size: 768 MB or higher.
|
||||
|
||||
1. New Hard Disk of 10 GB or higher.
|
||||
1. New Hard Disk of 8 GB or higher.
|
||||
|
||||
1. Mount the CD-ROM with the NixOS ISO (by clicking on CD/DVD-ROM)
|
||||
|
||||
|
||||
@@ -1874,9 +1874,6 @@
|
||||
"test-opt-meta.platforms": [
|
||||
"index.html#test-opt-meta.platforms"
|
||||
],
|
||||
"test-opt-meta.hydraPlatforms": [
|
||||
"index.html#test-opt-meta.hydraPlatforms"
|
||||
],
|
||||
"test-opt-meta.timeout": [
|
||||
"index.html#test-opt-meta.timeout"
|
||||
],
|
||||
|
||||
@@ -22,28 +22,29 @@
|
||||
|
||||
- OpenSSH has been updated from 9.9p2 to 10.0p2, dropping support for DSA keys and adding a new `ssh-auth` binary to handle user authentication in a different address space from unauthenticated sessions. Additionally, we now enable a configure option by default that attempts to lock sshd into RAM to prevent it from being swapped out, which may improve performance if the system is under memory pressure. See the [full changelog](https://www.openwall.com/lists/oss-security/2025/04/09/1) for more details.
|
||||
|
||||
- GNOME has been updated to version 48.
|
||||
|
||||
- `decibels` music player is now installed by default. You can disable it using [](#opt-environment.gnome.excludePackages).
|
||||
- `gnome-shell-extensions` extension collection (which included GNOME Classic extensions, Apps Menu, and User Themes, among others) are no longer installed by default. You can install them again with [](#opt-services.xserver.desktopManager.gnome.sessionPath).
|
||||
- Option [](#opt-services.gnome.core-developer-tools.enable) now also installs `sysprof` and `d-spy`.
|
||||
- Option `services.gnome.core-utilities.enable` has been renamed to [](#opt-services.gnome.core-apps.enable).
|
||||
- `cantarell-fonts`, `source-code-pro` and `source-sans` fonts are no longer installed by default. They have been replaced by `adwaita-fonts`.
|
||||
|
||||
Refer to the [GNOME release notes](https://release.gnome.org/48/) for more details.
|
||||
|
||||
- The `intel` video driver for X.org (from the xf86-video-intel package, which was previously removed because it was non-functional) has been fixed and the driver has been re-introduced.
|
||||
|
||||
- The Mattermost module ([`services.mattermost`](#opt-services.mattermost.enable)) and packages (`mattermost` and `mmctl`) have been substantially updated:
|
||||
- [](#opt-services.mattermost.preferNixConfig) now defaults to true if you advance [](#opt-system.stateVersion) to 25.05. This means that if you have [](#opt-services.mattermost.mutableConfig) set, NixOS will override your settings to those that you define in the module. It is recommended to leave this at the default, even if you used a mutable config before, because it will ensure that your Mattermost data directories are correct. If you moved your data directories, you may want to review the module changes before upgrading.
|
||||
- Mattermost telemetry reporting is now disabled by default, though security update notifications are enabled. Look at [`services.mattermost.telemetry`](#opt-services.mattermost.telemetry.enableDiagnostics) for options to control this behavior.
|
||||
- `pkgs.mattermost` has been updated from 9.11 to 10.5 to track the latest extended support release, since 9.11 will become end-of-life during the lifetime of NixOS 25.05.
|
||||
- `pkgs.mattermostLatest` is now an option to track the latest (non-prerelease) Mattermost release. We test upgrade migrations from ESR releases (`pkgs.mattermost`) to `pkgs.mattermostLatest`.
|
||||
- The Mattermost frontend is now built from source and can be overridden.
|
||||
- Note that the Mattermost derivation containing both the webapp and server is now wrapped to allow them to be built independently, so overrides to both webapp and server look like `mattermost.overrideAttrs (prev: { webapp = prev.webapp.override { ... }; server = prev.server.override { ... }; })` now.
|
||||
- `services.mattermost.listenAddress` has been split into [](#opt-services.mattermost.host) and [](#opt-services.mattermost.port). If your `listenAddress` contained a port, you will need to edit your configuration.
|
||||
- Mattermost now supports peer authentication on both MySQL and Postgres database backends. Updating [](#opt-system.stateVersion) to 25.05 or later will result in peer authentication being used by default if the Mattermost server would otherwise be connecting to localhost. This is the recommended configuration.
|
||||
- The Mattermost module will produce eval warnings if a database password would end up in the Nix store, and recommend alternatives such as peer authentication or using the environment file.
|
||||
- We now support `mmctl` for Mattermost administration if both [](#opt-services.mattermost.socket.enable) and [](#opt-services.mattermost.socket.export) are set, which export the Mattermost control socket path into the system environment.
|
||||
- A new `pkgs.mattermost.buildPlugin` function has been added, which allows plugins to be built from source, including webapp frontends with a supported package-lock.json. See the Mattermost NixOS test and [manual](https://nixos.org/manual/nixpkgs/unstable/#sec-mattermost-plugins-build) for an example.
|
||||
- Note that the Mattermost module will create an account _without_ a well-known UID if the username differs from the default (`mattermost`). If you used Mattermost with a nonstandard username, you may want to review the module changes before upgrading.
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
## New Modules {#sec-release-25.05-new-modules}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- [AmneziaVPN](https://amnezia.org/en), a self-hostable open-source VPN client, is available in two variants:
|
||||
- [programs.amnezia-vpn](#opt-programs.amnezia-vpn.enable): a GUI client which can also deploy a VPN endpoint to a remote server
|
||||
- {option}`networking.wireguard` adds support for the [AmneziaWG](https://docs.amnezia.org/documentation/amnezia-wg/) variant of the protocol, featuring better masking against Deep Packet Inspection. The variant to be used is set per interface as `networking.wireguard.interfaces.<name>.type`, defaulting to wireguard.
|
||||
|
||||
- [AmneziaVPN](https://amnezia.org/en), an open-source VPN client, with a key feature that enables you to deploy your own VPN server on your server. Available as [programs.amnezia-vpn](#opt-programs.amnezia-vpn.enable).
|
||||
|
||||
- [Bazecor](https://github.com/Dygmalab/Bazecor), the graphical configurator for Dygma Products.
|
||||
|
||||
@@ -57,8 +58,6 @@
|
||||
|
||||
- [vwifi](https://github.com/Raizo62/vwifi), a Wi-Fi simulator daemon leveraging the `mac80211_hwsim` and `vhost_vsock` kernel modules for efficient simulation of multi-node Wi-Fi networks. Available as {option}`services.vwifi`.
|
||||
|
||||
- [Oncall](https://oncall.tools), a web-based calendar tool designed for scheduling and managing on-call shifts. Available as [services.oncall](options.html#opt-services.oncall).
|
||||
|
||||
- [Homer](https://homer-demo.netlify.app/), a very simple static homepage for your server. Available as [services.homer](options.html#opt-services.homer).
|
||||
|
||||
- [Ghidra](https://ghidra-sre.org/), a software reverse engineering (SRE) suite of tools. Available as [programs.ghidra](options.html#opt-programs.ghidra).
|
||||
@@ -300,8 +299,6 @@
|
||||
After you run ALTER EXTENSION, you must run [this SQL script](https://github.com/timescale/timescaledb-extras/blob/master/utils/2.15.X-fix_hypertable_foreign_keys.sql). For more details, see the following pull requests [#6797](https://github.com/timescale/timescaledb/pull/6797).
|
||||
PostgreSQL 13 is no longer supported in TimescaleDB v2.16.
|
||||
|
||||
- `networking.wireguard.enable = true` does not always add `wireguard-tools` to system packages anymore. Only when wireguard interfaces are configured, the backing implementation packages are added to system PATH.
|
||||
|
||||
- `virtualisation/azure-common.nix`'s filesystem and grub configurations have been moved to `virtualisation/azure-image.nix`. This makes `azure-common.nix` more generic so it could be used for users who generate Azure image using other methods (e.g. nixos-generators and disko). For existing users depending on these configurations, please also import `azure-image.nix`.
|
||||
|
||||
- `zammad` has had its support for MySQL removed, since it was never working correctly and is now deprecated upstream. Check the [migration guide](https://docs.zammad.org/en/latest/appendix/migrate-to-postgresql.html) for how to convert your database to PostgreSQL.
|
||||
@@ -340,10 +337,6 @@
|
||||
|
||||
- `python3Packages.jaeger-client` was removed because it was deprecated upstream. [OpenTelemetry](https://opentelemetry.io) is the recommended replacement.
|
||||
|
||||
- `rocmPackages_6` has been updated to ROCm 6.3.
|
||||
|
||||
- `rocmPackages_5` has been removed.
|
||||
|
||||
- `rocmPackages.rocm-thunk` has been removed and its functionality has been integrated with the ROCm CLR. Use `rocmPackages.clr` instead.
|
||||
|
||||
- `rocmPackages.clang-ocl` has been removed. [It was deprecated by AMD in 2023.](https://github.com/ROCm/clang-ocl)
|
||||
@@ -356,12 +349,6 @@
|
||||
Read the [release blog post](https://prometheus.io/blog/2024/11/14/prometheus-3-0/) and
|
||||
[migration guide](https://prometheus.io/docs/prometheus/3.1/migration/).
|
||||
|
||||
- The Mattermost module ([`services.mattermost`](#opt-services.mattermost.enable)) and packages (`mattermost` and `mmctl`) have been substantially updated:
|
||||
- `services.mattermost.listenAddress` has been split into [](#opt-services.mattermost.host) and [](#opt-services.mattermost.port). If your `listenAddress` contained a port, you will need to edit your configuration. This will be the only truly breaking change in this release for most configurations.
|
||||
- [](#opt-services.mattermost.preferNixConfig) now defaults to true if you advance [](#opt-system.stateVersion) to 25.05. This means that if you have [](#opt-services.mattermost.mutableConfig) set, NixOS will override settings set in the Admin Console to those that you define in the module configuration. It is recommended to leave this at the default, even if you used a fully mutable configuration before, because it will ensure that your Mattermost data directories are correct. If you moved your data directories, you may want to review the module changes before upgrading.
|
||||
- Mattermost now supports peer authentication on both MySQL and Postgres database backends. Updating [](#opt-system.stateVersion) to 25.05 or later will result in peer authentication being used by default if the Mattermost server would otherwise be connecting to localhost. This is the recommended configuration.
|
||||
- Note that the Mattermost module will create an account _without_ a well-known UID if the username differs from the default (`mattermost`). If you used Mattermost with a nonstandard username, you may want to review the module changes before upgrading.
|
||||
|
||||
- `kanata` was updated to v1.8.0, which introduces several breaking changes.
|
||||
See the release notes of
|
||||
[v1.7.0](https://github.com/jtroo/kanata/releases/tag/v1.7.0) and
|
||||
@@ -554,7 +541,7 @@
|
||||
|
||||
- All services that require a root certificate bundle now use the value of a new read-only option, `security.pki.caBundle`.
|
||||
|
||||
- hddfancontrol has been updated to major release 2. See the [migration guide](https://github.com/desbma/hddfancontrol/tree/master?tab=readme-ov-file#migrating-from-v1x), as there are breaking changes. The settings options have been modified to use an attrset, enabling configurations with multiple instances of the daemon running at once, eg, for two separate drive bays.
|
||||
- hddfancontrol has been updated to major release 2. See the [migration guide](https://github.com/desbma/hddfancontrol/tree/master?tab=readme-ov-file#migrating-from-v1x), as there are breaking changes.
|
||||
|
||||
- `nextcloud-news-updater` is unmaintained and was removed from nixpkgs.
|
||||
|
||||
@@ -616,15 +603,6 @@
|
||||
This allows packaging configuration to be overridden in a consistent manner by
|
||||
providing an alternative to `rec {}` syntax.
|
||||
|
||||
- [Mattermost](#opt-services.mattermost.enable), a self-hosted chat collaboration platform supporting calls, playbooks, and boards, has been updated. It now has multiple versions, disabled telemetry, and a native frontend build in nixpkgs, removing all upstream prebuilt blobs.
|
||||
- A new `pkgs.mattermost.buildPlugin` function has been added, which allows plugins to be built from source, including webapp frontends with a supported package-lock.json. See the Mattermost NixOS test and [manual](https://nixos.org/manual/nixpkgs/unstable/#sec-mattermost-plugins-build) for an example.
|
||||
- Mattermost telemetry reporting is now disabled by default, though security update notifications are enabled. Look at [`services.mattermost.telemetry`](#opt-services.mattermost.telemetry.enableDiagnostics) for options to control this behavior.
|
||||
- The Mattermost frontend is now built from source and can be overridden. Note that the Mattermost derivation containing both the webapp and server is now wrapped to allow them to be built independently, so overrides to both webapp and server look like `mattermost.overrideAttrs (prev: { webapp = prev.webapp.override { ... }; server = prev.server.override { ... }; })` now.
|
||||
- `pkgs.mattermost` has been updated from 9.11 to 10.5 to track the latest extended support release, since 9.11 will become end-of-life during the lifetime of NixOS 25.05.
|
||||
- `pkgs.mattermostLatest` is now an option to track the latest (non-prerelease) Mattermost release. We test upgrade migrations from ESR releases (`pkgs.mattermost`) to `pkgs.mattermostLatest`.
|
||||
- The Mattermost module will produce eval warnings if a database password would end up in the Nix store, and recommend alternatives such as peer authentication or using the environment file.
|
||||
- We now support `mmctl` for Mattermost administration if both [](#opt-services.mattermost.socket.enable) and [](#opt-services.mattermost.socket.export) are set, which export the Mattermost control socket path into the system environment.
|
||||
|
||||
- KDE Partition Manager `partitionmanager`'s support for ReiserFS is removed.
|
||||
ReiserFS has not been actively maintained for many years. It has been marked as obsolete since Linux 6.6, and
|
||||
[is removed](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c01f664e4ca210823b7594b50669bbd9b0a3c3b0)
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# Release 25.11 (2025.11/??) {#sec-release-25.11}
|
||||
|
||||
## Highlights {#sec-release-25.11-highlights}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
|
||||
## New Modules {#sec-release-25.11-new-modules}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
|
||||
## Backward Incompatibilities {#sec-release-25.11-incompatibilities}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
|
||||
## Other Notable Changes {#sec-release-25.11-notable-changes}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
@@ -9,13 +9,15 @@ let
|
||||
};
|
||||
runTest =
|
||||
module:
|
||||
(evalTest (
|
||||
{ config, ... }:
|
||||
{
|
||||
imports = [ module ];
|
||||
result = config.test;
|
||||
}
|
||||
)).config.result;
|
||||
# Infra issue: virtualization on darwin doesn't seem to work yet.
|
||||
lib.addMetaAttrs { hydraPlatforms = lib.platforms.linux; }
|
||||
(evalTest (
|
||||
{ config, ... }:
|
||||
{
|
||||
imports = [ module ];
|
||||
result = config.test;
|
||||
}
|
||||
)).config.result;
|
||||
|
||||
testModules = [
|
||||
./call-test.nix
|
||||
|
||||
@@ -1,61 +1,50 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) types mkOption literalMD;
|
||||
inherit (lib) types mkOption;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
meta = mkOption {
|
||||
meta = lib.mkOption {
|
||||
description = ''
|
||||
The [`meta`](https://nixos.org/manual/nixpkgs/stable/#chap-meta) attributes that will be set on the returned derivations.
|
||||
|
||||
Not all [`meta`](https://nixos.org/manual/nixpkgs/stable/#chap-meta) attributes are supported, but more can be added as desired.
|
||||
'';
|
||||
apply = lib.filterAttrs (k: v: v != null);
|
||||
type = types.submodule (
|
||||
{ config, ... }:
|
||||
{
|
||||
options = {
|
||||
maintainers = mkOption {
|
||||
type = types.listOf types.raw;
|
||||
default = [ ];
|
||||
description = ''
|
||||
The [list of maintainers](https://nixos.org/manual/nixpkgs/stable/#var-meta-maintainers) for this test.
|
||||
'';
|
||||
};
|
||||
timeout = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = 3600; # 1 hour
|
||||
description = ''
|
||||
The [{option}`test`](#test-opt-test)'s [`meta.timeout`](https://nixos.org/manual/nixpkgs/stable/#var-meta-timeout) in seconds.
|
||||
'';
|
||||
};
|
||||
broken = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Sets the [`meta.broken`](https://nixos.org/manual/nixpkgs/stable/#var-meta-broken) attribute on the [{option}`test`](#test-opt-test) derivation.
|
||||
'';
|
||||
};
|
||||
platforms = mkOption {
|
||||
type = types.listOf types.raw;
|
||||
default = lib.platforms.linux ++ lib.platforms.darwin;
|
||||
description = ''
|
||||
Sets the [`meta.platforms`](https://nixos.org/manual/nixpkgs/stable/#var-meta-platforms) attribute on the [{option}`test`](#test-opt-test) derivation.
|
||||
'';
|
||||
};
|
||||
hydraPlatforms = mkOption {
|
||||
type = types.listOf types.raw;
|
||||
# Ideally this would default to `platforms` again:
|
||||
# default = config.platforms;
|
||||
default = lib.platforms.linux;
|
||||
defaultText = literalMD "`lib.platforms.linux` only, as the `hydra.nixos.org` build farm does not currently support virtualisation on Darwin.";
|
||||
description = ''
|
||||
Sets the [`meta.hydraPlatforms`](https://nixos.org/manual/nixpkgs/stable/#var-meta-hydraPlatforms) attribute on the [{option}`test`](#test-opt-test) derivation.
|
||||
'';
|
||||
};
|
||||
type = types.submodule {
|
||||
options = {
|
||||
maintainers = lib.mkOption {
|
||||
type = types.listOf types.raw;
|
||||
default = [ ];
|
||||
description = ''
|
||||
The [list of maintainers](https://nixos.org/manual/nixpkgs/stable/#var-meta-maintainers) for this test.
|
||||
'';
|
||||
};
|
||||
}
|
||||
);
|
||||
timeout = lib.mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = 3600; # 1 hour
|
||||
description = ''
|
||||
The [{option}`test`](#test-opt-test)'s [`meta.timeout`](https://nixos.org/manual/nixpkgs/stable/#var-meta-timeout) in seconds.
|
||||
'';
|
||||
};
|
||||
broken = lib.mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Sets the [`meta.broken`](https://nixos.org/manual/nixpkgs/stable/#var-meta-broken) attribute on the [{option}`test`](#test-opt-test) derivation.
|
||||
'';
|
||||
};
|
||||
platforms = lib.mkOption {
|
||||
type = types.listOf types.raw;
|
||||
# darwin could be added, but it would add VM tests that don't work on Hydra.nixos.org (so far)
|
||||
# see https://github.com/NixOS/nixpkgs/pull/303597#issuecomment-2128782362
|
||||
default = lib.platforms.linux;
|
||||
description = ''
|
||||
Sets the [`meta.platforms`](https://nixos.org/manual/nixpkgs/stable/#var-meta-platforms) attribute on the [{option}`test`](#test-opt-test) derivation.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
|
||||
@@ -43,30 +43,27 @@ in
|
||||
};
|
||||
|
||||
config = {
|
||||
rawTestDerivation =
|
||||
assert lib.assertMsg (!config.sshBackdoor.enable)
|
||||
"The SSH backdoor is currently not supported for non-interactive testing! Please make sure to only set `interactive.sshBackdoor.enable = true;`!";
|
||||
hostPkgs.stdenv.mkDerivation {
|
||||
name = "vm-test-run-${config.name}";
|
||||
rawTestDerivation = hostPkgs.stdenv.mkDerivation {
|
||||
name = "vm-test-run-${config.name}";
|
||||
|
||||
requiredSystemFeatures =
|
||||
[ "nixos-test" ]
|
||||
++ lib.optionals hostPkgs.stdenv.hostPlatform.isLinux [ "kvm" ]
|
||||
++ lib.optionals hostPkgs.stdenv.hostPlatform.isDarwin [ "apple-virt" ];
|
||||
requiredSystemFeatures =
|
||||
[ "nixos-test" ]
|
||||
++ lib.optionals hostPkgs.stdenv.hostPlatform.isLinux [ "kvm" ]
|
||||
++ lib.optionals hostPkgs.stdenv.hostPlatform.isDarwin [ "apple-virt" ];
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p $out
|
||||
buildCommand = ''
|
||||
mkdir -p $out
|
||||
|
||||
# effectively mute the XMLLogger
|
||||
export LOGFILE=/dev/null
|
||||
# effectively mute the XMLLogger
|
||||
export LOGFILE=/dev/null
|
||||
|
||||
${config.driver}/bin/nixos-test-driver -o $out
|
||||
'';
|
||||
${config.driver}/bin/nixos-test-driver -o $out
|
||||
'';
|
||||
|
||||
passthru = config.passthru;
|
||||
passthru = config.passthru;
|
||||
|
||||
meta = config.meta;
|
||||
};
|
||||
meta = config.meta;
|
||||
};
|
||||
test = lib.lazyDerivation {
|
||||
# lazyDerivation improves performance when only passthru items and/or meta are used.
|
||||
derivation = config.rawTestDerivation;
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
baseName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "nixos-image-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}";
|
||||
defaultText = lib.literalExpression "nixos-image-\${config.system.nixos.label}-\${pkgs.stdenv.hostPlatform.system}";
|
||||
description = ''
|
||||
Basename of the image filename without any extension (e.g. `image_1`).
|
||||
'';
|
||||
@@ -30,7 +29,6 @@
|
||||
fileName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${config.image.baseName}.${config.image.extension}";
|
||||
defaultText = lib.literalExpression "\${config.image.baseName}.\${config.image.extension}";
|
||||
description = ''
|
||||
Filename of the image including all extensions (e.g `image_1.raw` or
|
||||
`image_1.raw.zst`).
|
||||
@@ -40,7 +38,6 @@
|
||||
filePath = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = config.image.fileName;
|
||||
defaultText = lib.literalExpression "config.image.fileName";
|
||||
description = ''
|
||||
Path of the image, relative to `$out` in `system.build.image`.
|
||||
While it defaults to `config.image.fileName`, it can be different for builders where
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
{
|
||||
config,
|
||||
options,
|
||||
pkgs,
|
||||
lib,
|
||||
utils,
|
||||
@@ -89,31 +88,6 @@ in
|
||||
{
|
||||
imports = [
|
||||
./repart-verity-store.nix
|
||||
./file-options.nix
|
||||
(lib.mkRenamedOptionModuleWith {
|
||||
sinceRelease = 2411;
|
||||
from = [
|
||||
"image"
|
||||
"repart"
|
||||
"imageFileBasename"
|
||||
];
|
||||
to = [
|
||||
"image"
|
||||
"baseName"
|
||||
];
|
||||
})
|
||||
(lib.mkRenamedOptionModuleWith {
|
||||
sinceRelease = 2411;
|
||||
from = [
|
||||
"image"
|
||||
"repart"
|
||||
"imageFile"
|
||||
];
|
||||
to = [
|
||||
"image"
|
||||
"fileName"
|
||||
];
|
||||
})
|
||||
];
|
||||
|
||||
options.image.repart = {
|
||||
@@ -121,7 +95,7 @@ in
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Name of the image.
|
||||
Name of the image.
|
||||
|
||||
If this option is unset but config.system.image.id is set,
|
||||
config.system.image.id is used as the default value.
|
||||
@@ -135,6 +109,23 @@ in
|
||||
description = "Version of the image";
|
||||
};
|
||||
|
||||
imageFileBasename = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
readOnly = true;
|
||||
description = ''
|
||||
Basename of the image filename without any extension (e.g. `image_1`).
|
||||
'';
|
||||
};
|
||||
|
||||
imageFile = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
readOnly = true;
|
||||
description = ''
|
||||
Filename of the image including all extensions (e.g `image_1.raw` or
|
||||
`image_1.raw.zst`).
|
||||
'';
|
||||
};
|
||||
|
||||
compression = {
|
||||
enable = lib.mkEnableOption "Image compression";
|
||||
|
||||
@@ -259,37 +250,55 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
assertions = lib.mkOption {
|
||||
type = options.assertions.type;
|
||||
default = [ ];
|
||||
internal = true;
|
||||
visible = false;
|
||||
description = ''
|
||||
Assertions only evaluated by the repart image, not by the system toplevel.
|
||||
'';
|
||||
};
|
||||
|
||||
warnings = lib.mkOption {
|
||||
type = options.warnings.type;
|
||||
default = [ ];
|
||||
internal = true;
|
||||
visible = false;
|
||||
description = ''
|
||||
Warnings only evaluated by the repart image, not by the system toplevel.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = {
|
||||
image.baseName =
|
||||
|
||||
assertions = lib.mapAttrsToList (
|
||||
fileName: partitionConfig:
|
||||
let
|
||||
inherit (partitionConfig) repartConfig;
|
||||
labelLength = builtins.stringLength repartConfig.Label;
|
||||
in
|
||||
{
|
||||
assertion = repartConfig ? Label -> GPTMaxLabelLength >= labelLength;
|
||||
message = ''
|
||||
The partition label '${repartConfig.Label}'
|
||||
defined for '${fileName}' is ${toString labelLength} characters long,
|
||||
but the maximum label length supported by UEFI is ${toString GPTMaxLabelLength}.
|
||||
'';
|
||||
}
|
||||
) cfg.partitions;
|
||||
|
||||
warnings = lib.filter (v: v != null) (
|
||||
lib.mapAttrsToList (
|
||||
fileName: partitionConfig:
|
||||
let
|
||||
inherit (partitionConfig) repartConfig;
|
||||
suggestedMaxLabelLength = GPTMaxLabelLength - 2;
|
||||
labelLength = builtins.stringLength repartConfig.Label;
|
||||
in
|
||||
if (repartConfig ? Label && labelLength >= suggestedMaxLabelLength) then
|
||||
''
|
||||
The partition label '${repartConfig.Label}'
|
||||
defined for '${fileName}' is ${toString labelLength} characters long.
|
||||
The suggested maximum label length is ${toString suggestedMaxLabelLength}.
|
||||
|
||||
If you use sytemd-sysupdate style A/B updates, this might
|
||||
not leave enough space to increment the version number included in
|
||||
the label in a future release. For example, if your label is
|
||||
${toString GPTMaxLabelLength} characters long (the maximum enforced by UEFI) and
|
||||
you're at version 9, you cannot increment this to 10.
|
||||
''
|
||||
else
|
||||
null
|
||||
) cfg.partitions
|
||||
);
|
||||
|
||||
image.repart =
|
||||
let
|
||||
version = config.image.repart.version;
|
||||
versionInfix = if version != null then "_${version}" else "";
|
||||
in
|
||||
cfg.name + versionInfix;
|
||||
image.extension =
|
||||
let
|
||||
compressionSuffix =
|
||||
lib.optionalString cfg.compression.enable
|
||||
{
|
||||
@@ -299,11 +308,6 @@ in
|
||||
}
|
||||
."${cfg.compression.algorithm}";
|
||||
|
||||
in
|
||||
"raw" + compressionSuffix;
|
||||
|
||||
image.repart =
|
||||
let
|
||||
makeClosure = paths: pkgs.closureInfo { rootPaths = paths; };
|
||||
|
||||
# Add the closure of the provided Nix store paths to cfg.partitions so
|
||||
@@ -317,6 +321,9 @@ in
|
||||
in
|
||||
{
|
||||
name = lib.mkIf (config.system.image.id != null) (lib.mkOptionDefault config.system.image.id);
|
||||
imageFileBasename = cfg.name + versionInfix;
|
||||
imageFile = cfg.imageFileBasename + ".raw" + compressionSuffix;
|
||||
|
||||
compression = {
|
||||
# Generally default to slightly faster than default compression
|
||||
# levels under the assumption that most of the building will be done
|
||||
@@ -332,47 +339,6 @@ in
|
||||
};
|
||||
|
||||
finalPartitions = lib.mapAttrs addClosure cfg.partitions;
|
||||
|
||||
assertions = lib.mapAttrsToList (
|
||||
fileName: partitionConfig:
|
||||
let
|
||||
inherit (partitionConfig) repartConfig;
|
||||
labelLength = builtins.stringLength repartConfig.Label;
|
||||
in
|
||||
{
|
||||
assertion = repartConfig ? Label -> GPTMaxLabelLength >= labelLength;
|
||||
message = ''
|
||||
The partition label '${repartConfig.Label}'
|
||||
defined for '${fileName}' is ${toString labelLength} characters long,
|
||||
but the maximum label length supported by UEFI is ${toString GPTMaxLabelLength}.
|
||||
'';
|
||||
}
|
||||
) cfg.partitions;
|
||||
|
||||
warnings = lib.filter (v: v != null) (
|
||||
lib.mapAttrsToList (
|
||||
fileName: partitionConfig:
|
||||
let
|
||||
inherit (partitionConfig) repartConfig;
|
||||
suggestedMaxLabelLength = GPTMaxLabelLength - 2;
|
||||
labelLength = builtins.stringLength repartConfig.Label;
|
||||
in
|
||||
if (repartConfig ? Label && labelLength >= suggestedMaxLabelLength) then
|
||||
''
|
||||
The partition label '${repartConfig.Label}'
|
||||
defined for '${fileName}' is ${toString labelLength} characters long.
|
||||
The suggested maximum label length is ${toString suggestedMaxLabelLength}.
|
||||
|
||||
If you use sytemd-sysupdate style A/B updates, this might
|
||||
not leave enough space to increment the version number included in
|
||||
the label in a future release. For example, if your label is
|
||||
${toString GPTMaxLabelLength} characters long (the maximum enforced by UEFI) and
|
||||
you're at version 9, you cannot increment this to 10.
|
||||
''
|
||||
else
|
||||
null
|
||||
) cfg.partitions
|
||||
);
|
||||
};
|
||||
|
||||
system.build.image =
|
||||
@@ -388,22 +354,21 @@ in
|
||||
);
|
||||
|
||||
mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions;
|
||||
val = pkgs.callPackage ./repart-image.nix {
|
||||
systemd = cfg.package;
|
||||
imageFileBasename = config.image.baseName;
|
||||
inherit (cfg)
|
||||
name
|
||||
version
|
||||
compression
|
||||
split
|
||||
seed
|
||||
sectorSize
|
||||
finalPartitions
|
||||
;
|
||||
inherit fileSystems definitionsDirectory mkfsEnv;
|
||||
};
|
||||
in
|
||||
lib.asserts.checkAssertWarn cfg.assertions cfg.warnings val;
|
||||
pkgs.callPackage ./repart-image.nix {
|
||||
systemd = cfg.package;
|
||||
inherit (cfg)
|
||||
name
|
||||
version
|
||||
imageFileBasename
|
||||
compression
|
||||
split
|
||||
seed
|
||||
sectorSize
|
||||
finalPartitions
|
||||
;
|
||||
inherit fileSystems definitionsDirectory mkfsEnv;
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
|
||||
@@ -160,7 +160,6 @@
|
||||
./programs/arp-scan.nix
|
||||
./programs/atop.nix
|
||||
./programs/ausweisapp.nix
|
||||
./programs/autoenv.nix
|
||||
./programs/autojump.nix
|
||||
./programs/bandwhich.nix
|
||||
./programs/bash-my-aws.nix
|
||||
@@ -187,6 +186,7 @@
|
||||
./programs/corefreq.nix
|
||||
./programs/cpu-energy-meter.nix
|
||||
./programs/criu.nix
|
||||
./programs/darling.nix
|
||||
./programs/dconf.nix
|
||||
./programs/digitalbitbox/default.nix
|
||||
./programs/direnv.nix
|
||||
@@ -1076,7 +1076,6 @@
|
||||
./services/networking/bitlbee.nix
|
||||
./services/networking/blockbook-frontend.nix
|
||||
./services/networking/blocky.nix
|
||||
./services/networking/cato-client.nix
|
||||
./services/networking/centrifugo.nix
|
||||
./services/networking/cgit.nix
|
||||
./services/networking/charybdis.nix
|
||||
@@ -1609,7 +1608,6 @@
|
||||
./services/web-apps/nostr-rs-relay.nix
|
||||
./services/web-apps/ocis.nix
|
||||
./services/web-apps/olivetin.nix
|
||||
./services/web-apps/oncall.nix
|
||||
./services/web-apps/onlyoffice.nix
|
||||
./services/web-apps/open-web-calendar.nix
|
||||
./services/web-apps/openvscode-server.nix
|
||||
|
||||
@@ -163,7 +163,7 @@ in
|
||||
|
||||
hostPkgs = config.virtualisation.host.pkgs;
|
||||
|
||||
add-keys = hostPkgs.writeShellScriptBin "add-keys" (
|
||||
script = hostPkgs.writeShellScriptBin "create-builder" (
|
||||
''
|
||||
set -euo pipefail
|
||||
''
|
||||
@@ -191,22 +191,10 @@ in
|
||||
if ! ${hostPkgs.diffutils}/bin/cmp "''${PUBLIC_KEY}" ${publicKey}; then
|
||||
(set -x; sudo --reset-timestamp ${installCredentials} "''${KEYS}")
|
||||
fi
|
||||
KEYS="$(${hostPkgs.nix}/bin/nix-store --add "$KEYS")" ${lib.getExe config.system.build.vm}
|
||||
''
|
||||
);
|
||||
|
||||
run-builder = hostPkgs.writeShellScriptBin "run-builder" (''
|
||||
set -euo pipefail
|
||||
KEYS="''${KEYS:-./keys}"
|
||||
KEYS="$(${hostPkgs.nix}/bin/nix-store --add "$KEYS")" ${lib.getExe config.system.build.vm}
|
||||
'');
|
||||
|
||||
script = hostPkgs.writeShellScriptBin "create-builder" (''
|
||||
set -euo pipefail
|
||||
export KEYS="''${KEYS:-./keys}"
|
||||
${lib.getExe add-keys}
|
||||
${lib.getExe run-builder}
|
||||
'');
|
||||
|
||||
in
|
||||
script.overrideAttrs (old: {
|
||||
pos = __curPos; # sets meta.position to point here; see script binding above for package definition
|
||||
@@ -217,8 +205,6 @@ in
|
||||
# Let users in the repl inspect the config
|
||||
nixosConfig = config;
|
||||
nixosOptions = options;
|
||||
|
||||
inherit add-keys run-builder;
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
27
nixos/modules/programs/darling.nix
Normal file
27
nixos/modules/programs/darling.nix
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.programs.darling;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
programs.darling = {
|
||||
enable = lib.mkEnableOption "Darling, a Darwin/macOS compatibility layer for Linux";
|
||||
package = lib.mkPackageOption pkgs "darling" { };
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
security.wrappers.darling = {
|
||||
source = lib.getExe cfg.package;
|
||||
owner = "root";
|
||||
group = "root";
|
||||
setuid = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -28,7 +28,6 @@
|
||||
description = "Network manager applet";
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
partOf = [ "graphical-session.target" ];
|
||||
after = [ "graphical-session.target" ];
|
||||
serviceConfig.ExecStart = "${pkgs.networkmanagerapplet}/bin/nm-applet ${lib.optionalString config.programs.nm-applet.indicator "--indicator"}";
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
let
|
||||
cfg = config.services.speechd;
|
||||
inherit (lib)
|
||||
getExe
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkPackageOption
|
||||
@@ -20,12 +21,12 @@ in
|
||||
package = mkPackageOption pkgs "speechd" { };
|
||||
};
|
||||
|
||||
# FIXME: speechd 0.12 (or whatever the next version is)
|
||||
# will support socket activation, so switch to that once it's out.
|
||||
config = mkIf cfg.enable {
|
||||
environment = {
|
||||
systemPackages = [ cfg.package ];
|
||||
sessionVariables.SPEECHD_CMD = getExe cfg.package;
|
||||
};
|
||||
systemd.packages = [ cfg.package ];
|
||||
# have to set `wantedBy` since `systemd.packages` ignores `[Install]`
|
||||
systemd.user.sockets.speech-dispatcher.wantedBy = [ "sockets.target" ];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ in
|
||||
options.services.oxidized = {
|
||||
enable = lib.mkEnableOption "the oxidized configuration backup service";
|
||||
|
||||
package = lib.mkPackageOption pkgs "oxidized" { };
|
||||
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "oxidized";
|
||||
@@ -72,8 +70,7 @@ in
|
||||
};
|
||||
|
||||
routerDB = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
type = lib.types.path;
|
||||
example = lib.literalExpression ''
|
||||
pkgs.writeText "oxidized-router.db" '''
|
||||
hostname-sw1:powerconnect:username1:password2
|
||||
@@ -97,57 +94,18 @@ in
|
||||
isSystemUser = true;
|
||||
};
|
||||
|
||||
systemd.tmpfiles.settings."10-oxidized" =
|
||||
{
|
||||
"${cfg.dataDir}" = {
|
||||
d = {
|
||||
mode = "0750";
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
};
|
||||
};
|
||||
|
||||
"${cfg.dataDir}/.config" = {
|
||||
d = {
|
||||
mode = "0750";
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
};
|
||||
};
|
||||
|
||||
"${cfg.dataDir}/.config/oxidized" = {
|
||||
d = {
|
||||
mode = "0750";
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
};
|
||||
};
|
||||
|
||||
"${cfg.dataDir}/.config/oxidized/config" = {
|
||||
L = {
|
||||
argument = "${cfg.configFile}";
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
// lib.optionalAttrs (cfg.routerDB != null) {
|
||||
"${cfg.dataDir}/.config/oxidized/router.db" = {
|
||||
L = {
|
||||
argument = "${cfg.routerDB}";
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.oxidized = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
preStart = ''
|
||||
mkdir -p ${cfg.dataDir}/.config/oxidized
|
||||
ln -f -s ${cfg.routerDB} ${cfg.dataDir}/.config/oxidized/router.db
|
||||
ln -f -s ${cfg.configFile} ${cfg.dataDir}/.config/oxidized/config
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = lib.getExe cfg.package;
|
||||
ExecStart = "${pkgs.oxidized}/bin/oxidized";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
UMask = "0077";
|
||||
|
||||
@@ -69,9 +69,6 @@ in
|
||||
description = "Music Assistant";
|
||||
documentation = [ "https://music-assistant.io" ];
|
||||
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
environment = {
|
||||
|
||||
@@ -18,162 +18,64 @@ in
|
||||
"hddfancontrol"
|
||||
"smartctl"
|
||||
] "Smartctl is now automatically used when necessary, which makes this option redundant")
|
||||
(lib.mkRemovedOptionModule [
|
||||
"services"
|
||||
"hddfancontrol"
|
||||
"disks"
|
||||
] "Disks should now be specified per hddfancontrol instance in its attrset")
|
||||
(lib.mkRemovedOptionModule [
|
||||
"services"
|
||||
"hddfancontrol"
|
||||
"pwmPaths"
|
||||
] "Pwm Paths should now be specified per hddfancontrol instance in its attrset")
|
||||
(lib.mkRemovedOptionModule [
|
||||
"services"
|
||||
"hddfancontrol"
|
||||
"logVerbosity"
|
||||
] "Log Verbosity should now be specified per hddfancontrol instance in its attrset")
|
||||
(lib.mkRemovedOptionModule [
|
||||
"services"
|
||||
"hddfancontrol"
|
||||
"extraArgs"
|
||||
] "Extra Args should now be specified per hddfancontrol instance in its attrset")
|
||||
];
|
||||
|
||||
options = {
|
||||
services.hddfancontrol.enable = lib.mkEnableOption "hddfancontrol daemon";
|
||||
|
||||
services.hddfancontrol.settings = lib.mkOption {
|
||||
type = lib.types.attrsWith {
|
||||
placeholder = "drive-bay-name";
|
||||
elemType = (
|
||||
lib.types.submodule (
|
||||
{ ... }:
|
||||
{
|
||||
options = {
|
||||
disks = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.path;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Drive(s) to get temperature from
|
||||
'';
|
||||
example = [ "/dev/sda" ];
|
||||
};
|
||||
|
||||
pwmPaths = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.path;
|
||||
default = [ ];
|
||||
description = ''
|
||||
PWM filepath(s) to control fan speed (under /sys), followed by initial and fan-stop PWM values
|
||||
'';
|
||||
example = [ "/sys/class/hwmon/hwmon2/pwm1:30:10" ];
|
||||
};
|
||||
|
||||
logVerbosity = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"TRACE"
|
||||
"DEBUG"
|
||||
"INFO"
|
||||
"WARN"
|
||||
"ERROR"
|
||||
];
|
||||
default = "INFO";
|
||||
description = ''
|
||||
Verbosity of the log level
|
||||
'';
|
||||
};
|
||||
|
||||
extraArgs = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Extra commandline arguments for hddfancontrol
|
||||
'';
|
||||
example = [
|
||||
"--min-fan-speed-prct=10"
|
||||
"--interval=1min"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
default = { };
|
||||
services.hddfancontrol.disks = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.path;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Parameter-sets for each instance of hddfancontrol.
|
||||
Drive(s) to get temperature from
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
harddrives = {
|
||||
disks = [
|
||||
"/dev/sda"
|
||||
"/dev/sdb"
|
||||
"/dev/sdc"
|
||||
];
|
||||
pwmPaths = [
|
||||
"/sys/class/hwmon/hwmon1/pwm1:25:10"
|
||||
];
|
||||
logVerbosity = "DEBUG";
|
||||
};
|
||||
ssddrives = {
|
||||
disks = [
|
||||
"/dev/sdd"
|
||||
"/dev/sde"
|
||||
"/dev/sdf"
|
||||
];
|
||||
pwmPaths = [
|
||||
"/sys/class/hwmon/hwmon1/pwm2:25:10"
|
||||
];
|
||||
extraArgs = [
|
||||
"--interval=30s"
|
||||
];
|
||||
};
|
||||
}
|
||||
example = [ "/dev/sda" ];
|
||||
};
|
||||
|
||||
services.hddfancontrol.pwmPaths = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.path;
|
||||
default = [ ];
|
||||
description = ''
|
||||
PWM filepath(s) to control fan speed (under /sys), followed by initial and fan-stop PWM values
|
||||
'';
|
||||
example = [ "/sys/class/hwmon/hwmon2/pwm1:30:10" ];
|
||||
};
|
||||
|
||||
services.hddfancontrol.logVerbosity = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"TRACE"
|
||||
"DEBUG"
|
||||
"INFO"
|
||||
"WARN"
|
||||
"ERROR"
|
||||
];
|
||||
default = "INFO";
|
||||
description = ''
|
||||
Verbosity of the log level
|
||||
'';
|
||||
};
|
||||
|
||||
services.hddfancontrol.extraArgs = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Extra commandline arguments for hddfancontrol
|
||||
'';
|
||||
example = [
|
||||
"--min-fan-speed-prct=10"
|
||||
"--interval=1min"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable (
|
||||
let
|
||||
args =
|
||||
cnf:
|
||||
lib.concatLists [
|
||||
[ "-d" ]
|
||||
cnf.disks
|
||||
[ "-p" ]
|
||||
cnf.pwmPaths
|
||||
cnf.extraArgs
|
||||
];
|
||||
|
||||
createService = cnf: {
|
||||
description = "HDD fan control";
|
||||
documentation = [ "man:hddfancontrol(1)" ];
|
||||
after = [ "hddtemp.service" ];
|
||||
wants = [ "hddtemp.service" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${lib.getExe pkgs.hddfancontrol} -v ${cnf.logVerbosity} daemon ${lib.escapeShellArgs (args cnf)}";
|
||||
|
||||
CPUSchedulingPolicy = "rr";
|
||||
CPUSchedulingPriority = 49;
|
||||
|
||||
ProtectSystem = "strict";
|
||||
PrivateTmp = true;
|
||||
ProtectHome = true;
|
||||
SystemCallArchitectures = "native";
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
services = lib.attrsets.mergeAttrsList [
|
||||
(lib.attrsets.mapAttrs' (
|
||||
name: cnf: lib.nameValuePair "hddfancontrol-${name}" (createService cnf)
|
||||
) cfg.settings)
|
||||
{
|
||||
"hddfancontrol".enable = false;
|
||||
}
|
||||
args = lib.concatLists [
|
||||
[ "-d" ]
|
||||
cfg.disks
|
||||
[ "-p" ]
|
||||
cfg.pwmPaths
|
||||
cfg.extraArgs
|
||||
];
|
||||
in
|
||||
{
|
||||
@@ -181,10 +83,16 @@ in
|
||||
|
||||
hardware.sensor.hddtemp = {
|
||||
enable = true;
|
||||
drives = lib.lists.flatten (lib.attrsets.catAttrs "disks" (lib.attrsets.attrValues cfg.settings));
|
||||
drives = cfg.disks;
|
||||
};
|
||||
|
||||
systemd.services = services;
|
||||
systemd.services.hddfancontrol = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
environment = {
|
||||
HDDFANCONTROL_LOG_LEVEL = cfg.logVerbosity;
|
||||
HDDFANCONTROL_DAEMON_ARGS = lib.escapeShellArgs args;
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -596,9 +596,7 @@ in
|
||||
${pkgs.envsubst}/bin/envsubst -i ${configJson} -o ${cfg.dataDir}/config.json
|
||||
export PHPRC=${phpIni}
|
||||
|
||||
INIT=false
|
||||
if [[ ! -s ${cfg.dataDir}/.env ]]; then
|
||||
INIT=true
|
||||
# init .env file
|
||||
echo "APP_KEY=" > ${cfg.dataDir}/.env
|
||||
${artisanWrapper}/bin/librenms-artisan key:generate --ansi
|
||||
@@ -657,10 +655,6 @@ in
|
||||
echo "${package.version}" > ${cfg.dataDir}/version
|
||||
fi
|
||||
|
||||
if [[ $INIT == "true" ]]; then
|
||||
${artisanWrapper}/bin/librenms-artisan db:seed --force --no-interaction
|
||||
fi
|
||||
|
||||
# regenerate cache if package has changed
|
||||
if [[ $OLD_PACKAGE != "${package}" ]]; then
|
||||
${artisanWrapper}/bin/librenms-artisan view:clear
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkIf mkEnableOption mkPackageOption;
|
||||
|
||||
cfg = config.services.cato-client;
|
||||
in
|
||||
{
|
||||
options.services.cato-client = {
|
||||
enable = mkEnableOption "cato-client service";
|
||||
package = mkPackageOption pkgs "cato-client" { };
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
users = {
|
||||
groups.cato-client = { };
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
cfg.package
|
||||
];
|
||||
|
||||
systemd.services.cato-client = {
|
||||
enable = true;
|
||||
description = "Cato Networks Linux client - connects tunnel to Cato cloud";
|
||||
after = [ "network.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = "root"; # Note: daemon runs as root, tools sticky to group
|
||||
Group = "cato-client";
|
||||
ExecStart = "${cfg.package}/bin/cato-clientd systemd";
|
||||
WorkingDirectory = "${cfg.package}";
|
||||
Restart = "always";
|
||||
|
||||
# Cato client seems to do the following:
|
||||
# - Look in each user's ~/.cato/ for configuration and keys
|
||||
# - Write to /var/log/cato-client.log
|
||||
# - Create and use sockets /var/run/cato-sdp.i, /var/run/cato-sdp.o
|
||||
# - Read and Write to /opt/cato/ for runtime settings
|
||||
# - Read /etc/systemd/resolved.conf (but fine if fails)
|
||||
# - Restart systemd-resolved (also fine if doesn't exist)
|
||||
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectSystem = true;
|
||||
};
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
# set up Security wrapper Same as inteded in deb post install
|
||||
security.wrappers.cato-clientd = {
|
||||
source = "${cfg.package}/bin/cato-clientd";
|
||||
owner = "root";
|
||||
group = "cato-client";
|
||||
permissions = "u+rwx,g+rwx"; # 770
|
||||
setgid = true;
|
||||
};
|
||||
|
||||
security.wrappers.cato-sdp = {
|
||||
source = "${cfg.package}/bin/cato-sdp";
|
||||
owner = "root";
|
||||
group = "cato-client";
|
||||
permissions = "u+rwx,g+rx,a+rx"; # 755
|
||||
setgid = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -369,7 +369,7 @@ in
|
||||
RuntimeDirectoryMode = "0400";
|
||||
LoadCredential = [
|
||||
"credentials.json:${tunnel.credentialsFile}"
|
||||
] ++ (lib.optional (certFile != null) "cert.pem:${certFile}");
|
||||
] ++ (lib.optional (certFile != null) "cert.pem:certFile");
|
||||
|
||||
ExecStart = "${cfg.package}/bin/cloudflared tunnel --config=${mkConfigFile} --no-autoupdate run";
|
||||
Restart = "on-failure";
|
||||
|
||||
@@ -164,7 +164,7 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
auto_update_enabled = lib.mkOption {
|
||||
auto_update_enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
@@ -493,11 +493,7 @@ in
|
||||
imports = with lib; [
|
||||
(mkRenamedOptionModule
|
||||
[ "services" "headscale" "derp" "autoUpdate" ]
|
||||
[ "services" "headscale" "settings" "derp" "auto_update_enabled" ]
|
||||
)
|
||||
(mkRenamedOptionModule
|
||||
[ "services" "headscale" "derp" "auto_update_enable" ]
|
||||
[ "services" "headscale" "settings" "derp" "auto_update_enabled" ]
|
||||
[ "services" "headscale" "settings" "derp" "auto_update_enable" ]
|
||||
)
|
||||
(mkRenamedOptionModule
|
||||
[ "services" "headscale" "derp" "paths" ]
|
||||
|
||||
@@ -55,19 +55,10 @@ let
|
||||
were removed. Please use, respectively, {rescanIntervalS,fsWatcherEnabled,fsWatcherDelayS} instead.
|
||||
''
|
||||
{
|
||||
devices =
|
||||
let
|
||||
folderDevices = folder.devices;
|
||||
in
|
||||
map (
|
||||
device:
|
||||
if builtins.isString device then
|
||||
{ deviceId = cfg.settings.devices.${device}.id; }
|
||||
else if builtins.isAttrs device then
|
||||
{ deviceId = cfg.settings.devices.${device.name}.id; } // device
|
||||
else
|
||||
throw "Invalid type for devices in folder '${folderName}'; expected list or attrset."
|
||||
) folderDevices;
|
||||
devices = map (
|
||||
device:
|
||||
if builtins.isString device then { deviceId = cfg.settings.devices.${device}.id; } else device
|
||||
) folder.devices;
|
||||
}
|
||||
) (filterAttrs (_: folder: folder.enable) cfg.settings.folders);
|
||||
|
||||
@@ -137,79 +128,9 @@ let
|
||||
# don't exist in the array given. That's why we use here `POST`, and
|
||||
# only if s.override == true then we DELETE the relevant folders
|
||||
# afterwards.
|
||||
(map (
|
||||
new_cfg:
|
||||
let
|
||||
jsonPreSecretsFile = pkgs.writeTextFile {
|
||||
name = "${conf_type}-${new_cfg.id}-conf-pre-secrets.json";
|
||||
text = builtins.toJSON new_cfg;
|
||||
};
|
||||
injectSecretsJqCmd =
|
||||
{
|
||||
# There are no secrets in `devs`, so no massaging needed.
|
||||
"devs" = "${jq} .";
|
||||
"dirs" =
|
||||
let
|
||||
folder = new_cfg;
|
||||
devicesWithSecrets = lib.pipe folder.devices [
|
||||
(lib.filter (device: (builtins.isAttrs device) && device ? encryptionPasswordFile))
|
||||
(map (device: {
|
||||
deviceId = device.deviceId;
|
||||
variableName = "secret_${builtins.hashString "sha256" device.encryptionPasswordFile}";
|
||||
secretPath = device.encryptionPasswordFile;
|
||||
}))
|
||||
];
|
||||
# At this point, `jsonPreSecretsFile` looks something like this:
|
||||
#
|
||||
# {
|
||||
# ...,
|
||||
# "devices": [
|
||||
# {
|
||||
# "deviceId": "id1",
|
||||
# "encryptionPasswordFile": "/etc/bar-encryption-password",
|
||||
# "name": "..."
|
||||
# }
|
||||
# ],
|
||||
# }
|
||||
#
|
||||
# We now generate a `jq` command that can replace those
|
||||
# `encryptionPasswordFile`s with `encryptionPassword`.
|
||||
# The `jq` command ends up looking like this:
|
||||
#
|
||||
# jq --rawfile secret_DEADBEEF /etc/bar-encryption-password '
|
||||
# .devices[] |= (
|
||||
# if .deviceId == "id1" then
|
||||
# del(.encryptionPasswordFile) |
|
||||
# .encryptionPassword = $secret_DEADBEEF
|
||||
# else
|
||||
# .
|
||||
# end
|
||||
# )
|
||||
# '
|
||||
jqUpdates = map (device: ''
|
||||
.devices[] |= (
|
||||
if .deviceId == "${device.deviceId}" then
|
||||
del(.encryptionPasswordFile) |
|
||||
.encryptionPassword = ''$${device.variableName}
|
||||
else
|
||||
.
|
||||
end
|
||||
)
|
||||
'') devicesWithSecrets;
|
||||
jqRawFiles = map (
|
||||
device: "--rawfile ${device.variableName} ${lib.escapeShellArg device.secretPath}"
|
||||
) devicesWithSecrets;
|
||||
in
|
||||
"${jq} ${lib.concatStringsSep " " jqRawFiles} ${
|
||||
lib.escapeShellArg (lib.concatStringsSep "|" ([ "." ] ++ jqUpdates))
|
||||
}";
|
||||
}
|
||||
.${conf_type};
|
||||
in
|
||||
''
|
||||
${injectSecretsJqCmd} ${jsonPreSecretsFile} | curl --json @- -X POST ${s.baseAddress}
|
||||
''
|
||||
))
|
||||
(map (new_cfg: ''
|
||||
curl -d ${lib.escapeShellArg (builtins.toJSON new_cfg)} -X POST ${s.baseAddress}
|
||||
''))
|
||||
(lib.concatStringsSep "\n")
|
||||
]
|
||||
/*
|
||||
@@ -517,48 +438,11 @@ in
|
||||
};
|
||||
|
||||
devices = mkOption {
|
||||
type = types.listOf (
|
||||
types.oneOf [
|
||||
types.str
|
||||
(types.submodule (
|
||||
{ ... }:
|
||||
{
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
The name of a device defined in the
|
||||
[devices](#opt-services.syncthing.settings.devices)
|
||||
option.
|
||||
'';
|
||||
};
|
||||
encryptionPasswordFile = mkOption {
|
||||
type = types.nullOr (
|
||||
types.pathWith {
|
||||
inStore = false;
|
||||
absolute = true;
|
||||
}
|
||||
);
|
||||
default = null;
|
||||
description = ''
|
||||
Path to encryption password. If set, the file will be read during
|
||||
service activation, without being embedded in derivation.
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
))
|
||||
]
|
||||
);
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
The devices this folder should be shared with. Each device must
|
||||
be defined in the [devices](#opt-services.syncthing.settings.devices) option.
|
||||
|
||||
A list of either strings or attribute sets, where values
|
||||
are device names or device configurations.
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
@@ -669,11 +669,7 @@ in
|
||||
|
||||
# Caches
|
||||
PrivateTmp = true;
|
||||
CacheDirectory = [
|
||||
"frigate"
|
||||
# https://github.com/blakeblackshear/frigate/discussions/18129
|
||||
"frigate/model_cache"
|
||||
];
|
||||
CacheDirectory = "frigate";
|
||||
CacheDirectoryMode = "0750";
|
||||
|
||||
# Sockets/IPC
|
||||
|
||||
@@ -174,7 +174,7 @@ in
|
||||
if [[ "$USER" != ${cfg.user} ]]; then
|
||||
sudo="exec /run/wrappers/bin/sudo -u ${cfg.user}"
|
||||
fi
|
||||
$sudo ${lib.getExe cfg.package} "''${@:--help}"
|
||||
$sudo ${lib.getExe cfg.package} ''${1:--help}
|
||||
' > $out/bin/gancio
|
||||
chmod +x $out/bin/gancio
|
||||
'')
|
||||
|
||||
@@ -324,14 +324,12 @@ in
|
||||
${pkg hostName cfg}/bin/console lint:yaml --parse-tags \
|
||||
${pkg hostName cfg}/share/php/kimai/config
|
||||
|
||||
# Before running any further console commands, clear cache. This
|
||||
# avoids errors due to old cache getting used with new version
|
||||
# of Kimai.
|
||||
${pkg hostName cfg}/bin/console cache:clear --env=prod
|
||||
# Then, run kimai:install to ensure database is created or updated.
|
||||
# Run kimai:install to ensure database is created or updated.
|
||||
# Note that kimai:update is an alias to kimai:install.
|
||||
${pkg hostName cfg}/bin/console kimai:install --no-cache
|
||||
# Finally, warm up cache.
|
||||
# Clear cache and warmup cache separately, to avoid "Cannot declare
|
||||
# class App\Entity\Timesheet" error on first init after upgrade.
|
||||
${pkg hostName cfg}/bin/console cache:clear --env=prod
|
||||
${pkg hostName cfg}/bin/console cache:warmup --env=prod
|
||||
'';
|
||||
|
||||
|
||||
@@ -9,11 +9,6 @@ with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.nextcloud;
|
||||
|
||||
overridePackage = cfg.package.override {
|
||||
inherit (config.security.pki) caBundle;
|
||||
};
|
||||
|
||||
fpm = config.services.phpfpm.pools.nextcloud;
|
||||
|
||||
jsonFormat = pkgs.formats.json { };
|
||||
@@ -56,13 +51,13 @@ let
|
||||
};
|
||||
|
||||
webroot =
|
||||
pkgs.runCommand "${overridePackage.name or "nextcloud"}-with-apps"
|
||||
pkgs.runCommand "${cfg.package.name or "nextcloud"}-with-apps"
|
||||
{
|
||||
preferLocalBuild = true;
|
||||
}
|
||||
''
|
||||
mkdir $out
|
||||
ln -sfv "${overridePackage}"/* "$out"
|
||||
ln -sfv "${cfg.package}"/* "$out"
|
||||
${concatStrings (
|
||||
mapAttrsToList (
|
||||
name: store:
|
||||
@@ -121,8 +116,7 @@ let
|
||||
++ (lib.optional (cfg.config.objectstore.s3.enable) "s3_secret:${cfg.config.objectstore.s3.secretFile}")
|
||||
++ (lib.optional (
|
||||
cfg.config.objectstore.s3.sseCKeyFile != null
|
||||
) "s3_sse_c_key:${cfg.config.objectstore.s3.sseCKeyFile}")
|
||||
++ (lib.optional (cfg.secretFile != null) "secret_file:${cfg.secretFile}");
|
||||
) "s3_sse_c_key:${cfg.config.objectstore.s3.sseCKeyFile}");
|
||||
|
||||
requiresRuntimeSystemdCredentials = (lib.length runtimeSystemdCredentials) != 0;
|
||||
|
||||
@@ -190,8 +184,8 @@ let
|
||||
mysqlLocal = cfg.database.createLocally && cfg.config.dbtype == "mysql";
|
||||
pgsqlLocal = cfg.database.createLocally && cfg.config.dbtype == "pgsql";
|
||||
|
||||
nextcloudGreaterOrEqualThan = versionAtLeast overridePackage.version;
|
||||
nextcloudOlderThan = versionOlder overridePackage.version;
|
||||
nextcloudGreaterOrEqualThan = versionAtLeast cfg.package.version;
|
||||
nextcloudOlderThan = versionOlder cfg.package.version;
|
||||
|
||||
# https://github.com/nextcloud/documentation/pull/11179
|
||||
ocmProviderIsNotAStaticDirAnymore =
|
||||
@@ -201,6 +195,7 @@ let
|
||||
overrideConfig =
|
||||
let
|
||||
c = cfg.config;
|
||||
requiresReadSecretFunction = c.dbpassFile != null || c.objectstore.s3.enable;
|
||||
objectstoreConfig =
|
||||
let
|
||||
s3 = c.objectstore.s3;
|
||||
@@ -237,7 +232,7 @@ let
|
||||
in
|
||||
pkgs.writeText "nextcloud-config.php" ''
|
||||
<?php
|
||||
${optionalString requiresRuntimeSystemdCredentials ''
|
||||
${optionalString requiresReadSecretFunction ''
|
||||
function nix_read_secret($credential_name) {
|
||||
$credentials_directory = getenv("CREDENTIALS_DIRECTORY");
|
||||
if (!$credentials_directory) {
|
||||
@@ -258,19 +253,7 @@ let
|
||||
}
|
||||
|
||||
return trim(file_get_contents($credential_path));
|
||||
}
|
||||
|
||||
function nix_read_secret_and_decode_json_file($credential_name) {
|
||||
$decoded = json_decode(nix_read_secret($credential_name), true);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
error_log(sprintf("Cannot decode %s, because: %s", $file, json_last_error_msg()));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
''}
|
||||
}''}
|
||||
function nix_decode_json_file($file, $error) {
|
||||
if (!file_exists($file)) {
|
||||
throw new \RuntimeException(sprintf($error, $file));
|
||||
@@ -304,7 +287,10 @@ let
|
||||
));
|
||||
|
||||
${optionalString (cfg.secretFile != null) ''
|
||||
$CONFIG = array_replace_recursive($CONFIG, nix_read_secret_and_decode_json_file('secret_file'));
|
||||
$CONFIG = array_replace_recursive($CONFIG, nix_decode_json_file(
|
||||
"${cfg.secretFile}",
|
||||
"Cannot start Nextcloud, secrets file %s set by NixOS doesn't exist!"
|
||||
));
|
||||
''}
|
||||
'';
|
||||
in
|
||||
@@ -1033,12 +1019,12 @@ in
|
||||
If you have an existing installation with a custom table prefix, make sure it is
|
||||
set correctly in `config.php` and remove the option from your NixOS config.
|
||||
'')
|
||||
++ (optional (versionOlder overridePackage.version "26") (upgradeWarning 25 "23.05"))
|
||||
++ (optional (versionOlder overridePackage.version "27") (upgradeWarning 26 "23.11"))
|
||||
++ (optional (versionOlder overridePackage.version "28") (upgradeWarning 27 "24.05"))
|
||||
++ (optional (versionOlder overridePackage.version "29") (upgradeWarning 28 "24.11"))
|
||||
++ (optional (versionOlder overridePackage.version "30") (upgradeWarning 29 "24.11"))
|
||||
++ (optional (versionOlder overridePackage.version "31") (upgradeWarning 30 "25.05"));
|
||||
++ (optional (versionOlder cfg.package.version "26") (upgradeWarning 25 "23.05"))
|
||||
++ (optional (versionOlder cfg.package.version "27") (upgradeWarning 26 "23.11"))
|
||||
++ (optional (versionOlder cfg.package.version "28") (upgradeWarning 27 "24.05"))
|
||||
++ (optional (versionOlder cfg.package.version "29") (upgradeWarning 28 "24.11"))
|
||||
++ (optional (versionOlder cfg.package.version "30") (upgradeWarning 29 "24.11"))
|
||||
++ (optional (versionOlder cfg.package.version "31") (upgradeWarning 30 "25.05"));
|
||||
|
||||
services.nextcloud.package =
|
||||
with pkgs;
|
||||
@@ -1391,8 +1377,6 @@ in
|
||||
datadirectory = lib.mkDefault "${datadir}/data";
|
||||
trusted_domains = [ cfg.hostName ];
|
||||
"upgrade.disable-web" = true;
|
||||
# NixOS already provides its own integrity check and the nix store is read-only, therefore Nextcloud does not need to do its own integrity checks.
|
||||
"integrity.check.disabled" = true;
|
||||
})
|
||||
(lib.mkIf cfg.configureRedis {
|
||||
"memcache.distributed" = ''\OC\Memcache\Redis'';
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
|
||||
cfg = config.services.oncall;
|
||||
settingsFormat = pkgs.formats.yaml { };
|
||||
configFile = settingsFormat.generate "oncall_extra_settings.yaml" cfg.settings;
|
||||
|
||||
in
|
||||
{
|
||||
options.services.oncall = {
|
||||
|
||||
enable = lib.mkEnableOption "Oncall web app";
|
||||
|
||||
package = lib.mkPackageOption pkgs "oncall" { };
|
||||
|
||||
database.createLocally = lib.mkEnableOption "Create the database and database user locally." // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
options = {
|
||||
oncall_host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "localhost";
|
||||
description = "FQDN for the Oncall instance.";
|
||||
};
|
||||
db.conn = {
|
||||
kwargs = {
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "oncall";
|
||||
description = "Database user.";
|
||||
};
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "localhost";
|
||||
description = "Database host.";
|
||||
};
|
||||
database = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "oncall";
|
||||
description = "Database name.";
|
||||
};
|
||||
};
|
||||
str = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "%(scheme)s://%(user)s@%(host)s:%(port)s/%(database)s?charset=%(charset)s&unix_socket=/run/mysqld/mysqld.sock";
|
||||
description = ''
|
||||
Database connection scheme. The default specifies the
|
||||
connection through a local socket.
|
||||
'';
|
||||
};
|
||||
require_auth = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether authentication is required to access the web app.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
Extra configuration options to append or override.
|
||||
For available and default option values see
|
||||
[upstream configuration file](https://github.com/linkedin/oncall/blob/master/configs/config.yaml)
|
||||
and the administration part in the
|
||||
[offical documentation](https://oncall.tools/docs/admin_guide.html).
|
||||
'';
|
||||
};
|
||||
|
||||
secretFile = lib.mkOption {
|
||||
type = lib.types.pathWith {
|
||||
inStore = false;
|
||||
absolute = true;
|
||||
};
|
||||
example = "/run/keys/oncall-dbpassword";
|
||||
description = ''
|
||||
A YAML file containing secrets such as database or user passwords.
|
||||
Some variables that can be considered secrets are:
|
||||
|
||||
- db.conn.kwargs.password:
|
||||
Password used to authenticate to the database.
|
||||
|
||||
- session.encrypt_key:
|
||||
Key for encrypting/signing session cookies.
|
||||
Change to random long values in production.
|
||||
|
||||
- session.sign_key:
|
||||
Key for encrypting/signing session cookies.
|
||||
Change to random long values in production.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# Disable debug, only needed for development
|
||||
services.oncall.settings = lib.mkMerge [
|
||||
({
|
||||
debug = lib.mkDefault false;
|
||||
auth.debug = lib.mkDefault false;
|
||||
})
|
||||
];
|
||||
|
||||
services.uwsgi = {
|
||||
enable = true;
|
||||
plugins = [ "python3" ];
|
||||
user = "oncall";
|
||||
instance = {
|
||||
type = "emperor";
|
||||
vassals = {
|
||||
oncall = {
|
||||
type = "normal";
|
||||
env = [
|
||||
"PYTHONPATH=${pkgs.oncall.pythonPath}"
|
||||
(
|
||||
"ONCALL_EXTRA_CONFIG="
|
||||
+ (lib.concatStringsSep "," (
|
||||
[ configFile ] ++ lib.optional (cfg.secretFile != null) cfg.secretFile
|
||||
))
|
||||
)
|
||||
"STATIC_ROOT=/var/lib/oncall"
|
||||
];
|
||||
module = "oncall.app:get_wsgi_app()";
|
||||
socket = "${config.services.uwsgi.runDir}/oncall.sock";
|
||||
socketGroup = "nginx";
|
||||
immediate-gid = "nginx";
|
||||
chmod-socket = "770";
|
||||
pyargv = "${pkgs.oncall}/share/configs/config.yaml";
|
||||
buffer-size = 32768;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = lib.mkDefault true;
|
||||
virtualHosts."${cfg.settings.oncall_host}".locations = {
|
||||
"/".extraConfig = "uwsgi_pass unix://${config.services.uwsgi.runDir}/oncall.sock;";
|
||||
};
|
||||
};
|
||||
|
||||
services.mysql = lib.mkIf cfg.database.createLocally {
|
||||
enable = true;
|
||||
package = lib.mkDefault pkgs.mariadb;
|
||||
ensureDatabases = [ cfg.settings.db.conn.kwargs.database ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = cfg.settings.db.conn.kwargs.user;
|
||||
ensurePermissions = {
|
||||
"${cfg.settings.db.conn.kwargs.database}.*" = "ALL PRIVILEGES";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
users.users.oncall = {
|
||||
group = "nginx";
|
||||
isSystemUser = true;
|
||||
};
|
||||
|
||||
systemd = {
|
||||
services = {
|
||||
uwsgi.serviceConfig.StateDirectory = "oncall";
|
||||
oncall-setup-database = lib.mkIf cfg.database.createLocally {
|
||||
description = "Set up Oncall database";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
requiredBy = [ "uwsgi.service" ];
|
||||
after = [ "mysql.service" ];
|
||||
script =
|
||||
let
|
||||
mysql = "${lib.getExe' config.services.mysql.package "mysql"}";
|
||||
in
|
||||
''
|
||||
if [ ! -f /var/lib/oncall/.dbexists ]; then
|
||||
# Load database schema provided with package
|
||||
${mysql} ${cfg.settings.db.conn.kwargs.database} < ${cfg.package}/share/db/schema.v0.sql
|
||||
${mysql} ${cfg.settings.db.conn.kwargs.database} < ${cfg.package}/share/db/schema-update.v0-1602184489.sql
|
||||
touch /var/lib/oncall/.dbexists
|
||||
fi
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ onny ];
|
||||
|
||||
}
|
||||
@@ -68,6 +68,7 @@ in
|
||||
ExecStart = "${lib.getExe cfg.package} serve -config ${configFile}";
|
||||
ProtectSystem = "full";
|
||||
SystemCallArchitectures = "native";
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
@@ -88,6 +89,7 @@ in
|
||||
ProtectKernelTunables = true;
|
||||
LockPersonality = true;
|
||||
Restart = "on-failure";
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ To enable the GNOME desktop use:
|
||||
While it is not strictly necessary to use GDM as the display manager with GNOME, it is recommended, as some features such as screen lock [might not work](#sec-gnome-faq-can-i-use-lightdm-with-gnome) without it.
|
||||
:::
|
||||
|
||||
The default applications used in NixOS are very minimal, inspired by the defaults used in [gnome-build-meta](https://gitlab.gnome.org/GNOME/gnome-build-meta/blob/48.0/elements/core/meta-gnome-core-apps.bst).
|
||||
The default applications used in NixOS are very minimal, inspired by the defaults used in [gnome-build-meta](https://gitlab.gnome.org/GNOME/gnome-build-meta/blob/40.0/elements/core/meta-gnome-core-utilities.bst).
|
||||
|
||||
### GNOME without the apps {#sec-gnome-without-the-apps}
|
||||
|
||||
@@ -27,7 +27,7 @@ If you’d like to only use the GNOME desktop and not the apps, you can disable
|
||||
|
||||
```nix
|
||||
{
|
||||
services.gnome.core-apps.enable = false;
|
||||
services.gnome.core-utilities.enable = false;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -84,19 +84,12 @@ in
|
||||
maintainers = lib.teams.gnome.members;
|
||||
};
|
||||
|
||||
imports = [
|
||||
(lib.mkRenamedOptionModule
|
||||
[ "services" "gnome" "core-utilities" "enable" ]
|
||||
[ "services" "gnome" "core-apps" "enable" ]
|
||||
)
|
||||
];
|
||||
|
||||
options = {
|
||||
|
||||
services.gnome = {
|
||||
core-os-services.enable = mkEnableOption "essential services for GNOME3";
|
||||
core-shell.enable = mkEnableOption "GNOME Shell services";
|
||||
core-apps.enable = mkEnableOption "GNOME core apps";
|
||||
core-utilities.enable = mkEnableOption "GNOME core utilities";
|
||||
core-developer-tools.enable = mkEnableOption "GNOME core developer tools";
|
||||
games.enable = mkEnableOption "GNOME games";
|
||||
};
|
||||
@@ -220,7 +213,7 @@ in
|
||||
|
||||
services.gnome.core-os-services.enable = true;
|
||||
services.gnome.core-shell.enable = true;
|
||||
services.gnome.core-apps.enable = mkDefault true;
|
||||
services.gnome.core-utilities.enable = mkDefault true;
|
||||
|
||||
services.displayManager.sessionPackages = [ pkgs.gnome-session.sessions ];
|
||||
|
||||
@@ -333,9 +326,17 @@ in
|
||||
})
|
||||
|
||||
(lib.mkIf serviceCfg.core-shell.enable {
|
||||
services.xserver.desktopManager.gnome.sessionPath = [
|
||||
pkgs.gnome-shell
|
||||
];
|
||||
services.xserver.desktopManager.gnome.sessionPath =
|
||||
let
|
||||
mandatoryPackages = [
|
||||
pkgs.gnome-shell
|
||||
];
|
||||
optionalPackages = [
|
||||
pkgs.gnome-shell-extensions
|
||||
];
|
||||
in
|
||||
mandatoryPackages
|
||||
++ utils.removePackagesByName optionalPackages config.environment.gnome.excludePackages;
|
||||
|
||||
services.colord.enable = mkDefault true;
|
||||
services.gnome.glib-networking.enable = true;
|
||||
@@ -379,11 +380,14 @@ in
|
||||
|
||||
services.orca.enable = notExcluded pkgs.orca;
|
||||
|
||||
fonts.packages = utils.removePackagesByName [
|
||||
pkgs.adwaita-fonts
|
||||
] config.environment.gnome.excludePackages;
|
||||
fonts.packages = with pkgs; [
|
||||
cantarell-fonts
|
||||
dejavu_fonts
|
||||
source-code-pro # Default monospace font in 3.32
|
||||
source-sans
|
||||
];
|
||||
|
||||
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/blob/gnome-48/elements/core/meta-gnome-core-shell.bst
|
||||
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/blob/gnome-3-38/elements/core/meta-gnome-core-shell.bst
|
||||
environment.systemPackages =
|
||||
let
|
||||
mandatoryPackages = [
|
||||
@@ -396,6 +400,7 @@ in
|
||||
pkgs.gnome-bluetooth
|
||||
pkgs.gnome-color-manager
|
||||
pkgs.gnome-control-center
|
||||
pkgs.gnome-shell-extensions
|
||||
pkgs.gnome-tour # GNOME Shell detects the .desktop file on first log-in.
|
||||
pkgs.gnome-user-docs
|
||||
pkgs.glib # for gsettings program
|
||||
@@ -409,12 +414,11 @@ in
|
||||
++ utils.removePackagesByName optionalPackages config.environment.gnome.excludePackages;
|
||||
})
|
||||
|
||||
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/gnome-48/elements/core/meta-gnome-core-apps.bst
|
||||
(lib.mkIf serviceCfg.core-apps.enable {
|
||||
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/gnome-45/elements/core/meta-gnome-core-utilities.bst
|
||||
(lib.mkIf serviceCfg.core-utilities.enable {
|
||||
environment.systemPackages = utils.removePackagesByName (
|
||||
[
|
||||
pkgs.baobab
|
||||
pkgs.decibels
|
||||
pkgs.epiphany
|
||||
pkgs.gnome-text-editor
|
||||
pkgs.gnome-calculator
|
||||
@@ -496,19 +500,17 @@ in
|
||||
] config.environment.gnome.excludePackages;
|
||||
})
|
||||
|
||||
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/gnome-48/elements/core/meta-gnome-core-developer-tools.bst
|
||||
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/3.38.0/elements/core/meta-gnome-core-developer-tools.bst
|
||||
(lib.mkIf serviceCfg.core-developer-tools.enable {
|
||||
environment.systemPackages = utils.removePackagesByName [
|
||||
pkgs.dconf-editor
|
||||
pkgs.devhelp
|
||||
pkgs.d-spy
|
||||
pkgs.gnome-builder
|
||||
# boxes would make sense in this option, however
|
||||
# it doesn't function well enough to be included
|
||||
# in default configurations.
|
||||
# https://github.com/NixOS/nixpkgs/issues/60908
|
||||
# pkgs.gnome-boxes
|
||||
pkgs.sysprof
|
||||
] config.environment.gnome.excludePackages;
|
||||
|
||||
services.sysprof.enable = notExcluded pkgs.sysprof;
|
||||
|
||||
@@ -211,10 +211,7 @@ in
|
||||
pkgs.gnome-session
|
||||
pkgs.gnome-shell
|
||||
];
|
||||
environment.systemPackages = [
|
||||
pkgs.adwaita-icon-theme
|
||||
pkgs.gdm # For polkit rules
|
||||
];
|
||||
environment.systemPackages = [ pkgs.adwaita-icon-theme ];
|
||||
|
||||
# We dont use the upstream gdm service
|
||||
# it has to be disabled since the gdm package has it
|
||||
|
||||
@@ -26,7 +26,6 @@ onerr() {
|
||||
}
|
||||
trap onerr ERR
|
||||
|
||||
# shellcheck source-path=SCRIPTDIR
|
||||
source ./lib.sh
|
||||
|
||||
(warn hi, this works >/dev/null) 2>&1 | grep -E $'.*warning:.* hi, this works' >/dev/null
|
||||
|
||||
@@ -77,7 +77,14 @@ let
|
||||
);
|
||||
|
||||
# Handle assertions and warnings
|
||||
baseSystemAssertWarn = lib.asserts.checkAssertWarn config.assertions config.warnings baseSystem;
|
||||
|
||||
failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions);
|
||||
|
||||
baseSystemAssertWarn =
|
||||
if failedAssertions != [ ] then
|
||||
throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
|
||||
else
|
||||
showWarnings config.warnings baseSystem;
|
||||
|
||||
# Replace runtime dependencies
|
||||
system =
|
||||
|
||||
@@ -132,20 +132,13 @@ let
|
||||
initialRamdisk = pkgs.makeInitrdNG {
|
||||
name = "initrd-${kernel-name}";
|
||||
inherit (config.boot.initrd) compressor compressorArgs prepend;
|
||||
inherit (cfg) strip;
|
||||
|
||||
contents = lib.filter ({ source, ... }: !lib.elem source cfg.suppressedStorePaths) cfg.storePaths;
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(lib.mkRemovedOptionModule [ "boot" "initrd" "systemd" "strip" ] ''
|
||||
The option to strip ELF files in initrd has been removed.
|
||||
It only saved ~1MiB of initramfs size, but caused a few issues
|
||||
like unloadable kernel modules.
|
||||
'')
|
||||
];
|
||||
|
||||
options.boot.initrd.systemd = {
|
||||
enable = mkEnableOption "systemd in initrd" // {
|
||||
description = ''
|
||||
@@ -215,6 +208,19 @@ in
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
strip = mkOption {
|
||||
description = ''
|
||||
Whether to completely strip executables and libraries copied to the initramfs.
|
||||
|
||||
Setting this to false may save on the order of 30MiB on the
|
||||
machine building the system (by avoiding a binutils
|
||||
reference), at the cost of ~1MiB of initramfs size. This puts
|
||||
this option firmly in the territory of micro-optimisation.
|
||||
'';
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
extraBin = mkOption {
|
||||
description = ''
|
||||
Tools to add to /bin
|
||||
|
||||
@@ -373,6 +373,7 @@ in
|
||||
croc = handleTest ./croc.nix { };
|
||||
cross-seed = runTest ./cross-seed.nix;
|
||||
cyrus-imap = runTest ./cyrus-imap.nix;
|
||||
darling = handleTest ./darling.nix { };
|
||||
darling-dmg = runTest ./darling-dmg.nix;
|
||||
dae = handleTest ./dae.nix { };
|
||||
davis = runTest ./davis.nix;
|
||||
@@ -618,7 +619,6 @@ in
|
||||
odoo = handleTest ./odoo.nix { };
|
||||
odoo17 = handleTest ./odoo.nix { package = pkgs.odoo17; };
|
||||
odoo16 = handleTest ./odoo.nix { package = pkgs.odoo16; };
|
||||
oncall = runTest ./web-apps/oncall.nix;
|
||||
# 9pnet_virtio used to mount /nix partition doesn't support
|
||||
# hibernation. This test happens to work on x86_64-linux but
|
||||
# not on other platforms.
|
||||
@@ -1273,7 +1273,6 @@ in
|
||||
syncthing-no-settings = handleTest ./syncthing-no-settings.nix { };
|
||||
syncthing-init = handleTest ./syncthing-init.nix { };
|
||||
syncthing-many-devices = handleTest ./syncthing-many-devices.nix { };
|
||||
syncthing-folders = runTest ./syncthing-folders.nix;
|
||||
syncthing-relay = handleTest ./syncthing-relay.nix { };
|
||||
sysinit-reactivation = runTest ./sysinit-reactivation.nix;
|
||||
systemd = handleTest ./systemd.nix { };
|
||||
@@ -1425,6 +1424,10 @@ in
|
||||
imports = [ ./varnish.nix ];
|
||||
_module.args.package = pkgs.varnish60;
|
||||
};
|
||||
varnish76 = runTest {
|
||||
imports = [ ./varnish.nix ];
|
||||
_module.args.package = pkgs.varnish76;
|
||||
};
|
||||
varnish77 = runTest {
|
||||
imports = [ ./varnish.nix ];
|
||||
_module.args.package = pkgs.varnish77;
|
||||
|
||||
52
nixos/tests/darling.nix
Normal file
52
nixos/tests/darling.nix
Normal file
@@ -0,0 +1,52 @@
|
||||
import ./make-test-python.nix (
|
||||
{ pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
# Well, we _can_ cross-compile from Linux :)
|
||||
hello =
|
||||
pkgs.runCommand "hello"
|
||||
{
|
||||
sdk = "${pkgs.darling.sdk}/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk";
|
||||
nativeBuildInputs = with pkgs.llvmPackages_14; [
|
||||
clang-unwrapped
|
||||
lld
|
||||
];
|
||||
src = pkgs.writeText "hello.c" ''
|
||||
#include <stdio.h>
|
||||
int main() {
|
||||
printf("Hello, Darling!\n");
|
||||
return 0;
|
||||
}
|
||||
'';
|
||||
}
|
||||
''
|
||||
clang \
|
||||
-target x86_64-apple-darwin \
|
||||
-fuse-ld=lld \
|
||||
-nostdinc -nostdlib \
|
||||
-mmacosx-version-min=10.15 \
|
||||
--sysroot $sdk \
|
||||
-isystem $sdk/usr/include \
|
||||
-L $sdk/usr/lib -lSystem \
|
||||
$src -o $out
|
||||
'';
|
||||
in
|
||||
{
|
||||
name = "darling";
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ zhaofengli ];
|
||||
|
||||
nodes.machine = {
|
||||
programs.darling.enable = true;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
# Darling holds stdout until the server is shutdown
|
||||
machine.succeed("darling ${hello} >hello.out")
|
||||
machine.succeed("grep Hello hello.out")
|
||||
machine.succeed("darling shutdown")
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -2,10 +2,4 @@
|
||||
|
||||
makeInstalledTest {
|
||||
tested = pkgs.libxmlb;
|
||||
|
||||
testConfig = {
|
||||
environment.variables = {
|
||||
G_TEST_SRCDIR = "${pkgs.libxmlb.installedTests}/libexec/installed-tests/libxmlb";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@ in
|
||||
API_USER_NAME=api
|
||||
API_TOKEN=${api_token} # random md5 hash
|
||||
|
||||
# seeding database to get the admin roles
|
||||
${pkgs.librenms}/artisan db:seed --force --no-interaction
|
||||
|
||||
# we don't need to know the password, it just has to exist
|
||||
API_USER_PASS=$(${pkgs.pwgen}/bin/pwgen -s 64 1)
|
||||
${pkgs.librenms}/artisan user:add $API_USER_NAME -r admin -p $API_USER_PASS
|
||||
|
||||
@@ -44,33 +44,23 @@
|
||||
|
||||
with subtest("lomiri calendar launches"):
|
||||
machine.succeed("lomiri-calendar-app >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(2)
|
||||
# Default page is unbearably slow to OCR on, switch to another
|
||||
machine.succeed("xdotool mousemove 580 50 click 1")
|
||||
machine.sleep(2)
|
||||
machine.wait_for_text(r"(January|February|March|April|May|June|July|August|September|October|November|December|Mon|Tue|Wed|Thu|Fri|Sat|Sun)")
|
||||
machine.wait_for_text(r"(January|February|March|April|May|June|July|August|September|October|November|December)")
|
||||
machine.screenshot("lomiri-calendar")
|
||||
|
||||
with subtest("lomiri calendar works"):
|
||||
# Switch to Agenda tab, less busy
|
||||
machine.succeed("xdotool mousemove 380 50 click 1")
|
||||
machine.sleep(2)
|
||||
machine.succeed("xdotool mousemove 300 50 click 1")
|
||||
|
||||
# Still on main page
|
||||
machine.succeed("xdotool mousemove 500 720 click 1")
|
||||
machine.sleep(2)
|
||||
machine.succeed("xdotool mousemove 500 650 click 1")
|
||||
machine.wait_for_text(r"(Date|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday|All day|Name|Details|More)")
|
||||
machine.screenshot("lomiri-calendar_newevent")
|
||||
|
||||
# On New Event page
|
||||
machine.succeed("xdotool mousemove 500 230 click 1")
|
||||
machine.sleep(2)
|
||||
machine.send_chars("foobar")
|
||||
machine.sleep(2) # make sure they're actually in there
|
||||
machine.succeed("xdotool mousemove 1000 40 click 1")
|
||||
machine.sleep(2)
|
||||
machine.succeed("xdotool mousemove 780 40 click 1")
|
||||
machine.wait_for_text("Agenda")
|
||||
machine.screenshot("lomiri-calendar_eventadded")
|
||||
|
||||
@@ -83,9 +73,6 @@
|
||||
|
||||
with subtest("lomiri calendar localisation works"):
|
||||
machine.succeed("env LANG=de_DE.UTF-8 lomiri-calendar-app >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(2)
|
||||
machine.wait_for_text(r"(Montag|Dienstag|Mittwoch|Donnerstag|Freitag|Samstag|Sonntag)")
|
||||
machine.screenshot("lomiri-calendar_localised")
|
||||
'';
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
testScript =
|
||||
let
|
||||
qrLabel = "Feed";
|
||||
qrLabel = "Image";
|
||||
qrContent = "Test";
|
||||
in
|
||||
''
|
||||
@@ -55,10 +55,6 @@
|
||||
|
||||
with subtest("lomiri camera launches"):
|
||||
machine.succeed("lomiri-camera-app >&2 &")
|
||||
machine.wait_for_console_text("updateViewfinderResolution: viewfinder resolutions is not known yet")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.wait_for_text("Cannot access")
|
||||
machine.screenshot("lomiri-camera_open")
|
||||
|
||||
@@ -68,26 +64,21 @@
|
||||
machine.succeed("modprobe v4l2loopback video_nr=10 card_label=Video-Loopback exclusive_caps=1")
|
||||
machine.succeed("qrtool encode '${qrContent}' -s 20 -m 10 > qr.png")
|
||||
# Horizontal flip, add text, flip back. Camera displays image mirrored, so need reversed text for OCR
|
||||
machine.succeed("magick qr.png -flop -pointsize 30 -fill black -annotate +100+100 '${qrLabel}' -flop output.png")
|
||||
machine.succeed("magick qr.png -flop -pointsize 70 -fill black -annotate +100+100 '${qrLabel}' -flop output.png")
|
||||
machine.succeed("ffmpeg -re -loop 1 -i output.png -vf format=yuv420p -f v4l2 /dev/video10 -loglevel fatal >&2 &")
|
||||
|
||||
with subtest("lomiri camera uses camera"):
|
||||
machine.succeed("lomiri-camera-app >&2 &")
|
||||
machine.wait_for_console_text("updateViewfinderResolution: For target resolution")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.wait_for_text("${qrLabel}")
|
||||
machine.screenshot("lomiri-camera_feed")
|
||||
|
||||
machine.succeed("xdotool mousemove 510 670 click 1") # take photo
|
||||
machine.wait_until_succeeds("ls /root/Pictures/camera.ubports | grep '\\.jpg$'")
|
||||
machine.succeed("xdotool mousemove 320 610 click 1") # take photo
|
||||
machine.wait_until_succeeds("find /root/Pictures/camera.ubports -name '*.jpg'")
|
||||
|
||||
# Check that the image is correct
|
||||
machine.send_key("ctrl-alt-right")
|
||||
machine.succeed("magick /root/Pictures/camera.ubports/IMG_00000001.jpg -flop photo_flip.png")
|
||||
machine.succeed("feh photo_flip.png >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.wait_for_text("${qrLabel}")
|
||||
machine.screenshot("lomiri-camera_photo")
|
||||
|
||||
@@ -97,25 +88,18 @@
|
||||
|
||||
with subtest("lomiri barcode scanner uses camera"):
|
||||
machine.succeed("lomiri-camera-app --mode=barcode-reader >&2 &")
|
||||
machine.wait_for_console_text("updateViewfinderResolution: For target resolution")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.wait_for_text("${qrLabel}")
|
||||
machine.succeed("xdotool mousemove 510 670 click 1") # open up QR decode result
|
||||
machine.succeed("xdotool mousemove 320 610 click 1") # open up QR decode result
|
||||
|
||||
# OCR is struggling to recognise the text. Click the clipboard button and paste the result somewhere else
|
||||
machine.sleep(5)
|
||||
machine.screenshot("lomiri-barcode_decode")
|
||||
machine.succeed("xdotool mousemove 540 590 click 1")
|
||||
machine.succeed("xdotool mousemove 350 530 click 1")
|
||||
machine.sleep(5)
|
||||
|
||||
# Need to make a new window without closing camera app, otherwise clipboard content gets lost?
|
||||
machine.send_key("ctrl-alt-right")
|
||||
machine.succeed("gnome-text-editor >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.wait_for_text("New")
|
||||
|
||||
# Font size up to help with OCR
|
||||
@@ -145,10 +129,6 @@
|
||||
|
||||
with subtest("lomiri camera localisation works"):
|
||||
machine.succeed("env LANG=de_DE.UTF-8 lomiri-camera-app >&2 &")
|
||||
machine.wait_for_console_text("updateViewfinderResolution: For target resolution")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.wait_for_text("Kamera")
|
||||
machine.screenshot("lomiri-camera_localised")
|
||||
'';
|
||||
|
||||
@@ -34,20 +34,14 @@
|
||||
machine.wait_for_x()
|
||||
|
||||
with subtest("lomiri clock launches"):
|
||||
machine.succeed("lomiri-clock-app >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.execute("lomiri-clock-app >&2 &")
|
||||
machine.wait_for_text(r"(clock.ubports|City|Alarms)")
|
||||
machine.screenshot("lomiri-clock_open")
|
||||
|
||||
machine.succeed("pkill -f lomiri-clock-app")
|
||||
|
||||
with subtest("lomiri clock localisation works"):
|
||||
machine.succeed("env LANG=de_DE.UTF-8 lomiri-clock-app >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.execute("env LANG=de_DE.UTF-8 lomiri-clock-app >&2 &")
|
||||
machine.wait_for_text(r"(Stadt|Weckzeiten)")
|
||||
machine.screenshot("lomiri-clock_localised")
|
||||
'';
|
||||
|
||||
@@ -46,9 +46,6 @@ in
|
||||
|
||||
with subtest("lomiri docviewer launches"):
|
||||
machine.succeed("lomiri-docviewer-app >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.wait_for_text("No documents")
|
||||
machine.screenshot("lomiri-docviewer_open")
|
||||
|
||||
@@ -60,9 +57,6 @@ in
|
||||
|
||||
with subtest("lomiri docviewer txt works"):
|
||||
machine.succeed("lomiri-docviewer-app /etc/docviewer-sampletext.txt >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.wait_for_text("${exampleText}")
|
||||
machine.screenshot("lomiri-docviewer_txt")
|
||||
|
||||
@@ -70,9 +64,6 @@ in
|
||||
|
||||
with subtest("lomiri docviewer odt works"):
|
||||
machine.succeed("lomiri-docviewer-app /root/docviewer-sampletext.odt >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.wait_for_text("${exampleText}")
|
||||
machine.screenshot("lomiri-docviewer_odt")
|
||||
|
||||
@@ -80,9 +71,6 @@ in
|
||||
|
||||
with subtest("lomiri docviewer pdf works"):
|
||||
machine.succeed("lomiri-docviewer-app /root/docviewer-sampletext.pdf >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.wait_for_text("${exampleText}")
|
||||
machine.screenshot("lomiri-docviewer_pdf")
|
||||
|
||||
@@ -90,9 +78,6 @@ in
|
||||
|
||||
with subtest("lomiri docviewer localisation works"):
|
||||
machine.succeed("env LANG=de_DE.UTF-8 lomiri-docviewer-app >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.wait_for_text("Keine Dokumente")
|
||||
machine.screenshot("lomiri-docviewer_localised")
|
||||
'';
|
||||
|
||||
@@ -59,15 +59,8 @@
|
||||
machine.succeed("mkdir /root/Pictures /root/Videos")
|
||||
# Setup example data, OCR-friendly:
|
||||
# - White square, black text
|
||||
# - Small text for display OCR
|
||||
# - Big text for gallery preview OCR
|
||||
# - uppercase extension
|
||||
machine.succeed(
|
||||
"magick -size 500x500 -background white -fill black canvas:white "
|
||||
+ "-pointsize 20 -annotate +100+100 '${imageLabel}' "
|
||||
+ "-pointsize 50 -annotate +100+300 '${imageLabel}' "
|
||||
+ "/root/Pictures/output.PNG"
|
||||
)
|
||||
machine.succeed("magick -size 500x500 -background white -fill black canvas:white -pointsize 70 -annotate +100+300 '${imageLabel}' /root/Pictures/output.PNG")
|
||||
|
||||
# Different image formats
|
||||
machine.succeed("magick /root/Pictures/output.PNG /root/Pictures/output.JPG")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
ocrContent = "Feed";
|
||||
ocrContent = "Video Test";
|
||||
videoFile = "test.webm";
|
||||
in
|
||||
{
|
||||
@@ -25,8 +25,8 @@ in
|
||||
];
|
||||
}
|
||||
''
|
||||
magick -size 600x600 canvas:white -pointsize 20 -fill black -annotate +100+100 '${ocrContent}' output.png
|
||||
ffmpeg -re -loop 1 -i output.png -c:v libvpx -b:v 200K -t 120 $out -loglevel fatal
|
||||
magick -size 400x400 canvas:white -pointsize 40 -fill black -annotate +100+100 '${ocrContent}' output.png
|
||||
ffmpeg -re -loop 1 -i output.png -c:v libvpx -b:v 100K -t 120 $out -loglevel fatal
|
||||
'';
|
||||
systemPackages = with pkgs.lomiri; [
|
||||
suru-icon-theme
|
||||
@@ -54,8 +54,6 @@ in
|
||||
|
||||
with subtest("lomiri mediaplayer launches"):
|
||||
machine.succeed("lomiri-mediaplayer-app >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.wait_for_text("Choose from")
|
||||
machine.screenshot("lomiri-mediaplayer_open")
|
||||
|
||||
@@ -63,8 +61,6 @@ in
|
||||
|
||||
with subtest("lomiri mediaplayer plays video"):
|
||||
machine.succeed("lomiri-mediaplayer-app /etc/${videoFile} >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.wait_for_text("${ocrContent}")
|
||||
machine.screenshot("lomiri-mediaplayer_playback")
|
||||
|
||||
@@ -75,8 +71,6 @@ in
|
||||
# Cause an error, and look for the error popup
|
||||
machine.succeed("touch invalid.mp4")
|
||||
machine.succeed("env LANG=de_DE.UTF-8 lomiri-mediaplayer-app invalid.mp4 >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.wait_for_text("Fehler")
|
||||
machine.screenshot("lomiri-mediaplayer_localised")
|
||||
'';
|
||||
|
||||
@@ -140,10 +140,8 @@ in
|
||||
|
||||
with subtest("lomiri music launches"):
|
||||
machine.succeed("lomiri-music-app >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(2)
|
||||
machine.wait_for_text("favorite music")
|
||||
machine.send_key("alt-f10")
|
||||
machine.screenshot("lomiri-music")
|
||||
|
||||
with subtest("lomiri music plays music"):
|
||||
@@ -189,9 +187,6 @@ in
|
||||
|
||||
with subtest("lomiri music localisation works"):
|
||||
machine.succeed("env LANG=de_DE.UTF-8 lomiri-music-app .mp4 >&2 &")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(2)
|
||||
machine.wait_for_text("Titel")
|
||||
machine.screenshot("lomiri-music_localised")
|
||||
'';
|
||||
|
||||
@@ -109,11 +109,7 @@
|
||||
machine.wait_for_x()
|
||||
|
||||
with subtest("lomiri system settings launches"):
|
||||
machine.succeed("lomiri-system-settings >&2 &")
|
||||
machine.wait_for_console_text("qml: Plugin about does not exist")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.execute("lomiri-system-settings >&2 &")
|
||||
machine.wait_for_text("System Settings")
|
||||
machine.screenshot("lss_open")
|
||||
|
||||
@@ -141,11 +137,7 @@
|
||||
machine.execute("pkill -f lomiri-system-settings")
|
||||
|
||||
with subtest("lomiri system settings localisation works"):
|
||||
machine.succeed("env LANG=de_DE.UTF-8 lomiri-system-settings >&2 &")
|
||||
machine.wait_for_console_text("qml: Plugin about does not exist")
|
||||
machine.sleep(10)
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(5)
|
||||
machine.execute("env LANG=de_DE.UTF-8 lomiri-system-settings >&2 &")
|
||||
machine.wait_for_text("Systemeinstellungen")
|
||||
machine.screenshot("lss_localised_open")
|
||||
|
||||
|
||||
@@ -84,12 +84,13 @@ runTest (
|
||||
# This file is meant to contain secret options which should
|
||||
# not go into the nix store. Here it is just used to set the
|
||||
# redis password.
|
||||
environment.etc."nextcloud-secrets.json" = {
|
||||
mode = "0600";
|
||||
text = builtins.toJSON {
|
||||
redis.password = "secret";
|
||||
};
|
||||
};
|
||||
environment.etc."nextcloud-secrets.json".text = ''
|
||||
{
|
||||
"redis": {
|
||||
"password": "secret"
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -26,13 +26,11 @@ runTest (
|
||||
|
||||
nodes = {
|
||||
nextcloud =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
nodes,
|
||||
...
|
||||
}:
|
||||
{
|
||||
networking.firewall.allowedTCPPorts = [ 9000 ];
|
||||
environment.systemPackages = [ pkgs.minio-client ];
|
||||
|
||||
services.nextcloud.config.dbtype = "sqlite";
|
||||
|
||||
services.nextcloud.config.objectstore.s3 = {
|
||||
@@ -41,66 +39,13 @@ runTest (
|
||||
autocreate = true;
|
||||
key = accessKey;
|
||||
secretFile = "${pkgs.writeText "secretKey" secretKey}";
|
||||
hostname = "acme.test";
|
||||
useSsl = true;
|
||||
port = 443;
|
||||
hostname = "nextcloud";
|
||||
useSsl = false;
|
||||
port = 9000;
|
||||
usePathStyle = true;
|
||||
region = "us-east-1";
|
||||
};
|
||||
|
||||
security.pki.certificates = [
|
||||
(builtins.readFile ../common/acme/server/ca.cert.pem)
|
||||
];
|
||||
|
||||
environment.systemPackages = [ pkgs.minio-client ];
|
||||
|
||||
# The dummy certs are for acme.test, so we pretend that's the FQDN
|
||||
# of the minio VM.
|
||||
networking.extraHosts = ''
|
||||
${nodes.minio.networking.primaryIPAddress} acme.test
|
||||
'';
|
||||
};
|
||||
|
||||
client =
|
||||
{ nodes, ... }:
|
||||
{
|
||||
security.pki.certificates = [
|
||||
(builtins.readFile ../common/acme/server/ca.cert.pem)
|
||||
];
|
||||
networking.extraHosts = ''
|
||||
${nodes.minio.networking.primaryIPAddress} acme.test
|
||||
'';
|
||||
};
|
||||
|
||||
minio =
|
||||
{ ... }:
|
||||
{
|
||||
security.pki.certificates = [
|
||||
(builtins.readFile ../common/acme/server/ca.cert.pem)
|
||||
];
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedProxySettings = true;
|
||||
|
||||
virtualHosts."acme.test" = {
|
||||
onlySSL = true;
|
||||
sslCertificate = ../common/acme/server/acme.test.cert.pem;
|
||||
sslCertificateKey = ../common/acme/server/acme.test.key.pem;
|
||||
locations."/".proxyPass = "http://127.0.0.1:9000";
|
||||
};
|
||||
};
|
||||
|
||||
networking.extraHosts = ''
|
||||
127.0.0.1 acme.test
|
||||
'';
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
9000
|
||||
80
|
||||
443
|
||||
];
|
||||
|
||||
services.minio = {
|
||||
enable = true;
|
||||
listenAddress = "0.0.0.0:9000";
|
||||
@@ -111,22 +56,18 @@ runTest (
|
||||
};
|
||||
|
||||
test-helpers.init = ''
|
||||
minio.start()
|
||||
minio.wait_for_open_port(9000)
|
||||
minio.wait_for_unit("nginx.service")
|
||||
minio.wait_for_open_port(443)
|
||||
nextcloud.wait_for_open_port(9000)
|
||||
'';
|
||||
|
||||
test-helpers.extraTests =
|
||||
{ nodes, ... }:
|
||||
''
|
||||
|
||||
with subtest("File is not on the filesystem"):
|
||||
nextcloud.succeed("test ! -e ${nodes.nextcloud.services.nextcloud.home}/data/root/files/test-shared-file")
|
||||
|
||||
with subtest("Check if file is in S3"):
|
||||
nextcloud.succeed(
|
||||
"mc config host add minio https://acme.test ${accessKey} ${secretKey} --api s3v4"
|
||||
"mc config host add minio http://localhost:9000 ${accessKey} ${secretKey} --api s3v4"
|
||||
)
|
||||
files = nextcloud.succeed('mc ls minio/nextcloud|sort').strip().split('\n')
|
||||
|
||||
@@ -159,8 +100,8 @@ runTest (
|
||||
with subtest("Test download from S3"):
|
||||
client.succeed(
|
||||
"env AWS_ACCESS_KEY_ID=${accessKey} AWS_SECRET_ACCESS_KEY=${secretKey} "
|
||||
+ f"${lib.getExe pkgs.awscli2} s3 cp s3://nextcloud/{file} test --endpoint-url https://acme.test "
|
||||
+ "--region us-east-1 --ca-bundle /etc/ssl/certs/ca-bundle.crt"
|
||||
+ f"${lib.getExe pkgs.awscli2} s3 cp s3://nextcloud/{file} test --endpoint-url http://nextcloud:9000 "
|
||||
+ "--region us-east-1"
|
||||
)
|
||||
|
||||
client.succeed("test hi = $(cat test)")
|
||||
|
||||
@@ -90,10 +90,7 @@ in
|
||||
{
|
||||
name = "nvidia-container-toolkit";
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [
|
||||
ereslibre
|
||||
christoph-heiss
|
||||
];
|
||||
maintainers = [ ereslibre ];
|
||||
};
|
||||
defaults =
|
||||
{ config, ... }:
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
genNodeId =
|
||||
name:
|
||||
pkgs.runCommand "syncthing-test-certs-${name}" { } ''
|
||||
mkdir -p $out
|
||||
${pkgs.syncthing}/bin/syncthing generate --config=$out
|
||||
${pkgs.libxml2}/bin/xmllint --xpath 'string(configuration/device/@id)' $out/config.xml > $out/id
|
||||
'';
|
||||
idA = genNodeId "a";
|
||||
idB = genNodeId "b";
|
||||
idC = genNodeId "c";
|
||||
testPassword = "it's a secret";
|
||||
in
|
||||
{
|
||||
name = "syncthing";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ zarelit ];
|
||||
|
||||
nodes = {
|
||||
a =
|
||||
{ config, ... }:
|
||||
{
|
||||
environment.etc.bar-encryption-password.text = testPassword;
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
openDefaultPorts = true;
|
||||
cert = "${idA}/cert.pem";
|
||||
key = "${idA}/key.pem";
|
||||
settings = {
|
||||
devices.b.id = lib.fileContents "${idB}/id";
|
||||
devices.c.id = lib.fileContents "${idC}/id";
|
||||
folders.foo = {
|
||||
path = "/var/lib/syncthing/foo";
|
||||
devices = [ "b" ];
|
||||
};
|
||||
folders.bar = {
|
||||
path = "/var/lib/syncthing/bar";
|
||||
devices = [
|
||||
{
|
||||
name = "c";
|
||||
encryptionPasswordFile = "/etc/${config.environment.etc.bar-encryption-password.target}";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
b =
|
||||
{ config, ... }:
|
||||
{
|
||||
environment.etc.bar-encryption-password.text = testPassword;
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
openDefaultPorts = true;
|
||||
cert = "${idB}/cert.pem";
|
||||
key = "${idB}/key.pem";
|
||||
settings = {
|
||||
devices.a.id = lib.fileContents "${idA}/id";
|
||||
devices.c.id = lib.fileContents "${idC}/id";
|
||||
folders.foo = {
|
||||
path = "/var/lib/syncthing/foo";
|
||||
devices = [ "a" ];
|
||||
};
|
||||
folders.bar = {
|
||||
path = "/var/lib/syncthing/bar";
|
||||
devices = [
|
||||
{
|
||||
name = "c";
|
||||
encryptionPasswordFile = "/etc/${config.environment.etc.bar-encryption-password.target}";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
c = {
|
||||
services.syncthing = {
|
||||
enable = true;
|
||||
openDefaultPorts = true;
|
||||
cert = "${idC}/cert.pem";
|
||||
key = "${idC}/key.pem";
|
||||
settings = {
|
||||
devices.a.id = lib.fileContents "${idA}/id";
|
||||
devices.b.id = lib.fileContents "${idB}/id";
|
||||
folders.bar = {
|
||||
path = "/var/lib/syncthing/bar";
|
||||
devices = [
|
||||
"a"
|
||||
"b"
|
||||
];
|
||||
type = "receiveencrypted";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
a.wait_for_unit("syncthing.service")
|
||||
b.wait_for_unit("syncthing.service")
|
||||
c.wait_for_unit("syncthing.service")
|
||||
a.wait_for_open_port(22000)
|
||||
b.wait_for_open_port(22000)
|
||||
c.wait_for_open_port(22000)
|
||||
|
||||
# Test foo
|
||||
|
||||
a.wait_for_file("/var/lib/syncthing/foo")
|
||||
b.wait_for_file("/var/lib/syncthing/foo")
|
||||
|
||||
a.succeed("echo a2b > /var/lib/syncthing/foo/a2b")
|
||||
b.succeed("echo b2a > /var/lib/syncthing/foo/b2a")
|
||||
|
||||
a.wait_for_file("/var/lib/syncthing/foo/b2a")
|
||||
b.wait_for_file("/var/lib/syncthing/foo/a2b")
|
||||
|
||||
# Test bar
|
||||
|
||||
a.wait_for_file("/var/lib/syncthing/bar")
|
||||
b.wait_for_file("/var/lib/syncthing/bar")
|
||||
c.wait_for_file("/var/lib/syncthing/bar")
|
||||
|
||||
a.succeed("echo plaincontent > /var/lib/syncthing/bar/plainname")
|
||||
|
||||
# B should be able to decrypt, check that content of file matches
|
||||
b.wait_for_file("/var/lib/syncthing/bar/plainname")
|
||||
file_contents = b.succeed("cat /var/lib/syncthing/bar/plainname")
|
||||
assert "plaincontent\n" == file_contents, f"Unexpected file contents: {file_contents=}"
|
||||
|
||||
# Bar on C is untrusted, check that content is not in cleartext
|
||||
c.fail("grep -R plaincontent /var/lib/syncthing/bar")
|
||||
'';
|
||||
}
|
||||
@@ -34,20 +34,14 @@
|
||||
machine.wait_for_x()
|
||||
|
||||
with subtest("teleports launches"):
|
||||
machine.succeed("teleports >&2 &")
|
||||
machine.wait_for_console_text("authorizationStateWaitPhoneNumber")
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(2)
|
||||
machine.execute("teleports >&2 &")
|
||||
machine.wait_for_text(r"(TELEports|Phone Number)")
|
||||
machine.screenshot("teleports_open")
|
||||
|
||||
machine.succeed("pkill -f teleports")
|
||||
|
||||
with subtest("teleports localisation works"):
|
||||
machine.succeed("env LANG=de_DE.UTF-8 teleports >&2 &")
|
||||
machine.wait_for_console_text("authorizationStateWaitPhoneNumber")
|
||||
machine.send_key("alt-f10")
|
||||
machine.sleep(2)
|
||||
machine.execute("env LANG=de_DE.UTF-8 teleports >&2 &")
|
||||
machine.wait_for_text("Telefonnummer")
|
||||
machine.screenshot("teleports_localised")
|
||||
'';
|
||||
|
||||
@@ -62,14 +62,14 @@ let
|
||||
codium_running.wait() # type: ignore[union-attr]
|
||||
with codium_running: # type: ignore[union-attr]
|
||||
# Wait until vscodium is visible. "File" is in the menu bar.
|
||||
machine.wait_for_text('(Get|Started|with|Customize|theme)')
|
||||
machine.wait_for_text('Get Started with')
|
||||
machine.screenshot('start_screen')
|
||||
|
||||
test_string = 'testfile'
|
||||
|
||||
# Create a new file
|
||||
machine.send_key('ctrl-n')
|
||||
machine.wait_for_text('(Untitled|Select|language|template|dismiss)')
|
||||
machine.wait_for_text('Untitled')
|
||||
machine.screenshot('empty_editor')
|
||||
|
||||
# Type a string
|
||||
|
||||
@@ -1,18 +1,8 @@
|
||||
import ../make-test-python.nix (
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
oldNetbox = "netbox_4_1";
|
||||
newNetbox = "netbox_4_2";
|
||||
|
||||
apiVersion =
|
||||
version:
|
||||
lib.pipe version [
|
||||
(lib.splitString ".")
|
||||
(lib.take 2)
|
||||
(lib.concatStringsSep ".")
|
||||
];
|
||||
oldApiVersion = apiVersion pkgs."${oldNetbox}".version;
|
||||
newApiVersion = apiVersion pkgs."${newNetbox}".version;
|
||||
oldNetbox = pkgs.netbox_3_7;
|
||||
newNetbox = pkgs.netbox_4_1;
|
||||
in
|
||||
{
|
||||
name = "netbox-upgrade";
|
||||
@@ -25,14 +15,12 @@ import ../make-test-python.nix (
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ config, pkgs, ... }:
|
||||
{ config, ... }:
|
||||
{
|
||||
virtualisation.memorySize = 2048;
|
||||
services.netbox = {
|
||||
enable = true;
|
||||
# Pick the NetBox package from this config's "pkgs" argument,
|
||||
# so that `nixpkgs.config.permittedInsecurePackages` works
|
||||
package = pkgs."${oldNetbox}";
|
||||
package = oldNetbox;
|
||||
secretKeyFile = pkgs.writeText "secret" ''
|
||||
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
|
||||
'';
|
||||
@@ -54,13 +42,22 @@ import ../make-test-python.nix (
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
|
||||
nixpkgs.config.permittedInsecurePackages = [ pkgs."${oldNetbox}".name ];
|
||||
|
||||
specialisation.upgrade.configuration.services.netbox.package = lib.mkForce pkgs."${newNetbox}";
|
||||
specialisation.upgrade.configuration.services.netbox.package = lib.mkForce newNetbox;
|
||||
};
|
||||
|
||||
testScript =
|
||||
{ nodes, ... }:
|
||||
let
|
||||
apiVersion =
|
||||
version:
|
||||
lib.pipe version [
|
||||
(lib.splitString ".")
|
||||
(lib.take 2)
|
||||
(lib.concatStringsSep ".")
|
||||
];
|
||||
oldApiVersion = apiVersion oldNetbox.version;
|
||||
newApiVersion = apiVersion newNetbox.version;
|
||||
in
|
||||
''
|
||||
start_all()
|
||||
machine.wait_for_unit("netbox.target")
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
ldapDomain = "example.org";
|
||||
ldapSuffix = "dc=example,dc=org";
|
||||
|
||||
ldapRootUser = "root";
|
||||
ldapRootPassword = "foobar23";
|
||||
|
||||
testUser = "myuser";
|
||||
testPassword = "foobar23";
|
||||
teamName = "myteam";
|
||||
in
|
||||
{
|
||||
name = "oncall";
|
||||
meta.maintainers = with lib.maintainers; [ onny ];
|
||||
|
||||
nodes = {
|
||||
machine = {
|
||||
virtualisation.memorySize = 2048;
|
||||
|
||||
environment.etc."oncall-secrets.yml".text = ''
|
||||
auth:
|
||||
ldap_bind_password: "${ldapRootPassword}"
|
||||
'';
|
||||
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
|
||||
services.oncall = {
|
||||
enable = true;
|
||||
settings = {
|
||||
auth = {
|
||||
module = "oncall.auth.modules.ldap_import";
|
||||
ldap_url = "ldap://localhost";
|
||||
ldap_user_suffix = "";
|
||||
ldap_bind_user = "cn=${ldapRootUser},${ldapSuffix}";
|
||||
ldap_base_dn = "ou=accounts,${ldapSuffix}";
|
||||
ldap_search_filter = "(uid=%s)";
|
||||
import_user = true;
|
||||
attrs = {
|
||||
username = "uid";
|
||||
full_name = "cn";
|
||||
email = "mail";
|
||||
mobile = "telephoneNumber";
|
||||
sms = "mobile";
|
||||
};
|
||||
};
|
||||
};
|
||||
secretFile = "/etc/oncall-secrets.yml";
|
||||
};
|
||||
|
||||
services.openldap = {
|
||||
enable = true;
|
||||
settings = {
|
||||
children = {
|
||||
"cn=schema".includes = [
|
||||
"${pkgs.openldap}/etc/schema/core.ldif"
|
||||
"${pkgs.openldap}/etc/schema/cosine.ldif"
|
||||
"${pkgs.openldap}/etc/schema/inetorgperson.ldif"
|
||||
"${pkgs.openldap}/etc/schema/nis.ldif"
|
||||
];
|
||||
"olcDatabase={1}mdb" = {
|
||||
attrs = {
|
||||
objectClass = [
|
||||
"olcDatabaseConfig"
|
||||
"olcMdbConfig"
|
||||
];
|
||||
olcDatabase = "{1}mdb";
|
||||
olcDbDirectory = "/var/lib/openldap/db";
|
||||
olcSuffix = ldapSuffix;
|
||||
olcRootDN = "cn=${ldapRootUser},${ldapSuffix}";
|
||||
olcRootPW = ldapRootPassword;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
declarativeContents = {
|
||||
${ldapSuffix} = ''
|
||||
dn: ${ldapSuffix}
|
||||
objectClass: top
|
||||
objectClass: dcObject
|
||||
objectClass: organization
|
||||
o: ${ldapDomain}
|
||||
|
||||
dn: ou=accounts,${ldapSuffix}
|
||||
objectClass: top
|
||||
objectClass: organizationalUnit
|
||||
|
||||
dn: uid=${testUser},ou=accounts,${ldapSuffix}
|
||||
objectClass: top
|
||||
objectClass: inetOrgPerson
|
||||
uid: ${testUser}
|
||||
userPassword: ${testPassword}
|
||||
cn: Test User
|
||||
sn: User
|
||||
mail: test@example.org
|
||||
telephoneNumber: 012345678910
|
||||
mobile: 012345678910
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_for_unit("uwsgi.service")
|
||||
machine.wait_for_unit("nginx.service")
|
||||
machine.wait_for_file("/run/uwsgi/oncall.sock")
|
||||
machine.wait_for_unit("oncall-setup-database.service")
|
||||
|
||||
with subtest("Home screen loads"):
|
||||
machine.succeed(
|
||||
"curl -sSfL http://[::1]:80 | grep '<title>Oncall</title>'"
|
||||
)
|
||||
|
||||
with subtest("Staticfiles can be fetched"):
|
||||
machine.wait_until_succeeds(
|
||||
"curl -sSfL http://[::1]:80/static/bundles/libs.js"
|
||||
)
|
||||
|
||||
with subtest("Staticfiles are generated"):
|
||||
machine.succeed(
|
||||
"test -e /var/lib/oncall/static/bundles/libs.js"
|
||||
)
|
||||
|
||||
with subtest("Create and verify team via REST API"):
|
||||
import json
|
||||
|
||||
# Log in and store the session cookie
|
||||
login_response = machine.succeed("""
|
||||
curl -sSfL -c cookies -X POST \
|
||||
--data-raw 'username=${testUser}&password=${testPassword}' \
|
||||
http://[::1]:80/login
|
||||
""")
|
||||
|
||||
# Parse csrf token
|
||||
login_response_data = json.loads(login_response)
|
||||
csrf_token = login_response_data["csrf_token"]
|
||||
|
||||
# Create the team
|
||||
machine.succeed(
|
||||
f"""curl -sSfL -b cookies -X POST -H 'Content-Type: application/json' -H 'X-CSRF-Token: {csrf_token}' -d '{{"name": "${teamName}", "email": "test@example.com", "scheduling_timezone": "Europe/Berlin", "iris_enabled": false}}' http://[::1]:80/api/v0/teams/"""
|
||||
)
|
||||
|
||||
# Query the created team
|
||||
machine.succeed("""
|
||||
curl -sSfL -b cookies http://[::1]:80/api/v0/teams/${teamName} | jq -e '.name == "${teamName}"'
|
||||
""")
|
||||
|
||||
'';
|
||||
}
|
||||
@@ -501,12 +501,12 @@ When using the `patches` parameter to `mkDerivation`, make sure the patch name c
|
||||
|
||||
### Fetching patches
|
||||
|
||||
In the interest of keeping our maintenance burden and the size of Nixpkgs to a minimum, patches already merged upstream or published elsewhere _should_ be retrieved using `fetchpatch2`:
|
||||
In the interest of keeping our maintenance burden and the size of Nixpkgs to a minimum, patches already merged upstream or published elsewhere _should_ be retrieved using `fetchpatch`:
|
||||
|
||||
```nix
|
||||
{
|
||||
patches = [
|
||||
(fetchpatch2 {
|
||||
(fetchpatch {
|
||||
name = "fix-check-for-using-shared-freetype-lib.patch";
|
||||
url = "https://cgit.ghostscript.com/cgi-bin/cgit.cgi/ghostpdl.git/patch/?id=8f5d28536e4518716fdfe974e580194c8f57871d";
|
||||
hash = "sha256-uRcxaCjd+WAuGrXOmGfFeu79cUILwkRdBu48mwcBE7g=";
|
||||
@@ -515,7 +515,7 @@ In the interest of keeping our maintenance burden and the size of Nixpkgs to a m
|
||||
}
|
||||
```
|
||||
|
||||
If a patch is available online but does not cleanly apply, it can be modified in some fixed ways by using additional optional arguments for `fetchpatch2`. Check [the `fetchpatch` reference](https://nixos.org/manual/nixpkgs/unstable/#fetchpatch) for details.
|
||||
If a patch is available online but does not cleanly apply, it can be modified in some fixed ways by using additional optional arguments for `fetchpatch`. Check [the `fetchpatch` reference](https://nixos.org/manual/nixpkgs/unstable/#fetchpatch) for details.
|
||||
|
||||
When adding patches in this manner you should be reasonably sure that the used URL is stable. Patches referencing open pull requests will change when the PR is updated and code forges (such as GitHub) usually garbage collect commits that are no longer reachable due to rebases/amends.
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
# Enabling JACK requires a JACK server at runtime, no fallback mechanism
|
||||
withJack ? false,
|
||||
libjack2,
|
||||
jack,
|
||||
|
||||
type ? "ADL",
|
||||
}:
|
||||
@@ -34,7 +34,7 @@ let
|
||||
.${type};
|
||||
mainProgram = "${type}plug";
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "${lib.strings.toLower type}plug";
|
||||
version = "unstable-2021-12-17";
|
||||
|
||||
@@ -47,9 +47,9 @@ stdenv.mkDerivation {
|
||||
};
|
||||
|
||||
cmakeFlags = [
|
||||
(lib.cmakeFeature "ADLplug_CHIP" chip)
|
||||
(lib.cmakeBool "ADLplug_USE_SYSTEM_FMT" true)
|
||||
(lib.cmakeBool "ADLplug_Jack" withJack)
|
||||
"-DADLplug_CHIP=${chip}"
|
||||
"-DADLplug_USE_SYSTEM_FMT=ON"
|
||||
"-DADLplug_Jack=${if withJack then "ON" else "OFF"}"
|
||||
];
|
||||
|
||||
NIX_LDFLAGS = toString (
|
||||
@@ -88,7 +88,7 @@ stdenv.mkDerivation {
|
||||
libXext
|
||||
libXcursor
|
||||
]
|
||||
++ lib.optionals withJack [ libjack2 ];
|
||||
++ lib.optional withJack jack;
|
||||
|
||||
postInstall = lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||
mkdir -p $out/{Applications,Library/Audio/Plug-Ins/{VST,Components}}
|
||||
@@ -100,12 +100,12 @@ stdenv.mkDerivation {
|
||||
mv au/${mainProgram}.component $out/Library/Audio/Plug-Ins/Components/
|
||||
'';
|
||||
|
||||
meta = {
|
||||
meta = with lib; {
|
||||
inherit mainProgram;
|
||||
description = "${chip} FM Chip Synthesizer";
|
||||
homepage = "https://github.com/jpcima/ADLplug";
|
||||
license = lib.licenses.boost;
|
||||
platforms = lib.platforms.all;
|
||||
maintainers = with lib.maintainers; [ OPNA2608 ];
|
||||
homepage = src.meta.homepage;
|
||||
license = licenses.boost;
|
||||
platforms = platforms.all;
|
||||
maintainers = with maintainers; [ OPNA2608 ];
|
||||
};
|
||||
}
|
||||
@@ -85,6 +85,5 @@ stdenv.mkDerivation {
|
||||
license = licenses.lgpl21Plus;
|
||||
maintainers = [ maintainers.marcweber ];
|
||||
platforms = platforms.unix;
|
||||
broken = stdenv.hostPlatform.isDarwin;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
fetchpatch,
|
||||
}:
|
||||
|
||||
with lib.strings;
|
||||
|
||||
let
|
||||
|
||||
version = "2.79.3";
|
||||
@@ -168,7 +170,7 @@ let
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p "$out/bin"
|
||||
for script in ${lib.concatStringsSep " " scripts}; do
|
||||
for script in ${concatStringsSep " " scripts}; do
|
||||
cp "${dir}/$script" "$out/bin/"
|
||||
done
|
||||
|
||||
@@ -265,7 +267,7 @@ let
|
||||
|
||||
let
|
||||
|
||||
runtimePath = lib.concatStringsSep ":" (map (p: "${p}/bin") ([ faust ] ++ runtimeInputs));
|
||||
runtimePath = concatStringsSep ":" (map (p: "${p}/bin") ([ faust ] ++ runtimeInputs));
|
||||
|
||||
in
|
||||
stdenv.mkDerivation (
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
faust,
|
||||
alsa-lib,
|
||||
qt5,
|
||||
qtbase,
|
||||
writeText,
|
||||
buildPackages,
|
||||
}:
|
||||
@@ -14,7 +14,7 @@ let
|
||||
cd -- "$(dirname "$p")"
|
||||
binary=$(basename --suffix=.dsp "$p")
|
||||
rm -f .$binary-wrapped
|
||||
wrapProgram $binary --set QT_PLUGIN_PATH "${qt5.qtbase}/${qt5.qtbase.qtPluginPrefix}"
|
||||
wrapProgram $binary --set QT_PLUGIN_PATH "${qtbase}/${qtbase.qtPluginPrefix}"
|
||||
sed -i $binary -e 's@exec@cd "$(dirname "$(readlink -f "''${BASH_SOURCE[0]}")")" \&\& exec@g'
|
||||
cd $workpath
|
||||
done
|
||||
@@ -26,7 +26,7 @@ faust.wrapWithBuildEnv {
|
||||
|
||||
propagatedBuildInputs = [
|
||||
alsa-lib
|
||||
qt5.qtbase
|
||||
qtbase
|
||||
];
|
||||
|
||||
dontWrapQtApps = true;
|
||||
@@ -36,7 +36,7 @@ faust.wrapWithBuildEnv {
|
||||
# append the wrapping code to the compilation script
|
||||
cat ${wrapBinary} >> $script
|
||||
# prevent the qmake error when running the script
|
||||
sed -i "/QMAKE=/c\ QMAKE="${qt5.qtbase.dev}/bin/qmake"" $script
|
||||
sed -i "/QMAKE=/c\ QMAKE="${qtbase.dev}/bin/qmake"" $script
|
||||
done
|
||||
'';
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
{
|
||||
bash,
|
||||
faust,
|
||||
gtk2,
|
||||
jack2,
|
||||
@@ -18,10 +17,6 @@ faust.wrapWithBuildEnv {
|
||||
"faust2jackconsole"
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
bash # required for some scripts
|
||||
];
|
||||
|
||||
propagatedBuildInputs = [
|
||||
gtk2
|
||||
jack2
|
||||
@@ -2,7 +2,7 @@
|
||||
bash,
|
||||
faust,
|
||||
jack2,
|
||||
qt5,
|
||||
qtbase,
|
||||
libsndfile,
|
||||
alsa-lib,
|
||||
writeText,
|
||||
@@ -18,7 +18,7 @@ let
|
||||
cd -- "$(dirname "$p")"
|
||||
binary=$(basename --suffix=.dsp "$p")
|
||||
rm -f .$binary-wrapped
|
||||
wrapProgram $binary --set QT_PLUGIN_PATH "${qt5.qtbase}/${qt5.qtbase.qtPluginPrefix}"
|
||||
wrapProgram $binary --set QT_PLUGIN_PATH "${qtbase}/${qtbase.qtPluginPrefix}"
|
||||
sed -i $binary -e 's@exec@cd "$(dirname "$(readlink -f "''${BASH_SOURCE[0]}")")" \&\& exec@g'
|
||||
cd $workpath
|
||||
done
|
||||
@@ -39,7 +39,7 @@ faust.wrapWithBuildEnv {
|
||||
|
||||
propagatedBuildInputs = [
|
||||
jack2
|
||||
qt5.qtbase
|
||||
qtbase
|
||||
libsndfile
|
||||
alsa-lib
|
||||
which
|
||||
@@ -52,7 +52,7 @@ faust.wrapWithBuildEnv {
|
||||
# append the wrapping code to the compilation script
|
||||
cat ${wrapBinary} >> $script
|
||||
# prevent the qmake error when running the script
|
||||
sed -i "/QMAKE=/c\ QMAKE="${qt5.qtbase.dev}/bin/qmake"" $script
|
||||
sed -i "/QMAKE=/c\ QMAKE="${qtbase.dev}/bin/qmake"" $script
|
||||
done
|
||||
'';
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user