Merge branch 'master' of github.com:xosnrdev/nixpkgs into add-cargonode-0.1.2
pull from master branch
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
---
|
||||
name: Tracking issue
|
||||
about: Provide an overview on a multi-step effort
|
||||
title: 'Tracking issue: ISSUENAME'
|
||||
labels: '5.scope: tracking'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
### Tracking description
|
||||
|
||||
<!--
|
||||
Provide a brief summary of the project or multi-step effort. Explain why it is
|
||||
necessary and what the goals are.
|
||||
|
||||
You may include way to reproduce the problem, screenshots or any information
|
||||
that you find relevant.
|
||||
-->
|
||||
|
||||
#### Reference Issue(s)/PR(s)
|
||||
|
||||
- ...
|
||||
|
||||
### Follow-up issues/notes
|
||||
|
||||
<!--
|
||||
List any follow-up issues that need to be addressed after the main tasks are
|
||||
completed, or any notes related to the project.
|
||||
-->
|
||||
|
||||
#### Additional context
|
||||
Add any other context about the problem here.
|
||||
|
||||
---
|
||||
|
||||
Add a :+1: [reaction] to [issues you find important].
|
||||
|
||||
[reaction]: https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/
|
||||
[issues you find important]: https://github.com/NixOS/nixpkgs/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc
|
||||
@@ -83,7 +83,7 @@ jobs:
|
||||
|
||||
if (( "${#unformattedFiles[@]}" > 0 )); then
|
||||
echo "Some new/changed Nix files are not properly formatted"
|
||||
echo "Please go to the Nixpkgs root directory, run \`nix-shell\`, then:"
|
||||
echo "Please format them using the Nixpkgs-specific \`nixfmt\` by going to the Nixpkgs root directory, running \`nix-shell\`, then:"
|
||||
echo "nixfmt ${unformattedFiles[*]@Q}"
|
||||
echo "Make sure your branch is up to date with master, rebase if not."
|
||||
echo "If you're having trouble, please ping @NixOS/nix-formatting"
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
name: "Building Nixpkgs lib-tests"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- 'lib/**'
|
||||
jobs:
|
||||
get-merge-commit:
|
||||
uses: ./.github/workflows/get-merge-commit.yml
|
||||
|
||||
nixpkgs-lib-tests:
|
||||
name: nixpkgs-lib-tests
|
||||
runs-on: ubuntu-latest
|
||||
needs: get-merge-commit
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
if: needs.get-merge-commit.outputs.mergedSha
|
||||
with:
|
||||
# pull_request_target checks out the base branch by default
|
||||
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
|
||||
- uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
|
||||
with:
|
||||
# explicitly enable sandbox
|
||||
extra_nix_config: sandbox = true
|
||||
- name: Building Nixpkgs lib-tests
|
||||
run: |
|
||||
nix-build --arg pkgs "(import ./ci/. {}).pkgs" ./lib/tests/release.nix
|
||||
+32
-35
@@ -16,53 +16,29 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
get-merge-commit:
|
||||
uses: ./.github/workflows/get-merge-commit.yml
|
||||
|
||||
attrs:
|
||||
name: Attributes
|
||||
runs-on: ubuntu-latest
|
||||
needs: get-merge-commit
|
||||
outputs:
|
||||
mergedSha: ${{ steps.merged.outputs.mergedSha }}
|
||||
mergedSha: ${{ needs.get-merge-commit.outputs.mergedSha }}
|
||||
baseSha: ${{ steps.baseSha.outputs.baseSha }}
|
||||
systems: ${{ steps.systems.outputs.systems }}
|
||||
steps:
|
||||
# Important: Because of `pull_request_target`, this doesn't check out the PR,
|
||||
# but rather the base branch of the PR, which is needed so we don't run untrusted code
|
||||
- name: Check out the ci directory of the base branch
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
path: base
|
||||
sparse-checkout: ci
|
||||
- name: Check if the PR can be merged and get the test merge commit
|
||||
id: merged
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_EVENT: ${{ github.event_name }}
|
||||
run: |
|
||||
case "$GH_EVENT" in
|
||||
push)
|
||||
echo "mergedSha=${{ github.sha }}" >> "$GITHUB_OUTPUT"
|
||||
;;
|
||||
pull_request_target)
|
||||
if mergedSha=$(base/ci/get-merge-commit.sh ${{ github.repository }} ${{ github.event.number }}); then
|
||||
echo "Checking the merge commit $mergedSha"
|
||||
echo "mergedSha=$mergedSha" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
# Skipping so that no notifications are sent
|
||||
echo "Skipping the rest..."
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
rm -rf base
|
||||
- name: Check out the PR at the test merge commit
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
# Add this to _all_ subsequent steps to skip them
|
||||
if: steps.merged.outputs.mergedSha
|
||||
if: needs.get-merge-commit.outputs.mergedSha
|
||||
with:
|
||||
ref: ${{ steps.merged.outputs.mergedSha }}
|
||||
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
|
||||
fetch-depth: 2
|
||||
path: nixpkgs
|
||||
|
||||
- name: Determine base commit
|
||||
if: github.event_name == 'pull_request_target' && steps.merged.outputs.mergedSha
|
||||
if: github.event_name == 'pull_request_target' && needs.get-merge-commit.outputs.mergedSha
|
||||
id: baseSha
|
||||
run: |
|
||||
baseSha=$(git -C nixpkgs rev-parse HEAD^1)
|
||||
@@ -70,18 +46,18 @@ jobs:
|
||||
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
|
||||
if: steps.merged.outputs.mergedSha
|
||||
if: needs.get-merge-commit.outputs.mergedSha
|
||||
|
||||
- name: Evaluate the list of all attributes and get the systems matrix
|
||||
id: systems
|
||||
if: steps.merged.outputs.mergedSha
|
||||
if: needs.get-merge-commit.outputs.mergedSha
|
||||
run: |
|
||||
nix-build nixpkgs/ci -A eval.attrpathsSuperset
|
||||
echo "systems=$(<result/systems.json)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Upload the list of all attributes
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
|
||||
if: steps.merged.outputs.mergedSha
|
||||
if: needs.get-merge-commit.outputs.mergedSha
|
||||
with:
|
||||
name: paths
|
||||
path: result/*
|
||||
@@ -246,6 +222,7 @@ jobs:
|
||||
if: needs.process.outputs.baseRunId
|
||||
permissions:
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
steps:
|
||||
- name: Download process result
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
@@ -285,3 +262,23 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
NUMBER: ${{ github.event.number }}
|
||||
|
||||
- name: Add eval summary to commit statuses
|
||||
if: ${{ github.event_name == 'pull_request_target' }}
|
||||
run: |
|
||||
description=$(jq -r '
|
||||
"Package: added " + (.attrdiff.added | length | tostring) +
|
||||
", removed " + (.attrdiff.removed | length | tostring) +
|
||||
", changed " + (.attrdiff.changed | length | tostring) +
|
||||
", Rebuild: linux " + (.rebuildCountByKernel.linux | tostring) +
|
||||
", darwin " + (.rebuildCountByKernel.darwin | tostring)
|
||||
' <comparison/changed-paths.json)
|
||||
target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID?pr=$NUMBER"
|
||||
gh api --method POST \
|
||||
-H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"/repos/$GITHUB_REPOSITORY/statuses/$PR_HEAD_SHA" \
|
||||
-f "context=Eval / Summary" -f "state=success" -f "description=$description" -f "target_url=$target_url"
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
NUMBER: ${{ github.event.number }}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
name: Get merge commit
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
outputs:
|
||||
mergedSha:
|
||||
description: "The merge commit SHA"
|
||||
value: ${{ jobs.resolve-merge-commit.outputs.mergedSha }}
|
||||
|
||||
# We need a token to query the API, but it doesn't need any special permissions
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
resolve-merge-commit:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
mergedSha: ${{ steps.merged.outputs.mergedSha }}
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
path: base
|
||||
sparse-checkout: ci
|
||||
- name: Check if the PR can be merged and get the test merge commit
|
||||
id: merged
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
GH_EVENT: ${{ github.event_name }}
|
||||
run: |
|
||||
case "$GH_EVENT" in
|
||||
push)
|
||||
echo "mergedSha=${{ github.sha }}" >> "$GITHUB_OUTPUT"
|
||||
;;
|
||||
pull_request_target)
|
||||
if mergedSha=$(base/ci/get-merge-commit.sh ${{ github.repository }} ${{ github.event.number }}); then
|
||||
echo "Checking the merge commit $mergedSha"
|
||||
echo "mergedSha=$mergedSha" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
# Skipping so that no notifications are sent
|
||||
echo "Skipping the rest..."
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
rm -rf base
|
||||
@@ -19,46 +19,34 @@ permissions: {}
|
||||
# There is a feature request for suppressing notifications on concurrency-canceled runs: https://github.com/orgs/community/discussions/13015
|
||||
|
||||
jobs:
|
||||
get-merge-commit:
|
||||
uses: ./.github/workflows/get-merge-commit.yml
|
||||
|
||||
check:
|
||||
name: nixpkgs-vet
|
||||
# This needs to be x86_64-linux, because we depend on the tooling being pre-built in the GitHub releases.
|
||||
runs-on: ubuntu-latest
|
||||
# This should take 1 minute at most, but let's be generous. The default of 6 hours is definitely too long.
|
||||
timeout-minutes: 10
|
||||
needs: get-merge-commit
|
||||
steps:
|
||||
# This checks out the base branch because of pull_request_target
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
path: base
|
||||
sparse-checkout: ci
|
||||
- name: Resolving the merge commit
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if mergedSha=$(base/ci/get-merge-commit.sh ${{ github.repository }} ${{ github.event.number }}); then
|
||||
echo "Checking the merge commit $mergedSha"
|
||||
echo "mergedSha=$mergedSha" >> "$GITHUB_ENV"
|
||||
else
|
||||
echo "Skipping the rest..."
|
||||
fi
|
||||
rm -rf base
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
if: env.mergedSha
|
||||
if: needs.get-merge-commit.outputs.mergedSha
|
||||
with:
|
||||
# pull_request_target checks out the base branch by default
|
||||
ref: ${{ env.mergedSha }}
|
||||
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
|
||||
# Fetches the merge commit and its parents
|
||||
fetch-depth: 2
|
||||
- name: Checking out base branch
|
||||
if: env.mergedSha
|
||||
if: needs.get-merge-commit.outputs.mergedSha
|
||||
run: |
|
||||
base=$(mktemp -d)
|
||||
git worktree add "$base" "$(git rev-parse HEAD^1)"
|
||||
echo "base=$base" >> "$GITHUB_ENV"
|
||||
- uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
|
||||
if: env.mergedSha
|
||||
if: needs.get-merge-commit.outputs.mergedSha
|
||||
- name: Fetching the pinned tool
|
||||
if: env.mergedSha
|
||||
if: needs.get-merge-commit.outputs.mergedSha
|
||||
# Update the pinned version using ci/nixpkgs-vet/update-pinned-tool.sh
|
||||
run: |
|
||||
# The pinned version of the tooling to use.
|
||||
@@ -71,7 +59,7 @@ jobs:
|
||||
# Adds a result symlink as a GC root.
|
||||
nix-store --realise "$toolPath" --add-root result
|
||||
- name: Running nixpkgs-vet
|
||||
if: env.mergedSha
|
||||
if: needs.get-merge-commit.outputs.mergedSha
|
||||
env:
|
||||
# Force terminal colors to be enabled. The library that `nixpkgs-vet` uses respects https://bixense.com/clicolors/
|
||||
CLICOLOR_FORCE: 1
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
queue_rules:
|
||||
# This rule is for https://docs.mergify.com/commands/queue/
|
||||
# and can be triggered with: @mergifyio queue
|
||||
- name: default
|
||||
merge_conditions:
|
||||
# all github action checks in this list are required to merge a pull request
|
||||
- check-success=Attributes
|
||||
- check-success=Check
|
||||
- check-success=Outpaths (aarch64-darwin)
|
||||
- check-success=Outpaths (aarch64-linux)
|
||||
- check-success=Outpaths (x86_64-darwin)
|
||||
- check-success=Outpaths (x86_64-linux)
|
||||
- check-success=Process
|
||||
- check-success=Request
|
||||
- check-success=Tag
|
||||
- check-success=editorconfig-check
|
||||
- check-success=label-pr
|
||||
- check-success=nix-files-parseable-check
|
||||
- check-success=nixfmt-check
|
||||
- check-success=nixpkgs-vet
|
||||
# queue up to 5 pull requests at a time
|
||||
batch_size: 5
|
||||
@@ -157,6 +157,7 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobeza
|
||||
# Python-related code and docs
|
||||
/doc/languages-frameworks/python.section.md @mweinelt @natsukium
|
||||
/maintainers/scripts/update-python-libraries @mweinelt @natsukium
|
||||
/pkgs/by-name/up/update-python-libraries @mweinelt @natsukium
|
||||
/pkgs/development/interpreters/python @mweinelt @natsukium
|
||||
/pkgs/top-level/python-packages.nix @natsukium
|
||||
/pkgs/top-level/release-python.nix @natsukium
|
||||
@@ -206,8 +207,8 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobeza
|
||||
|
||||
# Browsers
|
||||
/pkgs/applications/networking/browsers/firefox @mweinelt
|
||||
/pkgs/applications/networking/browsers/chromium @emilylange
|
||||
/nixos/tests/chromium.nix @emilylange
|
||||
/pkgs/applications/networking/browsers/chromium @emilylange @networkException
|
||||
/nixos/tests/chromium.nix @emilylange @networkException
|
||||
|
||||
# Certificate Authorities
|
||||
pkgs/data/misc/cacert/ @ajs124 @lukegb @mweinelt
|
||||
|
||||
+8
-21
@@ -58,7 +58,7 @@ Exit codes:
|
||||
|
||||
### Usage
|
||||
|
||||
This script can be used in GitHub Actions workflows as follows:
|
||||
This script is implemented as a reusable GitHub Actions workflow, and can be used as follows:
|
||||
|
||||
```yaml
|
||||
on: pull_request_target
|
||||
@@ -67,32 +67,19 @@ on: pull_request_target
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
get-merge-commit:
|
||||
# use the relative path of the get-merge-commit workflow yaml here
|
||||
uses: ./.github/workflows/get-merge-commit.yml
|
||||
|
||||
build:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
needs: get-merge-commit
|
||||
steps:
|
||||
# Important: Because of `pull_request_target`, this doesn't check out the PR,
|
||||
# but rather the base branch of the PR, which is needed so we don't run untrusted code
|
||||
- uses: actions/checkout@<VERSION>
|
||||
with:
|
||||
path: base
|
||||
sparse-checkout: ci
|
||||
- name: Resolving the merge commit
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if mergedSha=$(base/ci/get-merge-commit.sh ${{ github.repository }} ${{ github.event.number }}); then
|
||||
echo "Checking the merge commit $mergedSha"
|
||||
echo "mergedSha=$mergedSha" >> "$GITHUB_ENV"
|
||||
else
|
||||
# Skipping so that no notifications are sent
|
||||
echo "Skipping the rest..."
|
||||
fi
|
||||
rm -rf base
|
||||
- uses: actions/checkout@<VERSION>
|
||||
# Add this to _all_ subsequent steps to skip them
|
||||
if: env.mergedSha
|
||||
if: needs.get-merge-commit.outputs.mergedSha
|
||||
with:
|
||||
ref: ${{ env.mergedSha }}
|
||||
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
|
||||
- ...
|
||||
```
|
||||
|
||||
@@ -755,6 +755,9 @@ Used with Subversion. Expects `url` to a Subversion directory, `rev`, and `hash`
|
||||
|
||||
Used with Git. Expects `url` to a Git repo, `rev`, and `hash`. `rev` in this case can be full the git commit id (SHA1 hash) or a tag name like `refs/tags/v1.0`.
|
||||
|
||||
If you want to fetch a tag you should pass the `tag` parameter instead of `rev` which has the same effect as setting `rev = "refs/tags"/${version}"`.
|
||||
This is safer than just setting `rev = version` w.r.t. possible branch and tag name conflicts.
|
||||
|
||||
Additionally, the following optional arguments can be given:
|
||||
|
||||
*`fetchSubmodules`* (Boolean)
|
||||
@@ -833,7 +836,7 @@ A number of fetcher functions wrap part of `fetchurl` and `fetchzip`. They are m
|
||||
|
||||
## `fetchFromGitHub` {#fetchfromgithub}
|
||||
|
||||
`fetchFromGitHub` expects four arguments. `owner` is a string corresponding to the GitHub user or organization that controls this repository. `repo` corresponds to the name of the software repository. These are located at the top of every GitHub HTML page as `owner`/`repo`. `rev` corresponds to the Git commit hash or tag (e.g `v1.0`) that will be downloaded from Git. Finally, `hash` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available, but `hash` is currently preferred.
|
||||
`fetchFromGitHub` expects four arguments. `owner` is a string corresponding to the GitHub user or organization that controls this repository. `repo` corresponds to the name of the software repository. These are located at the top of every GitHub HTML page as `owner`/`repo`. `rev` corresponds to the Git commit hash or tag (e.g `v1.0`) that will be downloaded from Git. If you need to fetch a tag however, you should prefer to use the `tag` parameter which achieves this in a safer way with less boilerplate. Finally, `hash` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available, but `hash` is currently preferred.
|
||||
|
||||
To use a different GitHub instance, use `githubBase` (defaults to `"github.com"`).
|
||||
|
||||
|
||||
@@ -364,7 +364,7 @@ including `nativeBuildInputs` to specify dependencies available to the `script`.
|
||||
```nix
|
||||
testers.runCommand {
|
||||
name = "access-the-internet";
|
||||
command = ''
|
||||
script = ''
|
||||
curl -o /dev/null https://example.com
|
||||
touch $out
|
||||
'';
|
||||
|
||||
@@ -14,15 +14,13 @@ In Nixpkgs, `cargo-tauri.hook` overrides the default build and install phases.
|
||||
rustPlatform,
|
||||
fetchNpmDeps,
|
||||
cargo-tauri,
|
||||
darwin,
|
||||
glib-networking,
|
||||
libsoup,
|
||||
nodejs,
|
||||
npmHooks,
|
||||
openssl,
|
||||
pkg-config,
|
||||
webkitgtk_4_0,
|
||||
wrapGAppsHook3,
|
||||
webkitgtk_4_1,
|
||||
wrapGAppsHook4,
|
||||
}:
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
@@ -47,25 +45,15 @@ rustPlatform.buildRustPackage rec {
|
||||
|
||||
# Make sure we can find our libraries
|
||||
pkg-config
|
||||
wrapGAppsHook3
|
||||
wrapGAppsHook4
|
||||
];
|
||||
|
||||
buildInputs =
|
||||
[ openssl ]
|
||||
++ lib.optionals stdenv.hostPlatform.isLinux [
|
||||
glib-networking # Most Tauri apps need networking
|
||||
libsoup
|
||||
webkitgtk_4_0
|
||||
]
|
||||
++ lib.optionals stdenv.hostPlatform.isDarwin (
|
||||
with darwin.apple_sdk.frameworks;
|
||||
[
|
||||
AppKit
|
||||
CoreServices
|
||||
Security
|
||||
WebKit
|
||||
]
|
||||
);
|
||||
webkitgtk_4_1
|
||||
];
|
||||
|
||||
# Set our Tauri source directory
|
||||
cargoRoot = "src-tauri";
|
||||
|
||||
@@ -27,42 +27,48 @@ mkShell {
|
||||
name = "dotnet-env";
|
||||
packages = [
|
||||
(with dotnetCorePackages; combinePackages [
|
||||
sdk_6_0
|
||||
sdk_7_0
|
||||
sdk_8_0
|
||||
sdk_9_0
|
||||
])
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
This will produce a dotnet installation that has the dotnet 6.0 7.0 sdk. The first sdk listed will have it's cli utility present in the resulting environment. Example info output:
|
||||
This will produce a dotnet installation that has the dotnet 8.0 9.0 sdk. The first sdk listed will have it's cli utility present in the resulting environment. Example info output:
|
||||
|
||||
```ShellSession
|
||||
$ dotnet --info
|
||||
.NET SDK:
|
||||
Version: 7.0.202
|
||||
Commit: 6c74320bc3
|
||||
Version: 9.0.100
|
||||
Commit: 59db016f11
|
||||
Workload version: 9.0.100-manifests.3068a692
|
||||
MSBuild version: 17.12.7+5b8665660
|
||||
|
||||
Runtime Environment:
|
||||
OS Name: nixos
|
||||
OS Version: 23.05
|
||||
OS Version: 25.05
|
||||
OS Platform: Linux
|
||||
RID: linux-x64
|
||||
Base Path: /nix/store/n2pm44xq20hz7ybsasgmd7p3yh31gnh4-dotnet-sdk-7.0.202/sdk/7.0.202/
|
||||
Base Path: /nix/store/a03c70i7x6rjdr6vikczsp5ck3v6rixh-dotnet-sdk-9.0.100/share/dotnet/sdk/9.0.100/
|
||||
|
||||
.NET workloads installed:
|
||||
There are no installed workloads to display.
|
||||
Configured to use loose manifests when installing new manifests.
|
||||
|
||||
Host:
|
||||
Version: 7.0.4
|
||||
Version: 9.0.0
|
||||
Architecture: x64
|
||||
Commit: 0a396acafe
|
||||
Commit: 9d5a6a9aa4
|
||||
|
||||
.NET SDKs installed:
|
||||
6.0.407 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/sdk]
|
||||
7.0.202 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/sdk]
|
||||
8.0.404 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/sdk]
|
||||
9.0.100 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/sdk]
|
||||
|
||||
.NET runtimes installed:
|
||||
Microsoft.AspNetCore.App 6.0.15 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.AspNetCore.App]
|
||||
Microsoft.AspNetCore.App 7.0.4 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.AspNetCore.App]
|
||||
Microsoft.NETCore.App 6.0.15 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.NETCore.App]
|
||||
Microsoft.NETCore.App 7.0.4 [/nix/store/3b19303vwrhv0xxz1hg355c7f2hgxxgd-dotnet-core-combined/shared/Microsoft.NETCore.App]
|
||||
Microsoft.AspNetCore.App 8.0.11 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.AspNetCore.App]
|
||||
Microsoft.AspNetCore.App 9.0.0 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.AspNetCore.App]
|
||||
Microsoft.NETCore.App 8.0.11 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.NETCore.App]
|
||||
Microsoft.NETCore.App 9.0.0 [/nix/store/6wlrjiy10wg766490dcmp6x64zb1vc8j-dotnet-core-combined/share/dotnet/shared/Microsoft.NETCore.App]
|
||||
|
||||
Other architectures found:
|
||||
None
|
||||
@@ -146,8 +152,8 @@ in buildDotnetModule rec {
|
||||
|
||||
buildInputs = [ referencedProject ]; # `referencedProject` must contain `nupkg` in the folder structure.
|
||||
|
||||
dotnet-sdk = dotnetCorePackages.sdk_6_0;
|
||||
dotnet-runtime = dotnetCorePackages.runtime_6_0;
|
||||
dotnet-sdk = dotnetCorePackages.sdk_8_0;
|
||||
dotnet-runtime = dotnetCorePackages.runtime_8_0;
|
||||
|
||||
executables = [ "foo" ]; # This wraps "$out/lib/$pname/foo" to `$out/bin/foo`.
|
||||
executables = []; # Don't install any executables.
|
||||
|
||||
@@ -67,3 +67,14 @@ nix-shell -p 'julia.withPackages ["Plots"]' --run julia
|
||||
|
||||
This normally points at a special augmented version of the Julia [General packages registry](https://github.com/JuliaRegistries/General).
|
||||
If you want to use a bleeding-edge version to pick up the latest package updates, you can plug in a later revision than the one in Nixpkgs.
|
||||
|
||||
* `juliaCpuTarget`: Allows you to set `JULIA_CPU_TARGET` when precompiling. Has no effect if `precompile=false`.
|
||||
|
||||
You may want to use this if you're building a Julia depot that will end up in a Nix cache and used on machines with
|
||||
different CPUs.
|
||||
|
||||
Why? Julia will detect the CPU microarchitecture of the build machine and include this information in the precompiled
|
||||
`*.ji` files. Starting in 1.10 Julia became more strict about checking the CPU target compatibility, so it may reject
|
||||
your precompiled files if they were compiled on a different machine.
|
||||
A good option to provide wide compatibility is to set this to `"generic"`, although this may reduce performance.
|
||||
You can also set a semicolon-separated list of multiple different targets. See the Julia documentation for details.
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ let
|
||||
length head tail elem elemAt isList;
|
||||
inherit (self.strings) concatStrings concatMapStrings concatImapStrings
|
||||
stringLength substring isString replaceStrings
|
||||
intersperse concatStringsSep concatMapStringsSep
|
||||
intersperse concatStringsSep concatMapStringsSep concatMapAttrsStringSep
|
||||
concatImapStringsSep concatLines makeSearchPath makeSearchPathOutput
|
||||
makeLibraryPath makeIncludePath makeBinPath optionalString
|
||||
hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
|
||||
|
||||
+48
-23
@@ -306,35 +306,29 @@ in
|
||||
As a result, directories with no `.nix` files (including empty
|
||||
directories) will be transformed into empty attribute sets.
|
||||
|
||||
# Inputs
|
||||
|
||||
Structured function argument
|
||||
|
||||
: Attribute set containing the following attributes.
|
||||
Additional attributes are ignored.
|
||||
|
||||
`callPackage`
|
||||
|
||||
: `pkgs.callPackage`
|
||||
|
||||
Type: `Path -> AttrSet -> a`
|
||||
|
||||
`directory`
|
||||
|
||||
: The directory to read package files from
|
||||
|
||||
Type: `Path`
|
||||
|
||||
|
||||
# Type
|
||||
|
||||
```
|
||||
packagesFromDirectoryRecursive :: AttrSet -> AttrSet
|
||||
packagesFromDirectoryRecursive :: {
|
||||
callPackage :: Path -> {} -> a,
|
||||
directory :: Path,
|
||||
...
|
||||
} -> AttrSet
|
||||
```
|
||||
|
||||
# Inputs
|
||||
|
||||
`callPackage`
|
||||
: The function used to convert a Nix file's path into a leaf of the attribute set.
|
||||
It is typically the `callPackage` function, taken from either `pkgs` or a new scope corresponding to the `directory`.
|
||||
|
||||
`directory`
|
||||
: The directory to read package files from.
|
||||
|
||||
|
||||
# Examples
|
||||
:::{.example}
|
||||
## `lib.filesystem.packagesFromDirectoryRecursive` usage example
|
||||
## Basic use of `lib.packagesFromDirectoryRecursive`
|
||||
|
||||
```nix
|
||||
packagesFromDirectoryRecursive {
|
||||
@@ -342,17 +336,48 @@ in
|
||||
directory = ./my-packages;
|
||||
}
|
||||
=> { ... }
|
||||
```
|
||||
|
||||
In this case, `callPackage` will only search `pkgs` for a file's input parameters.
|
||||
In other words, a file cannot refer to another file in the directory in its input parameters.
|
||||
:::
|
||||
|
||||
::::{.example}
|
||||
## Create a scope for the nix files found in a directory
|
||||
```nix
|
||||
lib.makeScope pkgs.newScope (
|
||||
self: packagesFromDirectoryRecursive {
|
||||
callPackage = self.callPackage;
|
||||
inherit (self) callPackage;
|
||||
directory = ./my-packages;
|
||||
}
|
||||
)
|
||||
=> { ... }
|
||||
```
|
||||
|
||||
For example, take the following directory structure:
|
||||
```
|
||||
my-packages
|
||||
├── a.nix → { b }: assert b ? b1; ...
|
||||
└── b
|
||||
├── b1.nix → { a }: ...
|
||||
└── b2.nix
|
||||
```
|
||||
|
||||
Here, `b1.nix` can specify `{ a }` as a parameter, which `callPackage` will resolve as expected.
|
||||
Likewise, `a.nix` receive an attrset corresponding to the contents of the `b` directory.
|
||||
|
||||
:::{.note}
|
||||
`a.nix` cannot directly take as inputs packages defined in a child directory, such as `b1`.
|
||||
:::
|
||||
|
||||
:::{.warning}
|
||||
As of now, `lib.packagesFromDirectoryRecursive` cannot create nested scopes for sub-directories.
|
||||
|
||||
In particular, files under `b/` can only require (as inputs) other files under `my-packages`,
|
||||
but not to those in the same directory, nor those in a parent directory; e.g, `b2.nix` cannot directly
|
||||
require `b1`.
|
||||
:::
|
||||
::::
|
||||
*/
|
||||
packagesFromDirectoryRecursive =
|
||||
{
|
||||
|
||||
+35
-5
@@ -751,17 +751,47 @@ let
|
||||
t' = opt.options.type;
|
||||
mergedType = t.typeMerge t'.functor;
|
||||
typesMergeable = mergedType != null;
|
||||
typeSet = if (bothHave "type") && typesMergeable
|
||||
then { type = mergedType; }
|
||||
else {};
|
||||
|
||||
# TODO: Remove this when all downstream reliances of internals: 'functor.wrapped' are sufficiently migrated.
|
||||
# A function that adds the deprecated wrapped message to a type.
|
||||
addDeprecatedWrapped = t:
|
||||
t // {
|
||||
functor = t.functor // {
|
||||
wrapped = t.functor.wrappedDeprecationMessage {
|
||||
inherit loc;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
typeSet =
|
||||
if opt.options ? type then
|
||||
if res ? type then
|
||||
if typesMergeable then
|
||||
{
|
||||
type =
|
||||
if mergedType ? functor.wrappedDeprecationMessage then
|
||||
addDeprecatedWrapped mergedType
|
||||
else
|
||||
mergedType;
|
||||
}
|
||||
else
|
||||
# Keep in sync with the same error below!
|
||||
throw "The option `${showOption loc}' in `${opt._file}' is already declared in ${showFiles res.declarations}."
|
||||
else if opt.options.type ? functor.wrappedDeprecationMessage then
|
||||
{ type = addDeprecatedWrapped opt.options.type; }
|
||||
else
|
||||
{}
|
||||
else
|
||||
{};
|
||||
|
||||
bothHave = k: opt.options ? ${k} && res ? ${k};
|
||||
in
|
||||
if bothHave "default" ||
|
||||
bothHave "example" ||
|
||||
bothHave "description" ||
|
||||
bothHave "apply" ||
|
||||
(bothHave "type" && (! typesMergeable))
|
||||
bothHave "apply"
|
||||
then
|
||||
# Keep in sync with the same error above!
|
||||
throw "The option `${showOption loc}' in `${opt._file}' is already declared in ${showFiles res.declarations}."
|
||||
else
|
||||
let
|
||||
|
||||
@@ -269,6 +269,43 @@ rec {
|
||||
f:
|
||||
list: concatStringsSep sep (lib.imap1 f list);
|
||||
|
||||
/**
|
||||
Like [`concatMapStringsSep`](#function-library-lib.strings.concatMapStringsSep)
|
||||
but takes an attribute set instead of a list.
|
||||
|
||||
# Inputs
|
||||
|
||||
`sep`
|
||||
: Separator to add between item strings
|
||||
|
||||
`f`
|
||||
: Function that takes each key and value and return a string
|
||||
|
||||
`attrs`
|
||||
: Attribute set to map from
|
||||
|
||||
# Type
|
||||
|
||||
```
|
||||
concatMapAttrsStringSep :: String -> (String -> Any -> String) -> AttrSet -> String
|
||||
```
|
||||
|
||||
# Examples
|
||||
|
||||
:::{.example}
|
||||
## `lib.strings.concatMapAttrsStringSep` usage example
|
||||
|
||||
```nix
|
||||
concatMapAttrsStringSep "\n" (name: value: "${name}: foo-${value}") { a = "0.1.0"; b = "0.2.0"; }
|
||||
=> "a: foo-0.1.0\nb: foo-0.2.0"
|
||||
```
|
||||
|
||||
:::
|
||||
*/
|
||||
concatMapAttrsStringSep =
|
||||
sep: f: attrs:
|
||||
concatStringsSep sep (lib.attrValues (lib.mapAttrs f attrs));
|
||||
|
||||
/**
|
||||
Concatenate a list of strings, adding a newline at the end of each one.
|
||||
Defined as `concatMapStrings (s: s + "\n")`.
|
||||
|
||||
@@ -39,6 +39,7 @@ let
|
||||
composeManyExtensions
|
||||
concatLines
|
||||
concatMapAttrs
|
||||
concatMapAttrsStringSep
|
||||
concatMapStrings
|
||||
concatStrings
|
||||
concatStringsSep
|
||||
@@ -328,6 +329,11 @@ runTests {
|
||||
expected = "a,b,c";
|
||||
};
|
||||
|
||||
testConcatMapAttrsStringSepExamples = {
|
||||
expr = concatMapAttrsStringSep "\n" (name: value: "${name}: foo-${value}") { a = "0.1.0"; b = "0.2.0"; };
|
||||
expected = "a: foo-0.1.0\nb: foo-0.2.0";
|
||||
};
|
||||
|
||||
testConcatLines = {
|
||||
expr = concatLines ["a" "b" "c"];
|
||||
expected = "a\nb\nc\n";
|
||||
|
||||
@@ -386,6 +386,10 @@ checkConfigOutput '^true$' config.conditionalWorks ./declare-attrsOf.nix ./attrs
|
||||
checkConfigOutput '^false$' config.conditionalWorks ./declare-lazyAttrsOf.nix ./attrsOf-conditional-check.nix
|
||||
checkConfigOutput '^"empty"$' config.value.foo ./declare-lazyAttrsOf.nix ./attrsOf-conditional-check.nix
|
||||
|
||||
# Check attrsWith type merging
|
||||
checkConfigError 'The option `mergedLazyNonLazy'\'' in `.*'\'' is already declared in `.*'\''\.' options.mergedLazyNonLazy ./lazy-attrsWith.nix
|
||||
checkConfigOutput '^11$' config.lazyResult ./lazy-attrsWith.nix
|
||||
checkConfigError 'infinite recursion encountered' config.nonLazyResult ./lazy-attrsWith.nix
|
||||
|
||||
# Even with multiple assignments, a type error should be thrown if any of them aren't valid
|
||||
checkConfigError 'A definition for option .* is not of type .*' \
|
||||
@@ -575,6 +579,7 @@ checkConfigOutput '^38|27$' options.submoduleLine38.declarationPositions.1.line
|
||||
# nested options work
|
||||
checkConfigOutput '^34$' options.nested.nestedLine34.declarationPositions.0.line ./declaration-positions.nix
|
||||
|
||||
|
||||
cat <<EOF
|
||||
====== module tests ======
|
||||
$pass Pass
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
# Check that AttrsWith { lazy = true; } is lazy
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) types mkOption;
|
||||
|
||||
lazyAttrsOf = mkOption {
|
||||
# Same as lazyAttrsOf
|
||||
type = types.attrsWith {
|
||||
lazy = true;
|
||||
elemType = types.int;
|
||||
};
|
||||
};
|
||||
|
||||
attrsOf = mkOption {
|
||||
# Same as lazyAttrsOf
|
||||
type = types.attrsWith {
|
||||
elemType = types.int;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
# Module A
|
||||
(
|
||||
{ ... }:
|
||||
{
|
||||
options.mergedLazyLazy = lazyAttrsOf;
|
||||
options.mergedLazyNonLazy = lazyAttrsOf;
|
||||
options.mergedNonLazyNonLazy = attrsOf;
|
||||
}
|
||||
)
|
||||
# Module B
|
||||
(
|
||||
{ ... }:
|
||||
{
|
||||
options.mergedLazyLazy = lazyAttrsOf;
|
||||
options.mergedLazyNonLazy = attrsOf;
|
||||
options.mergedNonLazyNonLazy = attrsOf;
|
||||
}
|
||||
)
|
||||
# Result
|
||||
(
|
||||
{ config, ... }:
|
||||
{
|
||||
# Can only evaluate if lazy
|
||||
config.mergedLazyLazy.bar = config.mergedLazyLazy.baz + 1;
|
||||
config.mergedLazyLazy.baz = 10;
|
||||
options.lazyResult = mkOption { default = config.mergedLazyLazy.bar; };
|
||||
|
||||
# Can not only evaluate if not lazy
|
||||
config.mergedNonLazyNonLazy.bar = config.mergedNonLazyNonLazy.baz + 1;
|
||||
config.mergedNonLazyNonLazy.baz = 10;
|
||||
options.nonLazyResult = mkOption { default = config.mergedNonLazyNonLazy.bar; };
|
||||
}
|
||||
)
|
||||
];
|
||||
}
|
||||
+76
-42
@@ -83,11 +83,15 @@ rec {
|
||||
# Default type merging function
|
||||
# takes two type functors and return the merged type
|
||||
defaultTypeMerge = f: f':
|
||||
let mergedWrapped = f.wrapped.typeMerge f'.wrapped.functor;
|
||||
mergedPayload = f.binOp f.payload f'.payload;
|
||||
let
|
||||
mergedWrapped = f.wrapped.typeMerge f'.wrapped.functor;
|
||||
mergedPayload = f.binOp f.payload f'.payload;
|
||||
|
||||
hasPayload = assert (f'.payload != null) == (f.payload != null); f.payload != null;
|
||||
hasWrapped = assert (f'.wrapped != null) == (f.wrapped != null); f.wrapped != null;
|
||||
hasPayload = assert (f'.payload != null) == (f.payload != null); f.payload != null;
|
||||
hasWrapped = assert (f'.wrapped != null) == (f.wrapped != null); f.wrapped != null;
|
||||
|
||||
typeFromPayload = if mergedPayload == null then null else f.type mergedPayload;
|
||||
typeFromWrapped = if mergedWrapped == null then null else f.type mergedWrapped;
|
||||
in
|
||||
# Abort early: cannot merge different types
|
||||
if f.name != f'.name
|
||||
@@ -95,23 +99,23 @@ rec {
|
||||
else
|
||||
|
||||
if hasPayload then
|
||||
if hasWrapped then
|
||||
# Just return the payload if returning wrapped is deprecated
|
||||
if f ? wrappedDeprecationMessage then
|
||||
typeFromPayload
|
||||
else if hasWrapped then
|
||||
# Has both wrapped and payload
|
||||
throw ''
|
||||
Type ${f.name} defines both `functor.payload` and `functor.wrapped` at the same time, which is not supported.
|
||||
|
||||
Use either `functor.payload` or `functor.wrapped` but not both.
|
||||
|
||||
If your code worked before remove `functor.payload` from the type definition.
|
||||
If your code worked before remove either `functor.wrapped` or `functor.payload` from the type definition.
|
||||
''
|
||||
else
|
||||
# Has payload
|
||||
if mergedPayload == null then null else f.type mergedPayload
|
||||
typeFromPayload
|
||||
else
|
||||
if hasWrapped then
|
||||
# Has wrapped
|
||||
# TODO(@hsjobeki): This could also be a warning and removed in the future
|
||||
if mergedWrapped == null then null else f.type mergedWrapped
|
||||
typeFromWrapped
|
||||
else
|
||||
f.type;
|
||||
|
||||
@@ -582,48 +586,78 @@ rec {
|
||||
substSubModules = m: nonEmptyListOf (elemType.substSubModules m);
|
||||
};
|
||||
|
||||
attrsOf = elemType: mkOptionType rec {
|
||||
name = "attrsOf";
|
||||
description = "attribute set of ${optionDescriptionPhrase (class: class == "noun" || class == "composite") elemType}";
|
||||
descriptionClass = "composite";
|
||||
check = isAttrs;
|
||||
merge = loc: defs:
|
||||
mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs:
|
||||
(mergeDefinitions (loc ++ [name]) elemType defs).optionalValue
|
||||
)
|
||||
# Push down position info.
|
||||
(map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value) defs)));
|
||||
emptyValue = { value = {}; };
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: attrsOf (elemType.substSubModules m);
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
nestedTypes.elemType = elemType;
|
||||
};
|
||||
attrsOf = elemType: attrsWith { inherit elemType; };
|
||||
|
||||
# A version of attrsOf that's lazy in its values at the expense of
|
||||
# conditional definitions not working properly. E.g. defining a value with
|
||||
# `foo.attr = mkIf false 10`, then `foo ? attr == true`, whereas with
|
||||
# attrsOf it would correctly be `false`. Accessing `foo.attr` would throw an
|
||||
# error that it's not defined. Use only if conditional definitions don't make sense.
|
||||
lazyAttrsOf = elemType: mkOptionType rec {
|
||||
name = "lazyAttrsOf";
|
||||
description = "lazy attribute set of ${optionDescriptionPhrase (class: class == "noun" || class == "composite") elemType}";
|
||||
lazyAttrsOf = elemType: attrsWith { inherit elemType; lazy = true; };
|
||||
|
||||
# base type for lazyAttrsOf and attrsOf
|
||||
attrsWith =
|
||||
let
|
||||
# Push down position info.
|
||||
pushPositions = map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value);
|
||||
binOp = lhs: rhs:
|
||||
let
|
||||
elemType = lhs.elemType.typeMerge rhs.elemType.functor;
|
||||
lazy =
|
||||
if lhs.lazy == rhs.lazy then
|
||||
lhs.lazy
|
||||
else
|
||||
null;
|
||||
in
|
||||
if elemType == null || lazy == null then
|
||||
null
|
||||
else
|
||||
{
|
||||
inherit elemType lazy;
|
||||
};
|
||||
in
|
||||
{
|
||||
elemType,
|
||||
lazy ? false,
|
||||
}:
|
||||
mkOptionType {
|
||||
name = if lazy then "lazyAttrsOf" else "attrsOf";
|
||||
description = (if lazy then "lazy attribute set" else "attribute set") + " of ${optionDescriptionPhrase (class: class == "noun" || class == "composite") elemType}";
|
||||
descriptionClass = "composite";
|
||||
check = isAttrs;
|
||||
merge = loc: defs:
|
||||
zipAttrsWith (name: defs:
|
||||
let merged = mergeDefinitions (loc ++ [name]) elemType defs;
|
||||
# mergedValue will trigger an appropriate error when accessed
|
||||
in merged.optionalValue.value or elemType.emptyValue.value or merged.mergedValue
|
||||
)
|
||||
# Push down position info.
|
||||
(map (def: mapAttrs (n: v: { inherit (def) file; value = v; }) def.value) defs);
|
||||
merge = if lazy then (
|
||||
# Lazy merge Function
|
||||
loc: defs:
|
||||
zipAttrsWith (name: defs:
|
||||
let merged = mergeDefinitions (loc ++ [name]) elemType defs;
|
||||
# mergedValue will trigger an appropriate error when accessed
|
||||
in merged.optionalValue.value or elemType.emptyValue.value or merged.mergedValue
|
||||
)
|
||||
# Push down position info.
|
||||
(pushPositions defs)
|
||||
) else (
|
||||
# Non-lazy merge Function
|
||||
loc: defs:
|
||||
mapAttrs (n: v: v.value) (filterAttrs (n: v: v ? value) (zipAttrsWith (name: defs:
|
||||
(mergeDefinitions (loc ++ [name]) elemType (defs)).optionalValue
|
||||
)
|
||||
# Push down position info.
|
||||
(pushPositions defs)))
|
||||
);
|
||||
emptyValue = { value = {}; };
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ ["<name>"]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: lazyAttrsOf (elemType.substSubModules m);
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
substSubModules = m: attrsWith { elemType = elemType.substSubModules m; inherit lazy; };
|
||||
functor = defaultFunctor "attrsWith" // {
|
||||
wrappedDeprecationMessage = { loc }: lib.warn ''
|
||||
The deprecated `type.functor.wrapped` attribute of the option `${showOption loc}` is accessed, use `type.nestedTypes.elemType` instead.
|
||||
'' elemType;
|
||||
payload = {
|
||||
# Important!: Add new function attributes here in case of future changes
|
||||
inherit elemType lazy;
|
||||
};
|
||||
inherit binOp;
|
||||
};
|
||||
nestedTypes.elemType = elemType;
|
||||
};
|
||||
|
||||
|
||||
+196
-83
@@ -85,7 +85,7 @@
|
||||
};
|
||||
_0qq = {
|
||||
email = "0qqw0qqw@gmail.com";
|
||||
github = "0qq";
|
||||
github = "0xKDI";
|
||||
githubId = 64707304;
|
||||
name = "Dmitry Kulikov";
|
||||
};
|
||||
@@ -155,7 +155,7 @@
|
||||
};
|
||||
_1000teslas = {
|
||||
name = "Kevin Tran";
|
||||
github = "1000teslas";
|
||||
github = "sledgehammervampire";
|
||||
githubId = 47207223;
|
||||
};
|
||||
_13r0ck = {
|
||||
@@ -219,7 +219,7 @@
|
||||
};
|
||||
_404wolf = {
|
||||
email = "wolfmermelstein@gmail.com";
|
||||
github = "404wolf";
|
||||
github = "404Wolf";
|
||||
githubId = 108041238;
|
||||
name = "Wolf Mermelstein";
|
||||
};
|
||||
@@ -537,6 +537,13 @@
|
||||
githubId = 749381;
|
||||
name = "Adam Tulinius";
|
||||
};
|
||||
adda = {
|
||||
email = "chocholaty.david@protonmail.com";
|
||||
matrix = "@adda0:matrix.org";
|
||||
github = "adda0";
|
||||
githubId = 52529234;
|
||||
name = "David Chocholatý";
|
||||
};
|
||||
addict3d = {
|
||||
email = "nickbathum@gmail.com";
|
||||
matrix = "@nbathum:matrix.org";
|
||||
@@ -792,7 +799,7 @@
|
||||
};
|
||||
ajgrf = {
|
||||
email = "a@ajgrf.com";
|
||||
github = "ajgrf";
|
||||
github = "axgfn";
|
||||
githubId = 10733175;
|
||||
name = "Alex Griffin";
|
||||
};
|
||||
@@ -805,7 +812,7 @@
|
||||
};
|
||||
ajwhouse = {
|
||||
email = "adam@ajwh.chat";
|
||||
github = "ajwhouse";
|
||||
github = "adam-dakota";
|
||||
githubId = 56616368;
|
||||
name = "Adam House";
|
||||
};
|
||||
@@ -1229,7 +1236,7 @@
|
||||
};
|
||||
amanse = {
|
||||
email = "amansetiarjp@gmail.com";
|
||||
github = "amanse";
|
||||
github = "Amanse";
|
||||
githubId = 13214574;
|
||||
name = "Aman Setia";
|
||||
};
|
||||
@@ -1315,6 +1322,7 @@
|
||||
};
|
||||
amozeo = {
|
||||
email = "wroclaw223@outlook.com";
|
||||
github = "amozeo";
|
||||
githubId = 37040543;
|
||||
name = "Wroclaw";
|
||||
};
|
||||
@@ -1394,7 +1402,7 @@
|
||||
};
|
||||
andreasfelix = {
|
||||
email = "fandreas@physik.hu-berlin.de";
|
||||
github = "andreasfelix";
|
||||
github = "felix-andreas";
|
||||
githubId = 24651767;
|
||||
name = "Felix Andreas";
|
||||
};
|
||||
@@ -1710,7 +1718,7 @@
|
||||
};
|
||||
aprl = {
|
||||
email = "aprl@acab.dev";
|
||||
github = "cutestnekoaqua";
|
||||
github = "CutestNekoAqua";
|
||||
githubId = 30842467;
|
||||
name = "April John";
|
||||
};
|
||||
@@ -1787,13 +1795,13 @@
|
||||
};
|
||||
argrat = {
|
||||
email = "n.bertazzo@protonmail.com";
|
||||
github = "argrat";
|
||||
github = "argo-v5";
|
||||
githubId = 98821629;
|
||||
name = "Nicolò Bertazzo";
|
||||
};
|
||||
arian-d = {
|
||||
email = "arianxdehghani@gmail.com";
|
||||
github = "arian-d";
|
||||
github = "Arian-D";
|
||||
githubId = 40076285;
|
||||
name = "Arian Dehghani";
|
||||
};
|
||||
@@ -2022,7 +2030,7 @@
|
||||
};
|
||||
aspulse = {
|
||||
email = "contact@aspulse.dev";
|
||||
github = "aspulse";
|
||||
github = "AsPulse";
|
||||
githubId = 84216737;
|
||||
name = "AsPulse / あすぱる";
|
||||
keys = [ { fingerprint = "C919 E69E A7C0 E147 9E0F C26E 1EDA D0C6 70BD 062D"; } ];
|
||||
@@ -2036,7 +2044,7 @@
|
||||
};
|
||||
astavie = {
|
||||
email = "astavie@pm.me";
|
||||
github = "astavie";
|
||||
github = "Astavie";
|
||||
githubId = 7745457;
|
||||
name = "Astavie";
|
||||
};
|
||||
@@ -2292,7 +2300,7 @@
|
||||
};
|
||||
axertheaxe = {
|
||||
email = "axertheaxe@proton.me";
|
||||
github = "axertheaxe";
|
||||
github = "AxerTheAxe";
|
||||
githubId = 99703210;
|
||||
name = "Katherine Jamison";
|
||||
};
|
||||
@@ -2425,7 +2433,7 @@
|
||||
};
|
||||
balssh = {
|
||||
email = "george.bals25@gmail.com";
|
||||
github = "balssh";
|
||||
github = "Balssh";
|
||||
githubId = 82440615;
|
||||
name = "George Bals";
|
||||
};
|
||||
@@ -2497,6 +2505,13 @@
|
||||
githubId = 6987136;
|
||||
keys = [ { fingerprint = "2C6D 37D4 6AA1 DCDA BE8D F346 43E2 CF4C 01B9 4940"; } ];
|
||||
};
|
||||
BastianAsmussen = {
|
||||
name = "Bastian Asmussen";
|
||||
email = "bastian@asmussen.tech";
|
||||
github = "BastianAsmussen";
|
||||
githubId = 76102128;
|
||||
keys = [ { fingerprint = "3B11 7469 0893 85E7 16C2 7CD9 0FE5 A355 DBC9 2568"; } ];
|
||||
};
|
||||
basvandijk = {
|
||||
email = "v.dijk.bas@gmail.com";
|
||||
github = "basvandijk";
|
||||
@@ -2654,7 +2669,7 @@
|
||||
ben9986 = {
|
||||
name = "Ben Carmichael";
|
||||
email = "ben9986.unvmn@passinbox.com";
|
||||
github = "ben9986";
|
||||
github = "Ben9986";
|
||||
githubId = 38633150;
|
||||
keys = [ { fingerprint = "03C7 A587 74B3 F0E8 CE1F 4F8E ABBC DD77 69BC D3B0"; } ];
|
||||
};
|
||||
@@ -2863,7 +2878,7 @@
|
||||
};
|
||||
bhasherbel = {
|
||||
email = "nixos.maintainer@bhasher.com";
|
||||
github = "bhasherbel";
|
||||
github = "BhasherBEL";
|
||||
githubId = 45831883;
|
||||
name = "Brieuc Dubois";
|
||||
};
|
||||
@@ -3017,7 +3032,7 @@
|
||||
};
|
||||
blusk = {
|
||||
email = "bluskript@gmail.com";
|
||||
github = "Bluskript";
|
||||
github = "bluskript";
|
||||
githubId = 52386117;
|
||||
name = "Blusk";
|
||||
};
|
||||
@@ -3373,7 +3388,7 @@
|
||||
};
|
||||
ByteSudoer = {
|
||||
email = "bytesudoer@gmail.com";
|
||||
github = "bytesudoer";
|
||||
github = "ByteSudoer";
|
||||
githubId = 88513682;
|
||||
name = "ByteSudoer";
|
||||
};
|
||||
@@ -3549,7 +3564,7 @@
|
||||
};
|
||||
campadrenalin = {
|
||||
email = "campadrenalin@gmail.com";
|
||||
github = "campadrenalin";
|
||||
github = "MaddieM4";
|
||||
githubId = 289492;
|
||||
name = "Philip Horger";
|
||||
};
|
||||
@@ -3887,7 +3902,7 @@
|
||||
};
|
||||
cherrykitten = {
|
||||
email = "contact@cherrykitten.dev";
|
||||
github = "cherrykitten";
|
||||
github = "CherryKitten";
|
||||
githubId = 20300586;
|
||||
matrix = "@sammy:cherrykitten.dev";
|
||||
name = "CherryKitten";
|
||||
@@ -4018,7 +4033,7 @@
|
||||
};
|
||||
chrispwill = {
|
||||
email = "chris@chrispwill.com";
|
||||
github = "chrispwill";
|
||||
github = "ChrisPWill";
|
||||
githubId = 271099;
|
||||
name = "Chris Williams";
|
||||
};
|
||||
@@ -4110,7 +4125,7 @@
|
||||
};
|
||||
citadelcore = {
|
||||
email = "alex@arctarus.co.uk";
|
||||
github = "VertexA115";
|
||||
github = "RealityAnomaly";
|
||||
githubId = 5567402;
|
||||
name = "Alex Zero";
|
||||
keys = [ { fingerprint = "A0AA 4646 B8F6 9D45 4553 5A88 A515 50ED B450 302C"; } ];
|
||||
@@ -4376,7 +4391,7 @@
|
||||
colamaroro = {
|
||||
name = "Corentin Rondier";
|
||||
email = "github@rondier.io";
|
||||
github = "colamaroro";
|
||||
github = "COLAMAroro";
|
||||
githubId = 12484955;
|
||||
matrix = "@colamaroro:lovelyrad.io";
|
||||
};
|
||||
@@ -4416,7 +4431,7 @@
|
||||
};
|
||||
coloquinte = {
|
||||
email = "gabriel.gouvine_nix@m4x.org";
|
||||
github = "coloquinte";
|
||||
github = "Coloquinte";
|
||||
githubId = 4102525;
|
||||
name = "Gabriel Gouvine";
|
||||
};
|
||||
@@ -4472,7 +4487,7 @@
|
||||
connorbaker = {
|
||||
email = "connor.baker@tweag.io";
|
||||
matrix = "@connorbaker:matrix.org";
|
||||
github = "connorbaker";
|
||||
github = "ConnorBaker";
|
||||
name = "Connor Baker";
|
||||
githubId = 3880346;
|
||||
};
|
||||
@@ -4597,7 +4612,7 @@
|
||||
};
|
||||
crem = {
|
||||
email = "max@alstercaminer.com";
|
||||
github = "MaxCaminer";
|
||||
github = "ItsCrem";
|
||||
githubId = 16345077;
|
||||
name = "crem";
|
||||
};
|
||||
@@ -4635,7 +4650,7 @@
|
||||
croissong = {
|
||||
email = "jan.moeller0@pm.me";
|
||||
name = "Jan Möller";
|
||||
github = "Croissong";
|
||||
github = "croissong";
|
||||
githubId = 4162215;
|
||||
keys = [ { fingerprint = "CE97 9DEE 904C 26AA 3716 78C2 96A4 38F9 EE72 572F"; } ];
|
||||
};
|
||||
@@ -4653,6 +4668,13 @@
|
||||
name = "Carl Richard Theodor Schneider";
|
||||
keys = [ { fingerprint = "2017 E152 BB81 5C16 955C E612 45BC C1E2 709B 1788"; } ];
|
||||
};
|
||||
cryo = {
|
||||
email = "cryo@disroot.org";
|
||||
github = "cry0ice";
|
||||
githubId = 176274027;
|
||||
name = "Cryo";
|
||||
keys = [ { fingerprint = "2CF7 F8E8 2258 5751 2591 F97F 4B12 E34A 25A9 AB35"; } ];
|
||||
};
|
||||
Cryolitia = {
|
||||
name = "Cryolitia PukNgae";
|
||||
email = "Cryolitia@gmail.com";
|
||||
@@ -4689,6 +4711,12 @@
|
||||
githubId = 490965;
|
||||
name = "Craig Swank";
|
||||
};
|
||||
cterence = {
|
||||
email = "terence.chateigne@posteo.net";
|
||||
github = "cterence";
|
||||
githubId = 25285508;
|
||||
name = "Térence Chateigné";
|
||||
};
|
||||
ctron = {
|
||||
email = "ctron@dentrassi.de";
|
||||
github = "ctron";
|
||||
@@ -4779,6 +4807,12 @@
|
||||
github = "d4ilyrun";
|
||||
githubId = 34611103;
|
||||
};
|
||||
d4rk = {
|
||||
name = "Anoop Menon";
|
||||
email = "d4rk@blackvoltage.org";
|
||||
github = "d4rk";
|
||||
githubId = 22163;
|
||||
};
|
||||
d4rkstar = {
|
||||
name = "Bruno Salzano";
|
||||
email = "d4rkstar@gmail.com";
|
||||
@@ -5126,7 +5160,7 @@
|
||||
};
|
||||
dawoox = {
|
||||
email = "contact@antoinebellanger.fr";
|
||||
github = "dawoox";
|
||||
github = "Dawoox";
|
||||
githubId = 48325941;
|
||||
name = "Dawoox";
|
||||
};
|
||||
@@ -5224,7 +5258,7 @@
|
||||
declan = {
|
||||
name = "Declan Rixon";
|
||||
email = "declan.fraser.rixon@gmail.com";
|
||||
github = "DeclanRixon";
|
||||
github = "DeclanBaggins";
|
||||
githubId = 57464835;
|
||||
};
|
||||
deeengan = {
|
||||
@@ -5242,7 +5276,7 @@
|
||||
};
|
||||
deekahy = {
|
||||
email = "Lennart.Diego.Kahn@gmail.com";
|
||||
github = "deekahy";
|
||||
github = "DeeKahy";
|
||||
githubId = 97156953;
|
||||
name = "Lennart Diego Kahn";
|
||||
};
|
||||
@@ -5343,7 +5377,7 @@
|
||||
};
|
||||
demine = {
|
||||
email = "riches_tweaks0o@icloud.com";
|
||||
github = "demine0";
|
||||
github = "Demine0";
|
||||
githubId = 51992962;
|
||||
name = "Nikita Demin";
|
||||
};
|
||||
@@ -5361,7 +5395,7 @@
|
||||
};
|
||||
denperidge = {
|
||||
email = "contact@denperidge.com";
|
||||
github = "denperidge";
|
||||
github = "Denperidge";
|
||||
githubId = 27348469;
|
||||
name = "Cat";
|
||||
};
|
||||
@@ -5373,7 +5407,7 @@
|
||||
};
|
||||
derdennisop = {
|
||||
email = "dennish@wuitz.de";
|
||||
github = "derdennisop";
|
||||
github = "DerDennisOP";
|
||||
githubId = 52411861;
|
||||
name = "Dennis";
|
||||
};
|
||||
@@ -5539,13 +5573,13 @@
|
||||
};
|
||||
dgollings = {
|
||||
email = "daniel.gollings+nixpkgs@gmail.com";
|
||||
github = "dgollings";
|
||||
github = "DGollings";
|
||||
githubId = 2032823;
|
||||
name = "Daniel Gollings";
|
||||
};
|
||||
dgonyeo = {
|
||||
email = "derek@gonyeo.com";
|
||||
github = "dgonyeo";
|
||||
github = "cgonyeo";
|
||||
githubId = 2439413;
|
||||
name = "Derek Gonyeo";
|
||||
};
|
||||
@@ -5578,6 +5612,12 @@
|
||||
githubId = 15774340;
|
||||
name = "Thomas Depierre";
|
||||
};
|
||||
DictXiong = {
|
||||
email = "me@beardic.cn";
|
||||
github = "DictXiong";
|
||||
githubId = 41772157;
|
||||
name = "Dict Xiong";
|
||||
};
|
||||
diegolelis = {
|
||||
email = "diego.o.lelis@gmail.com";
|
||||
github = "DiegoLelis";
|
||||
@@ -6093,7 +6133,7 @@
|
||||
};
|
||||
dwrege = {
|
||||
email = "email@dwrege.de";
|
||||
github = "dominicwrege";
|
||||
github = "DominicWrege";
|
||||
githubId = 7389000;
|
||||
name = "Dominic Wrege";
|
||||
};
|
||||
@@ -6236,7 +6276,7 @@
|
||||
};
|
||||
edeneast = {
|
||||
email = "edenofest@gmail.com";
|
||||
github = "edeneast";
|
||||
github = "EdenEast";
|
||||
githubId = 2746374;
|
||||
name = "edeneast";
|
||||
};
|
||||
@@ -6340,6 +6380,12 @@
|
||||
githubId = 701128;
|
||||
name = "Eike Kettner";
|
||||
};
|
||||
eilvelia = {
|
||||
email = "hi@eilvelia.cat";
|
||||
github = "eilvelia";
|
||||
githubId = 10106819;
|
||||
name = "eilvelia";
|
||||
};
|
||||
eken = {
|
||||
email = "edvin.kallstrom@protonmail.com";
|
||||
github = "Eken-beep";
|
||||
@@ -6663,7 +6709,7 @@
|
||||
};
|
||||
ercao = {
|
||||
email = "vip@ercao.cn";
|
||||
github = "ercao";
|
||||
github = "O8888";
|
||||
githubId = 51725284;
|
||||
name = "ercao";
|
||||
keys = [ { fingerprint = "F3B0 36F7 B0CB 0964 3C12 D3C7 FFAB D125 7ECF 0889"; } ];
|
||||
@@ -6685,7 +6731,7 @@
|
||||
erethon = {
|
||||
email = "dgrig@erethon.com";
|
||||
matrix = "@dgrig:erethon.com";
|
||||
github = "erethon";
|
||||
github = "Erethon";
|
||||
githubId = 1254842;
|
||||
name = "Dionysis Grigoropoulos";
|
||||
};
|
||||
@@ -6919,7 +6965,7 @@
|
||||
};
|
||||
eveeifyeve = {
|
||||
name = "Eveeifyeve";
|
||||
github = "eveeifyeve";
|
||||
github = "Eveeifyeve";
|
||||
githubId = 88671402;
|
||||
matrix = "@eveeifyeve:matrix.org";
|
||||
email = "eveeg1971@gmail.com";
|
||||
@@ -6970,7 +7016,7 @@
|
||||
};
|
||||
ewuuwe = {
|
||||
email = "ewu.uweq@pm.me";
|
||||
github = "ewuuwe";
|
||||
github = "EwuUwe";
|
||||
githubId = 63652646;
|
||||
name = "Xaver Oswald";
|
||||
};
|
||||
@@ -7064,7 +7110,7 @@
|
||||
};
|
||||
fabianrig = {
|
||||
email = "fabianrig@posteo.de";
|
||||
github = "fabianrig";
|
||||
github = "FabianRig";
|
||||
githubId = 88741530;
|
||||
name = "Fabian Rigoll";
|
||||
};
|
||||
@@ -7606,7 +7652,7 @@
|
||||
name = "Christian Friedow";
|
||||
};
|
||||
friedrichaltheide = {
|
||||
github = "friedrichaltheide";
|
||||
github = "FriedrichAltheide";
|
||||
githubId = 11352905;
|
||||
name = "Friedrich Altheide";
|
||||
};
|
||||
@@ -8052,7 +8098,7 @@
|
||||
name = "Priyanshu Tripathi";
|
||||
email = "nixos@getpsyched.dev";
|
||||
matrix = "@getpsyched:matrix.org";
|
||||
github = "getpsyched";
|
||||
github = "GetPsyched";
|
||||
githubId = 43472218;
|
||||
};
|
||||
getreu = {
|
||||
@@ -8115,7 +8161,7 @@
|
||||
};
|
||||
gigglesquid = {
|
||||
email = "jack.connors@protonmail.com";
|
||||
github = "gigglesquid";
|
||||
github = "GiggleSquid";
|
||||
githubId = 3685154;
|
||||
name = "Jack connors";
|
||||
keys = [ { fingerprint = "21DF 8034 B212 EDFF 9F19 9C19 F65B 7583 7ABF D019"; } ];
|
||||
@@ -8525,6 +8571,12 @@
|
||||
githubId = 6578603;
|
||||
name = "Jonas Rembser";
|
||||
};
|
||||
gurjaka = {
|
||||
name = "Gurami Esartia";
|
||||
email = "esartia.gurika@gmail.com";
|
||||
github = "Gurjaka";
|
||||
githubId = 143032436;
|
||||
};
|
||||
guserav = {
|
||||
github = "guserav";
|
||||
githubId = 28863828;
|
||||
@@ -8627,7 +8679,7 @@
|
||||
};
|
||||
hannesgith = {
|
||||
email = "nix@h-h.win";
|
||||
github = "hannesgith";
|
||||
github = "HannesGitH";
|
||||
githubId = 33062605;
|
||||
name = "Hannes Hattenbach";
|
||||
};
|
||||
@@ -8666,7 +8718,7 @@
|
||||
harbiinger = {
|
||||
email = "theo.godin@protonmail.com";
|
||||
matrix = "@hrbgr:matrix.org";
|
||||
github = "harbiinger";
|
||||
github = "Harbiinger";
|
||||
githubId = 55398594;
|
||||
name = "Theo Godin";
|
||||
};
|
||||
@@ -8950,7 +9002,7 @@
|
||||
};
|
||||
hhydraa = {
|
||||
email = "hcurfman@keemail.me";
|
||||
github = "hhydraa";
|
||||
github = "hcur";
|
||||
githubId = 58676303;
|
||||
name = "hhydraa";
|
||||
};
|
||||
@@ -9085,7 +9137,7 @@
|
||||
};
|
||||
hornwall = {
|
||||
email = "hannes@hornwall.me";
|
||||
github = "hornwall";
|
||||
github = "Hornwall";
|
||||
githubId = 1064477;
|
||||
name = "Hannes Hornwall";
|
||||
};
|
||||
@@ -9191,7 +9243,7 @@
|
||||
};
|
||||
humancalico = {
|
||||
email = "humancalico@disroot.org";
|
||||
github = "humancalico";
|
||||
github = "akshatagarwl";
|
||||
githubId = 51334444;
|
||||
name = "Akshat Agarwal";
|
||||
};
|
||||
@@ -9616,7 +9668,7 @@
|
||||
iogamaster = {
|
||||
email = "iogamastercode+nixpkgs@gmail.com";
|
||||
name = "IogaMaster";
|
||||
github = "iogamaster";
|
||||
github = "IogaMaster";
|
||||
githubId = 67164465;
|
||||
};
|
||||
ionutnechita = {
|
||||
@@ -9684,7 +9736,7 @@
|
||||
istoph = {
|
||||
email = "chr@istoph.de";
|
||||
name = "Christoph Hüffelmann";
|
||||
github = "istoph";
|
||||
github = "istof";
|
||||
githubId = 114227790;
|
||||
};
|
||||
istudyatuni = {
|
||||
@@ -9999,7 +10051,7 @@
|
||||
janlikar = {
|
||||
name = "Jan Likar";
|
||||
email = "jan.likar@protonmail.com";
|
||||
github = "janlikar";
|
||||
github = "JanLikar";
|
||||
githubId = 4228250;
|
||||
};
|
||||
jansol = {
|
||||
@@ -10058,7 +10110,7 @@
|
||||
jayesh-bhoot = {
|
||||
name = "Jayesh Bhoot";
|
||||
email = "jb@jayeshbhoot.com";
|
||||
github = "jyssh";
|
||||
github = "jbhoot";
|
||||
githubId = 1915507;
|
||||
};
|
||||
jayman2000 = {
|
||||
@@ -10236,7 +10288,7 @@
|
||||
};
|
||||
jedsek = {
|
||||
email = "jedsek@qq.com";
|
||||
github = "jedsek";
|
||||
github = "Jedsek";
|
||||
githubId = 63626406;
|
||||
name = "Jedsek";
|
||||
};
|
||||
@@ -10512,6 +10564,12 @@
|
||||
githubId = 1058504;
|
||||
name = "José Luis Lafuente";
|
||||
};
|
||||
jljox = {
|
||||
email = "jeanluc.jox@gmail.com";
|
||||
github = "jljox";
|
||||
githubId = 3665886;
|
||||
name = "Jean-Luc Jox";
|
||||
};
|
||||
jloyet = {
|
||||
email = "ml@fatbsd.com";
|
||||
github = "fatpat";
|
||||
@@ -11823,7 +11881,7 @@
|
||||
knarkzel = {
|
||||
email = "knarkzel@gmail.com";
|
||||
name = "Knarkzel";
|
||||
github = "Knarkzel";
|
||||
github = "svelterust";
|
||||
githubId = 85593302;
|
||||
};
|
||||
knedlsepp = {
|
||||
@@ -12375,7 +12433,7 @@
|
||||
name = "Jacob LeCoq";
|
||||
email = "lecoqjacob@gmail.com";
|
||||
githubId = 9278174;
|
||||
github = "lecoqjacob";
|
||||
github = "bayou-brogrammer";
|
||||
keys = [ { fingerprint = "C505 1E8B 06AC 1776 6875 1B60 93AF DAD0 10B3 CB8D"; } ];
|
||||
};
|
||||
ledif = {
|
||||
@@ -12467,7 +12525,7 @@
|
||||
};
|
||||
leonid = {
|
||||
email = "belyaev.l@northeastern.edu";
|
||||
github = "leonidbelyaev";
|
||||
github = "aeblyve";
|
||||
githubId = 77865363;
|
||||
name = "Leonid Belyaev";
|
||||
};
|
||||
@@ -12573,7 +12631,7 @@
|
||||
};
|
||||
libjared = {
|
||||
email = "jared@perrycode.com";
|
||||
github = "libjared";
|
||||
github = "hypevhs";
|
||||
githubId = 3746656;
|
||||
matrix = "@libjared:matrix.org";
|
||||
name = "Jared Perry";
|
||||
@@ -12630,7 +12688,7 @@
|
||||
};
|
||||
lillycham = {
|
||||
email = "lillycat332@gmail.com";
|
||||
github = "lillycat332";
|
||||
github = "lillycham";
|
||||
githubId = 54189319;
|
||||
name = "Lilly Cham";
|
||||
};
|
||||
@@ -12783,7 +12841,7 @@
|
||||
logo = {
|
||||
email = "logo4poop@protonmail.com";
|
||||
matrix = "@logo4poop:matrix.org";
|
||||
github = "logo4poop";
|
||||
github = "l0go";
|
||||
githubId = 24994565;
|
||||
name = "Isaac Silverstein";
|
||||
};
|
||||
@@ -12851,6 +12909,13 @@
|
||||
githubId = 1202012;
|
||||
name = "Ignat Loskutov";
|
||||
};
|
||||
lostmsu = {
|
||||
email = "lostfreeman@gmail.com";
|
||||
github = "lostmsu";
|
||||
githubId = 239520;
|
||||
matrix = "@lostmsu:matrix.org";
|
||||
name = "Victor Nova";
|
||||
};
|
||||
lostnet = {
|
||||
email = "lost.networking@gmail.com";
|
||||
github = "lostnet";
|
||||
@@ -12949,7 +13014,7 @@
|
||||
};
|
||||
lu15w1r7h = {
|
||||
email = "lwirth2000@gmail.com";
|
||||
github = "LU15W1R7H";
|
||||
github = "luiswirth";
|
||||
githubId = 37505890;
|
||||
name = "Luis Wirth";
|
||||
};
|
||||
@@ -14794,7 +14859,7 @@
|
||||
};
|
||||
modderme123 = {
|
||||
email = "modderme123@gmail.com";
|
||||
github = "modderme123";
|
||||
github = "milomg";
|
||||
githubId = 14153763;
|
||||
name = "modderme123";
|
||||
};
|
||||
@@ -15140,7 +15205,7 @@
|
||||
};
|
||||
mtrsk = {
|
||||
email = "marcos.schonfinkel@protonmail.com";
|
||||
github = "mtrsk";
|
||||
github = "schonfinkel";
|
||||
githubId = 16356569;
|
||||
name = "Marcos Benevides";
|
||||
};
|
||||
@@ -15339,7 +15404,7 @@
|
||||
Name = {
|
||||
name = "Name";
|
||||
email = "lasagna@garfunkles.space";
|
||||
github = "namescode";
|
||||
github = "NamesCode";
|
||||
githubId = 86119896;
|
||||
};
|
||||
name-snrl = {
|
||||
@@ -15394,7 +15459,7 @@
|
||||
name = "Nathan Bijnens";
|
||||
};
|
||||
nathanielbrough = {
|
||||
github = "silvergasp";
|
||||
github = "nathaniel-brough";
|
||||
githubId = 7277663;
|
||||
email = "nathaniel.brough@gmail.com";
|
||||
name = "Nathaniel Brough";
|
||||
@@ -15460,7 +15525,7 @@
|
||||
nbsp = {
|
||||
email = "aoife@enby.space";
|
||||
matrix = "@nbsp:enby.space";
|
||||
github = "enbyspace";
|
||||
github = "nbsp";
|
||||
githubId = 57151943;
|
||||
name = "aoife cassidy";
|
||||
};
|
||||
@@ -15565,7 +15630,7 @@
|
||||
};
|
||||
nerdypepper = {
|
||||
email = "nerdy@peppe.rs";
|
||||
github = "nerdypepper";
|
||||
github = "oppiliappan";
|
||||
githubId = 23743547;
|
||||
name = "Akshay Oppiliappan";
|
||||
};
|
||||
@@ -16573,7 +16638,7 @@
|
||||
};
|
||||
osener = {
|
||||
email = "ozan@ozansener.com";
|
||||
github = "osener";
|
||||
github = "ozanmakes";
|
||||
githubId = 111265;
|
||||
name = "Ozan Sener";
|
||||
};
|
||||
@@ -16636,7 +16701,7 @@
|
||||
};
|
||||
oxapentane = {
|
||||
email = "blame@oxapentane.com";
|
||||
github = "oxapentane";
|
||||
github = "gshipunov";
|
||||
githubId = 1297357;
|
||||
name = "Grigory Shipunov";
|
||||
keys = [ { fingerprint = "DD09 98E6 CDF2 9453 7FC6 04F9 91FA 5E5B F9AA 901C"; } ];
|
||||
@@ -16712,7 +16777,7 @@
|
||||
};
|
||||
paddygord = {
|
||||
email = "pgpatrickgordon@gmail.com";
|
||||
github = "avaunit02";
|
||||
github = "avagordon01";
|
||||
githubId = 10776658;
|
||||
name = "Patrick Gordon";
|
||||
};
|
||||
@@ -16766,6 +16831,11 @@
|
||||
githubId = 686076;
|
||||
name = "Vitalii Voloshyn";
|
||||
};
|
||||
pancaek = {
|
||||
github = "pancaek";
|
||||
githubId = 20342389;
|
||||
name = "paneku";
|
||||
};
|
||||
panda2134 = {
|
||||
email = "me+nixpkgs@panda2134.site";
|
||||
github = "panda2134";
|
||||
@@ -16875,7 +16945,7 @@
|
||||
};
|
||||
patricksjackson = {
|
||||
email = "patrick@jackson.dev";
|
||||
github = "patricksjackson";
|
||||
github = "arcuru";
|
||||
githubId = 160646;
|
||||
name = "Patrick Jackson";
|
||||
};
|
||||
@@ -16929,7 +16999,7 @@
|
||||
};
|
||||
pawelpacana = {
|
||||
email = "pawel.pacana@gmail.com";
|
||||
github = "pawelpacana";
|
||||
github = "mostlyobvious";
|
||||
githubId = 116740;
|
||||
name = "Paweł Pacana";
|
||||
};
|
||||
@@ -17092,7 +17162,7 @@
|
||||
};
|
||||
petercommand = {
|
||||
email = "petercommand@gmail.com";
|
||||
github = "petercommand";
|
||||
github = "ptrcmd";
|
||||
githubId = 1260660;
|
||||
name = "petercommand";
|
||||
};
|
||||
@@ -17179,7 +17249,7 @@
|
||||
name = "Léo Lavaur";
|
||||
email = "phdcybersec@pm.me";
|
||||
|
||||
github = "phdcybersec";
|
||||
github = "leolavaur";
|
||||
githubId = 82591009;
|
||||
keys = [ { fingerprint = "7756 E88F 3C6A 47A5 C5F0 CDFB AB54 6777 F93E 20BF"; } ];
|
||||
};
|
||||
@@ -18507,7 +18577,7 @@
|
||||
realsnick = {
|
||||
name = "Ido Samuelson";
|
||||
email = "ido.samuelson@gmail.com";
|
||||
github = "realsnick";
|
||||
github = "i-am-logger";
|
||||
githubId = 1440852;
|
||||
};
|
||||
reckenrode = {
|
||||
@@ -19539,6 +19609,14 @@
|
||||
github = "Sail0rd";
|
||||
githubId = 55802415;
|
||||
};
|
||||
sako = {
|
||||
name = "Sako";
|
||||
email = "sako@cock.email";
|
||||
matrix = "@sako:imagisphe.re";
|
||||
github = "Sakooooo";
|
||||
githubId = 78461130;
|
||||
keys = [ { fingerprint = "CA52 EE7B E681 720E 32B6 6792 FE52 FD65 B76E 4751"; } ];
|
||||
};
|
||||
samalws = {
|
||||
email = "sam@samalws.com";
|
||||
name = "Sam Alws";
|
||||
@@ -19653,7 +19731,7 @@
|
||||
};
|
||||
sanana = {
|
||||
email = "asya@waifu.club";
|
||||
github = "AsyaTheAbove";
|
||||
github = "lunabunja";
|
||||
githubId = 40492846;
|
||||
keys = [ { fingerprint = "B766 7717 1644 5ABC DE82 94AA 4679 BF7D CC04 4783"; } ];
|
||||
name = "sanana the skenana";
|
||||
@@ -19793,7 +19871,7 @@
|
||||
};
|
||||
schinmai-akamai = {
|
||||
email = "schinmai@akamai.com";
|
||||
github = "schinmai-akamai";
|
||||
github = "tchinmai7";
|
||||
githubId = 70169773;
|
||||
name = "Tarun Chinmai Sekar";
|
||||
};
|
||||
@@ -19866,7 +19944,7 @@
|
||||
};
|
||||
scoder12 = {
|
||||
name = "Spencer Pogorzelski";
|
||||
github = "Scoder12";
|
||||
github = "spencerpogo";
|
||||
githubId = 34356756;
|
||||
};
|
||||
scolobb = {
|
||||
@@ -20233,6 +20311,12 @@
|
||||
githubId = 293035;
|
||||
name = "Shawn Dellysse";
|
||||
};
|
||||
ShawnToubeau = {
|
||||
name = "Shawn Toubeau";
|
||||
email = "shawntoubeau@gmail.com";
|
||||
github = "ShawnToubeau";
|
||||
githubId = 22332636;
|
||||
};
|
||||
shayne = {
|
||||
email = "shaynesweeney@gmail.com";
|
||||
github = "shayne";
|
||||
@@ -20704,7 +20788,7 @@
|
||||
};
|
||||
smironov = {
|
||||
email = "grrwlf@gmail.com";
|
||||
github = "grwlf";
|
||||
github = "sergei-mironov";
|
||||
githubId = 4477729;
|
||||
name = "Sergey Mironov";
|
||||
};
|
||||
@@ -21101,6 +21185,12 @@
|
||||
github = "stasjok";
|
||||
githubId = 1353637;
|
||||
};
|
||||
StayBlue = {
|
||||
name = "StayBlue";
|
||||
email = "blue@spook.rip";
|
||||
github = "StayBlue";
|
||||
githubId = 23127866;
|
||||
};
|
||||
steamwalker = {
|
||||
email = "steamwalker@xs4all.nl";
|
||||
github = "steamwalker";
|
||||
@@ -21638,6 +21728,17 @@
|
||||
githubId = 6064962;
|
||||
name = "TakWolf";
|
||||
};
|
||||
talhaHavadar = {
|
||||
email = "havadartalha@gmail.com";
|
||||
github = "talhaHavadar";
|
||||
githubId = 6908462;
|
||||
name = "Talha Can Havadar";
|
||||
keys = [
|
||||
{
|
||||
fingerprint = "1E13 12DF 4B71 58B6 EBF9 DE78 2574 3879 62FE B0D1";
|
||||
}
|
||||
];
|
||||
};
|
||||
talkara = {
|
||||
email = "taito.horiuchi@relexsolutions.com";
|
||||
github = "talkara";
|
||||
@@ -21826,6 +21927,12 @@
|
||||
githubId = 2084639;
|
||||
name = "Manu";
|
||||
};
|
||||
tensor5 = {
|
||||
github = "tensor5";
|
||||
githubId = 1545895;
|
||||
matrix = "@tensor5:matrix.org";
|
||||
name = "Nicola Squartini";
|
||||
};
|
||||
teozkr = {
|
||||
email = "teo@nullable.se";
|
||||
github = "nightkr";
|
||||
@@ -22076,7 +22183,7 @@
|
||||
};
|
||||
therealr5 = {
|
||||
email = "rouven@rfive.de";
|
||||
github = "therealr5";
|
||||
github = "rouven0";
|
||||
githubId = 72568063;
|
||||
name = "Rouven Seifert";
|
||||
keys = [ { fingerprint = "1169 87A8 DD3F 78FF 8601 BF4D B95E 8FE6 B11C 4D09"; } ];
|
||||
@@ -22513,7 +22620,7 @@
|
||||
tomsiewert = {
|
||||
email = "tom@siewert.io";
|
||||
matrix = "@tom:frickel.earth";
|
||||
github = "tomsiewert";
|
||||
github = "sinuscosinustan";
|
||||
githubId = 8794235;
|
||||
name = "Tom Siewert";
|
||||
};
|
||||
@@ -22579,6 +22686,12 @@
|
||||
githubId = 2125828;
|
||||
name = "Alex Davies";
|
||||
};
|
||||
travgm = {
|
||||
email = "travis@travgm.org";
|
||||
github = "travgm";
|
||||
githubId = 99630881;
|
||||
name = "Travis Montoya";
|
||||
};
|
||||
travisbhartwell = {
|
||||
email = "nafai@travishartwell.net";
|
||||
github = "travisbhartwell";
|
||||
@@ -23416,7 +23529,7 @@
|
||||
};
|
||||
voidless = {
|
||||
email = "julius.schmitt@yahoo.de";
|
||||
github = "voidIess";
|
||||
github = "bratorange";
|
||||
githubId = 45292658;
|
||||
name = "Julius Schmitt";
|
||||
};
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/target
|
||||
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "check-maintainers"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
octocrab = "0.42.1"
|
||||
serde_json = "1.0.133"
|
||||
tokio = { version = "1.41.1", features = ["fs", "macros", "rt-multi-thread"] }
|
||||
@@ -0,0 +1,42 @@
|
||||
use std::{env, error::Error, io::{self, Write}};
|
||||
|
||||
use tokio::fs;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
real_main().await.unwrap();
|
||||
}
|
||||
|
||||
async fn real_main() -> Result<(), Box<dyn Error>> {
|
||||
let gh = octocrab::OctocrabBuilder::default()
|
||||
.personal_token(env::var("GITHUB_PAT").expect("no GITHUB_PAT configured"))
|
||||
.build()?;
|
||||
|
||||
// first run: nix-instantiate -A lib.maintainers --eval --strict --json > maintainers.json
|
||||
let data: serde_json::Value = serde_json::from_str(&fs::read_to_string("maintainers.json").await?)?;
|
||||
|
||||
let data = data.as_object().unwrap();
|
||||
let total = data.len();
|
||||
for (i, (maintainer_name, v)) in data.iter().enumerate() {
|
||||
print!("\r{i}/{total}");
|
||||
io::stdout().flush()?;
|
||||
let Some(github_id) = v.get("githubId") else {
|
||||
println!("\rWARN: no id for {maintainer_name}");
|
||||
continue;
|
||||
};
|
||||
let Some(github) = v.get("github") else {
|
||||
println!("\rWARN: no username for {maintainer_name}");
|
||||
continue;
|
||||
};
|
||||
let Ok(name) = gh.users_by_id(github_id.as_u64().unwrap()).profile().await else {
|
||||
println!("\rWARN: error fetching {maintainer_name}");
|
||||
continue;
|
||||
};
|
||||
let name = name.login;
|
||||
if name.to_ascii_lowercase() != github.as_str().unwrap().to_ascii_lowercase() {
|
||||
println!("\rERR: {maintainer_name} has github = {github}, but username really is '{name}'");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -I nixpkgs=channel:nixpkgs-unstable -i bash -p "python3.withPackages (ps: with ps; [ packaging requests ])" -p nix-prefetch-git
|
||||
exec python3 pkgs/development/interpreters/python/update-python-libraries/update-python-libraries.py $@
|
||||
exec python3 pkgs/by-name/up/update-python-libraries/update-python-libraries.py $@
|
||||
|
||||
@@ -399,6 +399,23 @@ Composed types are types that take a type as parameter. `listOf
|
||||
returned instead for the same `mkIf false` definition.
|
||||
:::
|
||||
|
||||
`types.attrsWith` { *`elemType`*, *`lazy`* ? false }
|
||||
|
||||
: An attribute set of where all the values are of *`elemType`* type.
|
||||
|
||||
**Parameters**
|
||||
|
||||
`elemType` (Required)
|
||||
: Specifies the type of the values contained in the attribute set.
|
||||
|
||||
`lazy`
|
||||
: Determines whether the attribute set is lazily evaluated. See: `types.lazyAttrsOf`
|
||||
|
||||
**Behavior**
|
||||
|
||||
- `attrsWith { elemType = t; }` is equivalent to `attrsOf t`
|
||||
- `attrsWith { lazy = true; elemType = t; }` is equivalent to `lazyAttrsOf t`
|
||||
|
||||
`types.uniq` *`t`*
|
||||
|
||||
: Ensures that type *`t`* cannot be merged. It is used to ensure option
|
||||
|
||||
@@ -109,7 +109,7 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
|
||||
- [Maddy](https://maddy.email/), a free an open source mail server. Available as [services.maddy](#opt-services.maddy.enable).
|
||||
|
||||
- [matrix-conduit](https://conduit.rs/), a simple, fast and reliable chat server powered by matrix. Available as [services.matrix-conduit](option.html#opt-services.matrix-conduit.enable).
|
||||
- [matrix-conduit](https://conduit.rs/), a simple, fast and reliable chat server powered by matrix. Available as [services.matrix-conduit](options.html#opt-services.matrix-conduit.enable).
|
||||
|
||||
- [Moosefs](https://moosefs.com), fault tolerant petabyte distributed file system. Available as [moosefs](#opt-services.moosefs.master.enable).
|
||||
|
||||
|
||||
@@ -173,11 +173,11 @@
|
||||
|
||||
- [Suricata](https://suricata.io/), a free and open source, mature, fast and robust network threat detection engine. Available as [services.suricata](options.html#opt-services.suricata.enable).
|
||||
|
||||
- [Playerctld](https://github.com/altdesktop/playerctl), a daemon to track media player activity. Available as [services.playerctld](option.html#opt-services.playerctld.enable).
|
||||
- [Playerctld](https://github.com/altdesktop/playerctl), a daemon to track media player activity. Available as [services.playerctld](options.html#opt-services.playerctld.enable).
|
||||
|
||||
- [Glance](https://github.com/glanceapp/glance), a self-hosted dashboard that puts all your feeds in one place. Available as [services.glance](option.html#opt-services.glance.enable).
|
||||
- [Glance](https://github.com/glanceapp/glance), a self-hosted dashboard that puts all your feeds in one place. Available as [services.glance](options.html#opt-services.glance.enable).
|
||||
|
||||
- [Apache Tika](https://github.com/apache/tika), a toolkit that detects and extracts metadata and text from over a thousand different file types. Available as [services.tika](option.html#opt-services.tika.enable).
|
||||
- [Apache Tika](https://github.com/apache/tika), a toolkit that detects and extracts metadata and text from over a thousand different file types. Available as [services.tika](options.html#opt-services.tika.enable).
|
||||
|
||||
- [Misskey](https://misskey-hub.net/en/), an interplanetary microblogging platform. Available as [services.misskey](options.html#opt-services.misskey.enable).
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
|
||||
- [ToDesk](https://www.todesk.com/linux.html), a remote desktop application. Available as [services.todesk](#opt-services.todesk.enable).
|
||||
|
||||
- [Dependency Track](https://dependencytrack.org/), an intelligent Component Analysis platform that allows organizations to identify and reduce risk in the software supply chain. Available as [services.dependency-track](option.html#opt-services.dependency-track.enable).
|
||||
- [Dependency Track](https://dependencytrack.org/), an intelligent Component Analysis platform that allows organizations to identify and reduce risk in the software supply chain. Available as [services.dependency-track](options.html#opt-services.dependency-track.enable).
|
||||
|
||||
- [Immich](https://github.com/immich-app/immich), a self-hosted photo and video backup solution. Available as [services.immich](#opt-services.immich.enable).
|
||||
|
||||
@@ -215,9 +215,9 @@
|
||||
|
||||
- [Swapspace](https://github.com/Tookmund/Swapspace), a dynamic swap space manager that turns your unused free space into swap automatically. Available as [services.swapspace](#opt-services.swapspace.enable).
|
||||
|
||||
- [Zapret](https://github.com/bol-van/zapret), a DPI bypass tool. Available as [services.zapret](option.html#opt-services.zapret.enable).
|
||||
- [Zapret](https://github.com/bol-van/zapret), a DPI bypass tool. Available as [services.zapret](options.html#opt-services.zapret.enable).
|
||||
|
||||
- [Glances](https://github.com/nicolargo/glances), an open-source system cross-platform monitoring tool. Available as [services.glances](option.html#opt-services.glances).
|
||||
- [Glances](https://github.com/nicolargo/glances), an open-source system cross-platform monitoring tool. Available as [services.glances](options.html#opt-services.glances).
|
||||
|
||||
## Backward Incompatibilities {#sec-release-24.11-incompatibilities}
|
||||
|
||||
|
||||
@@ -12,13 +12,19 @@
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- [Kimai](https://www.kimai.org/), a web-based multi-user time-tracking application. Available as [services.kimai](option.html#opt-services.kimai).
|
||||
- [Kimai](https://www.kimai.org/), a web-based multi-user time-tracking application. Available as [services.kimai](options.html#opt-services.kimai).
|
||||
|
||||
- [Omnom](https://github.com/asciimoo/omnom), a webpage bookmarking and snapshotting service. Available as [services.omnom](options.html#opt-services.omnom.enable).
|
||||
|
||||
- [Amazon CloudWatch Agent](https://github.com/aws/amazon-cloudwatch-agent), the official telemetry collector for AWS CloudWatch and AWS X-Ray. Available as [services.amazon-cloudwatch-agent](#opt-services.amazon-cloudwatch-agent.enable).
|
||||
- [Traccar](https://www.traccar.org/), a modern GPS Tracking Platform. Available as [services.traccar](#opt-services.traccar.enable).
|
||||
|
||||
- [agorakit](https://github.com/agorakit/agorakit), an organization tool for citizens' collectives. Available with [services.agorakit](#opt-services.agorakit.enable).
|
||||
- [Amazon CloudWatch Agent](https://github.com/aws/amazon-cloudwatch-agent), the official telemetry collector for AWS CloudWatch and AWS X-Ray. Available as [services.amazon-cloudwatch-agent](options.html#opt-services.amazon-cloudwatch-agent.enable).
|
||||
|
||||
- [agorakit](https://github.com/agorakit/agorakit), an organization tool for citizens' collectives. Available with [services.agorakit](options.html#opt-services.agorakit.enable).
|
||||
|
||||
- [mqtt-exporter](https://github.com/kpetremann/mqtt-exporter/), a Prometheus exporter for exposing messages from MQTT. Available as [services.prometheus.exporters.mqtt](#opt-services.prometheus.exporters.mqtt.enable).
|
||||
|
||||
- [Buffyboard](https://gitlab.postmarketos.org/postmarketOS/buffybox/-/tree/master/buffyboard), a framebuffer on-screen keyboard. Available as [services.buffyboard](option.html#opt-services.buffyboard).
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
@@ -31,6 +37,9 @@
|
||||
|
||||
- `buildGoPackage` has been removed. Use `buildGoModule` instead. See the [Go section in the nixpkgs manual](https://nixos.org/manual/nixpkgs/unstable/#sec-language-go) for details.
|
||||
|
||||
- `strawberry` has been updated to 1.2, which drops support for the VLC backend and Qt 5. The `strawberry-qt5` package
|
||||
and `withGstreamer`/`withVlc` override options have been removed due to this.
|
||||
|
||||
- `timescaledb` requires manual upgrade steps.
|
||||
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.
|
||||
@@ -39,8 +48,18 @@
|
||||
|
||||
- `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.
|
||||
|
||||
- `nodePackages.insect` has been removed, as it's deprecated by upstream. The suggested replacement is `numbat`.
|
||||
|
||||
- `nodePackages.webpack-dev-server` has been removed, as it should be installed in projects that use it instead.
|
||||
|
||||
- `racket_7_9` has been removed, as it is insecure. It is recommended to use Racket 8 instead.
|
||||
|
||||
- `fluxus` has been removed, as it depends on `racket_7_9` and had no updates in 9 years.
|
||||
|
||||
- The behavior of the `networking.nat.externalIP` and `networking.nat.externalIPv6` options has been changed. `networking.nat.forwardPorts` now only forwards packets destined for the specified IP addresses.
|
||||
|
||||
- `nodePackages.meshcommander` has been removed, as the package was deprecated by Intel.
|
||||
|
||||
- `kanata` was updated to v1.7.0, which introduces several breaking changes.
|
||||
See the release notes of
|
||||
[v1.7.0](https://github.com/jtroo/kanata/releases/tag/v1.7.0)
|
||||
@@ -51,14 +70,20 @@
|
||||
files have changed from `$out/share/fonts/{opentype,truetype}/NerdFonts` to
|
||||
`$out/share/fonts/{opentype,truetype}/NerdFonts/<fontDirName>`, where `<fontDirName>` can be found in the
|
||||
[official website](https://www.nerdfonts.com/font-downloads) as the titles in preview images, with the "Nerd Font"
|
||||
suffix and any whitespaces trimmed.
|
||||
suffix and any whitespaces trimmed. Configuration changes are required, see build output.
|
||||
|
||||
- `retroarch` has been refactored and the older `retroarch.override { cores = [ ... ]; }` to create a RetroArch derivation with custom cores doesn't work anymore, use `retroarch.withCores (cores: [ ... ])` instead. If you need more customization (e.g.: custom settings), use `wrapRetroArch` instead.
|
||||
|
||||
- `gkraken` software and `hardware.gkraken.enable` option have been removed, use `coolercontrol` via `programs.coolercontrol.enable` option instead.
|
||||
|
||||
- `nodePackages.ganache` has been removed, as the package has been deprecated by upstream.
|
||||
|
||||
- `containerd` has been updated to v2, which contains breaking changes. See the [containerd
|
||||
2.0](https://github.com/containerd/containerd/blob/main/docs/containerd-2.0.md) documentation for more
|
||||
details.
|
||||
|
||||
- `nodePackages.stackdriver-statsd-backend` has been removed, as the StackDriver service has been discontinued by Google, and therefore the package no longer works.
|
||||
|
||||
- the notmuch vim plugin now lives in a separate output of the `notmuch`
|
||||
package. Installing `notmuch` will not bring the notmuch vim package anymore,
|
||||
add `vimPlugins.notmuch-vim` to your (Neo)vim configuration if you want the
|
||||
@@ -70,6 +95,10 @@
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- Cinnamon has been updated to 6.4.
|
||||
|
||||
- `services.avahi.ipv6` now defaults to true.
|
||||
|
||||
- `bind.cacheNetworks` now only controls access for recursive queries, where it previously controlled access for all queries.
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
@@ -473,7 +473,7 @@ let format' = format; in let
|
||||
additionalSpace=$(( $(numfmt --from=iec '${additionalSpace}') + reservedSpace ))
|
||||
|
||||
# Compute required space in filesystem blocks
|
||||
diskUsage=$(find . ! -type d -print0 | du --files0-from=- --apparent-size --block-size "${blockSize}" | cut -f1 | sum_lines)
|
||||
diskUsage=$(find . ! -type d -print0 | du --files0-from=- --apparent-size --count-links --block-size "${blockSize}" | cut -f1 | sum_lines)
|
||||
# Each inode takes space!
|
||||
numInodes=$(find . | wc -l)
|
||||
# Convert to bytes, inodes take two blocks each!
|
||||
|
||||
@@ -30,14 +30,14 @@ rec {
|
||||
guestSystem = pkgs.stdenv.hostPlatform.system;
|
||||
|
||||
linuxHostGuestMatrix = {
|
||||
x86_64-linux = "${qemuPkg}/bin/qemu-kvm -cpu max";
|
||||
x86_64-linux = "${qemuPkg}/bin/qemu-system-x86_64 -machine accel=kvm:tcg -cpu max";
|
||||
armv7l-linux = "${qemuPkg}/bin/qemu-system-arm -machine virt,accel=kvm:tcg -cpu max";
|
||||
aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -machine virt,gic-version=max,accel=kvm:tcg -cpu max";
|
||||
powerpc64le-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv";
|
||||
powerpc64-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv";
|
||||
riscv32-linux = "${qemuPkg}/bin/qemu-system-riscv32 -machine virt";
|
||||
riscv64-linux = "${qemuPkg}/bin/qemu-system-riscv64 -machine virt";
|
||||
x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu max";
|
||||
x86_64-darwin = "${qemuPkg}/bin/qemu-system-x86_64 -machine accel=kvm:tcg -cpu max";
|
||||
};
|
||||
otherHostGuestMatrix = {
|
||||
aarch64-darwin = {
|
||||
|
||||
@@ -343,6 +343,25 @@ utils = rec {
|
||||
in
|
||||
filter (x: !(elem (getName x) namesToRemove)) packages;
|
||||
|
||||
/* Returns false if a package with the same name as the `package` is present in `packagesToDisable`.
|
||||
|
||||
Type:
|
||||
disablePackageByName :: package -> [package] -> bool
|
||||
|
||||
Example:
|
||||
disablePackageByName file-roller [ file-roller totem ]
|
||||
=> false
|
||||
|
||||
Example:
|
||||
disablePackageByName nautilus [ file-roller totem ]
|
||||
=> true
|
||||
*/
|
||||
disablePackageByName = package: packagesToDisable:
|
||||
let
|
||||
namesToDisable = map getName packagesToDisable;
|
||||
in
|
||||
!elem (getName package) namesToDisable;
|
||||
|
||||
systemdUtils = {
|
||||
lib = import ./systemd-lib.nix { inherit lib config pkgs utils; };
|
||||
unitOptions = import ./systemd-unit-options.nix { inherit lib systemdUtils; };
|
||||
|
||||
@@ -131,18 +131,30 @@ with lib;
|
||||
|
||||
boot.loader.timeout = 10;
|
||||
|
||||
boot.postBootCommands =
|
||||
''
|
||||
# After booting, register the contents of the Nix store
|
||||
# in the Nix database in the tmpfs.
|
||||
${config.nix.package}/bin/nix-store --load-db < /nix/store/nix-path-registration
|
||||
boot.postBootCommands = ''
|
||||
# After booting, register the contents of the Nix store
|
||||
# in the Nix database in the tmpfs.
|
||||
${config.nix.package}/bin/nix-store --load-db < /nix/store/nix-path-registration
|
||||
|
||||
# nixos-rebuild also requires a "system" profile and an
|
||||
# /etc/NIXOS tag.
|
||||
touch /etc/NIXOS
|
||||
${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
|
||||
'';
|
||||
# nixos-rebuild also requires a "system" profile and an
|
||||
# /etc/NIXOS tag.
|
||||
touch /etc/NIXOS
|
||||
${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
|
||||
|
||||
# Set password for user nixos if specified on cmdline
|
||||
# Allows using nixos-anywhere in headless environments
|
||||
for o in $(</proc/cmdline); do
|
||||
case "$o" in
|
||||
live.nixos.passwordHash=*)
|
||||
set -- $(IFS==; echo $o)
|
||||
${pkgs.gnugrep}/bin/grep -q "root::" /etc/shadow && ${pkgs.shadow}/bin/usermod -p "$2" root
|
||||
;;
|
||||
live.nixos.password=*)
|
||||
set -- $(IFS==; echo $o)
|
||||
${pkgs.gnugrep}/bin/grep -q "root::" /etc/shadow && echo "root:$2" | ${pkgs.shadow}/bin/chpasswd
|
||||
;;
|
||||
esac
|
||||
done
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -57,17 +57,6 @@ in
|
||||
"nmi_watchdog=panic"
|
||||
"softlockup_panic=1"
|
||||
];
|
||||
kernelPatches = [ {
|
||||
name = "crashdump-config";
|
||||
patch = null;
|
||||
extraConfig = ''
|
||||
CRASH_DUMP y
|
||||
DEBUG_INFO y
|
||||
PROC_VMCORE y
|
||||
LOCKUP_DETECTOR y
|
||||
HARDLOCKUP_DETECTOR y
|
||||
'';
|
||||
} ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -278,11 +278,23 @@ in
|
||||
PRUNE_BIND_MOUNTS = if cfg.pruneBindMounts then "yes" else "no";
|
||||
};
|
||||
serviceConfig = {
|
||||
CapabilityBoundingSet = "CAP_DAC_READ_SEARCH CAP_CHOWN";
|
||||
Nice = 19;
|
||||
IOSchedulingClass = "idle";
|
||||
IPAddressDeny = "any";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = "yes";
|
||||
PrivateDevices = true;
|
||||
PrivateNetwork = "yes";
|
||||
NoNewPrivileges = "yes";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHostname = true;
|
||||
RestrictAddressFamilies = "AF_UNIX";
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
ReadOnlyPaths = "/";
|
||||
# Use dirOf cfg.output because mlocate creates temporary files next to
|
||||
# the actual database. We could specify and create them as well,
|
||||
@@ -290,6 +302,8 @@ in
|
||||
# NOTE: If /var/cache does not exist, this leads to the misleading error message:
|
||||
# update-locatedb.service: Failed at step NAMESPACE spawning …/update-locatedb-start: No such file or directory
|
||||
ReadWritePaths = dirOf cfg.output;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "@system-service @chown";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -588,6 +588,7 @@
|
||||
./services/hardware/bluetooth.nix
|
||||
./services/hardware/bolt.nix
|
||||
./services/hardware/brltty.nix
|
||||
./services/hardware/buffyboard.nix
|
||||
./services/hardware/ddccontrol.nix
|
||||
./services/hardware/display.nix
|
||||
./services/hardware/fancontrol.nix
|
||||
@@ -947,6 +948,7 @@
|
||||
./services/monitoring/telegraf.nix
|
||||
./services/monitoring/thanos.nix
|
||||
./services/monitoring/todesk.nix
|
||||
./services/monitoring/traccar.nix
|
||||
./services/monitoring/tremor-rs.nix
|
||||
./services/monitoring/tuptime.nix
|
||||
./services/monitoring/unpoller.nix
|
||||
|
||||
@@ -313,5 +313,5 @@ in
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ sigmasquadron ];
|
||||
}
|
||||
|
||||
@@ -1668,13 +1668,11 @@ in
|
||||
(lib.concatMap lib.attrValues)
|
||||
(lib.filter (rule: rule.enable))
|
||||
(lib.catAttrs "modulePath")
|
||||
# TODO(@uninsane): replace this warning + lib.filter with just an assertion
|
||||
(map (modulePath: lib.warnIfNot
|
||||
(map (modulePath: lib.throwIfNot
|
||||
(lib.hasPrefix "/" modulePath)
|
||||
''non-absolute PAM modulePath "${modulePath}" is unsupported by apparmor and will be treated as an error by future versions of nixpkgs; see <https://github.com/NixOS/nixpkgs/pull/314791>''
|
||||
''non-absolute PAM modulePath "${modulePath}" is unsupported by apparmor''
|
||||
modulePath
|
||||
))
|
||||
(lib.filter (lib.hasPrefix "/"))
|
||||
lib.unique
|
||||
(map (module: "mr ${module},"))
|
||||
concatLines
|
||||
|
||||
@@ -170,15 +170,6 @@ static int make_caps_ambient(const char *self_path) {
|
||||
"MALLOC_ARENA_TEST\0"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
ASSERT(argc >= 1);
|
||||
|
||||
// argv[0] goes into a lot of places, to a far greater degree than other elements
|
||||
// of argv. glibc has had buffer overflows relating to argv[0], eg CVE-2023-6246.
|
||||
// Since we expect the wrappers to be invoked from either $PATH or /run/wrappers/bin,
|
||||
// there should be no reason to pass any particularly large values here, so we can
|
||||
// be strict for strictness' sake.
|
||||
ASSERT(strlen(argv[0]) < 512);
|
||||
|
||||
int debug = getenv(wrapper_debug) != NULL;
|
||||
|
||||
// Drop insecure environment variables explicitly
|
||||
@@ -209,10 +200,22 @@ int main(int argc, char **argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *replacement_argv[2] = {SOURCE_PROG, NULL};
|
||||
char *old_argv0;
|
||||
// Replace untrusted or missing argv[0] by the wrapped program path.
|
||||
// This mitigates vulnerabilities caused by incorrect handling in privileged code.
|
||||
if (argv[0]) {
|
||||
old_argv0 = argv[0];
|
||||
argv[0] = SOURCE_PROG;
|
||||
} else {
|
||||
old_argv0 = "«nullptr»";
|
||||
argv = replacement_argv;
|
||||
}
|
||||
|
||||
execve(SOURCE_PROG, argv, environ);
|
||||
|
||||
|
||||
fprintf(stderr, "%s: cannot run `%s': %s\n",
|
||||
argv[0], SOURCE_PROG, strerror(errno));
|
||||
old_argv0, SOURCE_PROG, strerror(errno));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ with lib;
|
||||
} // cfg.extraEnvironment;
|
||||
|
||||
path = (with pkgs; [
|
||||
bash
|
||||
bashInteractive
|
||||
coreutils
|
||||
git
|
||||
gnutar
|
||||
|
||||
@@ -139,7 +139,7 @@ in
|
||||
serviceConfig = {
|
||||
ExecStart = lib.escapeShellArgs (
|
||||
startCLIList
|
||||
++ lib.optionals (cfg.prometheusConfig != null) [ "-promscrape.config=${prometheusConfigYml}" ]
|
||||
++ lib.optionals (cfg.prometheusConfig != {}) [ "-promscrape.config=${prometheusConfigYml}" ]
|
||||
);
|
||||
|
||||
DynamicUser = true;
|
||||
|
||||
@@ -90,6 +90,7 @@ in
|
||||
lomiri-filemanager-app
|
||||
lomiri-gallery-app
|
||||
lomiri-history-service
|
||||
lomiri-mediaplayer-app
|
||||
lomiri-polkit-agent
|
||||
lomiri-schemas # exposes some required dbus interfaces
|
||||
lomiri-session # wrappers to properly launch the session
|
||||
|
||||
@@ -8,7 +8,6 @@ in {
|
||||
options = {
|
||||
services.espanso = {
|
||||
enable = mkEnableOption "Espanso";
|
||||
wayland = mkEnableOption "use the Wayland compatible espanso package";
|
||||
package = mkPackageOption pkgs "espanso" {
|
||||
example = "pkgs.espanso-wayland";
|
||||
};
|
||||
|
||||
@@ -88,7 +88,7 @@ in
|
||||
"asusd/anime.ron" = maybeConfig "anime.ron" cfg.animeConfig;
|
||||
"asusd/asusd.ron" = maybeConfig "asusd.ron" cfg.asusdConfig;
|
||||
"asusd/aura.ron" = maybeConfig "aura.ron" cfg.auraConfig;
|
||||
"asusd/profile.conf" = maybeConfig "profile.ron" cfg.profileConfig;
|
||||
"asusd/profile.ron" = maybeConfig "profile.ron" cfg.profileConfig;
|
||||
"asusd/fan_curves.ron" = maybeConfig "fan_curves.ron" cfg.fanCurvesConfig;
|
||||
"asusd/asusd_user_ledmodes.ron" = maybeConfig "asusd_user_ledmodes.ron" cfg.userLedModesConfig;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
# INTEGRATION NOTES:
|
||||
# Buffyboard integrates as a virtual device in /dev/input
|
||||
# which reads touch or pointer events from other input devices
|
||||
# and generates events based on where those map to the keys it renders to the framebuffer.
|
||||
#
|
||||
# Buffyboard generates these events whether or not its onscreen keyboard is actually visible.
|
||||
# Hence special care is needed if running anything which claims ownership of the display (such as a desktop environment),
|
||||
# to avoid unwanted input events being triggered during normal desktop operation.
|
||||
#
|
||||
# Desktop users are recommended to either:
|
||||
# 1. Stop buffyboard once your DE is started.
|
||||
# e.g. `services.buffyboard.unitConfig.Conflicts = [ "my-de.service" ];`
|
||||
# 2. Configure your DE to ignore input events from buffyboard (product-id=25209; vendor-id=26214; name=rd)
|
||||
# e.g. `echo 'input "26214:25209:rd" events disabled' > ~/.config/sway/config`
|
||||
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
utils,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.buffyboard;
|
||||
ini = pkgs.formats.ini { };
|
||||
in
|
||||
{
|
||||
meta.maintainers = with lib.maintainers; [ colinsane ];
|
||||
|
||||
options = {
|
||||
services.buffyboard = with lib; {
|
||||
enable = mkEnableOption "buffyboard framebuffer keyboard (on-screen keyboard)";
|
||||
package = mkPackageOption pkgs "buffybox" { };
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Extra CLI arguments to pass to buffyboard.
|
||||
'';
|
||||
example = [
|
||||
"--geometry=1920x1080@640,0"
|
||||
"--dpi=192"
|
||||
"--rotate=2"
|
||||
"--verbose"
|
||||
];
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
type = lib.types.path;
|
||||
default = ini.generate "buffyboard.conf" (lib.filterAttrsRecursive (_: v: v != null) cfg.settings);
|
||||
defaultText = lib.literalExpression ''ini.generate "buffyboard.conf" cfg.settings'';
|
||||
description = ''
|
||||
Path to an INI format configuration file to provide Buffyboard.
|
||||
By default, this is generated from whatever you've set in `settings`.
|
||||
If specified manually, then `settings` is ignored.
|
||||
|
||||
For an example config file see [here](https://gitlab.postmarketos.org/postmarketOS/buffybox/-/blob/master/buffyboard/buffyboard.conf)
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
description = ''
|
||||
Settings to include in /etc/buffyboard.conf.
|
||||
Every option here is strictly optional:
|
||||
Buffyboard will use its own baked-in defaults for those options left unset.
|
||||
'';
|
||||
type = types.submodule {
|
||||
freeformType = ini.type;
|
||||
|
||||
options.input.pointer = mkOption {
|
||||
type = types.nullOr types.bool;
|
||||
default = null;
|
||||
description = ''
|
||||
Enable or disable the use of a hardware mouse or other pointing device.
|
||||
'';
|
||||
};
|
||||
options.input.touchscreen = mkOption {
|
||||
type = types.nullOr types.bool;
|
||||
default = null;
|
||||
description = ''
|
||||
Enable or disable the use of the touchscreen.
|
||||
'';
|
||||
};
|
||||
|
||||
options.theme.default = mkOption {
|
||||
type = types.either types.str (
|
||||
types.enum [
|
||||
null
|
||||
"adwaita-dark"
|
||||
"breezy-dark"
|
||||
"breezy-light"
|
||||
"nord-dark"
|
||||
"nord-light"
|
||||
"pmos-dark"
|
||||
"pmos-light"
|
||||
]
|
||||
);
|
||||
default = null;
|
||||
description = ''
|
||||
Selects the default theme on boot. Can be changed at runtime to the alternative theme.
|
||||
'';
|
||||
};
|
||||
options.quirks.fbdev_force_refresh = mkOption {
|
||||
type = types.nullOr types.bool;
|
||||
default = null;
|
||||
description = ''
|
||||
If true and using the framebuffer backend, this triggers a display refresh after every draw operation.
|
||||
This has a negative performance impact.
|
||||
'';
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.packages = [ cfg.package ];
|
||||
systemd.services.buffyboard = {
|
||||
# upstream provides the service (including systemd hardening): we just configure it to start by default
|
||||
# and override ExecStart so as to optionally pass extra arguments
|
||||
serviceConfig.ExecStart = [
|
||||
"" # clear default ExecStart
|
||||
(utils.escapeSystemdExecArgs (
|
||||
[
|
||||
(lib.getExe' cfg.package "buffyboard")
|
||||
"--config-override"
|
||||
cfg.configFile
|
||||
]
|
||||
++ cfg.extraFlags
|
||||
))
|
||||
];
|
||||
wantedBy = [ "getty.target" ];
|
||||
before = [ "getty.target" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -853,7 +853,8 @@ in
|
||||
smtpd_tls_cert_file = cfg.sslCert;
|
||||
smtpd_tls_key_file = cfg.sslKey;
|
||||
|
||||
smtpd_tls_security_level = "may";
|
||||
smtpd_tls_security_level = lib.mkDefault "may";
|
||||
|
||||
};
|
||||
|
||||
services.postfix.masterConfig = {
|
||||
|
||||
@@ -228,7 +228,6 @@ in
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
|
||||
RestrictAddressFamilies = [
|
||||
"AF_UNIX"
|
||||
@@ -240,11 +239,10 @@ in
|
||||
RestrictRealtime = true;
|
||||
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
|
||||
SystemCallFilter = [
|
||||
"@sandbox"
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
];
|
||||
SystemCallArchitectures = "native";
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ in
|
||||
description = ''
|
||||
Set the Access-Control-Allow-Origin header in the HTTP response,
|
||||
used for direct (non-proxy) JavaScript-based access from browsers.
|
||||
`null` to allow access from all sites.
|
||||
`"*"` to allow access from all sites.
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
@@ -69,9 +69,9 @@ in
|
||||
serviceConfig = with pkgs; {
|
||||
DynamicUser = true;
|
||||
StateDirectory = baseNameOf libDir;
|
||||
ExecStartPre = "${getBin pykms}/libexec/create_pykms_db.sh ${libDir}/clients.db";
|
||||
ExecStartPre = "${lib.getBin pykms}/libexec/create_pykms_db.sh ${libDir}/clients.db";
|
||||
ExecStart = lib.concatStringsSep " " ([
|
||||
"${getBin pykms}/bin/server"
|
||||
"${lib.getBin pykms}/bin/server"
|
||||
"--logfile=STDOUT"
|
||||
"--loglevel=${cfg.logLevel}"
|
||||
"--sqlite=${libDir}/clients.db"
|
||||
|
||||
@@ -442,6 +442,7 @@ in
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
|
||||
@@ -52,11 +52,13 @@ let
|
||||
"keylight"
|
||||
"klipper"
|
||||
"knot"
|
||||
"libvirt"
|
||||
"lnd"
|
||||
"mail"
|
||||
"mikrotik"
|
||||
"modemmanager"
|
||||
"mongodb"
|
||||
"mqtt"
|
||||
"mysqld"
|
||||
"nats"
|
||||
"nextcloud"
|
||||
@@ -332,6 +334,13 @@ in
|
||||
Config file specified in `services.prometheus.exporters.ipmi.webConfigFile' must
|
||||
not reside within /tmp - it won't be visible to the systemd service.
|
||||
'';
|
||||
} {
|
||||
assertion =
|
||||
cfg.restic.enable -> ((cfg.restic.repository == null) != (cfg.restic.repositoryFile == null));
|
||||
message = ''
|
||||
Please specify either 'services.prometheus.exporters.restic.repository'
|
||||
or 'services.prometheus.exporters.restic.repositoryFile'.
|
||||
'';
|
||||
} {
|
||||
assertion = cfg.snmp.enable -> (
|
||||
(cfg.snmp.configurationPath == null) != (cfg.snmp.configuration == null)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.prometheus.exporters.libvirt;
|
||||
in
|
||||
{
|
||||
port = 9177;
|
||||
extraOpts = {
|
||||
libvirtUri = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "qemu:///system";
|
||||
description = "Libvirt URI from which to extract metrics";
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${lib.getExe pkgs.prometheus-libvirt-exporter} \
|
||||
--web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
|
||||
--libvirt.uri ${cfg.libvirtUri} ${lib.concatStringsSep " " cfg.extraFlags}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
options,
|
||||
utils,
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
mkIf
|
||||
mkEnableOption
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
cfg = config.services.prometheus.exporters.mqtt;
|
||||
toConfigBoolean = x: if x then "True" else "False";
|
||||
toConfigList = builtins.concatStringsSep ",";
|
||||
in
|
||||
{
|
||||
# https://github.com/kpetremann/mqtt-exporter/tree/master?tab=readme-ov-file#configuration
|
||||
port = 9000;
|
||||
extraOpts = {
|
||||
keepFullTopic = mkEnableOption "Keep entire topic instead of the first two elements only. Usecase: Shelly 3EM";
|
||||
logLevel = mkOption {
|
||||
type = types.enum [
|
||||
"CRITICAL"
|
||||
"ERROR"
|
||||
"WARNING"
|
||||
"INFO"
|
||||
"DEBUG"
|
||||
];
|
||||
default = "INFO";
|
||||
example = "DEBUG";
|
||||
description = "Logging level";
|
||||
};
|
||||
logMqttMessage = mkEnableOption "Log MQTT original message, only if `LOG_LEVEL` is set to DEBUG.";
|
||||
mqttIgnoredTopics = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = "Lists of topics to ignore. Accepts wildcards.";
|
||||
};
|
||||
mqttAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "IP or hostname of MQTT broker.";
|
||||
};
|
||||
mqttPort = mkOption {
|
||||
type = types.port;
|
||||
default = 1883;
|
||||
description = "TCP port of MQTT broker.";
|
||||
};
|
||||
mqttTopic = mkOption {
|
||||
type = types.str;
|
||||
default = "#";
|
||||
description = "Topic path to subscribe to.";
|
||||
};
|
||||
mqttKeepAlive = mkOption {
|
||||
type = types.int;
|
||||
default = 60;
|
||||
example = 30;
|
||||
description = "Keep alive interval to maintain connection with MQTT broker.";
|
||||
};
|
||||
mqttUsername = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "mqttexporter";
|
||||
description = "Username which should be used to authenticate against the MQTT broker.";
|
||||
};
|
||||
mqttV5Protocol = mkEnableOption "Force to use MQTT protocol v5 instead of 3.1.1.";
|
||||
mqttClientId = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Set client ID manually for MQTT connection";
|
||||
};
|
||||
mqttExposeClientId = mkEnableOption "Expose the client ID as a label in Prometheus metrics.";
|
||||
prometheusPrefix = mkOption {
|
||||
type = types.str;
|
||||
default = "mqtt_";
|
||||
description = "Prefix added to the metric name.";
|
||||
};
|
||||
topicLabel = mkOption {
|
||||
type = types.str;
|
||||
default = "topic";
|
||||
description = "Define the Prometheus label for the topic.";
|
||||
};
|
||||
zigbee2MqttAvailability = mkEnableOption "Normalize sensor name for device availability metric added by Zigbee2MQTT.";
|
||||
zwaveTopicPrefix = mkOption {
|
||||
type = types.str;
|
||||
default = "zwave/";
|
||||
description = "MQTT topic used for Zwavejs2Mqtt messages.";
|
||||
};
|
||||
esphomeTopicPrefixes = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = "MQTT topic used for ESPHome messages.";
|
||||
};
|
||||
hubitatTopicPrefixes = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "hubitat/" ];
|
||||
description = "MQTT topic used for Hubitat messages.";
|
||||
};
|
||||
environmentFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = [ "/run/secrets/mqtt-exporter" ];
|
||||
description = ''
|
||||
File to load as environment file. Useful for e.g. setting `MQTT_PASSWORD`
|
||||
without putting any secrets into the Nix store.
|
||||
'';
|
||||
};
|
||||
};
|
||||
serviceOpts = {
|
||||
environment = {
|
||||
KEEP_FULL_TOPIC = toConfigBoolean cfg.keepFullTopic;
|
||||
LOG_LEVEL = cfg.logLevel;
|
||||
LOG_MQTT_MESSAGE = toConfigBoolean cfg.logMqttMessage;
|
||||
MQTT_IGNORED_TOPIC = toConfigList cfg.mqttIgnoredTopics;
|
||||
MQTT_ADDRESS = cfg.mqttAddress;
|
||||
MQTT_PORT = toString cfg.mqttPort;
|
||||
MQTT_TOPIC = cfg.mqttTopic;
|
||||
MQTT_KEEPALIVE = toString cfg.mqttKeepAlive;
|
||||
MQTT_USERNAME = cfg.mqttUsername;
|
||||
MQTT_V5_PROTOCOL = toConfigBoolean cfg.mqttV5Protocol;
|
||||
MQTT_CLIENT_ID = mkIf (cfg.mqttClientId != null) cfg.mqttClientId;
|
||||
PROMETHEUS_ADDRESS = cfg.listenAddress;
|
||||
PROMETHEUS_PORT = toString cfg.port;
|
||||
PROMETHEUS_PREFIX = cfg.prometheusPrefix;
|
||||
TOPIC_LABEL = cfg.topicLabel;
|
||||
ZIGBEE2MQTT_AVAILABILITY = toConfigBoolean cfg.zigbee2MqttAvailability;
|
||||
ZWAVE_TOPIC_PREFIX = cfg.zwaveTopicPrefix;
|
||||
ESPHOME_TOPIC_PREFIXES = toConfigList cfg.esphomeTopicPrefixes;
|
||||
HUBITAT_TOPIC_PREFIXES = toConfigList cfg.hubitatTopicPrefixes;
|
||||
};
|
||||
serviceConfig = {
|
||||
EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
||||
ExecStart = lib.getExe pkgs.mqtt-exporter;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -10,6 +10,7 @@ let
|
||||
mapAttrs'
|
||||
splitString
|
||||
toUpper
|
||||
optional
|
||||
optionalAttrs
|
||||
nameValuePair
|
||||
;
|
||||
@@ -18,13 +19,22 @@ in
|
||||
port = 9753;
|
||||
extraOpts = {
|
||||
repository = mkOption {
|
||||
type = types.str;
|
||||
type = with lib.types; nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
URI pointing to the repository to monitor.
|
||||
'';
|
||||
example = "sftp:backup@192.168.1.100:/backups/example";
|
||||
};
|
||||
|
||||
repositoryFile = mkOption {
|
||||
type = with lib.types; nullOr path;
|
||||
default = null;
|
||||
description = ''
|
||||
Path to the file containing the URI for the repository to monitor.
|
||||
'';
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
@@ -103,13 +113,21 @@ in
|
||||
|
||||
serviceOpts = {
|
||||
script = ''
|
||||
export RESTIC_REPOSITORY=${
|
||||
if cfg.repositoryFile != null
|
||||
then "$(cat $CREDENTIALS_DIRECTORY/RESTIC_REPOSITORY)"
|
||||
else "${cfg.repository}"
|
||||
}
|
||||
export RESTIC_PASSWORD_FILE=$CREDENTIALS_DIRECTORY/RESTIC_PASSWORD_FILE
|
||||
${pkgs.prometheus-restic-exporter}/bin/restic-exporter.py \
|
||||
${concatStringsSep " \\\n " cfg.extraFlags}
|
||||
'';
|
||||
serviceConfig = {
|
||||
EnvironmentFile = mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
||||
LoadCredential = [ "RESTIC_PASSWORD_FILE:${cfg.passwordFile}" ];
|
||||
LoadCredential =
|
||||
[ "RESTIC_PASSWORD_FILE:${cfg.passwordFile}" ]
|
||||
++ optional (cfg.repositoryFile != null)
|
||||
[ "RESTIC_REPOSITORY:${cfg.repositoryFile}" ];
|
||||
};
|
||||
environment =
|
||||
let
|
||||
@@ -119,7 +137,6 @@ in
|
||||
toRcloneVal = v: if lib.isBool v then lib.boolToString v else v;
|
||||
in
|
||||
{
|
||||
RESTIC_REPOSITORY = cfg.repository;
|
||||
LISTEN_ADDRESS = cfg.listenAddress;
|
||||
LISTEN_PORT = toString cfg.port;
|
||||
REFRESH_INTERVAL = toString cfg.refreshInterval;
|
||||
|
||||
@@ -87,7 +87,6 @@ in
|
||||
"console"
|
||||
"repeater"
|
||||
"statsd-librato-backend"
|
||||
"stackdriver-statsd-backend"
|
||||
"statsd-influxdb-backend"
|
||||
];
|
||||
type = lib.types.listOf lib.types.str;
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.traccar;
|
||||
stateDirectory = "/var/lib/traccar";
|
||||
configFilePath = "${stateDirectory}/config.xml";
|
||||
expandCamelCase = lib.replaceStrings lib.upperChars (map (s: ".${s}") lib.lowerChars);
|
||||
mkConfigEntry = key: value: "<entry key='${expandCamelCase key}'>${value}</entry>";
|
||||
mkConfig =
|
||||
configurationOptions:
|
||||
pkgs.writeText "traccar.xml" ''
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE properties SYSTEM 'http://java.sun.com/dtd/properties.dtd'>
|
||||
<properties>
|
||||
${builtins.concatStringsSep "\n" (lib.mapAttrsToList mkConfigEntry configurationOptions)}
|
||||
</properties>
|
||||
'';
|
||||
|
||||
defaultConfig = {
|
||||
databaseDriver = "org.h2.Driver";
|
||||
databasePassword = "";
|
||||
databaseUrl = "jdbc:h2:${stateDirectory}/traccar";
|
||||
databaseUser = "sa";
|
||||
loggerConsole = "true";
|
||||
mediaPath = "${stateDirectory}/media";
|
||||
templatesRoot = "${stateDirectory}/templates";
|
||||
};
|
||||
in
|
||||
{
|
||||
options.services.traccar = {
|
||||
enable = lib.mkEnableOption "Traccar, an open source GPS tracking system";
|
||||
settings = lib.mkOption {
|
||||
apply = lib.recursiveUpdate defaultConfig;
|
||||
default = defaultConfig;
|
||||
description = ''
|
||||
{file}`config.xml` configuration as a Nix attribute set.
|
||||
Attribute names are translated from camelCase to dot-separated strings. For instance:
|
||||
{option}`mailSmtpPort = "25"`
|
||||
would result in the following configuration property:
|
||||
`<entry key='mail.smtp.port'>25</entry>`
|
||||
Configuration options should match those described in
|
||||
[Traccar - Configuration File](https://www.traccar.org/configuration-file/).
|
||||
Secret tokens should be specified using {option}`environmentFile`
|
||||
instead of this world-readable attribute set.
|
||||
'';
|
||||
};
|
||||
environmentFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
File containing environment variables to substitute in the configuration before starting Traccar.
|
||||
|
||||
Can be used for storing the secrets without making them available in the world-readable Nix store.
|
||||
|
||||
For example, you can set {option}`services.traccar.settings.databasePassword = "$TRACCAR_DB_PASSWORD"`
|
||||
and then specify `TRACCAR_DB_PASSWORD="<secret>"` in the environment file.
|
||||
This value will get substituted in the configuration file.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
let
|
||||
configuration = mkConfig cfg.settings;
|
||||
in
|
||||
lib.mkIf cfg.enable {
|
||||
systemd.services.traccar = {
|
||||
enable = true;
|
||||
description = "Traccar";
|
||||
|
||||
after = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
|
||||
preStart = ''
|
||||
# Copy new templates into our state directory.
|
||||
cp -a --update=none ${pkgs.traccar}/templates ${stateDirectory}
|
||||
test -f '${configFilePath}' && rm -f '${configFilePath}'
|
||||
|
||||
# Substitute the configFile from Envvars read from EnvironmentFile
|
||||
old_umask=$(umask)
|
||||
umask 0177
|
||||
${lib.getExe pkgs.envsubst} \
|
||||
-i ${configuration} \
|
||||
-o ${configFilePath}
|
||||
umask $old_umask
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
EnvironmentFile = cfg.environmentFile;
|
||||
ExecStart = "${lib.getExe pkgs.traccar} ${configFilePath}";
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectSystem = "strict";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 10;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
StateDirectory = "traccar";
|
||||
SuccessExitStatus = 143;
|
||||
Type = "simple";
|
||||
# Set the working directory to traccar's package.
|
||||
# Traccar only searches for the DB migrations relative to it's WorkingDirectory and nothing worked to
|
||||
# work around this. To avoid copying the migrations over to the state directory, we use the package as
|
||||
# WorkingDirectory.
|
||||
WorkingDirectory = "${pkgs.traccar}";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -51,21 +51,30 @@ in
|
||||
DynamicUser = true;
|
||||
ExecStart = "${cfg.package}/bin/uptime-kuma-server";
|
||||
Restart = "on-failure";
|
||||
ProtectHome = true;
|
||||
ProtectSystem = "strict";
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
AmbientCapabilities = "";
|
||||
CapabilityBoundingSet = "";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = false; # enabling it breaks execution
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "noaccess";
|
||||
ProtectSystem = "strict";
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" "AF_UNIX" "AF_NETLINK" ];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
RemoveIPC = true;
|
||||
PrivateMounts = true;
|
||||
SystemCallArchitectures = "native";
|
||||
UMask = 027;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -115,7 +115,7 @@ in {
|
||||
CacheDirectory = "vmagent";
|
||||
ExecStart = lib.escapeShellArgs (
|
||||
startCLIList
|
||||
++ lib.optionals (cfg.prometheusConfig != null) ["-promscrape.config=${prometheusConfigYml}"]
|
||||
++ lib.optionals (cfg.prometheusConfig != {}) ["-promscrape.config=${prometheusConfigYml}"]
|
||||
);
|
||||
LoadCredential = lib.optional (cfg.remoteWrite.basicAuthPasswordFile != null) [
|
||||
"remote_write_basic_auth_password:${cfg.remoteWrite.basicAuthPasswordFile}"
|
||||
|
||||
@@ -101,6 +101,19 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
usershares = {
|
||||
enable = lib.mkEnableOption "user-configurable Samba shares";
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "samba";
|
||||
description = ''
|
||||
Name of the group members of which will be allowed to create usershares.
|
||||
|
||||
The group will be created automatically.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
nsswins = lib.mkEnableOption ''
|
||||
WINS NSS (Name Service Switch) plug-in.
|
||||
|
||||
@@ -308,5 +321,22 @@ in
|
||||
restartTriggers = [ configFile ];
|
||||
};
|
||||
})
|
||||
|
||||
(lib.mkIf (cfg.enable && cfg.usershares.enable) {
|
||||
users.groups.${cfg.usershares.group} = {};
|
||||
|
||||
systemd.tmpfiles.settings."50-samba-usershares"."/var/lib/samba/usershares".d = {
|
||||
user = "root";
|
||||
group = cfg.usershares.group;
|
||||
mode = "1775"; # sticky so users can't delete others' shares
|
||||
};
|
||||
|
||||
# set some reasonable defaults
|
||||
services.samba.settings.global = lib.mkDefault {
|
||||
"usershare path" = "/var/lib/samba/usershares";
|
||||
"usershare max shares" = 100; # high enough to be considered ~unlimited
|
||||
"usershare allow guests" = true;
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ in
|
||||
|
||||
ipv6 = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
default = true;
|
||||
description = "Whether to use IPv6.";
|
||||
};
|
||||
|
||||
|
||||
@@ -300,7 +300,7 @@ in {
|
||||
|
||||
capabilities = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = ["HT40" "HT40-" "SHORT-GI-20" "SHORT-GI-40"];
|
||||
default = ["HT40" "SHORT-GI-20" "SHORT-GI-40"];
|
||||
example = ["LDPC" "HT40+" "HT40-" "GF" "SHORT-GI-20" "SHORT-GI-40" "TX-STBC" "RX-STBC1"];
|
||||
description = ''
|
||||
HT (High Throughput) capabilities given as a list of flags.
|
||||
|
||||
@@ -23,7 +23,7 @@ in with lib; {
|
||||
package = mkPackageOption pkgs "zeronet" { };
|
||||
|
||||
settings = mkOption {
|
||||
type = with types; attrsOf (oneOf [ str int bool (listOf str) ]);
|
||||
type = with types; attrsOf (attrsOf (oneOf [ str int bool (listOf str) ]));
|
||||
default = {};
|
||||
example = literalExpression "{ global.tor = enable; }";
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ with lib;
|
||||
|
||||
let
|
||||
|
||||
inherit (pkgs) cups-pk-helper cups-filters xdg-utils;
|
||||
inherit (pkgs) cups-pk-helper libcupsfilters cups-filters xdg-utils;
|
||||
|
||||
cfg = config.services.printing;
|
||||
cups = cfg.package;
|
||||
@@ -35,7 +35,7 @@ let
|
||||
bindir = pkgs.buildEnv {
|
||||
name = "cups-progs";
|
||||
paths =
|
||||
[ cups.out additionalBackends cups-filters pkgs.ghostscript ]
|
||||
[ cups.out additionalBackends libcupsfilters cups-filters pkgs.ghostscript ]
|
||||
++ cfg.drivers;
|
||||
pathsToLink = [ "/lib" "/share/cups" "/bin" ];
|
||||
postBuild = cfg.bindirCmds;
|
||||
@@ -278,6 +278,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
browsed.package = lib.mkPackageOption pkgs "cups-browsed" {};
|
||||
|
||||
browsedConf = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
@@ -436,7 +438,7 @@ in
|
||||
|
||||
path = [ cups ];
|
||||
|
||||
serviceConfig.ExecStart = "${cups-filters}/bin/cups-browsed";
|
||||
serviceConfig.ExecStart = "${cfg.browsed.package}/bin/cups-browsed";
|
||||
|
||||
restartTriggers = [ browsedFile ];
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ let
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(mkRemovedOptionModule [ "debug" ] ''
|
||||
(mkRemovedOptionModule [ "services" "aesmd" "debug" ] ''
|
||||
Enable debug mode by overriding the aesmd package directly:
|
||||
|
||||
services.aesmd.package = pkgs.sgx-psw.override { debug = true; };
|
||||
|
||||
@@ -231,7 +231,10 @@ in
|
||||
enableServer = mkEnableOption "the Kanidm server";
|
||||
enablePam = mkEnableOption "the Kanidm PAM and NSS integration";
|
||||
|
||||
package = mkPackageOption pkgs "kanidm" { };
|
||||
package = mkPackageOption pkgs "kanidm" {
|
||||
example = "kanidm_1_4";
|
||||
extraDescription = "If not set will receive a specific version based on stateVersion. Set to `pkgs.kanidm` to always receive the latest version, with the understanding that this could introduce breaking changes.";
|
||||
};
|
||||
|
||||
serverSettings = mkOption {
|
||||
type = types.submodule {
|
||||
@@ -811,6 +814,16 @@ in
|
||||
)
|
||||
);
|
||||
|
||||
services.kanidm.package =
|
||||
let
|
||||
pkg =
|
||||
if lib.versionAtLeast config.system.stateVersion "24.11" then
|
||||
pkgs.kanidm_1_4
|
||||
else
|
||||
lib.warn "No default kanidm package found for stateVersion = '${config.system.stateVersion}'. Using unpinned version. Consider setting `services.kanidm.package = pkgs.kanidm_1_x` to avoid upgrades introducing breaking changes." pkgs.kanidm;
|
||||
in
|
||||
lib.mkDefault pkg;
|
||||
|
||||
environment.systemPackages = mkIf cfg.enableClient [ cfg.package ];
|
||||
|
||||
systemd.tmpfiles.settings."10-kanidm" = {
|
||||
|
||||
@@ -46,8 +46,8 @@ let
|
||||
};
|
||||
|
||||
template = mkOption {
|
||||
default = [ ];
|
||||
type = with types; listOf (attrsOf anything);
|
||||
default = null;
|
||||
type = with types; nullOr (listOf (attrsOf anything));
|
||||
description =
|
||||
let upstreamDocs =
|
||||
if flavour == "vault-agent"
|
||||
|
||||
@@ -134,6 +134,8 @@ in
|
||||
Group = cfg.group;
|
||||
RemoveIPC = true;
|
||||
PrivateTmp = true;
|
||||
# https://github.com/twosigma/nsncd/pull/33/files#r1496927653
|
||||
Environment = [ "NSNCD_HANDOFF_TIMEOUT=10" ];
|
||||
NoNewPrivileges = true;
|
||||
RestrictSUIDSGID = true;
|
||||
ProtectSystem = "strict";
|
||||
|
||||
@@ -1,8 +1,29 @@
|
||||
{ config, lib, pkgs, options, ... }:
|
||||
|
||||
with lib;
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
options,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
mkRenamedOptionModule
|
||||
mkAliasOptionModuleMD
|
||||
mkEnableOption
|
||||
mkOption
|
||||
types
|
||||
literalExpression
|
||||
mkPackageOption
|
||||
mkIf
|
||||
optionalString
|
||||
optional
|
||||
mkDefault
|
||||
escapeShellArgs
|
||||
optionalAttrs
|
||||
mkMerge
|
||||
;
|
||||
|
||||
cfg = config.services.transmission;
|
||||
opt = options.services.transmission;
|
||||
inherit (config.environment) etc;
|
||||
@@ -12,15 +33,36 @@ let
|
||||
downloadsDir = "Downloads";
|
||||
incompleteDir = ".incomplete";
|
||||
watchDir = "watchdir";
|
||||
settingsFormat = pkgs.formats.json {};
|
||||
settingsFormat = pkgs.formats.json { };
|
||||
settingsFile = settingsFormat.generate "settings.json" cfg.settings;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(mkRenamedOptionModule ["services" "transmission" "port"]
|
||||
["services" "transmission" "settings" "rpc-port"])
|
||||
(mkAliasOptionModuleMD ["services" "transmission" "openFirewall"]
|
||||
["services" "transmission" "openPeerPorts"])
|
||||
(mkRenamedOptionModule
|
||||
[
|
||||
"services"
|
||||
"transmission"
|
||||
"port"
|
||||
]
|
||||
[
|
||||
"services"
|
||||
"transmission"
|
||||
"settings"
|
||||
"rpc-port"
|
||||
]
|
||||
)
|
||||
(mkAliasOptionModuleMD
|
||||
[
|
||||
"services"
|
||||
"transmission"
|
||||
"openFirewall"
|
||||
]
|
||||
[
|
||||
"services"
|
||||
"transmission"
|
||||
"openPeerPorts"
|
||||
]
|
||||
)
|
||||
];
|
||||
options = {
|
||||
services.transmission = {
|
||||
@@ -46,130 +88,137 @@ in
|
||||
See [Transmission's Wiki](https://github.com/transmission/transmission/wiki/Editing-Configuration-Files)
|
||||
for documentation of settings not explicitly covered by this module.
|
||||
'';
|
||||
default = {};
|
||||
default = { };
|
||||
type = types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
options.download-dir = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.home}/${downloadsDir}";
|
||||
defaultText = literalExpression ''"''${config.${opt.home}}/${downloadsDir}"'';
|
||||
description = "Directory where to download torrents.";
|
||||
};
|
||||
options.incomplete-dir = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.home}/${incompleteDir}";
|
||||
defaultText = literalExpression ''"''${config.${opt.home}}/${incompleteDir}"'';
|
||||
description = ''
|
||||
When enabled with
|
||||
services.transmission.home
|
||||
[](#opt-services.transmission.settings.incomplete-dir-enabled),
|
||||
new torrents will download the files to this directory.
|
||||
When complete, the files will be moved to download-dir
|
||||
[](#opt-services.transmission.settings.download-dir).
|
||||
'';
|
||||
};
|
||||
options.incomplete-dir-enabled = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "";
|
||||
};
|
||||
options.message-level = mkOption {
|
||||
type = types.ints.between 0 6;
|
||||
default = 2;
|
||||
description = "Set verbosity of transmission messages.";
|
||||
};
|
||||
options.peer-port = mkOption {
|
||||
type = types.port;
|
||||
default = 51413;
|
||||
description = "The peer port to listen for incoming connections.";
|
||||
};
|
||||
options.peer-port-random-high = mkOption {
|
||||
type = types.port;
|
||||
default = 65535;
|
||||
description = ''
|
||||
The maximum peer port to listen to for incoming connections
|
||||
when [](#opt-services.transmission.settings.peer-port-random-on-start) is enabled.
|
||||
'';
|
||||
};
|
||||
options.peer-port-random-low = mkOption {
|
||||
type = types.port;
|
||||
default = 65535;
|
||||
description = ''
|
||||
The minimal peer port to listen to for incoming connections
|
||||
when [](#opt-services.transmission.settings.peer-port-random-on-start) is enabled.
|
||||
'';
|
||||
};
|
||||
options.peer-port-random-on-start = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Randomize the peer port.";
|
||||
};
|
||||
options.rpc-bind-address = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
example = "0.0.0.0";
|
||||
description = ''
|
||||
Where to listen for RPC connections.
|
||||
Use `0.0.0.0` to listen on all interfaces.
|
||||
'';
|
||||
};
|
||||
options.rpc-port = mkOption {
|
||||
type = types.port;
|
||||
default = 9091;
|
||||
description = "The RPC port to listen to.";
|
||||
};
|
||||
options.script-torrent-done-enabled = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to run
|
||||
[](#opt-services.transmission.settings.script-torrent-done-filename)
|
||||
at torrent completion.
|
||||
'';
|
||||
};
|
||||
options.script-torrent-done-filename = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = "Executable to be run at torrent completion.";
|
||||
};
|
||||
options.umask = mkOption {
|
||||
type = types.int;
|
||||
default = 2;
|
||||
description = ''
|
||||
Sets transmission's file mode creation mask.
|
||||
See the umask(2) manpage for more information.
|
||||
Users who want their saved torrents to be world-writable
|
||||
may want to set this value to 0.
|
||||
Bear in mind that the json markup language only accepts numbers in base 10,
|
||||
so the standard umask(2) octal notation "022" is written in settings.json as 18.
|
||||
'';
|
||||
};
|
||||
options.utp-enabled = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to enable [Micro Transport Protocol (µTP)](https://en.wikipedia.org/wiki/Micro_Transport_Protocol).
|
||||
'';
|
||||
};
|
||||
options.watch-dir = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.home}/${watchDir}";
|
||||
defaultText = literalExpression ''"''${config.${opt.home}}/${watchDir}"'';
|
||||
description = "Watch a directory for torrent files and add them to transmission.";
|
||||
};
|
||||
options.watch-dir-enabled = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''Whether to enable the
|
||||
[](#opt-services.transmission.settings.watch-dir).
|
||||
'';
|
||||
};
|
||||
options.trash-original-torrent-files = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''Whether to delete torrents added from the
|
||||
[](#opt-services.transmission.settings.watch-dir).
|
||||
'';
|
||||
options = {
|
||||
download-dir = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.home}/${downloadsDir}";
|
||||
defaultText = literalExpression ''"''${config.${opt.home}}/${downloadsDir}"'';
|
||||
description = "Directory where to download torrents.";
|
||||
};
|
||||
incomplete-dir = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.home}/${incompleteDir}";
|
||||
defaultText = literalExpression ''"''${config.${opt.home}}/${incompleteDir}"'';
|
||||
description = ''
|
||||
When enabled with
|
||||
services.transmission.home
|
||||
[](#opt-services.transmission.settings.incomplete-dir-enabled),
|
||||
new torrents will download the files to this directory.
|
||||
When complete, the files will be moved to download-dir
|
||||
[](#opt-services.transmission.settings.download-dir).
|
||||
'';
|
||||
};
|
||||
incomplete-dir-enabled = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "";
|
||||
};
|
||||
message-level = mkOption {
|
||||
type = types.ints.between 0 6;
|
||||
default = 2;
|
||||
description = "Set verbosity of transmission messages.";
|
||||
};
|
||||
peer-port = mkOption {
|
||||
type = types.port;
|
||||
default = 51413;
|
||||
description = "The peer port to listen for incoming connections.";
|
||||
};
|
||||
peer-port-random-high = mkOption {
|
||||
type = types.port;
|
||||
default = 65535;
|
||||
description = ''
|
||||
The maximum peer port to listen to for incoming connections
|
||||
when [](#opt-services.transmission.settings.peer-port-random-on-start) is enabled.
|
||||
'';
|
||||
};
|
||||
peer-port-random-low = mkOption {
|
||||
type = types.port;
|
||||
default = 65535;
|
||||
description = ''
|
||||
The minimal peer port to listen to for incoming connections
|
||||
when [](#opt-services.transmission.settings.peer-port-random-on-start) is enabled.
|
||||
'';
|
||||
};
|
||||
peer-port-random-on-start = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = "Randomize the peer port.";
|
||||
};
|
||||
rpc-bind-address = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
example = "0.0.0.0";
|
||||
description = ''
|
||||
Where to listen for RPC connections.
|
||||
Use `0.0.0.0` to listen on all interfaces.
|
||||
'';
|
||||
};
|
||||
rpc-port = mkOption {
|
||||
type = types.port;
|
||||
default = 9091;
|
||||
description = "The RPC port to listen to.";
|
||||
};
|
||||
script-torrent-done-enabled = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to run
|
||||
[](#opt-services.transmission.settings.script-torrent-done-filename)
|
||||
at torrent completion.
|
||||
'';
|
||||
};
|
||||
script-torrent-done-filename = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = "Executable to be run at torrent completion.";
|
||||
};
|
||||
umask = mkOption {
|
||||
type = types.either types.int types.str;
|
||||
default = if cfg.package == pkgs.transmission_3 then 18 else "022";
|
||||
defaultText = literalExpression "if cfg.package == pkgs.transmission_3 then 18 else \"022\"";
|
||||
description = ''
|
||||
Sets transmission's file mode creation mask.
|
||||
See the umask(2) manpage for more information.
|
||||
Users who want their saved torrents to be world-writable
|
||||
may want to set this value to 0/`"000"`.
|
||||
|
||||
Keep in mind, that if you are using Transmission 3, this has to
|
||||
be passed as a base 10 integer, whereas Transmission 4 takes
|
||||
an octal number in a string instead.
|
||||
'';
|
||||
};
|
||||
utp-enabled = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to enable [Micro Transport Protocol (µTP)](https://en.wikipedia.org/wiki/Micro_Transport_Protocol).
|
||||
'';
|
||||
};
|
||||
watch-dir = mkOption {
|
||||
type = types.path;
|
||||
default = "${cfg.home}/${watchDir}";
|
||||
defaultText = literalExpression ''"''${config.${opt.home}}/${watchDir}"'';
|
||||
description = "Watch a directory for torrent files and add them to transmission.";
|
||||
};
|
||||
watch-dir-enabled = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable the
|
||||
[](#opt-services.transmission.settings.watch-dir).
|
||||
'';
|
||||
};
|
||||
trash-original-torrent-files = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to delete torrents added from the
|
||||
[](#opt-services.transmission.settings.watch-dir).
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -191,6 +240,17 @@ in
|
||||
and [](#opt-services.transmission.settings.watch-dir).
|
||||
Note that you may also want to change
|
||||
[](#opt-services.transmission.settings.umask).
|
||||
|
||||
Keep in mind, that if the default user is used, the `home` directory
|
||||
is locked behind a `750` permission, which affects all subdirectories
|
||||
as well. There are 3 ways to get around this:
|
||||
|
||||
1. (Recommended) add the users that should have access to the group
|
||||
set by [](#opt-services.transmission.group)
|
||||
2. Change [](#opt-services.transmission.settings.download-dir) to be
|
||||
under a directory that has the right permissions
|
||||
3. Change `systemd.services.transmission.serviceConfig.StateDirectoryMode`
|
||||
to the same value as this option
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -231,7 +291,7 @@ in
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
example = [ "--log-debug" ];
|
||||
description = ''
|
||||
Extra flags passed to the transmission command in the service definition.
|
||||
@@ -279,40 +339,51 @@ in
|
||||
# when /home/foo is not owned by cfg.user.
|
||||
# Note also that using an ExecStartPre= wouldn't work either
|
||||
# because BindPaths= needs these directories before.
|
||||
system.activationScripts = mkIf (cfg.downloadDirPermissions != null)
|
||||
{ transmission-daemon = ''
|
||||
install -d -m 700 '${cfg.home}/${settingsDir}'
|
||||
chown -R '${cfg.user}:${cfg.group}' ${cfg.home}/${settingsDir}
|
||||
system.activationScripts.transmission-daemon =
|
||||
''
|
||||
install -d -m 700 -o '${cfg.user}' -g '${cfg.group}' '${cfg.home}/${settingsDir}'
|
||||
''
|
||||
+ optionalString (cfg.downloadDirPermissions != null) ''
|
||||
install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.download-dir}'
|
||||
'' + optionalString cfg.settings.incomplete-dir-enabled ''
|
||||
install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.incomplete-dir}'
|
||||
'' + optionalString cfg.settings.watch-dir-enabled ''
|
||||
install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.watch-dir}'
|
||||
'';
|
||||
};
|
||||
|
||||
${optionalString cfg.settings.incomplete-dir-enabled ''
|
||||
install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.incomplete-dir}'
|
||||
''}
|
||||
${optionalString cfg.settings.watch-dir-enabled ''
|
||||
install -d -m '${cfg.downloadDirPermissions}' -o '${cfg.user}' -g '${cfg.group}' '${cfg.settings.watch-dir}'
|
||||
''}
|
||||
'';
|
||||
|
||||
systemd.services.transmission = {
|
||||
description = "Transmission BitTorrent Service";
|
||||
after = [ "network.target" ] ++ optional apparmor.enable "apparmor.service";
|
||||
requires = optional apparmor.enable "apparmor.service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
environment.CURL_CA_BUNDLE = etc."ssl/certs/ca-certificates.crt".source;
|
||||
environment.TRANSMISSION_WEB_HOME = lib.mkIf (cfg.webHome != null) cfg.webHome;
|
||||
|
||||
environment = {
|
||||
CURL_CA_BUNDLE = etc."ssl/certs/ca-certificates.crt".source;
|
||||
TRANSMISSION_WEB_HOME = lib.mkIf (cfg.webHome != null) cfg.webHome;
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
# Use "+" because credentialsFile may not be accessible to User= or Group=.
|
||||
ExecStartPre = [("+" + pkgs.writeShellScript "transmission-prestart" ''
|
||||
set -eu${lib.optionalString (cfg.settings.message-level >= 3) "x"}
|
||||
${pkgs.jq}/bin/jq --slurp add ${settingsFile} '${cfg.credentialsFile}' |
|
||||
install -D -m 600 -o '${cfg.user}' -g '${cfg.group}' /dev/stdin \
|
||||
'${cfg.home}/${settingsDir}/settings.json'
|
||||
'')];
|
||||
ExecStart="${cfg.package}/bin/transmission-daemon -f -g ${cfg.home}/${settingsDir} ${escapeShellArgs cfg.extraFlags}";
|
||||
ExecStartPre = [
|
||||
(
|
||||
"+"
|
||||
+ pkgs.writeShellScript "transmission-prestart" ''
|
||||
set -eu${lib.optionalString (cfg.settings.message-level >= 3) "x"}
|
||||
${pkgs.jq}/bin/jq --slurp add ${settingsFile} '${cfg.credentialsFile}' |
|
||||
install -D -m 600 -o '${cfg.user}' -g '${cfg.group}' /dev/stdin \
|
||||
'${cfg.home}/${settingsDir}/settings.json'
|
||||
''
|
||||
)
|
||||
];
|
||||
ExecStart = "${cfg.package}/bin/transmission-daemon -f -g ${cfg.home}/${settingsDir} ${escapeShellArgs cfg.extraFlags}";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
# Create rootDir in the host's mount namespace.
|
||||
RuntimeDirectory = [(baseNameOf rootDir)];
|
||||
RuntimeDirectory = [ (baseNameOf rootDir) ];
|
||||
RuntimeDirectoryMode = "755";
|
||||
# This is for BindPaths= and BindReadOnlyPaths=
|
||||
# to allow traversal of directories they create in RootDirectory=.
|
||||
@@ -330,27 +401,30 @@ in
|
||||
RootDirectoryStartOnly = true;
|
||||
MountAPIVFS = true;
|
||||
BindPaths =
|
||||
[ "${cfg.home}/${settingsDir}"
|
||||
[
|
||||
"${cfg.home}/${settingsDir}"
|
||||
cfg.settings.download-dir
|
||||
# Transmission may need to read in the host's /run (eg. /run/systemd/resolve)
|
||||
# or write in its private /run (eg. /run/host).
|
||||
"/run"
|
||||
] ++
|
||||
optional cfg.settings.incomplete-dir-enabled
|
||||
cfg.settings.incomplete-dir ++
|
||||
optional (cfg.settings.watch-dir-enabled && cfg.settings.trash-original-torrent-files)
|
||||
cfg.settings.watch-dir;
|
||||
BindReadOnlyPaths = [
|
||||
# No confinement done of /nix/store here like in systemd-confinement.nix,
|
||||
# an AppArmor profile is provided to get a confinement based upon paths and rights.
|
||||
builtins.storeDir
|
||||
"/etc"
|
||||
] ++
|
||||
optional (cfg.settings.script-torrent-done-enabled &&
|
||||
cfg.settings.script-torrent-done-filename != null)
|
||||
cfg.settings.script-torrent-done-filename ++
|
||||
optional (cfg.settings.watch-dir-enabled && !cfg.settings.trash-original-torrent-files)
|
||||
cfg.settings.watch-dir;
|
||||
]
|
||||
++ optional cfg.settings.incomplete-dir-enabled cfg.settings.incomplete-dir
|
||||
++ optional (
|
||||
cfg.settings.watch-dir-enabled && cfg.settings.trash-original-torrent-files
|
||||
) cfg.settings.watch-dir;
|
||||
BindReadOnlyPaths =
|
||||
[
|
||||
# No confinement done of /nix/store here like in systemd-confinement.nix,
|
||||
# an AppArmor profile is provided to get a confinement based upon paths and rights.
|
||||
builtins.storeDir
|
||||
"/etc"
|
||||
]
|
||||
++ optional (
|
||||
cfg.settings.script-torrent-done-enabled && cfg.settings.script-torrent-done-filename != null
|
||||
) cfg.settings.script-torrent-done-filename
|
||||
++ optional (
|
||||
cfg.settings.watch-dir-enabled && !cfg.settings.trash-original-torrent-files
|
||||
) cfg.settings.watch-dir;
|
||||
StateDirectory = [
|
||||
"transmission"
|
||||
"transmission/${settingsDir}"
|
||||
@@ -389,7 +463,11 @@ in
|
||||
RemoveIPC = true;
|
||||
# AF_UNIX may become usable one day:
|
||||
# https://github.com/transmission/transmission/issues/441
|
||||
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
||||
RestrictAddressFamilies = [
|
||||
"AF_UNIX"
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
@@ -398,7 +476,13 @@ in
|
||||
# Groups in @system-service which do not contain a syscall
|
||||
# listed by perf stat -e 'syscalls:sys_enter_*' transmission-daemon -f
|
||||
# in tests, and seem likely not necessary for transmission-daemon.
|
||||
"~@aio" "~@chown" "~@keyring" "~@memlock" "~@resources" "~@setuid" "~@timer"
|
||||
"~@aio"
|
||||
"~@chown"
|
||||
"~@keyring"
|
||||
"~@memlock"
|
||||
"~@resources"
|
||||
"~@setuid"
|
||||
"~@timer"
|
||||
# In the @privileged group, but reached when querying infos through RPC (eg. with stig).
|
||||
"quotactl"
|
||||
];
|
||||
@@ -409,38 +493,41 @@ in
|
||||
# It's useful to have transmission in path, e.g. for remote control
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
users.users = optionalAttrs (cfg.user == "transmission") ({
|
||||
users.users = optionalAttrs (cfg.user == "transmission") {
|
||||
transmission = {
|
||||
group = cfg.group;
|
||||
uid = config.ids.uids.transmission;
|
||||
description = "Transmission BitTorrent user";
|
||||
home = cfg.home;
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
users.groups = optionalAttrs (cfg.group == "transmission") ({
|
||||
users.groups = optionalAttrs (cfg.group == "transmission") {
|
||||
transmission = {
|
||||
gid = config.ids.gids.transmission;
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
networking.firewall = mkMerge [
|
||||
(mkIf cfg.openPeerPorts (
|
||||
if cfg.settings.peer-port-random-on-start
|
||||
then
|
||||
{ allowedTCPPortRanges =
|
||||
[ { from = cfg.settings.peer-port-random-low;
|
||||
to = cfg.settings.peer-port-random-high;
|
||||
}
|
||||
];
|
||||
allowedUDPPortRanges =
|
||||
[ { from = cfg.settings.peer-port-random-low;
|
||||
to = cfg.settings.peer-port-random-high;
|
||||
}
|
||||
];
|
||||
if cfg.settings.peer-port-random-on-start then
|
||||
{
|
||||
allowedTCPPortRanges = [
|
||||
{
|
||||
from = cfg.settings.peer-port-random-low;
|
||||
to = cfg.settings.peer-port-random-high;
|
||||
}
|
||||
];
|
||||
allowedUDPPortRanges = [
|
||||
{
|
||||
from = cfg.settings.peer-port-random-low;
|
||||
to = cfg.settings.peer-port-random-high;
|
||||
}
|
||||
];
|
||||
}
|
||||
else
|
||||
{ allowedTCPPorts = [ cfg.settings.peer-port ];
|
||||
{
|
||||
allowedTCPPorts = [ cfg.settings.peer-port ];
|
||||
allowedUDPPorts = [ cfg.settings.peer-port ];
|
||||
}
|
||||
))
|
||||
@@ -502,14 +589,16 @@ in
|
||||
''}
|
||||
}
|
||||
|
||||
${optionalString (cfg.settings.script-torrent-done-enabled &&
|
||||
cfg.settings.script-torrent-done-filename != null) ''
|
||||
# Stack transmission_directories profile on top of
|
||||
# any existing profile for script-torrent-done-filename
|
||||
# FIXME: to be tested as I'm not sure it works well with NoNewPrivileges=
|
||||
# https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorStacking#seccomp-and-no_new_privs
|
||||
px ${cfg.settings.script-torrent-done-filename} -> &@{dirs},
|
||||
''}
|
||||
${optionalString
|
||||
(cfg.settings.script-torrent-done-enabled && cfg.settings.script-torrent-done-filename != null)
|
||||
''
|
||||
# Stack transmission_directories profile on top of
|
||||
# any existing profile for script-torrent-done-filename
|
||||
# FIXME: to be tested as I'm not sure it works well with NoNewPrivileges=
|
||||
# https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorStacking#seccomp-and-no_new_privs
|
||||
px ${cfg.settings.script-torrent-done-filename} -> &@{dirs},
|
||||
''
|
||||
}
|
||||
|
||||
${optionalString (cfg.webHome != null) ''
|
||||
r ${cfg.webHome}/**,
|
||||
|
||||
@@ -41,6 +41,8 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
options.services.cage.package = mkPackageOption pkgs "cage" { };
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
# The service is partially based off of the one provided in the
|
||||
@@ -64,7 +66,7 @@ in {
|
||||
unitConfig.ConditionPathExists = "/dev/tty1";
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.cage}/bin/cage \
|
||||
${cfg.package}/bin/cage \
|
||||
${escapeShellArgs cfg.extraArguments} \
|
||||
-- ${cfg.program}
|
||||
'';
|
||||
|
||||
@@ -1,12 +1,57 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
inherit (lib)
|
||||
any
|
||||
attrsets
|
||||
attrByPath
|
||||
catAttrs
|
||||
collect
|
||||
concatMapStrings
|
||||
concatStringsSep
|
||||
escape
|
||||
escapeShellArg
|
||||
escapeShellArgs
|
||||
hasInfix
|
||||
isAttrs
|
||||
isList
|
||||
isStorePath
|
||||
isString
|
||||
mapAttrs
|
||||
mapAttrsToList
|
||||
optionalString
|
||||
optionals
|
||||
replaceStrings
|
||||
splitString
|
||||
substring
|
||||
versionOlder
|
||||
|
||||
fileContents
|
||||
readFile
|
||||
|
||||
literalExpression
|
||||
literalMD
|
||||
mkBefore
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkMerge
|
||||
mkOption
|
||||
mkOptionType
|
||||
mkPackageOption
|
||||
types;
|
||||
|
||||
cfg = config.services.akkoma;
|
||||
ex = cfg.config;
|
||||
db = ex.":pleroma"."Pleroma.Repo";
|
||||
web = ex.":pleroma"."Pleroma.Web.Endpoint";
|
||||
|
||||
format = pkgs.formats.elixirConf { elixir = cfg.package.elixirPackage; };
|
||||
inherit (format.lib)
|
||||
mkAtom
|
||||
mkMap
|
||||
mkRaw
|
||||
mkTuple;
|
||||
|
||||
isConfined = config.systemd.services.akkoma.confinement.enable;
|
||||
hasSmtp = (attrByPath [ ":pleroma" "Pleroma.Emails.Mailer" "adapter" "value" ] null ex) == "Swoosh.Adapters.SMTP";
|
||||
|
||||
@@ -96,16 +141,15 @@ let
|
||||
passAsFile = [ "code" ];
|
||||
} ''elixir "$codePath" >"$out"'');
|
||||
|
||||
format = pkgs.formats.elixirConf { elixir = cfg.package.elixirPackage; };
|
||||
configFile = format.generate "config.exs"
|
||||
(replaceSec
|
||||
(attrsets.updateManyAttrsByPath [{
|
||||
path = [ ":pleroma" "Pleroma.Web.Endpoint" "http" "ip" ];
|
||||
update = addr:
|
||||
if isAbsolutePath addr
|
||||
then format.lib.mkTuple
|
||||
[ (format.lib.mkAtom ":local") addr ]
|
||||
else format.lib.mkRaw (erlAddr addr);
|
||||
then mkTuple
|
||||
[ (mkAtom ":local") addr ]
|
||||
else mkRaw (erlAddr addr);
|
||||
}] cfg.config));
|
||||
|
||||
writeShell = { name, text, runtimeInputs ? [ ] }:
|
||||
@@ -282,7 +326,7 @@ let
|
||||
AKKOMA_CONFIG_PATH="''${RUNTIME_DIRECTORY%%:*}/config.exs" \
|
||||
ERL_EPMD_ADDRESS="${cfg.dist.address}" \
|
||||
ERL_EPMD_PORT="${toString cfg.dist.epmdPort}" \
|
||||
ERL_FLAGS=${lib.escapeShellArg (lib.escapeShellArgs ([
|
||||
ERL_FLAGS=${escapeShellArg (escapeShellArgs ([
|
||||
"-kernel" "inet_dist_use_interface" (erlAddr cfg.dist.address)
|
||||
"-kernel" "inet_dist_listen_min" (toString cfg.dist.portMin)
|
||||
"-kernel" "inet_dist_listen_max" (toString cfg.dist.portMax)
|
||||
@@ -639,7 +683,7 @@ in {
|
||||
"Pleroma.Repo" = mkOption {
|
||||
type = elixirValue;
|
||||
default = {
|
||||
adapter = format.lib.mkRaw "Ecto.Adapters.Postgres";
|
||||
adapter = mkRaw "Ecto.Adapters.Postgres";
|
||||
socket_dir = "/run/postgresql";
|
||||
username = cfg.user;
|
||||
database = "akkoma";
|
||||
@@ -769,7 +813,7 @@ in {
|
||||
in {
|
||||
base_url = mkOption {
|
||||
type = types.nonEmptyStr;
|
||||
default = if lib.versionOlder config.system.stateVersion "24.05"
|
||||
default = if versionOlder config.system.stateVersion "24.05"
|
||||
then "${httpConf.scheme}://${httpConf.host}:${builtins.toString httpConf.port}/media/"
|
||||
else null;
|
||||
defaultText = literalExpression ''
|
||||
@@ -787,7 +831,7 @@ in {
|
||||
":frontends" = mkOption {
|
||||
type = elixirValue;
|
||||
default = mapAttrs
|
||||
(key: val: format.lib.mkMap { name = val.name; ref = val.ref; })
|
||||
(key: val: mkMap { name = val.name; ref = val.ref; })
|
||||
cfg.frontends;
|
||||
defaultText = literalExpression ''
|
||||
lib.mapAttrs (key: val:
|
||||
@@ -816,7 +860,7 @@ in {
|
||||
};
|
||||
base_url = mkOption {
|
||||
type = types.nullOr types.nonEmptyStr;
|
||||
default = if lib.versionOlder config.system.stateVersion "24.05"
|
||||
default = if versionOlder config.system.stateVersion "24.05"
|
||||
then "${httpConf.scheme}://${httpConf.host}:${builtins.toString httpConf.port}"
|
||||
else null;
|
||||
defaultText = literalExpression ''
|
||||
@@ -899,7 +943,7 @@ in {
|
||||
":backends" = mkOption {
|
||||
type = types.listOf elixirValue;
|
||||
visible = false;
|
||||
default = with format.lib; [
|
||||
default = [
|
||||
(mkTuple [ (mkRaw "ExSyslogger") (mkAtom ":ex_syslogger") ])
|
||||
];
|
||||
};
|
||||
@@ -913,7 +957,7 @@ in {
|
||||
|
||||
level = mkOption {
|
||||
type = types.nonEmptyStr;
|
||||
apply = format.lib.mkAtom;
|
||||
apply = mkAtom;
|
||||
default = ":info";
|
||||
example = ":warning";
|
||||
description = ''
|
||||
@@ -931,7 +975,7 @@ in {
|
||||
":data_dir" = mkOption {
|
||||
type = elixirValue;
|
||||
internal = true;
|
||||
default = format.lib.mkRaw ''
|
||||
default = mkRaw ''
|
||||
Path.join(System.fetch_env!("CACHE_DIRECTORY"), "tzdata")
|
||||
'';
|
||||
};
|
||||
@@ -1136,6 +1180,6 @@ in {
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ mvs ];
|
||||
meta.maintainers = with lib.maintainers; [ mvs ];
|
||||
meta.doc = ./akkoma.md;
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ in
|
||||
DB_PORT = 3306;
|
||||
DB_DATABASE = "firefly";
|
||||
DB_USERNAME = "firefly";
|
||||
DB_PASSWORD_FILE = "/var/secrets/firefly-iii-mysql-password.txt;
|
||||
DB_PASSWORD_FILE = "/var/secrets/firefly-iii-mysql-password.txt";
|
||||
}
|
||||
'';
|
||||
type = lib.types.submodule {
|
||||
|
||||
@@ -226,7 +226,7 @@ in
|
||||
options.sites = mkOption {
|
||||
type = types.attrsOf (types.submodule siteOpts);
|
||||
default = {};
|
||||
description = "Specification of one or more WordPress sites to serve";
|
||||
description = "Specification of one or more InvoicePlane sites to serve";
|
||||
};
|
||||
|
||||
options.webserver = mkOption {
|
||||
|
||||
@@ -204,7 +204,6 @@ in
|
||||
};
|
||||
"/" = {
|
||||
# mixed frontend and backend requests, based on the request headers
|
||||
recommendedProxySettings = true;
|
||||
extraConfig = ''
|
||||
set $proxpass "${ui}";
|
||||
if ($http_accept = "application/activity+json") {
|
||||
@@ -221,6 +220,11 @@ in
|
||||
rewrite ^(.+)/+$ $1 permanent;
|
||||
|
||||
proxy_pass $proxpass;
|
||||
# Proxied `Host` header is required to validate ActivityPub HTTP signatures for incoming events.
|
||||
# The other headers are optional, for the sake of better log data.
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ let
|
||||
enableSshSocket = config.services.openssh.startWhenNeeded;
|
||||
};
|
||||
|
||||
notExcluded = pkg: (!(lib.elem pkg config.environment.budgie.excludePackages));
|
||||
notExcluded = pkg: utils.disablePackageByName pkg config.environment.budgie.excludePackages;
|
||||
in {
|
||||
meta.maintainers = lib.teams.budgie.members;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ let
|
||||
extraGSettingsOverrides = cfg.extraGSettingsOverrides;
|
||||
};
|
||||
|
||||
notExcluded = pkg: (!(lib.elem (lib.getName pkg) (map lib.getName config.environment.cinnamon.excludePackages)));
|
||||
notExcluded = pkg: utils.disablePackageByName pkg config.environment.cinnamon.excludePackages;
|
||||
in
|
||||
|
||||
{
|
||||
@@ -111,6 +111,7 @@ in
|
||||
services.gnome.glib-networking.enable = true;
|
||||
services.gnome.gnome-keyring.enable = true;
|
||||
services.gvfs.enable = true;
|
||||
services.power-profiles-daemon.enable = mkDefault true;
|
||||
services.switcherooControl.enable = mkDefault true; # xapp-gpu-offload-helper
|
||||
services.touchegg.enable = mkDefault true;
|
||||
services.udisks2.enable = true;
|
||||
@@ -151,9 +152,6 @@ in
|
||||
# cinnamon-killer-daemon: provided by cinnamon-common
|
||||
networkmanagerapplet # session requirement - also nm-applet not needed
|
||||
|
||||
# For a polkit authentication agent
|
||||
polkit_gnome
|
||||
|
||||
# packages
|
||||
nemo-with-extensions
|
||||
gnome-online-accounts-gtk
|
||||
|
||||
@@ -58,7 +58,7 @@ let
|
||||
enableGnomePanel = true;
|
||||
} ++ cfg.flashback.customSessions;
|
||||
|
||||
notExcluded = pkg: mkDefault (!(lib.elem (lib.getName pkg) (map lib.getName config.environment.gnome.excludePackages)));
|
||||
notExcluded = pkg: mkDefault (utils.disablePackageByName pkg config.environment.gnome.excludePackages);
|
||||
|
||||
in
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ let
|
||||
extraGSettingsOverrides = cfg.extraGSettingsOverrides;
|
||||
};
|
||||
|
||||
notExcluded = pkg: (!(lib.elem pkg config.environment.pantheon.excludePackages));
|
||||
notExcluded = pkg: utils.disablePackageByName pkg config.environment.pantheon.excludePackages;
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
@@ -6,16 +6,17 @@ let
|
||||
cfg = config.services.xserver.windowManager.exwm;
|
||||
loadScript = pkgs.writeText "emacs-exwm-load" ''
|
||||
${cfg.loadScript}
|
||||
${optionalString cfg.enableDefaultConfig ''
|
||||
(require 'exwm-config)
|
||||
(exwm-config-default)
|
||||
''}
|
||||
'';
|
||||
packages = epkgs: cfg.extraPackages epkgs ++ [ epkgs.exwm ];
|
||||
exwm-emacs = pkgs.emacsWithPackages packages;
|
||||
exwm-emacs = pkgs.emacs.pkgs.withPackages packages;
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
imports = [
|
||||
(mkRemovedOptionModule [ "services" "xserver" "windowManager" "exwm" "enableDefaultConfig" ]
|
||||
"The upstream EXWM project no longer provides a default configuration, instead copy (parts of) exwm-config.el to your local config.")
|
||||
];
|
||||
|
||||
options = {
|
||||
services.xserver.windowManager.exwm = {
|
||||
enable = mkEnableOption "exwm";
|
||||
@@ -28,15 +29,9 @@ in
|
||||
'';
|
||||
description = ''
|
||||
Emacs lisp code to be run after loading the user's init
|
||||
file. If enableDefaultConfig is true, this will be run
|
||||
before loading the default config.
|
||||
file.
|
||||
'';
|
||||
};
|
||||
enableDefaultConfig = mkOption {
|
||||
default = true;
|
||||
type = lib.types.bool;
|
||||
description = "Enable an uncustomised exwm configuration.";
|
||||
};
|
||||
extraPackages = mkOption {
|
||||
type = types.functionTo (types.listOf types.package);
|
||||
default = epkgs: [];
|
||||
|
||||
@@ -15,6 +15,8 @@ in
|
||||
description = ''Whether to enable the unl0kr on-screen keyboard in initrd to unlock LUKS.'';
|
||||
};
|
||||
|
||||
package = lib.mkPackageOption pkgs "unl0kr" { };
|
||||
|
||||
allowVendorDrivers = lib.mkEnableOption "load optional drivers" // {
|
||||
description = ''Whether to load additional drivers for certain vendors (I.E: Wacom, Intel, etc.)'';
|
||||
};
|
||||
@@ -85,7 +87,7 @@ in
|
||||
libinput
|
||||
xkeyboard_config
|
||||
"${config.boot.initrd.systemd.package}/lib/systemd/systemd-reply-password"
|
||||
"${pkgs.unl0kr}/bin/unl0kr"
|
||||
(lib.getExe' cfg.package "unl0kr")
|
||||
];
|
||||
services = {
|
||||
unl0kr-ask-password = {
|
||||
@@ -112,7 +114,7 @@ in
|
||||
do
|
||||
for file in `ls $DIR/ask.*`; do
|
||||
socket="$(cat "$file" | ${pkgs.gnugrep}/bin/grep "Socket=" | cut -d= -f2)"
|
||||
${pkgs.unl0kr}/bin/unl0kr -v -C "/etc/unl0kr.conf" | ${config.boot.initrd.systemd.package}/lib/systemd/systemd-reply-password 1 "$socket"
|
||||
${lib.getExe' cfg.package "unl0kr"} -v -C "/etc/unl0kr.conf" | ${config.boot.initrd.systemd.package}/lib/systemd/systemd-reply-password 1 "$socket"
|
||||
done
|
||||
done
|
||||
'';
|
||||
|
||||
@@ -4,6 +4,8 @@ with lib;
|
||||
with utils;
|
||||
|
||||
let
|
||||
# https://wiki.archlinux.org/index.php/fstab#Filepath_spaces
|
||||
escape = string: builtins.replaceStrings [ " " "\t" ] [ "\\040" "\\011" ] string;
|
||||
|
||||
addCheckDesc = desc: elemType: check: types.addCheck elemType check
|
||||
// { description = "${elemType.description} (with check: ${desc})"; };
|
||||
@@ -136,6 +138,8 @@ let
|
||||
|
||||
};
|
||||
|
||||
config.device = lib.mkIf (config.label != null) "/dev/disk/by-label/${escape config.label}";
|
||||
|
||||
config.options = let
|
||||
inInitrd = utils.fsNeededForBoot config;
|
||||
in mkMerge [
|
||||
@@ -196,11 +200,8 @@ let
|
||||
];
|
||||
isBindMount = fs: builtins.elem "bind" fs.options;
|
||||
skipCheck = fs: fs.noCheck || fs.device == "none" || builtins.elem fs.fsType fsToSkipCheck || isBindMount fs;
|
||||
# https://wiki.archlinux.org/index.php/fstab#Filepath_spaces
|
||||
escape = string: builtins.replaceStrings [ " " "\t" ] [ "\\040" "\\011" ] string;
|
||||
in fstabFileSystems: { }: concatMapStrings (fs:
|
||||
(if fs.device != null then escape fs.device
|
||||
else if fs.label != null then "/dev/disk/by-label/${escape fs.label}"
|
||||
else throw "No device specified for mount point ‘${fs.mountPoint}’.")
|
||||
+ " " + escape fs.mountPoint
|
||||
+ " " + fs.fsType
|
||||
|
||||
@@ -761,6 +761,7 @@ in
|
||||
lib.nameValuePair "zfs-sync-${pool}" {
|
||||
description = "Sync ZFS pool \"${pool}\"";
|
||||
wantedBy = [ "shutdown.target" ];
|
||||
before = [ "final.target" ];
|
||||
unitConfig = {
|
||||
DefaultDependencies = false;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
{ config, options, lib, pkgs, ... }:
|
||||
{
|
||||
config,
|
||||
options,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
let
|
||||
@@ -8,7 +14,8 @@ let
|
||||
defaultBackend = options.virtualisation.oci-containers.backend.default;
|
||||
|
||||
containerOptions =
|
||||
{ ... }: {
|
||||
{ ... }:
|
||||
{
|
||||
|
||||
options = {
|
||||
|
||||
@@ -77,8 +84,8 @@ let
|
||||
};
|
||||
|
||||
cmd = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
description = "Commandline arguments to pass to the image's entrypoint.";
|
||||
example = literalExpression ''
|
||||
["--port=9000"]
|
||||
@@ -87,7 +94,7 @@ let
|
||||
|
||||
labels = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
default = {};
|
||||
default = { };
|
||||
description = "Labels to attach to the container at runtime.";
|
||||
example = literalExpression ''
|
||||
{
|
||||
@@ -105,26 +112,26 @@ let
|
||||
|
||||
environment = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
default = {};
|
||||
default = { };
|
||||
description = "Environment variables to set for this container.";
|
||||
example = literalExpression ''
|
||||
{
|
||||
DATABASE_HOST = "db.example.com";
|
||||
DATABASE_PORT = "3306";
|
||||
}
|
||||
'';
|
||||
'';
|
||||
};
|
||||
|
||||
environmentFiles = mkOption {
|
||||
type = with types; listOf path;
|
||||
default = [];
|
||||
default = [ ];
|
||||
description = "Environment files for this container.";
|
||||
example = literalExpression ''
|
||||
[
|
||||
/path/to/.env
|
||||
/path/to/.env.secret
|
||||
]
|
||||
'';
|
||||
'';
|
||||
};
|
||||
|
||||
log-driver = mkOption {
|
||||
@@ -147,7 +154,7 @@ let
|
||||
|
||||
ports = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
description = ''
|
||||
Network ports to publish from the container to the outer host.
|
||||
|
||||
@@ -194,7 +201,7 @@ let
|
||||
|
||||
volumes = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
description = ''
|
||||
List of volumes to attach to this container.
|
||||
|
||||
@@ -222,7 +229,7 @@ let
|
||||
|
||||
dependsOn = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
description = ''
|
||||
Define which other containers this one depends on. They will be added to both After and Requires for the unit.
|
||||
|
||||
@@ -247,14 +254,17 @@ let
|
||||
|
||||
preRunExtraOptions = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
description = "Extra options for {command}`${defaultBackend}` that go before the `run` argument.";
|
||||
example = [ "--runtime" "runsc" ];
|
||||
example = [
|
||||
"--runtime"
|
||||
"runsc"
|
||||
];
|
||||
};
|
||||
|
||||
extraOptions = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
description = "Extra options for {command}`${defaultBackend} run`.";
|
||||
example = literalExpression ''
|
||||
["--network=host"]
|
||||
@@ -262,177 +272,293 @@ let
|
||||
};
|
||||
|
||||
autoStart = mkOption {
|
||||
type = types.bool;
|
||||
type = with types; bool;
|
||||
default = true;
|
||||
description = ''
|
||||
When enabled, the container is automatically started on boot.
|
||||
If this option is set to false, the container has to be started on-demand via its service.
|
||||
'';
|
||||
};
|
||||
|
||||
pull = mkOption {
|
||||
type =
|
||||
with types;
|
||||
enum [
|
||||
"always"
|
||||
"missing"
|
||||
"never"
|
||||
"newer"
|
||||
];
|
||||
default = "missing";
|
||||
description = ''
|
||||
Image pull policy for the container. Must be one of: always, missing, never, newer
|
||||
'';
|
||||
};
|
||||
|
||||
capAdd = mkOption {
|
||||
type = with types; lazyAttrsOf (nullOr bool);
|
||||
default = { };
|
||||
description = ''
|
||||
Capabilities to add to container
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
SYS_ADMIN = true;
|
||||
{
|
||||
'';
|
||||
};
|
||||
|
||||
capDrop = mkOption {
|
||||
type = with types; lazyAttrsOf (nullOr bool);
|
||||
default = { };
|
||||
description = ''
|
||||
Capabilities to drop from container
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{
|
||||
SYS_ADMIN = true;
|
||||
{
|
||||
'';
|
||||
};
|
||||
|
||||
devices = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
List of devices to attach to this container.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[
|
||||
"/dev/dri:/dev/dri"
|
||||
]
|
||||
'';
|
||||
};
|
||||
|
||||
privileged = mkOption {
|
||||
type = with types; bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Give extended privileges to the container
|
||||
'';
|
||||
};
|
||||
|
||||
networks = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
Networks to attach the container to
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
isValidLogin = login: login.username != null && login.passwordFile != null && login.registry != null;
|
||||
isValidLogin =
|
||||
login: login.username != null && login.passwordFile != null && login.registry != null;
|
||||
|
||||
mkService = name: container: let
|
||||
dependsOn = map (x: "${cfg.backend}-${x}.service") container.dependsOn;
|
||||
escapedName = escapeShellArg name;
|
||||
preStartScript = pkgs.writeShellApplication {
|
||||
name = "pre-start";
|
||||
runtimeInputs = [ ];
|
||||
text = ''
|
||||
${cfg.backend} rm -f ${name} || true
|
||||
${optionalString (isValidLogin container.login) ''
|
||||
# try logging in, if it fails, check if image exists locally
|
||||
${cfg.backend} login \
|
||||
${container.login.registry} \
|
||||
--username ${container.login.username} \
|
||||
--password-stdin < ${container.login.passwordFile} \
|
||||
|| ${cfg.backend} image inspect ${container.image} >/dev/null \
|
||||
|| { echo "image doesn't exist locally and login failed" >&2 ; exit 1; }
|
||||
''}
|
||||
${optionalString (container.imageFile != null) ''
|
||||
${cfg.backend} load -i ${container.imageFile}
|
||||
''}
|
||||
${optionalString (container.imageStream != null) ''
|
||||
${container.imageStream} | ${cfg.backend} load
|
||||
''}
|
||||
${optionalString (cfg.backend == "podman") ''
|
||||
rm -f /run/podman-${escapedName}.ctr-id
|
||||
''}
|
||||
'';
|
||||
mkService =
|
||||
name: container:
|
||||
let
|
||||
dependsOn = map (x: "${cfg.backend}-${x}.service") container.dependsOn;
|
||||
escapedName = escapeShellArg name;
|
||||
preStartScript = pkgs.writeShellApplication {
|
||||
name = "pre-start";
|
||||
runtimeInputs = [ ];
|
||||
text = ''
|
||||
${cfg.backend} rm -f ${name} || true
|
||||
${optionalString (isValidLogin container.login) ''
|
||||
# try logging in, if it fails, check if image exists locally
|
||||
${cfg.backend} login \
|
||||
${container.login.registry} \
|
||||
--username ${container.login.username} \
|
||||
--password-stdin < ${container.login.passwordFile} \
|
||||
|| ${cfg.backend} image inspect ${container.image} >/dev/null \
|
||||
|| { echo "image doesn't exist locally and login failed" >&2 ; exit 1; }
|
||||
''}
|
||||
${optionalString (container.imageFile != null) ''
|
||||
${cfg.backend} load -i ${container.imageFile}
|
||||
''}
|
||||
${optionalString (container.imageStream != null) ''
|
||||
${container.imageStream} | ${cfg.backend} load
|
||||
''}
|
||||
${optionalString (cfg.backend == "podman") ''
|
||||
rm -f /run/podman-${escapedName}.ctr-id
|
||||
''}
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
wantedBy = [ ] ++ optional (container.autoStart) "multi-user.target";
|
||||
wants = lib.optional (
|
||||
container.imageFile == null && container.imageStream == null
|
||||
) "network-online.target";
|
||||
after =
|
||||
lib.optionals (cfg.backend == "docker") [
|
||||
"docker.service"
|
||||
"docker.socket"
|
||||
]
|
||||
# if imageFile or imageStream is not set, the service needs the network to download the image from the registry
|
||||
++ lib.optionals (container.imageFile == null && container.imageStream == null) [
|
||||
"network-online.target"
|
||||
]
|
||||
++ dependsOn;
|
||||
requires = dependsOn;
|
||||
environment = proxy_env;
|
||||
|
||||
path =
|
||||
if cfg.backend == "docker" then
|
||||
[ config.virtualisation.docker.package ]
|
||||
else if cfg.backend == "podman" then
|
||||
[ config.virtualisation.podman.package ]
|
||||
else
|
||||
throw "Unhandled backend: ${cfg.backend}";
|
||||
|
||||
script = concatStringsSep " \\\n " (
|
||||
[
|
||||
"exec ${cfg.backend} "
|
||||
]
|
||||
++ map escapeShellArg container.preRunExtraOptions
|
||||
++ [
|
||||
"run"
|
||||
"--rm"
|
||||
"--name=${escapedName}"
|
||||
"--log-driver=${container.log-driver}"
|
||||
]
|
||||
++ optional (container.entrypoint != null) "--entrypoint=${escapeShellArg container.entrypoint}"
|
||||
++ optional (container.hostname != null) "--hostname=${escapeShellArg container.hostname}"
|
||||
++ lib.optionals (cfg.backend == "podman") [
|
||||
"--cidfile=/run/podman-${escapedName}.ctr-id"
|
||||
"--cgroups=no-conmon"
|
||||
"--sdnotify=conmon"
|
||||
"-d"
|
||||
"--replace"
|
||||
]
|
||||
++ (mapAttrsToList (k: v: "-e ${escapeShellArg k}=${escapeShellArg v}") container.environment)
|
||||
++ map (f: "--env-file ${escapeShellArg f}") container.environmentFiles
|
||||
++ map (p: "-p ${escapeShellArg p}") container.ports
|
||||
++ optional (container.user != null) "-u ${escapeShellArg container.user}"
|
||||
++ map (v: "-v ${escapeShellArg v}") container.volumes
|
||||
++ (mapAttrsToList (k: v: "-l ${escapeShellArg k}=${escapeShellArg v}") container.labels)
|
||||
++ optional (container.workdir != null) "-w ${escapeShellArg container.workdir}"
|
||||
++ optional (container.privileged) "--privileged"
|
||||
++ mapAttrsToList (k: _: "--cap-add=${escapeShellArg k}") (
|
||||
filterAttrs (_: v: v == true) container.capAdd
|
||||
)
|
||||
++ mapAttrsToList (k: _: "--cap-drop=${escapeShellArg k}") (
|
||||
filterAttrs (_: v: v == true) container.capDrop
|
||||
)
|
||||
++ map (d: "--device=${escapeShellArg d}") container.devices
|
||||
++ map (n: "--network=${escapeShellArg n}") container.networks
|
||||
++ [ "--pull ${escapeShellArg container.pull}" ]
|
||||
++ map escapeShellArg container.extraOptions
|
||||
++ [ container.image ]
|
||||
++ map escapeShellArg container.cmd
|
||||
);
|
||||
|
||||
preStop =
|
||||
if cfg.backend == "podman" then
|
||||
"podman stop --ignore --cidfile=/run/podman-${escapedName}.ctr-id"
|
||||
else
|
||||
"${cfg.backend} stop ${name} || true";
|
||||
|
||||
postStop =
|
||||
if cfg.backend == "podman" then
|
||||
"podman rm -f --ignore --cidfile=/run/podman-${escapedName}.ctr-id"
|
||||
else
|
||||
"${cfg.backend} rm -f ${name} || true";
|
||||
|
||||
serviceConfig =
|
||||
{
|
||||
### There is no generalized way of supporting `reload` for docker
|
||||
### containers. Some containers may respond well to SIGHUP sent to their
|
||||
### init process, but it is not guaranteed; some apps have other reload
|
||||
### mechanisms, some don't have a reload signal at all, and some docker
|
||||
### images just have broken signal handling. The best compromise in this
|
||||
### case is probably to leave ExecReload undefined, so `systemctl reload`
|
||||
### will at least result in an error instead of potentially undefined
|
||||
### behaviour.
|
||||
###
|
||||
### Advanced users can still override this part of the unit to implement
|
||||
### a custom reload handler, since the result of all this is a normal
|
||||
### systemd service from the perspective of the NixOS module system.
|
||||
###
|
||||
# ExecReload = ...;
|
||||
###
|
||||
ExecStartPre = [ "${preStartScript}/bin/pre-start" ];
|
||||
TimeoutStartSec = 0;
|
||||
TimeoutStopSec = 120;
|
||||
Restart = "always";
|
||||
}
|
||||
// optionalAttrs (cfg.backend == "podman") {
|
||||
Environment = "PODMAN_SYSTEMD_UNIT=podman-${name}.service";
|
||||
Type = "notify";
|
||||
NotifyAccess = "all";
|
||||
};
|
||||
};
|
||||
in {
|
||||
wantedBy = [] ++ optional (container.autoStart) "multi-user.target";
|
||||
wants = lib.optional (container.imageFile == null && container.imageStream == null) "network-online.target";
|
||||
after = lib.optionals (cfg.backend == "docker") [ "docker.service" "docker.socket" ]
|
||||
# if imageFile or imageStream is not set, the service needs the network to download the image from the registry
|
||||
++ lib.optionals (container.imageFile == null && container.imageStream == null) [ "network-online.target" ]
|
||||
++ dependsOn;
|
||||
requires = dependsOn;
|
||||
environment = proxy_env;
|
||||
|
||||
path =
|
||||
if cfg.backend == "docker" then [ config.virtualisation.docker.package ]
|
||||
else if cfg.backend == "podman" then [ config.virtualisation.podman.package ]
|
||||
else throw "Unhandled backend: ${cfg.backend}";
|
||||
|
||||
script = concatStringsSep " \\\n " ([
|
||||
"exec ${cfg.backend} "
|
||||
] ++ map escapeShellArg container.preRunExtraOptions ++ [
|
||||
"run"
|
||||
"--rm"
|
||||
"--name=${escapedName}"
|
||||
"--log-driver=${container.log-driver}"
|
||||
] ++ optional (container.entrypoint != null)
|
||||
"--entrypoint=${escapeShellArg container.entrypoint}"
|
||||
++ optional (container.hostname != null)
|
||||
"--hostname=${escapeShellArg container.hostname}"
|
||||
++ lib.optionals (cfg.backend == "podman") [
|
||||
"--cidfile=/run/podman-${escapedName}.ctr-id"
|
||||
"--cgroups=no-conmon"
|
||||
"--sdnotify=conmon"
|
||||
"-d"
|
||||
"--replace"
|
||||
] ++ (mapAttrsToList (k: v: "-e ${escapeShellArg k}=${escapeShellArg v}") container.environment)
|
||||
++ map (f: "--env-file ${escapeShellArg f}") container.environmentFiles
|
||||
++ map (p: "-p ${escapeShellArg p}") container.ports
|
||||
++ optional (container.user != null) "-u ${escapeShellArg container.user}"
|
||||
++ map (v: "-v ${escapeShellArg v}") container.volumes
|
||||
++ (mapAttrsToList (k: v: "-l ${escapeShellArg k}=${escapeShellArg v}") container.labels)
|
||||
++ optional (container.workdir != null) "-w ${escapeShellArg container.workdir}"
|
||||
++ map escapeShellArg container.extraOptions
|
||||
++ [container.image]
|
||||
++ map escapeShellArg container.cmd
|
||||
);
|
||||
|
||||
preStop = if cfg.backend == "podman"
|
||||
then "podman stop --ignore --cidfile=/run/podman-${escapedName}.ctr-id"
|
||||
else "${cfg.backend} stop ${name} || true";
|
||||
|
||||
postStop = if cfg.backend == "podman"
|
||||
then "podman rm -f --ignore --cidfile=/run/podman-${escapedName}.ctr-id"
|
||||
else "${cfg.backend} rm -f ${name} || true";
|
||||
|
||||
serviceConfig = {
|
||||
### There is no generalized way of supporting `reload` for docker
|
||||
### containers. Some containers may respond well to SIGHUP sent to their
|
||||
### init process, but it is not guaranteed; some apps have other reload
|
||||
### mechanisms, some don't have a reload signal at all, and some docker
|
||||
### images just have broken signal handling. The best compromise in this
|
||||
### case is probably to leave ExecReload undefined, so `systemctl reload`
|
||||
### will at least result in an error instead of potentially undefined
|
||||
### behaviour.
|
||||
###
|
||||
### Advanced users can still override this part of the unit to implement
|
||||
### a custom reload handler, since the result of all this is a normal
|
||||
### systemd service from the perspective of the NixOS module system.
|
||||
###
|
||||
# ExecReload = ...;
|
||||
###
|
||||
ExecStartPre = [ "${preStartScript}/bin/pre-start" ];
|
||||
TimeoutStartSec = 0;
|
||||
TimeoutStopSec = 120;
|
||||
Restart = "always";
|
||||
} // optionalAttrs (cfg.backend == "podman") {
|
||||
Environment="PODMAN_SYSTEMD_UNIT=podman-${name}.service";
|
||||
Type="notify";
|
||||
NotifyAccess="all";
|
||||
};
|
||||
};
|
||||
|
||||
in {
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(
|
||||
lib.mkChangedOptionModule
|
||||
[ "docker-containers" ]
|
||||
[ "virtualisation" "oci-containers" ]
|
||||
(oldcfg: {
|
||||
backend = "docker";
|
||||
containers = lib.mapAttrs (n: v: builtins.removeAttrs (v // {
|
||||
extraOptions = v.extraDockerOptions or [];
|
||||
}) [ "extraDockerOptions" ]) oldcfg.docker-containers;
|
||||
})
|
||||
)
|
||||
(lib.mkChangedOptionModule [ "docker-containers" ] [ "virtualisation" "oci-containers" ] (oldcfg: {
|
||||
backend = "docker";
|
||||
containers = lib.mapAttrs (
|
||||
n: v:
|
||||
builtins.removeAttrs (
|
||||
v
|
||||
// {
|
||||
extraOptions = v.extraDockerOptions or [ ];
|
||||
}
|
||||
) [ "extraDockerOptions" ]
|
||||
) oldcfg.docker-containers;
|
||||
}))
|
||||
];
|
||||
|
||||
options.virtualisation.oci-containers = {
|
||||
|
||||
backend = mkOption {
|
||||
type = types.enum [ "podman" "docker" ];
|
||||
type = types.enum [
|
||||
"podman"
|
||||
"docker"
|
||||
];
|
||||
default = if versionAtLeast config.system.stateVersion "22.05" then "podman" else "docker";
|
||||
description = "The underlying Docker implementation to use.";
|
||||
};
|
||||
|
||||
containers = mkOption {
|
||||
default = {};
|
||||
default = { };
|
||||
type = types.attrsOf (types.submodule containerOptions);
|
||||
description = "OCI (Docker) containers to run as systemd services.";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = lib.mkIf (cfg.containers != {}) (lib.mkMerge [
|
||||
{
|
||||
systemd.services = mapAttrs' (n: v: nameValuePair "${cfg.backend}-${n}" (mkService n v)) cfg.containers;
|
||||
config = lib.mkIf (cfg.containers != { }) (
|
||||
lib.mkMerge [
|
||||
{
|
||||
systemd.services = mapAttrs' (
|
||||
n: v: nameValuePair "${cfg.backend}-${n}" (mkService n v)
|
||||
) cfg.containers;
|
||||
|
||||
assertions =
|
||||
let
|
||||
toAssertion = _: { imageFile, imageStream, ... }:
|
||||
{ assertion = imageFile == null || imageStream == null;
|
||||
assertions =
|
||||
let
|
||||
toAssertion =
|
||||
_:
|
||||
{ imageFile, imageStream, ... }:
|
||||
{
|
||||
assertion = imageFile == null || imageStream == null;
|
||||
|
||||
message = "You can only define one of imageFile and imageStream";
|
||||
};
|
||||
message = "You can only define one of imageFile and imageStream";
|
||||
};
|
||||
|
||||
in
|
||||
in
|
||||
lib.mapAttrsToList toAssertion cfg.containers;
|
||||
}
|
||||
(lib.mkIf (cfg.backend == "podman") {
|
||||
virtualisation.podman.enable = true;
|
||||
})
|
||||
(lib.mkIf (cfg.backend == "docker") {
|
||||
virtualisation.docker.enable = true;
|
||||
})
|
||||
]);
|
||||
}
|
||||
(lib.mkIf (cfg.backend == "podman") {
|
||||
virtualisation.podman.enable = true;
|
||||
})
|
||||
(lib.mkIf (cfg.backend == "docker") {
|
||||
virtualisation.docker.enable = true;
|
||||
})
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -563,6 +563,7 @@ in {
|
||||
lomiri-clock-app = runTest ./lomiri-clock-app.nix;
|
||||
lomiri-docviewer-app = runTest ./lomiri-docviewer-app.nix;
|
||||
lomiri-filemanager-app = runTest ./lomiri-filemanager-app.nix;
|
||||
lomiri-mediaplayer-app = runTest ./lomiri-mediaplayer-app.nix;
|
||||
lomiri-gallery-app = runTest ./lomiri-gallery-app.nix;
|
||||
lomiri-system-settings = handleTest ./lomiri-system-settings.nix {};
|
||||
lorri = handleTest ./lorri/default.nix {};
|
||||
|
||||
+43
-30
@@ -85,11 +85,19 @@ let
|
||||
let
|
||||
config = (import ../lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules =
|
||||
[ ../modules/installer/netboot/netboot.nix
|
||||
../modules/testing/test-instrumentation.nix
|
||||
{ key = "serial"; }
|
||||
];
|
||||
modules = [
|
||||
../modules/installer/netboot/netboot.nix
|
||||
../modules/testing/test-instrumentation.nix
|
||||
{
|
||||
boot.kernelParams = [
|
||||
"serial"
|
||||
"live.nixos.passwordHash=$6$jnwR50SkbLYEq/Vp$wmggwioAkfmwuYqd5hIfatZWS/bO6hewzNIwIrWcgdh7k/fhUzZT29Vil3ioMo94sdji/nipbzwEpxecLZw0d0" # "password"
|
||||
];
|
||||
}
|
||||
{
|
||||
key = "serial";
|
||||
}
|
||||
];
|
||||
}).config;
|
||||
ipxeBootDir = pkgs.symlinkJoin {
|
||||
name = "ipxeBootDir";
|
||||
@@ -103,34 +111,39 @@ let
|
||||
pxe = ipxeBootDir;
|
||||
} // extraConfig);
|
||||
in
|
||||
makeTest {
|
||||
name = "boot-netboot-" + name;
|
||||
nodes = { };
|
||||
testScript = ''
|
||||
machine = create_machine("${startCommand}")
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
machine.shutdown()
|
||||
'';
|
||||
};
|
||||
in {
|
||||
uefiCdrom = makeBootTest "uefi-cdrom" {
|
||||
uefi = true;
|
||||
cdrom = "${iso}/iso/${iso.isoName}";
|
||||
makeTest {
|
||||
name = "boot-netboot-" + name;
|
||||
nodes = { };
|
||||
testScript = ''
|
||||
machine = create_machine("${startCommand}")
|
||||
machine.start()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
machine.succeed("grep 'serial' /proc/cmdline")
|
||||
machine.succeed("grep 'live.nixos.passwordHash' /proc/cmdline")
|
||||
machine.succeed("grep '$6$jnwR50SkbLYEq/Vp$wmggwioAkfmwuYqd5hIfatZWS/bO6hewzNIwIrWcgdh7k/fhUzZT29Vil3ioMo94sdji/nipbzwEpxecLZw0d0' /etc/shadow")
|
||||
machine.shutdown()
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
uefiCdrom = makeBootTest "uefi-cdrom" {
|
||||
uefi = true;
|
||||
cdrom = "${iso}/iso/${iso.isoName}";
|
||||
};
|
||||
|
||||
uefiUsb = makeBootTest "uefi-usb" {
|
||||
uefi = true;
|
||||
usb = "${iso}/iso/${iso.isoName}";
|
||||
};
|
||||
uefiUsb = makeBootTest "uefi-usb" {
|
||||
uefi = true;
|
||||
usb = "${iso}/iso/${iso.isoName}";
|
||||
};
|
||||
|
||||
uefiNetboot = makeNetbootTest "uefi" {
|
||||
uefi = true;
|
||||
};
|
||||
} // lib.optionalAttrs (pkgs.stdenv.hostPlatform.system == "x86_64-linux") {
|
||||
biosCdrom = makeBootTest "bios-cdrom" {
|
||||
cdrom = "${iso}/iso/${iso.isoName}";
|
||||
};
|
||||
uefiNetboot = makeNetbootTest "uefi" {
|
||||
uefi = true;
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs (pkgs.stdenv.hostPlatform.system == "x86_64-linux") {
|
||||
biosCdrom = makeBootTest "bios-cdrom" {
|
||||
cdrom = "${iso}/iso/${iso.isoName}";
|
||||
};
|
||||
|
||||
biosUsb = makeBootTest "bios-usb" {
|
||||
usb = "${iso}/iso/${iso.isoName}";
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
ocrContent = "Video Test";
|
||||
videoFile = "test.webm";
|
||||
in
|
||||
{
|
||||
name = "lomiri-mediaplayer-app-standalone";
|
||||
meta.maintainers = lib.teams.lomiri.members;
|
||||
|
||||
nodes.machine =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
imports = [ ./common/x11.nix ];
|
||||
|
||||
services.xserver.enable = true;
|
||||
|
||||
environment = {
|
||||
# Setup video
|
||||
etc."${videoFile}".source =
|
||||
pkgs.runCommand videoFile
|
||||
{
|
||||
nativeBuildInputs = with pkgs; [
|
||||
ffmpeg # produce video for OCR
|
||||
(imagemagick.override { ghostscriptSupport = true; }) # produce OCR-able image
|
||||
];
|
||||
}
|
||||
''
|
||||
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
|
||||
lomiri-mediaplayer-app
|
||||
];
|
||||
variables = {
|
||||
UITK_ICON_THEME = "suru";
|
||||
};
|
||||
};
|
||||
|
||||
i18n.supportedLocales = [ "all" ];
|
||||
|
||||
fonts = {
|
||||
packages = with pkgs; [
|
||||
# Intended font & helps with OCR
|
||||
ubuntu-classic
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
enableOCR = true;
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_x()
|
||||
|
||||
with subtest("lomiri mediaplayer launches"):
|
||||
machine.succeed("lomiri-mediaplayer-app >&2 &")
|
||||
machine.wait_for_text("Choose from")
|
||||
machine.screenshot("lomiri-mediaplayer_open")
|
||||
|
||||
machine.succeed("pkill -f lomiri-mediaplayer-app")
|
||||
|
||||
with subtest("lomiri mediaplayer plays video"):
|
||||
machine.succeed("lomiri-mediaplayer-app /etc/${videoFile} >&2 &")
|
||||
machine.wait_for_text("${ocrContent}")
|
||||
machine.screenshot("lomiri-mediaplayer_playback")
|
||||
|
||||
machine.succeed("pkill -f lomiri-mediaplayer-app")
|
||||
|
||||
with subtest("lomiri mediaplayer localisation works"):
|
||||
# OCR struggles with finding identifying the translated window title, and lomiri-content-hub QML isn't translated
|
||||
# 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.wait_for_text("Fehler")
|
||||
machine.screenshot("lomiri-mediaplayer_localised")
|
||||
'';
|
||||
}
|
||||
@@ -120,12 +120,13 @@ let
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
client.wait_for_unit("network.target")
|
||||
router.start()
|
||||
router.systemctl("start network-online.target")
|
||||
router.wait_for_unit("network-online.target")
|
||||
|
||||
client.start()
|
||||
client.wait_for_unit("network.target")
|
||||
|
||||
with subtest("Wait until we have an ip address on each interface"):
|
||||
client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q '192.168.1'")
|
||||
client.wait_until_succeeds("ip addr show dev enp1s0 | grep -q 'fd00:1234:5678:1:'")
|
||||
|
||||
@@ -22,6 +22,16 @@ let
|
||||
image = "nginx-container";
|
||||
imageStream = pkgs.dockerTools.examples.nginxStream;
|
||||
ports = ["8181:80"];
|
||||
capAdd = {
|
||||
CAP_AUDIT_READ = true;
|
||||
};
|
||||
capDrop = {
|
||||
CAP_AUDIT_WRITE = true;
|
||||
};
|
||||
privileged = false;
|
||||
devices = [
|
||||
"/dev/random:/dev/random"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
@@ -32,11 +42,18 @@ let
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
import json
|
||||
|
||||
start_all()
|
||||
${backend}.wait_for_unit("${backend}-nginx.service")
|
||||
${backend}.wait_for_open_port(8181)
|
||||
${backend}.wait_until_succeeds("curl -f http://localhost:8181 | grep Hello")
|
||||
output = json.loads(${backend}.succeed("${backend} inspect nginx --format json").strip())[0]
|
||||
${backend}.succeed("systemctl stop ${backend}-nginx.service", timeout=10)
|
||||
assert output['HostConfig']['CapAdd'] == ["CAP_AUDIT_READ"]
|
||||
assert output['HostConfig']['CapDrop'] == ${if backend == "docker" then "[\"CAP_AUDIT_WRITE\"]" else "[]"} # Rootless podman runs with no capabilities so it cannot drop them
|
||||
assert output['HostConfig']['Privileged'] == False
|
||||
assert output['HostConfig']['Devices'] == [{'PathOnHost': '/dev/random', 'PathInContainer': '/dev/random', 'CgroupPermissions': '${if backend == "docker" then "rwm" else ""}'}]
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
@@ -804,6 +804,38 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
mqtt = {
|
||||
exporterConfig = {
|
||||
enable = true;
|
||||
environmentFile = pkgs.writeText "mqtt-exporter-envfile" ''
|
||||
MQTT_PASSWORD=testpassword
|
||||
'';
|
||||
};
|
||||
metricProvider = {
|
||||
services.mosquitto = {
|
||||
enable = true;
|
||||
listeners = [{
|
||||
users.exporter = {
|
||||
acl = [ "read #" ];
|
||||
passwordFile = pkgs.writeText "mosquitto-password" "testpassword";
|
||||
};
|
||||
}];
|
||||
};
|
||||
systemd.services.prometheus-mqtt-exporter ={
|
||||
wants = [ "mosquitto.service" ];
|
||||
after = [ "mosquitto.service" ];
|
||||
};
|
||||
};
|
||||
exporterTest = ''
|
||||
wait_for_unit("mosquitto.service")
|
||||
wait_for_unit("prometheus-mqtt-exporter.service")
|
||||
wait_for_open_port(9000)
|
||||
succeed(
|
||||
"curl -sSf http://localhost:9000/metrics | grep '^python_info'"
|
||||
)
|
||||
'';
|
||||
};
|
||||
|
||||
mysqld = {
|
||||
exporterConfig = {
|
||||
enable = true;
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
{
|
||||
remote-write = import ./remote-write.nix { inherit system pkgs; };
|
||||
vmalert = import ./vmalert.nix { inherit system pkgs; };
|
||||
external-promscrape-config = import ./external-promscrape-config.nix { inherit system pkgs; };
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import ../make-test-python.nix (
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
nodeExporterPort = 9100;
|
||||
promscrapeConfig = {
|
||||
global = {
|
||||
scrape_interval = "2s";
|
||||
};
|
||||
scrape_configs = [
|
||||
{
|
||||
job_name = "node";
|
||||
static_configs = [
|
||||
{
|
||||
targets = [
|
||||
"node:${toString nodeExporterPort}"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
settingsFormat = pkgs.formats.yaml { };
|
||||
promscrapeConfigYaml = settingsFormat.generate "prometheusConfig.yaml" promscrapeConfig;
|
||||
in
|
||||
{
|
||||
name = "victoriametrics-external-promscrape-config";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [
|
||||
ryan4yin
|
||||
];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
victoriametrics =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
networking.firewall.allowedTCPPorts = [ 8428 ];
|
||||
services.victoriametrics = {
|
||||
enable = true;
|
||||
extraOptions = [
|
||||
"-promscrape.config=${toString promscrapeConfigYaml}"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
node =
|
||||
{ ... }:
|
||||
{
|
||||
services.prometheus.exporters.node = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
node.wait_for_unit("prometheus-node-exporter")
|
||||
node.wait_for_open_port(${toString nodeExporterPort})
|
||||
|
||||
victoriametrics.wait_for_unit("victoriametrics")
|
||||
victoriametrics.wait_for_open_port(8428)
|
||||
|
||||
|
||||
promscrape_config = victoriametrics.succeed("journalctl -u victoriametrics -o cat | grep 'promscrape.config'")
|
||||
assert '${toString promscrapeConfigYaml}' in promscrape_config
|
||||
|
||||
victoriametrics.wait_until_succeeds(
|
||||
"curl -sf 'http://localhost:8428/api/v1/query?query=node_exporter_build_info\{instance=\"node:9100\"\}' | "
|
||||
+ "jq '.data.result[0].value[1]' | grep '\"1\"'"
|
||||
)
|
||||
'';
|
||||
}
|
||||
)
|
||||
+15
-6
@@ -492,7 +492,9 @@ Examples going from bad to best practices:
|
||||
Sometimes, changes are needed to the source to allow building a derivation in nixpkgs, or to get earlier access to an upstream fix or improvement.
|
||||
When using the `patches` parameter to `mkDerivation`, make sure the patch name clearly describes the reason for the patch, or add a comment.
|
||||
|
||||
Patches already merged upstream or published elsewhere should be retrieved using `fetchpatch`.
|
||||
### 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 `fetchpatch`:
|
||||
|
||||
```nix
|
||||
{
|
||||
@@ -506,15 +508,22 @@ Patches already merged upstream or published elsewhere should be retrieved using
|
||||
}
|
||||
```
|
||||
|
||||
Otherwise, you can add a `.patch` file to the `nixpkgs` repository.
|
||||
In the interest of keeping our maintenance burden and the size of nixpkgs to a minimum, only do this for patches that are unique to `nixpkgs` or that have been proposed upstream but are not merged yet, cannot be easily fetched or have a high chance to disappear in the future due to unstable or unreliable URLs.
|
||||
The latter avoids link rot when the upstream abandons, squashes or rebases their change, in which case the commit may get garbage-collected.
|
||||
|
||||
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.
|
||||
|
||||
### Vendoring patches
|
||||
|
||||
In the following cases, a `.patch` file _should_ be added to Nixpkgs repository, instead of retrieved:
|
||||
|
||||
- solves problems unique to packaging in Nixpkgs
|
||||
- is already proposed upstream but not merged yet
|
||||
- cannot be fetched easily
|
||||
- has a high chance to disappear in the future due to unstable or unreliable URLs
|
||||
|
||||
The latter avoids link rot when the upstream abandons, squashes or rebases their change, in which case the commit may get garbage-collected.
|
||||
|
||||
```nix
|
||||
{
|
||||
patches = [ ./0001-changes.patch ];
|
||||
patches = [ ./0001-add-missing-include.patch ];
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
{ depname
|
||||
, version
|
||||
, src
|
||||
, sourceRoot
|
||||
, stdenv
|
||||
, lib
|
||||
, patches ? []
|
||||
, extraPostPatch ? ""
|
||||
, buildInputs ? []
|
||||
}:
|
||||
|
||||
let
|
||||
rebuildscriptName = if stdenv.hostPlatform.isLinux then
|
||||
"build_linux"
|
||||
else if stdenv.hostPlatform.isDarwin then
|
||||
"build_macos"
|
||||
else throw "Don't know how to rebuild FamiStudio's vendored ${depname} for ${stdenv.hostPlatform.system}";
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
pname = "famistudio-nativedep-${depname}";
|
||||
inherit version src sourceRoot patches buildInputs;
|
||||
|
||||
postPatch = let
|
||||
libnameBase = lib.optionalString stdenv.hostPlatform.isLinux "lib" + depname;
|
||||
in ''
|
||||
# Use one name for build script, eases with patching
|
||||
mv ${rebuildscriptName}.sh build.sh
|
||||
|
||||
# Scripts use hardcoded compilers and try to copy built libraries into FamiStudio's build tree
|
||||
# Not all scripts use the same compiler, so don't fail on replacing that
|
||||
substituteInPlace build.sh \
|
||||
--replace-fail '../../FamiStudio/' "$out/lib/" \
|
||||
--replace-quiet 'g++' "$CXX"
|
||||
|
||||
# Replacing gcc via sed, would break -static-libgcc otherwise
|
||||
sed -i -e "s/^gcc/$CC/g" build.sh
|
||||
'' + lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||
# Darwin rebuild scripts try to make a universal2 dylib
|
||||
# - build dylib for non-hostPlatform
|
||||
# - copy built library into special directory for later packaging script
|
||||
# - join two dylibs together into a universal2 dylib
|
||||
# Remove everything we don't need
|
||||
sed -ri \
|
||||
-e '/-target ${if stdenv.hostPlatform.isx86_64 then "arm64" else "x86_64"}/d' \
|
||||
-e '/..\/..\/Setup/d' \
|
||||
build.sh
|
||||
|
||||
# Replace joining multi-arch dylibs with copying dylib for target arch
|
||||
substituteInPlace build.sh \
|
||||
--replace-fail 'lipo -create -output ${libnameBase}.dylib' 'cp ${libnameBase}_${if stdenv.hostPlatform.isx86_64 then "x86_64" else "arm64"}.dylib ${libnameBase}.dylib #'
|
||||
'' + extraPostPatch;
|
||||
|
||||
dontConfigure = true;
|
||||
dontInstall = true; # rebuild script automatically installs
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
mkdir -p $out/lib
|
||||
|
||||
# Delete all prebuilt libraries, make sure everything is rebuilt
|
||||
find . -name '*.so' -or -name '*.dylib' -or -name '*.a' -delete
|
||||
|
||||
# When calling normally, an error won't cause derivation to fail
|
||||
source ./build.sh
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
{ stdenv
|
||||
, lib
|
||||
, buildDotnetModule
|
||||
, dotnetCorePackages
|
||||
, callPackage
|
||||
, fetchFromGitHub
|
||||
, ffmpeg
|
||||
, glfw
|
||||
, libglvnd
|
||||
, libogg
|
||||
, libvorbis
|
||||
, openal
|
||||
, portaudio
|
||||
, rtmidi
|
||||
}:
|
||||
|
||||
let
|
||||
csprojName = if stdenv.hostPlatform.isLinux then
|
||||
"FamiStudio.Linux"
|
||||
else if stdenv.hostPlatform.isDarwin then
|
||||
"FamiStudio.Mac"
|
||||
else throw "Don't know how to build FamiStudio for ${stdenv.hostPlatform.system}";
|
||||
in
|
||||
buildDotnetModule rec {
|
||||
pname = "famistudio";
|
||||
version = "4.2.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "BleuBleu";
|
||||
repo = "FamiStudio";
|
||||
rev = "refs/tags/${version}";
|
||||
hash = "sha256-WYy/6cWQg3Ayok/eAdnvlWAvdcuhy/sdlWOVvaYcPkc=";
|
||||
};
|
||||
|
||||
postPatch = let
|
||||
libname = library: "${library}${stdenv.hostPlatform.extensions.sharedLibrary}";
|
||||
buildNativeWrapper = args: callPackage ./build-native-wrapper.nix (args // {
|
||||
inherit version src;
|
||||
sourceRoot = "${src.name}/ThirdParty/${args.depname}";
|
||||
});
|
||||
nativeWrapperToReplaceFormat = args: let
|
||||
libPrefix = lib.optionalString stdenv.hostPlatform.isLinux "lib";
|
||||
in {
|
||||
package = buildNativeWrapper args;
|
||||
expectedName = "${libPrefix}${args.depname}";
|
||||
ourName = "${libPrefix}${args.depname}";
|
||||
};
|
||||
librariesToReplace = [
|
||||
# Unmodified native libraries that we can fully substitute
|
||||
{ package = glfw; expectedName = "libglfw"; ourName = "libglfw"; }
|
||||
{ package = rtmidi; expectedName = "librtmidi"; ourName = "librtmidi"; }
|
||||
] ++ lib.optionals stdenv.hostPlatform.isLinux [
|
||||
{ package = openal; expectedName = "libopenal32"; ourName = "libopenal"; }
|
||||
] ++ lib.optionals stdenv.hostPlatform.isDarwin [
|
||||
{ package = portaudio; expectedName = "libportaudio.2"; ourName = "libportaudio.2"; }
|
||||
] ++ [
|
||||
# Native libraries, with extra code for the C# wrapping
|
||||
(nativeWrapperToReplaceFormat { depname = "GifDec"; })
|
||||
(nativeWrapperToReplaceFormat { depname = "NesSndEmu"; })
|
||||
(nativeWrapperToReplaceFormat { depname = "NotSoFatso"; extraPostPatch = ''
|
||||
# C++17 does not allow register storage class specifier
|
||||
substituteInPlace build.sh \
|
||||
--replace-fail "$CXX" "$CXX -std=c++14"
|
||||
''; })
|
||||
(nativeWrapperToReplaceFormat { depname = "ShineMp3"; })
|
||||
(nativeWrapperToReplaceFormat { depname = "Stb"; })
|
||||
(nativeWrapperToReplaceFormat { depname = "Vorbis"; buildInputs = [ libogg libvorbis ]; })
|
||||
];
|
||||
libraryReplaceArgs = lib.strings.concatMapStringsSep " "
|
||||
(library: "--replace-fail '${libname library.expectedName}' '${lib.getLib library.package}/lib/${libname library.ourName}'")
|
||||
librariesToReplace;
|
||||
in ''
|
||||
# Don't use any prebuilt libraries
|
||||
rm FamiStudio/*.{dll,dylib,so*}
|
||||
|
||||
# Replace copying of vendored prebuilt native libraries with copying of our native libraries
|
||||
substituteInPlace ${projectFile} ${libraryReplaceArgs}
|
||||
|
||||
# Un-hardcode target platform if set
|
||||
sed -i -e '/PlatformTarget/d' ${projectFile}
|
||||
|
||||
# Don't require a special name to be preserved, our OpenAL isn't 32-bit
|
||||
substituteInPlace FamiStudio/Source/AudioStreams/OpenALStream.cs \
|
||||
--replace-fail 'libopenal32' 'libopenal'
|
||||
'';
|
||||
|
||||
projectFile = "FamiStudio/${csprojName}.csproj";
|
||||
nugetDeps = ./deps.nix;
|
||||
dotnet-sdk = dotnetCorePackages.sdk_7_0;
|
||||
dotnet-runtime = dotnetCorePackages.runtime_7_0;
|
||||
|
||||
runtimeDeps = lib.optionals stdenv.hostPlatform.isLinux [
|
||||
libglvnd
|
||||
];
|
||||
|
||||
executables = [ "FamiStudio" ];
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p $out/share/famistudio
|
||||
for datdir in Setup/Demo\ {Instruments,Songs}; do
|
||||
cp -R "$datdir" $out/share/famistudio/
|
||||
done
|
||||
'';
|
||||
|
||||
postFixup = ''
|
||||
# FFMpeg looked up from PATH
|
||||
wrapProgram $out/bin/FamiStudio \
|
||||
--prefix PATH : ${lib.makeBinPath [ ffmpeg ]}
|
||||
'';
|
||||
|
||||
passthru.updateScript = ./update.sh;
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://famistudio.org/";
|
||||
description = "NES Music Editor";
|
||||
longDescription = ''
|
||||
FamiStudio is very simple music editor for the Nintendo Entertainment System
|
||||
or Famicom. It is targeted at both chiptune artists and NES homebrewers.
|
||||
'';
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ OPNA2608 ];
|
||||
platforms = platforms.unix;
|
||||
mainProgram = "FamiStudio";
|
||||
};
|
||||
}
|
||||
@@ -63,7 +63,7 @@ mkDerivation rec {
|
||||
owner = "mixxxdj";
|
||||
repo = "mixxx";
|
||||
rev = version;
|
||||
hash = "sha256-foY4K1rSth0GUjM1xpctI3fpavVjGoPMnRN2tT4Lsqg=";
|
||||
hash = "sha256-YfpFRLosIIND+HnZN+76ZY0dQqEJaFkWZS84gZOCdfc=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ cmake pkg-config wrapGAppsHook3 ];
|
||||
|
||||
@@ -25,7 +25,7 @@ appimageTools.wrapType2 {
|
||||
--replace 'Exec=AppRun' 'Exec=${pname}'
|
||||
source "${makeWrapper}/nix-support/setup-hook"
|
||||
wrapProgram "$out/bin/plexamp" \
|
||||
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime}}"
|
||||
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}"
|
||||
'';
|
||||
|
||||
passthru.updateScript = ./update-plexamp.sh;
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "qpwgraph";
|
||||
version = "0.7.9";
|
||||
version = "0.8.0";
|
||||
|
||||
src = fetchFromGitLab {
|
||||
domain = "gitlab.freedesktop.org";
|
||||
owner = "rncbc";
|
||||
repo = "qpwgraph";
|
||||
rev = "v${finalAttrs.version}";
|
||||
sha256 = "sha256-VEJbjrXSMERGUyfIo43hg7v/S7lRzzvQ4gmwlqOMgAQ=";
|
||||
sha256 = "sha256-jB2mMLwJ1e/fIsf1R9Wd0stwp/RQH6f9pkF1qQX72Aw=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ cmake pkg-config wrapQtAppsHook ];
|
||||
|
||||
@@ -1,57 +1,52 @@
|
||||
{ stdenv
|
||||
, lib
|
||||
, fetchFromGitHub
|
||||
, cmake
|
||||
, pkg-config
|
||||
, wrapQtAppsHook
|
||||
, alsa-lib
|
||||
, boost
|
||||
, chromaprint
|
||||
, fftw
|
||||
, gnutls
|
||||
, libcdio
|
||||
, libebur128
|
||||
, libmtp
|
||||
, libpthreadstubs
|
||||
, libtasn1
|
||||
, libXdmcp
|
||||
, ninja
|
||||
, pcre
|
||||
, protobuf
|
||||
, sqlite
|
||||
, taglib
|
||||
, libgpod
|
||||
, libidn2
|
||||
, libpulseaudio
|
||||
, libselinux
|
||||
, libsepol
|
||||
, p11-kit
|
||||
, util-linux
|
||||
, qtbase
|
||||
, qtx11extras ? null # doesn't exist in qt6
|
||||
, qttools
|
||||
, withGstreamer ? true
|
||||
, glib-networking
|
||||
, gst_all_1
|
||||
, withVlc ? true
|
||||
, libvlc
|
||||
, nix-update-script
|
||||
{
|
||||
alsa-lib,
|
||||
boost,
|
||||
chromaprint,
|
||||
cmake,
|
||||
fetchFromGitHub,
|
||||
fftw,
|
||||
glib-networking,
|
||||
gnutls,
|
||||
gst_all_1,
|
||||
kdsingleapplication,
|
||||
lib,
|
||||
libXdmcp,
|
||||
libcdio,
|
||||
libebur128,
|
||||
libgpod,
|
||||
libidn2,
|
||||
libmtp,
|
||||
libpthreadstubs,
|
||||
libpulseaudio,
|
||||
libselinux,
|
||||
libsepol,
|
||||
libtasn1,
|
||||
ninja,
|
||||
nix-update-script,
|
||||
p11-kit,
|
||||
pkg-config,
|
||||
qtbase,
|
||||
qttools,
|
||||
sqlite,
|
||||
stdenv,
|
||||
taglib,
|
||||
util-linux,
|
||||
wrapQtAppsHook,
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) optionals optionalString;
|
||||
inherit (lib) optionals;
|
||||
|
||||
in
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "strawberry";
|
||||
version = "1.1.3";
|
||||
version = "1.2.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "jonaski";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
hash = "sha256-yca1BJWhSUVamqSKfvEzU3xbzdR+kwfSs0pyS08oUR0=";
|
||||
fetchSubmodules = true;
|
||||
hash = "sha256-X752GsP2b7rumQHzw52zI7PeE8tdM9Scgl3nHVcpO/s=";
|
||||
};
|
||||
|
||||
# the big strawberry shown in the context menu is *very* much in your face, so use the grey version instead
|
||||
@@ -60,52 +55,55 @@ stdenv.mkDerivation rec {
|
||||
--replace pictures/strawberry.png pictures/strawberry-grey.png
|
||||
'';
|
||||
|
||||
buildInputs = [
|
||||
alsa-lib
|
||||
boost
|
||||
chromaprint
|
||||
fftw
|
||||
gnutls
|
||||
libcdio
|
||||
libebur128
|
||||
libidn2
|
||||
libmtp
|
||||
libpthreadstubs
|
||||
libtasn1
|
||||
libXdmcp
|
||||
pcre
|
||||
protobuf
|
||||
sqlite
|
||||
taglib
|
||||
qtbase
|
||||
qtx11extras
|
||||
] ++ optionals stdenv.hostPlatform.isLinux [
|
||||
libgpod
|
||||
libpulseaudio
|
||||
libselinux
|
||||
libsepol
|
||||
p11-kit
|
||||
] ++ optionals withGstreamer (with gst_all_1; [
|
||||
glib-networking
|
||||
gstreamer
|
||||
gst-libav
|
||||
gst-plugins-base
|
||||
gst-plugins-good
|
||||
gst-plugins-bad
|
||||
gst-plugins-ugly
|
||||
]) ++ optionals withVlc [ libvlc ];
|
||||
buildInputs =
|
||||
[
|
||||
alsa-lib
|
||||
boost
|
||||
chromaprint
|
||||
fftw
|
||||
gnutls
|
||||
kdsingleapplication
|
||||
libXdmcp
|
||||
libcdio
|
||||
libebur128
|
||||
libidn2
|
||||
libmtp
|
||||
libpthreadstubs
|
||||
libtasn1
|
||||
qtbase
|
||||
sqlite
|
||||
taglib
|
||||
]
|
||||
++ optionals stdenv.hostPlatform.isLinux [
|
||||
libgpod
|
||||
libpulseaudio
|
||||
libselinux
|
||||
libsepol
|
||||
p11-kit
|
||||
]
|
||||
++ (with gst_all_1; [
|
||||
glib-networking
|
||||
gst-libav
|
||||
gst-plugins-bad
|
||||
gst-plugins-base
|
||||
gst-plugins-good
|
||||
gst-plugins-ugly
|
||||
gstreamer
|
||||
]);
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
ninja
|
||||
pkg-config
|
||||
qttools
|
||||
wrapQtAppsHook
|
||||
] ++ optionals stdenv.hostPlatform.isLinux [
|
||||
util-linux
|
||||
];
|
||||
nativeBuildInputs =
|
||||
[
|
||||
cmake
|
||||
ninja
|
||||
pkg-config
|
||||
qttools
|
||||
wrapQtAppsHook
|
||||
]
|
||||
++ optionals stdenv.hostPlatform.isLinux [
|
||||
util-linux
|
||||
];
|
||||
|
||||
postInstall = optionalString withGstreamer ''
|
||||
postInstall = ''
|
||||
qtWrapperArgs+=(
|
||||
--prefix GST_PLUGIN_SYSTEM_PATH_1_0 : "$GST_PLUGIN_SYSTEM_PATH_1_0"
|
||||
--prefix GIO_EXTRA_MODULES : "${glib-networking.out}/lib/gio/modules"
|
||||
|
||||
@@ -67,7 +67,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
postFixup = lib.optionalString (!stdenv.hostPlatform.isDarwin) ''
|
||||
makeWrapper ${electron}/bin/electron $out/bin/youtube-music \
|
||||
--add-flags $out/share/lib/youtube-music/resources/app.asar \
|
||||
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime}}" \
|
||||
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}" \
|
||||
--set-default ELECTRON_FORCE_IS_PACKAGED 1 \
|
||||
--set-default ELECTRON_IS_DEV 0 \
|
||||
--inherit-argv0
|
||||
@@ -78,8 +78,8 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
name = "youtube-music";
|
||||
exec = "youtube-music %u";
|
||||
icon = "youtube-music";
|
||||
desktopName = "Youtube Music";
|
||||
startupWMClass = "Youtube Music";
|
||||
desktopName = "YouTube Music";
|
||||
startupWMClass = "YouTube Music";
|
||||
categories = [ "AudioVideo" ];
|
||||
})
|
||||
];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user