Merge branch 'master' into invoiceplane-lang
This commit is contained in:
@@ -19,6 +19,8 @@ name: Codeowners v2
|
||||
#
|
||||
# This split is done because checking code owners requires handling untrusted PR input,
|
||||
# while requesting code owners requires PR write access, and those shouldn't be mixed.
|
||||
#
|
||||
# Note that the latter is also used for ./eval.yml requesting reviewers.
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
@@ -133,6 +133,7 @@ jobs:
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
|
||||
fetch-depth: 2
|
||||
path: nixpkgs
|
||||
|
||||
- name: Install Nix
|
||||
@@ -194,12 +195,18 @@ jobs:
|
||||
- name: Compare against the base branch
|
||||
if: steps.baseRunId.outputs.baseRunId
|
||||
run: |
|
||||
nix-build nixpkgs/ci -A eval.compare \
|
||||
git -C nixpkgs worktree add ../base ${{ needs.attrs.outputs.baseSha }}
|
||||
git -C nixpkgs diff --name-only ${{ needs.attrs.outputs.baseSha }} ${{ needs.attrs.outputs.mergedSha }} \
|
||||
| jq --raw-input --slurp 'split("\n")[:-1]' > touched-files.json
|
||||
|
||||
# Use the base branch to get accurate maintainer info
|
||||
nix-build base/ci -A eval.compare \
|
||||
--arg beforeResultDir ./baseResult \
|
||||
--arg afterResultDir ./prResult \
|
||||
--arg touchedFilesJson ./touched-files.json \
|
||||
-o comparison
|
||||
|
||||
cat comparison/step-summary.md >> "$GITHUB_STEP_SUMMARY"
|
||||
# TODO: Request reviews from maintainers for packages whose files are modified in the PR
|
||||
|
||||
- name: Upload the combined results
|
||||
if: steps.baseRunId.outputs.baseRunId
|
||||
@@ -212,18 +219,41 @@ jobs:
|
||||
tag:
|
||||
name: Tag
|
||||
runs-on: ubuntu-latest
|
||||
needs: process
|
||||
needs: [ attrs, process ]
|
||||
if: needs.process.outputs.baseRunId
|
||||
permissions:
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
steps:
|
||||
# See ./codeowners-v2.yml, reuse the same App because we need the same permissions
|
||||
# Can't use the token received from permissions above, because it can't get enough permissions
|
||||
- uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.OWNER_APP_ID }}
|
||||
private-key: ${{ secrets.OWNER_APP_PRIVATE_KEY }}
|
||||
|
||||
- name: Download process result
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: comparison
|
||||
path: comparison
|
||||
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
|
||||
|
||||
# Important: This workflow job runs with extra permissions,
|
||||
# so we need to make sure to not run untrusted code from PRs
|
||||
- name: Check out Nixpkgs at the base commit
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
ref: ${{ needs.attrs.outputs.baseSha }}
|
||||
path: base
|
||||
sparse-checkout: ci
|
||||
|
||||
- name: Build the requestReviews derivation
|
||||
run: nix-build base/ci -A requestReviews
|
||||
|
||||
- name: Tagging pull request
|
||||
run: |
|
||||
# Get all currently set rebuild labels
|
||||
@@ -252,10 +282,25 @@ jobs:
|
||||
/repos/"$REPOSITORY"/issues/"$NUMBER"/labels \
|
||||
-f "labels[]=$toAdd"
|
||||
done < <(comm -13 before after)
|
||||
|
||||
# maintainers.json contains GitHub IDs. Look up handles to request reviews from.
|
||||
# There appears to be no API to request reviews based on GitHub IDs
|
||||
jq -r 'keys[]' comparison/maintainers.json \
|
||||
| while read -r id; do gh api /user/"$id" --jq .login; done \
|
||||
| GH_TOKEN=${{ steps.app-token.outputs.token }} result/bin/process-reviewers.sh "$REPOSITORY" "$NUMBER" "$AUTHOR" \
|
||||
> reviewers.json
|
||||
|
||||
# Request reviewers from maintainers of changed output paths
|
||||
GH_TOKEN=${{ steps.app-token.outputs.token }} gh api \
|
||||
--method POST \
|
||||
/repos/"$REPOSITORY"/pulls/"$NUMBER"/requested_reviewers \
|
||||
--input reviewers.json
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
REPOSITORY: ${{ github.repository }}
|
||||
NUMBER: ${{ github.event.number }}
|
||||
AUTHOR: ${{ github.event.pull_request.user.login }}
|
||||
|
||||
- name: Add eval summary to commit statuses
|
||||
if: ${{ github.event_name == 'pull_request_target' }}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
name: "No channel PR"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
pull_request_target:
|
||||
# Re-run should be triggered when the base branch is updated, instead of silently failing
|
||||
types: [opened, synchronize, reopened, edited]
|
||||
branches:
|
||||
- 'nixos-**'
|
||||
- 'nixpkgs-**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
fail:
|
||||
permissions:
|
||||
contents: none
|
||||
name: "This PR is is targeting a channel branch"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
name: "Set pending OfBorg status"
|
||||
on:
|
||||
pull_request_target:
|
||||
|
||||
# Sets the ofborg-eval status to "pending" to signal that we are waiting for
|
||||
# OfBorg even if it is running late. The status will be overwritten by OfBorg
|
||||
# once it starts evaluation.
|
||||
|
||||
# WARNING:
|
||||
# When extending this action, be aware that $GITHUB_TOKEN allows (restricted) write access to
|
||||
# the GitHub repository. This means that it should not evaluate user input in a
|
||||
# way that allows code injection.
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
action:
|
||||
name: set-ofborg-pending
|
||||
if: github.repository_owner == 'NixOS'
|
||||
permissions:
|
||||
statuses: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Set pending OfBorg status"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
curl \
|
||||
-X POST \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||
-d '{"context": "ofborg-eval", "state": "pending", "description": "Waiting for OfBorg..."}' \
|
||||
"https://api.github.com/repos/NixOS/nixpkgs/commits/${{ github.event.pull_request.head.sha }}/statuses"
|
||||
@@ -33,12 +33,6 @@ jobs:
|
||||
max-parallel: 1
|
||||
matrix:
|
||||
pairs:
|
||||
- from: master
|
||||
into: haskell-updates
|
||||
- from: release-24.05
|
||||
into: staging-next-24.05
|
||||
- from: staging-next-24.05
|
||||
into: staging-24.05
|
||||
- from: release-24.11
|
||||
into: staging-next-24.11
|
||||
- from: staging-next-24.11
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# This action periodically merges a merge base of master and staging into haskell-updates.
|
||||
#
|
||||
# haskell-updates is based on master (so there are little unrelated failures and the cache
|
||||
# is already prepopulated), but needs to target staging due to the high amount of rebuilds
|
||||
# it typically causes. To prevent unrelated commits clattering the GitHub UI, we need to
|
||||
# take care to only merge the merge-base of master and staging into haskell-updates.
|
||||
#
|
||||
# See also https://github.com/NixOS/nixpkgs/issues/361143.
|
||||
|
||||
name: "Periodic Merges (haskell-updates)"
|
||||
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# * is a special character in YAML so you have to quote this string
|
||||
# Merge every 24 hours
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
periodic-merge:
|
||||
permissions:
|
||||
contents: write # for devmasx/merge-branch to merge branches
|
||||
pull-requests: write # for peter-evans/create-or-update-comment to create or update comment
|
||||
if: github.repository_owner == 'NixOS'
|
||||
runs-on: ubuntu-latest
|
||||
name: git merge-base master staging → haskell-updates
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# Note: If we want to do something similar for more branches, we can move this into a
|
||||
# separate job, so we can use the matrix strategy again.
|
||||
- name: Find merge base of master and staging
|
||||
id: find_merge_base_step
|
||||
run: |
|
||||
merge_base="$(git merge-base refs/remotes/origin/master refs/remotes/origin/staging)"
|
||||
echo "Found merge base: $merge_base" >&2
|
||||
echo "merge_base=$merge_base" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: git merge-base master staging → haskell-updates
|
||||
uses: devmasx/merge-branch@854d3ac71ed1e9deb668e0074781b81fdd6e771f # 1.4.0
|
||||
with:
|
||||
type: now
|
||||
head_to_merge: ${{ steps.find_merge_base_step.outputs.merge_base }}
|
||||
target_branch: haskell-updates
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Comment on failure
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
issue-number: 367709
|
||||
body: |
|
||||
Periodic merge from `${{ steps.find_merge_base_step.outputs.merge_base }}` into `haskell-updates` has [failed](https://github.com/NixOS/nixpkgs/actions/runs/${{ github.run_id }}).
|
||||
@@ -10,6 +10,9 @@ Fiona Behrens <me@kloenk.dev>
|
||||
Fiona Behrens <me@kloenk.dev> <me@kloenk.de>
|
||||
goatastronaut0212 <goatastronaut0212@outlook.com> <goatastronaut0212@proton.me>
|
||||
Janne Heß <janne@hess.ooo> <dasJ@users.noreply.github.com>
|
||||
jopejoe1 <nixpkgs@missing.ninja>
|
||||
jopejoe1 <nixpkgs@missing.ninja> <johannes@joens.email>
|
||||
jopejoe1 <nixpkgs@missing.ninja> <34899572+jopejoe1@users.noreply.github.com>
|
||||
Jörg Thalheim <joerg@thalheim.io> <Mic92@users.noreply.github.com>
|
||||
Lin Jian <me@linj.tech> <linj.dev@outlook.com>
|
||||
Lin Jian <me@linj.tech> <75130626+jian-lin@users.noreply.github.com>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2003-2024 Eelco Dolstra and the Nixpkgs/NixOS contributors
|
||||
Copyright (c) 2003-2025 Eelco Dolstra and the Nixpkgs/NixOS contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
writeText,
|
||||
...
|
||||
}:
|
||||
{ beforeResultDir, afterResultDir }:
|
||||
{
|
||||
beforeResultDir,
|
||||
afterResultDir,
|
||||
touchedFilesJson,
|
||||
}:
|
||||
let
|
||||
/*
|
||||
Derivation that computes which packages are affected (added, changed or removed) between two revisions of nixpkgs.
|
||||
@@ -77,11 +81,11 @@ let
|
||||
# - values: lists of `packagePlatformPath`s
|
||||
diffAttrs = diff beforeAttrs afterAttrs;
|
||||
|
||||
rebuilds = uniqueStrings (diffAttrs.added ++ diffAttrs.changed);
|
||||
rebuildsPackagePlatformAttrs = convertToPackagePlatformAttrs rebuilds;
|
||||
|
||||
changed-paths =
|
||||
let
|
||||
rebuilds = uniqueStrings (diffAttrs.added ++ diffAttrs.changed);
|
||||
rebuildsPackagePlatformAttrs = convertToPackagePlatformAttrs rebuilds;
|
||||
|
||||
rebuildsByPlatform = groupByPlatform rebuildsPackagePlatformAttrs;
|
||||
rebuildsByKernel = groupByKernel rebuildsPackagePlatformAttrs;
|
||||
rebuildCountByKernel = lib.mapAttrs (
|
||||
@@ -104,10 +108,17 @@ let
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
maintainers = import ./maintainers.nix {
|
||||
changedattrs = lib.unique (map (a: a.packagePath) rebuildsPackagePlatformAttrs);
|
||||
changedpathsjson = touchedFilesJson;
|
||||
};
|
||||
in
|
||||
runCommand "compare"
|
||||
{
|
||||
nativeBuildInputs = [ jq ];
|
||||
maintainers = builtins.toJSON maintainers;
|
||||
passAsFile = [ "maintainers" ];
|
||||
}
|
||||
''
|
||||
mkdir $out
|
||||
@@ -115,5 +126,8 @@ runCommand "compare"
|
||||
cp ${changed-paths} $out/changed-paths.json
|
||||
|
||||
jq -r -f ${./generate-step-summary.jq} < ${changed-paths} > $out/step-summary.md
|
||||
|
||||
cp "$maintainersPath" "$out/maintainers.json"
|
||||
|
||||
# TODO: Compare eval stats
|
||||
''
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
# Almost directly vendored from https://github.com/NixOS/ofborg/blob/5a4e743f192fb151915fcbe8789922fa401ecf48/ofborg/src/maintainers.nix
|
||||
{ changedattrs, changedpathsjson }:
|
||||
let
|
||||
pkgs = import ../../.. {
|
||||
system = "x86_64-linux";
|
||||
config = { };
|
||||
overlays = [ ];
|
||||
};
|
||||
inherit (pkgs) lib;
|
||||
|
||||
changedpaths = builtins.fromJSON (builtins.readFile changedpathsjson);
|
||||
|
||||
anyMatchingFile =
|
||||
filename:
|
||||
let
|
||||
matching = builtins.filter (changed: lib.strings.hasSuffix changed filename) changedpaths;
|
||||
in
|
||||
(builtins.length matching) > 0;
|
||||
|
||||
anyMatchingFiles = files: (builtins.length (builtins.filter anyMatchingFile files)) > 0;
|
||||
|
||||
enrichedAttrs = builtins.map (path: {
|
||||
path = path;
|
||||
name = builtins.concatStringsSep "." path;
|
||||
}) changedattrs;
|
||||
|
||||
validPackageAttributes = builtins.filter (
|
||||
pkg:
|
||||
if (lib.attrsets.hasAttrByPath pkg.path pkgs) then
|
||||
(
|
||||
if (builtins.tryEval (lib.attrsets.attrByPath pkg.path null pkgs)).success then
|
||||
true
|
||||
else
|
||||
builtins.trace "Failed to access ${pkg.name} even though it exists" false
|
||||
)
|
||||
else
|
||||
builtins.trace "Failed to locate ${pkg.name}." false
|
||||
) enrichedAttrs;
|
||||
|
||||
attrsWithPackages = builtins.map (
|
||||
pkg: pkg // { package = lib.attrsets.attrByPath pkg.path null pkgs; }
|
||||
) validPackageAttributes;
|
||||
|
||||
attrsWithMaintainers = builtins.map (
|
||||
pkg: pkg // { maintainers = (pkg.package.meta or { }).maintainers or [ ]; }
|
||||
) attrsWithPackages;
|
||||
|
||||
attrsWeCanPing = builtins.filter (
|
||||
pkg:
|
||||
if (builtins.length pkg.maintainers) > 0 then
|
||||
true
|
||||
else
|
||||
builtins.trace "Package has no maintainers: ${pkg.name}" false
|
||||
) attrsWithMaintainers;
|
||||
|
||||
relevantFilenames =
|
||||
drv:
|
||||
(lib.lists.unique (
|
||||
builtins.map (pos: lib.strings.removePrefix (toString ../..) pos.file) (
|
||||
builtins.filter (x: x != null) [
|
||||
(builtins.unsafeGetAttrPos "maintainers" (drv.meta or { }))
|
||||
(builtins.unsafeGetAttrPos "src" drv)
|
||||
# broken because name is always set by stdenv:
|
||||
# # A hack to make `nix-env -qa` and `nix search` ignore broken packages.
|
||||
# # TODO(@oxij): remove this assert when something like NixOS/nix#1771 gets merged into nix.
|
||||
# name = assert validity.handled; name + lib.optionalString
|
||||
#(builtins.unsafeGetAttrPos "name" drv)
|
||||
(builtins.unsafeGetAttrPos "pname" drv)
|
||||
(builtins.unsafeGetAttrPos "version" drv)
|
||||
|
||||
# Use ".meta.position" for cases when most of the package is
|
||||
# defined in a "common" section and the only place where
|
||||
# reference to the file with a derivation the "pos"
|
||||
# attribute.
|
||||
#
|
||||
# ".meta.position" has the following form:
|
||||
# "pkgs/tools/package-management/nix/default.nix:155"
|
||||
# We transform it to the following:
|
||||
# { file = "pkgs/tools/package-management/nix/default.nix"; }
|
||||
{ file = lib.head (lib.splitString ":" (drv.meta.position or "")); }
|
||||
]
|
||||
)
|
||||
));
|
||||
|
||||
attrsWithFilenames = builtins.map (
|
||||
pkg: pkg // { filenames = relevantFilenames pkg.package; }
|
||||
) attrsWithMaintainers;
|
||||
|
||||
attrsWithModifiedFiles = builtins.filter (pkg: anyMatchingFiles pkg.filenames) attrsWithFilenames;
|
||||
|
||||
listToPing = lib.lists.flatten (
|
||||
builtins.map (
|
||||
pkg:
|
||||
builtins.map (maintainer: {
|
||||
id = maintainer.githubId;
|
||||
packageName = pkg.name;
|
||||
dueToFiles = pkg.filenames;
|
||||
}) pkg.maintainers
|
||||
) attrsWithModifiedFiles
|
||||
);
|
||||
|
||||
byMaintainer = lib.lists.foldr (
|
||||
ping: collector:
|
||||
collector
|
||||
// {
|
||||
"${toString ping.id}" = [
|
||||
{ inherit (ping) packageName dueToFiles; }
|
||||
] ++ (collector."${toString ping.id}" or [ ]);
|
||||
}
|
||||
) { } listToPing;
|
||||
|
||||
textForPackages =
|
||||
packages: lib.strings.concatStringsSep ", " (builtins.map (pkg: pkg.packageName) packages);
|
||||
|
||||
textPerMaintainer = lib.attrsets.mapAttrs (
|
||||
maintainer: packages: "- @${maintainer} for ${textForPackages packages}"
|
||||
) byMaintainer;
|
||||
|
||||
packagesPerMaintainer = lib.attrsets.mapAttrs (
|
||||
maintainer: packages: builtins.map (pkg: pkg.packageName) packages
|
||||
) byMaintainer;
|
||||
in
|
||||
packagesPerMaintainer
|
||||
+22
-18
@@ -11,6 +11,7 @@ rec {
|
||||
into
|
||||
{
|
||||
name = "hello";
|
||||
packagePath = [ "hello" ];
|
||||
platform = "aarch64-linux";
|
||||
}
|
||||
*/
|
||||
@@ -30,6 +31,9 @@ rec {
|
||||
null
|
||||
else
|
||||
{
|
||||
# [ "python312Packages" "numpy" ]
|
||||
inherit packagePath;
|
||||
|
||||
# python312Packages.numpy
|
||||
inherit name;
|
||||
|
||||
@@ -52,12 +56,12 @@ rec {
|
||||
]
|
||||
into
|
||||
[
|
||||
{ name = "hello"; platform = "aarch64-linux"; }
|
||||
{ name = "hello"; platform = "x86_64-linux"; }
|
||||
{ name = "hello"; platform = "aarch64-darwin"; }
|
||||
{ name = "hello"; platform = "x86_64-darwin"; }
|
||||
{ name = "bye"; platform = "aarch64-darwin"; }
|
||||
{ name = "bye"; platform = "x86_64-darwin"; }
|
||||
{ name = "hello"; platform = "aarch64-linux"; packagePath = [ "hello" ]; }
|
||||
{ name = "hello"; platform = "x86_64-linux"; packagePath = [ "hello" ]; }
|
||||
{ name = "hello"; platform = "aarch64-darwin"; packagePath = [ "hello" ]; }
|
||||
{ name = "hello"; platform = "x86_64-darwin"; packagePath = [ "hello" ]; }
|
||||
{ name = "bye"; platform = "aarch64-darwin"; packagePath = [ "hello" ]; }
|
||||
{ name = "bye"; platform = "x86_64-darwin"; packagePath = [ "hello" ]; }
|
||||
]
|
||||
*/
|
||||
convertToPackagePlatformAttrs =
|
||||
@@ -120,12 +124,12 @@ rec {
|
||||
|
||||
Turns
|
||||
[
|
||||
{ name = "hello"; platform = "aarch64-linux"; }
|
||||
{ name = "hello"; platform = "x86_64-linux"; }
|
||||
{ name = "hello"; platform = "aarch64-darwin"; }
|
||||
{ name = "hello"; platform = "x86_64-darwin"; }
|
||||
{ name = "bye"; platform = "aarch64-darwin"; }
|
||||
{ name = "bye"; platform = "x86_64-darwin"; }
|
||||
{ name = "hello"; platform = "aarch64-linux"; ... }
|
||||
{ name = "hello"; platform = "x86_64-linux"; ... }
|
||||
{ name = "hello"; platform = "aarch64-darwin"; ... }
|
||||
{ name = "hello"; platform = "x86_64-darwin"; ... }
|
||||
{ name = "bye"; platform = "aarch64-darwin"; ... }
|
||||
{ name = "bye"; platform = "x86_64-darwin"; ... }
|
||||
]
|
||||
into
|
||||
{
|
||||
@@ -145,12 +149,12 @@ rec {
|
||||
|
||||
# Turns
|
||||
# [
|
||||
# { name = "hello"; platform = "aarch64-linux"; }
|
||||
# { name = "hello"; platform = "x86_64-linux"; }
|
||||
# { name = "hello"; platform = "aarch64-darwin"; }
|
||||
# { name = "hello"; platform = "x86_64-darwin"; }
|
||||
# { name = "bye"; platform = "aarch64-darwin"; }
|
||||
# { name = "bye"; platform = "x86_64-darwin"; }
|
||||
# { name = "hello"; platform = "aarch64-linux"; ... }
|
||||
# { name = "hello"; platform = "x86_64-linux"; ... }
|
||||
# { name = "hello"; platform = "aarch64-darwin"; ... }
|
||||
# { name = "hello"; platform = "x86_64-darwin"; ... }
|
||||
# { name = "bye"; platform = "aarch64-darwin"; ... }
|
||||
# { name = "bye"; platform = "x86_64-darwin"; ... }
|
||||
# ]
|
||||
#
|
||||
# into
|
||||
|
||||
@@ -15,6 +15,7 @@ stdenvNoCC.mkDerivation {
|
||||
root = ./.;
|
||||
fileset = lib.fileset.unions [
|
||||
./get-reviewers.sh
|
||||
./process-reviewers.sh
|
||||
./request-reviews.sh
|
||||
./verify-base-branch.sh
|
||||
./dev-branches.txt
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Get the code owners of the files changed by a PR,
|
||||
# suitable to be consumed by the API endpoint to request reviews:
|
||||
# https://docs.github.com/en/rest/pulls/review-requests?apiVersion=2022-11-28#request-reviewers-for-a-pull-request
|
||||
# Get the code owners of the files changed by a PR, returning one username per line
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -10,18 +8,15 @@ log() {
|
||||
echo "$@" >&2
|
||||
}
|
||||
|
||||
if (( "$#" < 7 )); then
|
||||
log "Usage: $0 GIT_REPO OWNERS_FILE BASE_REPO BASE_REF HEAD_REF PR_NUMBER PR_AUTHOR"
|
||||
if (( "$#" < 4 )); then
|
||||
log "Usage: $0 GIT_REPO OWNERS_FILE BASE_REF HEAD_REF"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
gitRepo=$1
|
||||
ownersFile=$2
|
||||
baseRepo=$3
|
||||
baseRef=$4
|
||||
headRef=$5
|
||||
prNumber=$6
|
||||
prAuthor=$7
|
||||
baseRef=$3
|
||||
headRef=$4
|
||||
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' exit
|
||||
@@ -98,29 +93,4 @@ for file in "${touchedFiles[@]}"; do
|
||||
|
||||
done
|
||||
|
||||
# Cannot request a review from the author
|
||||
if [[ -v users[${prAuthor,,}] ]]; then
|
||||
log "One or more files are owned by the PR author, ignoring"
|
||||
unset 'users[${prAuthor,,}]'
|
||||
fi
|
||||
|
||||
gh api \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"/repos/$baseRepo/pulls/$prNumber/reviews" \
|
||||
--jq '.[].user.login' > "$tmp/already-reviewed-by"
|
||||
|
||||
# And we don't want to rerequest reviews from people who already reviewed
|
||||
while read -r user; do
|
||||
if [[ -v users[${user,,}] ]]; then
|
||||
log "User $user is a code owner but has already left a review, ignoring"
|
||||
unset 'users[${user,,}]'
|
||||
fi
|
||||
done < "$tmp/already-reviewed-by"
|
||||
|
||||
# Turn it into a JSON for the GitHub API call to request PR reviewers
|
||||
jq -n \
|
||||
--arg users "${!users[*]}" \
|
||||
'{
|
||||
reviewers: $users | split(" "),
|
||||
}'
|
||||
printf "%s\n" "${!users[@]}"
|
||||
|
||||
Executable
+65
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Process reviewers for a PR, reading line-separated usernames on stdin,
|
||||
# returning a JSON suitable to be consumed by the API endpoint to request reviews:
|
||||
# https://docs.github.com/en/rest/pulls/review-requests?apiVersion=2022-11-28#request-reviewers-for-a-pull-request
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
log() {
|
||||
echo "$@" >&2
|
||||
}
|
||||
|
||||
if (( "$#" < 3 )); then
|
||||
log "Usage: $0 BASE_REPO PR_NUMBER PR_AUTHOR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
baseRepo=$1
|
||||
prNumber=$2
|
||||
prAuthor=$3
|
||||
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' exit
|
||||
|
||||
declare -A users=()
|
||||
while read -r handle && [[ -n "$handle" ]]; do
|
||||
users[${handle,,}]=
|
||||
done
|
||||
|
||||
# Cannot request a review from the author
|
||||
if [[ -v users[${prAuthor,,}] ]]; then
|
||||
log "One or more files are owned by the PR author, ignoring"
|
||||
unset 'users[${prAuthor,,}]'
|
||||
fi
|
||||
|
||||
gh api \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"/repos/$baseRepo/pulls/$prNumber/reviews" \
|
||||
--jq '.[].user.login' > "$tmp/already-reviewed-by"
|
||||
|
||||
# And we don't want to rerequest reviews from people who already reviewed
|
||||
while read -r user; do
|
||||
if [[ -v users[${user,,}] ]]; then
|
||||
log "User $user is a code owner but has already left a review, ignoring"
|
||||
unset 'users[${user,,}]'
|
||||
fi
|
||||
done < "$tmp/already-reviewed-by"
|
||||
|
||||
for user in "${!users[@]}"; do
|
||||
if ! gh api \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"/repos/$baseRepo/collaborators/$user" >&2; then
|
||||
log "User $user is not a repository collaborator, probably missed the automated invite to the maintainers team (see <https://github.com/NixOS/nixpkgs/issues/234293>), ignoring"
|
||||
unset 'users[$user]'
|
||||
fi
|
||||
done
|
||||
|
||||
# Turn it into a JSON for the GitHub API call to request PR reviewers
|
||||
jq -n \
|
||||
--arg users "${!users[*]}" \
|
||||
'{
|
||||
reviewers: $users | split(" "),
|
||||
}'
|
||||
@@ -78,7 +78,8 @@ if ! "$SCRIPT_DIR"/verify-base-branch.sh "$tmp/nixpkgs.git" "$headRef" "$baseRep
|
||||
fi
|
||||
|
||||
log "Getting code owners to request reviews from"
|
||||
"$SCRIPT_DIR"/get-reviewers.sh "$tmp/nixpkgs.git" "$ownersFile" "$baseRepo" "$baseBranch" "$headRef" "$prNumber" "$prAuthor" > "$tmp/reviewers.json"
|
||||
"$SCRIPT_DIR"/get-reviewers.sh "$tmp/nixpkgs.git" "$ownersFile" "$baseBranch" "$headRef" | \
|
||||
"$SCRIPT_DIR"/process-reviewers.sh "$baseRepo" "$prNumber" "$prAuthor" > "$tmp/reviewers.json"
|
||||
|
||||
log "Requesting reviews from: $(<"$tmp/reviewers.json")"
|
||||
|
||||
|
||||
@@ -728,7 +728,7 @@ buildPythonPackage rec {
|
||||
(fetchDebianPatch {
|
||||
inherit pname version;
|
||||
debianRevision = "5";
|
||||
name = "Add-quotes-to-SOAPAction-header-in-SoapClient.patch";
|
||||
patch = "Add-quotes-to-SOAPAction-header-in-SoapClient.patch";
|
||||
hash = "sha256-xA8Wnrpr31H8wy3zHSNfezFNjUJt1HbSXn3qUMzeKc0=";
|
||||
})
|
||||
];
|
||||
|
||||
@@ -94,10 +94,7 @@
|
||||
stdenvNoCC.mkDerivation {
|
||||
name = "nixpkgs-lib-docs";
|
||||
|
||||
src = lib.fileset.toSource {
|
||||
root = ../..;
|
||||
fileset = ../../lib;
|
||||
};
|
||||
src = ../../lib;
|
||||
|
||||
nativeBuildInputs = [
|
||||
nixdoc
|
||||
@@ -105,6 +102,8 @@ stdenvNoCC.mkDerivation {
|
||||
];
|
||||
|
||||
installPhase = ''
|
||||
cd ..
|
||||
|
||||
export NIX_STATE_DIR=$(mktemp -d)
|
||||
nix-instantiate --eval --strict --json ${./lib-function-locations.nix} \
|
||||
--arg nixpkgsPath "./." \
|
||||
|
||||
+16
-10
@@ -25,16 +25,22 @@ stdenvNoCC.mkDerivation (
|
||||
|
||||
nativeBuildInputs = [ nixos-render-docs ];
|
||||
|
||||
src = lib.fileset.toSource {
|
||||
root = ../.;
|
||||
fileset = lib.fileset.unions [
|
||||
(lib.fileset.fileFilter (file: file.hasExt "md" || file.hasExt "md.in") ../.)
|
||||
../style.css
|
||||
../anchor-use.js
|
||||
../anchor.min.js
|
||||
../manpage-urls.json
|
||||
../redirects.json
|
||||
];
|
||||
src = lib.cleanSourceWith {
|
||||
src = ../.;
|
||||
filter =
|
||||
path: type:
|
||||
type == "directory"
|
||||
|| lib.hasSuffix ".md" path
|
||||
|| lib.hasSuffix ".md.in" path
|
||||
|| lib.elem path (
|
||||
map toString [
|
||||
../style.css
|
||||
../anchor-use.js
|
||||
../anchor.min.js
|
||||
../manpage-urls.json
|
||||
../redirects.json
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
|
||||
@@ -95,6 +95,5 @@ scheme.section.md
|
||||
swift.section.md
|
||||
tcl.section.md
|
||||
texlive.section.md
|
||||
titanium.section.md
|
||||
vim.section.md
|
||||
```
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
# Titanium {#titanium}
|
||||
|
||||
The Nixpkgs repository contains facilities to deploy a variety of versions of
|
||||
the [Titanium SDK](https://www.appcelerator.com) versions, a cross-platform
|
||||
mobile app development framework using JavaScript as an implementation language,
|
||||
and includes a function abstraction making it possible to build Titanium
|
||||
applications for Android and iOS devices from source code.
|
||||
|
||||
Not all Titanium features supported -- currently, it can only be used to build
|
||||
Android and iOS apps.
|
||||
|
||||
## Building a Titanium app {#building-a-titanium-app}
|
||||
|
||||
We can build a Titanium app from source for Android or iOS and for debugging or
|
||||
release purposes by invoking the `titaniumenv.buildApp {}` function:
|
||||
|
||||
```nix
|
||||
titaniumenv.buildApp {
|
||||
name = "myapp";
|
||||
src = ./myappsource;
|
||||
|
||||
preBuild = "";
|
||||
target = "android"; # or 'iphone'
|
||||
tiVersion = "7.1.0.GA";
|
||||
release = true;
|
||||
|
||||
androidsdkArgs = {
|
||||
platformVersions = [ "25" "26" ];
|
||||
};
|
||||
androidKeyStore = ./keystore;
|
||||
androidKeyAlias = "myfirstapp";
|
||||
androidKeyStorePassword = "secret";
|
||||
|
||||
xcodeBaseDir = "/Applications/Xcode.app";
|
||||
xcodewrapperArgs = {
|
||||
version = "9.3";
|
||||
};
|
||||
iosMobileProvisioningProfile = ./myprovisioning.profile;
|
||||
iosCertificateName = "My Company";
|
||||
iosCertificate = ./mycertificate.p12;
|
||||
iosCertificatePassword = "secret";
|
||||
iosVersion = "11.3";
|
||||
iosBuildStore = false;
|
||||
|
||||
enableWirelessDistribution = true;
|
||||
installURL = "/installipa.php";
|
||||
}
|
||||
```
|
||||
|
||||
The `titaniumenv.buildApp {}` function takes the following parameters:
|
||||
|
||||
* The `name` parameter refers to the name in the Nix store.
|
||||
* The `src` parameter refers to the source code location of the app that needs
|
||||
to be built.
|
||||
* `preRebuild` contains optional build instructions that are carried out before
|
||||
the build starts.
|
||||
* `target` indicates for which device the app must be built. Currently only
|
||||
'android' and 'iphone' (for iOS) are supported.
|
||||
* `tiVersion` can be used to optionally override the requested Titanium version
|
||||
in `tiapp.xml`. If not specified, it will use the version in `tiapp.xml`.
|
||||
* `release` should be set to true when building an app for submission to the
|
||||
Google Playstore or Apple Appstore. Otherwise, it should be false.
|
||||
|
||||
When the `target` has been set to `android`, we can configure the following
|
||||
parameters:
|
||||
|
||||
* The `androidSdkArgs` parameter refers to an attribute set that propagates all
|
||||
parameters to the `androidenv.composeAndroidPackages {}` function. This can
|
||||
be used to install all relevant Android plugins that may be needed to perform
|
||||
the Android build. If no parameters are given, it will deploy the platform
|
||||
SDKs for API-levels 25 and 26 by default.
|
||||
|
||||
When the `release` parameter has been set to true, you need to provide
|
||||
parameters to sign the app:
|
||||
|
||||
* `androidKeyStore` is the path to the keystore file
|
||||
* `androidKeyAlias` is the key alias
|
||||
* `androidKeyStorePassword` refers to the password to open the keystore file.
|
||||
|
||||
When the `target` has been set to `iphone`, we can configure the following
|
||||
parameters:
|
||||
|
||||
* The `xcodeBaseDir` parameter refers to the location where Xcode has been
|
||||
installed. When none value is given, the above value is the default.
|
||||
* The `xcodewrapperArgs` parameter passes arbitrary parameters to the
|
||||
`xcodeenv.composeXcodeWrapper {}` function. This can, for example, be used
|
||||
to adjust the default version of Xcode.
|
||||
|
||||
When `release` has been set to true, you also need to provide the following
|
||||
parameters:
|
||||
|
||||
* `iosMobileProvisioningProfile` refers to a mobile provisioning profile needed
|
||||
for signing.
|
||||
* `iosCertificateName` refers to the company name in the P12 certificate.
|
||||
* `iosCertificate` refers to the path to the P12 file.
|
||||
* `iosCertificatePassword` contains the password to open the P12 file.
|
||||
* `iosVersion` refers to the iOS SDK version to use. It defaults to the latest
|
||||
version.
|
||||
* `iosBuildStore` should be set to `true` when building for the Apple Appstore
|
||||
submission. For enterprise or ad-hoc builds it should be set to `false`.
|
||||
|
||||
When `enableWirelessDistribution` has been enabled, you must also provide the
|
||||
path of the PHP script (`installURL`) (that is included with the iOS build
|
||||
environment) to enable wireless ad-hoc installations.
|
||||
|
||||
## Emulating or simulating the app {#emulating-or-simulating-the-app}
|
||||
|
||||
It is also possible to simulate the correspond iOS simulator build by using
|
||||
`xcodeenv.simulateApp {}` and emulate an Android APK by using
|
||||
`androidenv.emulateApp {}`.
|
||||
@@ -14,3 +14,7 @@ development.md
|
||||
contributing.md
|
||||
interoperability.md
|
||||
```
|
||||
|
||||
```{=include=} appendix html:into-file=//release-notes.html
|
||||
release-notes/release-notes.md
|
||||
```
|
||||
|
||||
@@ -7,9 +7,12 @@ The module system is a language for handling configuration, implemented as a Nix
|
||||
Compared to plain Nix, it adds documentation, type checking and composition or extensibility.
|
||||
|
||||
::: {.note}
|
||||
This chapter is new and not complete yet. For a gentle introduction to the module system, in the context of NixOS, see [Writing NixOS Modules](https://nixos.org/manual/nixos/unstable/index.html#sec-writing-modules) in the NixOS manual.
|
||||
:::
|
||||
This chapter is new and not complete yet.
|
||||
|
||||
See also:
|
||||
- Introduction to the module system, in the context of NixOS, see [Writing NixOS Modules](https://nixos.org/manual/nixos/unstable/index.html#sec-writing-modules) in the NixOS manual.
|
||||
- Generic guide to the module system on [nix.dev](https://nix.dev/tutorials/module-system/index.html).
|
||||
:::
|
||||
|
||||
## `lib.evalModules` {#module-system-lib-evalModules}
|
||||
|
||||
|
||||
@@ -98,5 +98,5 @@ substituteAllFiles {
|
||||
}
|
||||
```
|
||||
|
||||
in the resulting derivation, every instance of `@hello@` will be replaced with `there` in `$out/foo.txt` and` `$out/bar.txt`; `baz.txt` will not be processed nor will it appear in `$out`.
|
||||
in the resulting derivation, every instance of `@hello@` will be replaced with `there` in `$out/foo.txt` and `$out/bar.txt`; `baz.txt` will not be processed nor will it appear in `$out`.
|
||||
:::
|
||||
|
||||
+21
-9
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"chap-release-notes": [
|
||||
"release-notes.html#chap-release-notes"
|
||||
],
|
||||
"nixpkgs-manual": [
|
||||
"index.html#nixpkgs-manual"
|
||||
],
|
||||
@@ -50,6 +53,24 @@
|
||||
"chap-overlays": [
|
||||
"index.html#chap-overlays"
|
||||
],
|
||||
"sec-nixpkgs-release-25.05": [
|
||||
"release-notes.html#sec-nixpkgs-release-25.05"
|
||||
],
|
||||
"sec-nixpkgs-release-25.05-incompatibilities": [
|
||||
"release-notes.html#sec-nixpkgs-release-25.05-incompatibilities"
|
||||
],
|
||||
"sec-nixpkgs-release-25.05-incompatibilities-titanium-removed": [
|
||||
"release-notes.html#sec-nixpkgs-release-25.05-incompatibilities-titanium-removed",
|
||||
"index.html#titanium",
|
||||
"index.html#building-a-titanium-app",
|
||||
"index.html#emulating-or-simulating-the-app"
|
||||
],
|
||||
"sec-nixpkgs-release-25.05-lib": [
|
||||
"release-notes.html#sec-nixpkgs-release-25.05-lib"
|
||||
],
|
||||
"sec-nixpkgs-release-25.05-lib-breaking": [
|
||||
"release-notes.html#sec-nixpkgs-release-25.05-lib-breaking"
|
||||
],
|
||||
"sec-overlays-install": [
|
||||
"index.html#sec-overlays-install"
|
||||
],
|
||||
@@ -3736,15 +3757,6 @@
|
||||
"sec-language-texlive-lualatex-font-cache": [
|
||||
"index.html#sec-language-texlive-lualatex-font-cache"
|
||||
],
|
||||
"titanium": [
|
||||
"index.html#titanium"
|
||||
],
|
||||
"building-a-titanium-app": [
|
||||
"index.html#building-a-titanium-app"
|
||||
],
|
||||
"emulating-or-simulating-the-app": [
|
||||
"index.html#emulating-or-simulating-the-app"
|
||||
],
|
||||
"vim": [
|
||||
"index.html#vim"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Release Notes {#chap-release-notes}
|
||||
|
||||
This section lists the release notes for each stable version of Nixpkgs and current unstable revision.
|
||||
|
||||
```{=include=} sections
|
||||
rl-2505.section.md
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
# Nixpkgs 25.05 (2025.05/??) {#sec-nixpkgs-release-25.05}
|
||||
|
||||
## Backward Incompatibilities {#sec-nixpkgs-release-25.05-incompatibilities}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
### Titanium removed {#sec-nixpkgs-release-25.05-incompatibilities-titanium-removed}
|
||||
|
||||
- `titaniumenv`, `titanium`, and `titanium-alloy` have been removed due to lack of maintenance in Nixpkgs.
|
||||
|
||||
## Nixpkgs Library {#sec-nixpkgs-release-25.05-lib}
|
||||
|
||||
### Breaking changes {#sec-nixpkgs-release-25.05-lib-breaking}
|
||||
|
||||
- Structure of the `functor` of some types has changed. `functor` is an implementation detail and should not be relied upon. If you did rely on it let us know in this [PR](https://github.com/NixOS/nixpkgs/pull/363565).
|
||||
- [`lib.types.enum`](https://nixos.org/manual/nixos/unstable/#sec-option-types-basic): Previously the `functor.payload` was the list of enum values directly. Now it is an attribute set containing the values in the `values` attribute.
|
||||
- [`lib.types.separatedString`](https://nixos.org/manual/nixos/unstable/#sec-option-types-string): Previously the `functor.payload` was the seperator directly. Now it is an attribute set containing the seperator in the `sep` attribute.
|
||||
+1
-1
@@ -416,7 +416,7 @@ in {
|
||||
*/
|
||||
oldestSupportedRelease =
|
||||
# Update on master only. Do not backport.
|
||||
2405;
|
||||
2411;
|
||||
|
||||
/**
|
||||
Whether a feature is supported in all supported releases (at the time of
|
||||
|
||||
@@ -1632,6 +1632,12 @@
|
||||
matrix = "@anthonyrsl:matrix.org";
|
||||
keys = [ { fingerprint = "472D 368A F107 F443 F3A5 C712 9DC4 987B 1A55 E75E"; } ];
|
||||
};
|
||||
antipatico = {
|
||||
email = "code@bootkit.dev";
|
||||
github = "antipatico";
|
||||
githubId = 14838767;
|
||||
name = "Jacopo Scannella";
|
||||
};
|
||||
antoinerg = {
|
||||
email = "roygobeil.antoine@gmail.com";
|
||||
github = "antoinerg";
|
||||
@@ -2510,6 +2516,12 @@
|
||||
githubId = 66330398;
|
||||
name = "Victor Hang";
|
||||
};
|
||||
baongoc124 = {
|
||||
email = "baongoc124@gmail.com";
|
||||
github = "baongoc124";
|
||||
githubId = 766221;
|
||||
name = "Ngoc Nguyen";
|
||||
};
|
||||
barab-i = {
|
||||
email = "barab_i@outlook.com";
|
||||
github = "barab-i";
|
||||
@@ -4931,6 +4943,12 @@
|
||||
github = "damhiya";
|
||||
githubId = 13533446;
|
||||
};
|
||||
damidoug = {
|
||||
email = "contact@damidoug.dev";
|
||||
github = "damidoug";
|
||||
githubId = 75175586;
|
||||
name = "Douglas Damiano";
|
||||
};
|
||||
DamienCassou = {
|
||||
email = "damien@cassou.me";
|
||||
github = "DamienCassou";
|
||||
@@ -5874,6 +5892,11 @@
|
||||
githubId = 283316;
|
||||
name = "Dane Lipscombe";
|
||||
};
|
||||
dlurak = {
|
||||
github = "dlurak";
|
||||
githubId = 84224239;
|
||||
name = "dlurak";
|
||||
};
|
||||
dmadisetti = {
|
||||
email = "nix@madisetti.me";
|
||||
github = "dmadisetti";
|
||||
@@ -5970,6 +5993,12 @@
|
||||
githubId = 57304299;
|
||||
keys = [ { fingerprint = "33CD 5C0A 673C C54D 661E 5E4C 0DB5 361B EEE5 30AB"; } ];
|
||||
};
|
||||
dopplerian = {
|
||||
name = "Dopplerian";
|
||||
github = "Dopplerian";
|
||||
githubId = 53937537;
|
||||
keys = [ { fingerprint = "BBC4 C071 516B A147 8D07 F9DC D2FD E6EC 2E8C 2BF4"; } ];
|
||||
};
|
||||
doriath = {
|
||||
email = "tomasz.zurkowski@gmail.com";
|
||||
github = "doriath";
|
||||
@@ -9200,6 +9229,13 @@
|
||||
githubId = 287215;
|
||||
keys = [ { fingerprint = "D618 7A03 A40A 3D56 62F5 4B46 03EF BF83 9A5F DC15"; } ];
|
||||
};
|
||||
hlad = {
|
||||
email = "hlad+nix@hlad.org";
|
||||
name = "Marek Hladky";
|
||||
matrix = "@hlad:hlad.org";
|
||||
github = "hlad";
|
||||
githubId = 6285728;
|
||||
};
|
||||
hleboulanger = {
|
||||
email = "hleboulanger@protonmail.com";
|
||||
name = "Harold Leboulanger";
|
||||
@@ -10116,6 +10152,12 @@
|
||||
githubId = 45084216;
|
||||
keys = [ { fingerprint = "1BF9 8D10 E0D0 0B41 5723 5836 4C13 3A84 E646 9228"; } ];
|
||||
};
|
||||
jaculabilis = {
|
||||
name = "Tim Van Baak";
|
||||
email = "tim.vanbaak@gmail.com";
|
||||
github = "Jaculabilis";
|
||||
githubId = 10787844;
|
||||
};
|
||||
jaduff = {
|
||||
email = "jdduffpublic@proton.me";
|
||||
github = "jaduff";
|
||||
@@ -11117,11 +11159,11 @@
|
||||
githubId = 13179;
|
||||
};
|
||||
jopejoe1 = {
|
||||
email = "johannes@joens.email";
|
||||
email = "nixpkgs@missing.ninja";
|
||||
matrix = "@jopejoe1:matrix.org";
|
||||
github = "jopejoe1";
|
||||
githubId = 34899572;
|
||||
name = "Johannes Jöns";
|
||||
name = "jopejoe1";
|
||||
};
|
||||
jordanisaacs = {
|
||||
name = "Jordan Isaacs";
|
||||
@@ -12493,6 +12535,12 @@
|
||||
githubId = 168301;
|
||||
name = "Victor Engmark";
|
||||
};
|
||||
l1npengtul = {
|
||||
email = "l1npengtul@l1npengtul.lol";
|
||||
github = "l1npengtul";
|
||||
githubId = 35755164;
|
||||
name = "l1npengtul";
|
||||
};
|
||||
l33tname = {
|
||||
name = "l33tname";
|
||||
email = "hi@l33t.name";
|
||||
@@ -13714,6 +13762,17 @@
|
||||
githubId = 24735185;
|
||||
name = "Mahmoud Ayman";
|
||||
};
|
||||
mahtaran = {
|
||||
email = "luka.leer@gmail.com";
|
||||
github = "mahtaran";
|
||||
githubId = 22727323;
|
||||
name = "Luka Leer";
|
||||
keys = [
|
||||
{
|
||||
fingerprint = "C7FF B72E 0527 423A D470 E132 AA82 C4EB CB16 82E0";
|
||||
}
|
||||
];
|
||||
};
|
||||
majesticmullet = {
|
||||
email = "hoccthomas@gmail.com.au";
|
||||
github = "MajesticMullet";
|
||||
@@ -15282,6 +15341,12 @@
|
||||
githubId = 44561540;
|
||||
name = "Synth Morxemplum";
|
||||
};
|
||||
MostafaKhaled = {
|
||||
email = "mostafa.khaled.5422@gmail.com";
|
||||
github = "mostafa-khaled775";
|
||||
githubId = 112074172;
|
||||
name = "Mostafa Khaled";
|
||||
};
|
||||
MostAwesomeDude = {
|
||||
email = "cds@corbinsimpson.com";
|
||||
github = "MostAwesomeDude";
|
||||
@@ -15609,6 +15674,12 @@
|
||||
githubId = 38578268;
|
||||
name = "Morgan Wolfe";
|
||||
};
|
||||
mx2uller = {
|
||||
email = "mx2uller@pm.me";
|
||||
github = "mx2uller";
|
||||
githubId = 93703653;
|
||||
name = "Marko Müller";
|
||||
};
|
||||
mxkrsv = {
|
||||
email = "mxkrsv@disroot.org";
|
||||
github = "mxkrsv";
|
||||
@@ -15637,6 +15708,12 @@
|
||||
githubId = 9636071;
|
||||
name = "Myrl Hex";
|
||||
};
|
||||
myypo = {
|
||||
email = "nikirsmcgl@gmail.com";
|
||||
github = "myypo";
|
||||
githubId = 110892040;
|
||||
name = "Mykyta Polchanov";
|
||||
};
|
||||
mzacho = {
|
||||
email = "nixpkgs@martinzacho.net";
|
||||
github = "mzacho";
|
||||
@@ -16542,6 +16619,13 @@
|
||||
githubId = 22592293;
|
||||
name = "Kartik Gokte";
|
||||
};
|
||||
nullcube = {
|
||||
email = "nullcub3@gmail.com";
|
||||
name = "NullCube";
|
||||
github = "nullcub3";
|
||||
githubId = 51034487;
|
||||
matrix = "@nullcube:matrix.org";
|
||||
};
|
||||
nullishamy = {
|
||||
email = "spam@amyerskine.me";
|
||||
name = "nullishamy";
|
||||
@@ -18620,6 +18704,12 @@
|
||||
githubId = 40905037;
|
||||
name = "qwqawawow";
|
||||
};
|
||||
qxrein = {
|
||||
email = "mnv07@proton.me";
|
||||
github = "qxrein";
|
||||
githubId = 101001298;
|
||||
name = "qxrein";
|
||||
};
|
||||
qyliss = {
|
||||
email = "hi@alyssa.is";
|
||||
github = "alyssais";
|
||||
@@ -21639,6 +21729,13 @@
|
||||
githubId = 22163194;
|
||||
name = "Stel Abrego";
|
||||
};
|
||||
stellessia = {
|
||||
name = "Rachel Podya";
|
||||
email = "homicide@disroot.org";
|
||||
github = "stellessia";
|
||||
githubId = 81514356;
|
||||
keys = [ { fingerprint = "38E8 7F79 AE86 CA98 F8BC 45F8 1060 00A0 5E5B DB90"; } ];
|
||||
};
|
||||
stepbrobd = {
|
||||
name = "Yifei Sun";
|
||||
email = "ysun@hey.com";
|
||||
@@ -21720,6 +21817,13 @@
|
||||
githubId = 853468;
|
||||
name = "Steven Roose";
|
||||
};
|
||||
stevestreza = {
|
||||
email = "nixpkgs@stevestreza.com";
|
||||
github = "stevestreza";
|
||||
githubId = 28552;
|
||||
name = "Steve Streza";
|
||||
keys = [ { fingerprint = "DFED 4E42 34E7 348C 57D4 6568 C4DC 30F8 5ABC 6FA1"; } ];
|
||||
};
|
||||
stianlagstad = {
|
||||
email = "stianlagstad@gmail.com";
|
||||
github = "stianlagstad";
|
||||
@@ -22264,6 +22368,12 @@
|
||||
github = "teatwig";
|
||||
githubId = 18734648;
|
||||
};
|
||||
tebriel = {
|
||||
email = "tebriel@frodux.in";
|
||||
name = "tebriel";
|
||||
github = "tebriel";
|
||||
githubId = 821688;
|
||||
};
|
||||
techknowlogick = {
|
||||
email = "techknowlogick@gitea.com";
|
||||
github = "techknowlogick";
|
||||
@@ -24378,6 +24488,13 @@
|
||||
githubId = 20464732;
|
||||
name = "Willi Butz";
|
||||
};
|
||||
willow_ch = {
|
||||
email = "nix@w.wolo.dev";
|
||||
github = "spaghetus";
|
||||
githubId = 28763739;
|
||||
name = "Willow Carlson-Huber";
|
||||
keys = [ { fingerprint = "FE21E0981CDFD50ADD086423C21A693BA4693A60"; } ];
|
||||
};
|
||||
willswats = {
|
||||
email = "williamstuwatson@gmail.com";
|
||||
github = "willswats";
|
||||
|
||||
@@ -197,6 +197,7 @@ with lib.maintainers;
|
||||
siraben
|
||||
vbgl
|
||||
alizter
|
||||
stepbrobd
|
||||
];
|
||||
scope = "Maintain the Coq theorem prover and related packages.";
|
||||
shortName = "Coq";
|
||||
|
||||
@@ -79,6 +79,8 @@ let
|
||||
prepareManualFromMD = ''
|
||||
cp -r --no-preserve=all $inputs/* .
|
||||
|
||||
cp -r ${../../../doc/release-notes} ./release-notes-nixpkgs
|
||||
|
||||
substituteInPlace ./manual.md \
|
||||
--replace-fail '@NIXOS_VERSION@' "${version}"
|
||||
substituteInPlace ./configuration/configuration.md \
|
||||
|
||||
@@ -1886,11 +1886,23 @@
|
||||
"sec-release-25.05-notable-changes": [
|
||||
"release-notes.html#sec-release-25.05-notable-changes"
|
||||
],
|
||||
"sec-release-25.05-lib": [
|
||||
"release-notes.html#sec-release-25.05-lib"
|
||||
"sec-nixpkgs-release-25.05": [
|
||||
"release-notes.html#sec-nixpkgs-release-25.05"
|
||||
],
|
||||
"sec-release-25.05-lib-breaking": [
|
||||
"release-notes.html#sec-release-25.05-lib-breaking"
|
||||
"sec-nixpkgs-release-25.05-incompatibilities": [
|
||||
"release-notes.html#sec-nixpkgs-release-25.05-incompatibilities"
|
||||
],
|
||||
"sec-nixpkgs-release-25.05-incompatibilities-titanium-removed": [
|
||||
"release-notes.html#sec-nixpkgs-release-25.05-incompatibilities-titanium-removed",
|
||||
"index.html#titanium",
|
||||
"index.html#building-a-titanium-app",
|
||||
"index.html#emulating-or-simulating-the-app"
|
||||
],
|
||||
"sec-nixpkgs-release-25.05-lib": [
|
||||
"release-notes.html#sec-nixpkgs-release-25.05-lib"
|
||||
],
|
||||
"sec-nixpkgs-release-25.05-lib-breaking": [
|
||||
"release-notes.html#sec-nixpkgs-release-25.05-lib-breaking"
|
||||
],
|
||||
"sec-release-24.11": [
|
||||
"release-notes.html#sec-release-24.11"
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
|
||||
- [networking.modemmanager](options.html#opt-networking.modemmanager) has been split out of [networking.networkmanager](options.html#opt-networking.networkmanager). NetworkManager still enables ModemManager by default, but options exist now to run NetworkManager without ModemManager.
|
||||
|
||||
- [ncps](https://github.com/kalbasit/ncps), a Nix binary cache proxy service implemented in Go using [go-nix](https://github.com/nix-community/go-nix). Available as [services.ncps](options.html#opt-services.ncps.enable).
|
||||
|
||||
- [Conduwuit](https://conduwuit.puppyirl.gay/), a federated chat server implementing the Matrix protocol, forked from Conduit. Available as [services.conduwuit](#opt-services.conduwuit.enable).
|
||||
|
||||
- [Traccar](https://www.traccar.org/), a modern GPS Tracking Platform. Available as [services.traccar](#opt-services.traccar.enable).
|
||||
@@ -79,6 +81,8 @@
|
||||
|
||||
- [Actual Budget](https://actualbudget.org/), a local-first personal finance app. Available as [services.actual](#opt-services.actual.enable).
|
||||
|
||||
- [immich-public-proxy](https://github.com/alangrainger/immich-public-proxy), a proxy for sharing Immich albums without exposing the Immich API. Available as [services.immich-public-proxy](#opt-services.immich-public-proxy.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).
|
||||
|
||||
- [nvidia-gpu](https://github.com/utkuozdemir/nvidia_gpu_exporter), a Prometheus exporter that scrapes `nvidia-smi` for GPU metrics. Available as [services.prometheus.exporters.nvidia-gpu](#opt-services.prometheus.exporters.nvidia-gpu.enable).
|
||||
@@ -113,6 +117,15 @@
|
||||
|
||||
- `ps3-disc-dumper` was updated to 4.2.5, which removed the CLI project and now exclusively offers the GUI
|
||||
|
||||
- [](#opt-services.nextcloud.config.dbtype) is unset by default, the previous default was `sqlite`.
|
||||
This was done because `sqlite` is not a reasonable default since it's
|
||||
[not recommended by upstream](https://docs.nextcloud.com/server/30/admin_manual/installation/system_requirements.html)
|
||||
and thus doesn't qualify as default.
|
||||
|
||||
- Nextcloud's default FPM pool settings have been increased according to upstream recommentations. It's advised
|
||||
to review the new defaults and description of
|
||||
[](#opt-services.nextcloud.poolSettings).
|
||||
|
||||
- `asusd` has been upgraded to version 6 which supports multiple aura devices. To account for this, the single `auraConfig` configuration option has been replaced with `auraConfigs` which is an attribute set of config options per each device. The config files may also be now specified as either source files or text strings; to account for this you will need to specify that `text` is used for your existing configs, e.g.:
|
||||
```diff
|
||||
-services.asusd.asusdConfig = '''file contents'''
|
||||
@@ -127,6 +140,11 @@
|
||||
|
||||
- `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.
|
||||
|
||||
- The `earlyoom` service is now using upstream systemd service, which enables
|
||||
hardening and filesystem isolation by default. If you need filesystem write
|
||||
access or want to access home directory via `killHook`, hardening setting can
|
||||
be changed via, e.g. `systemd.services.earlyoom.serviceConfig.ProtectSystem`.
|
||||
|
||||
- `nodePackages.vls` has been deprecated, as the upstream consumer of it, vetur, has been deprecated by upstream. Upstream suggests migrating to Volar for Vue LSP tooling instead.
|
||||
|
||||
- `nodePackages.create-react-native-app` has been removed, as it is deprecated. Upstream suggests using a framework for React Native apps instead.
|
||||
@@ -151,8 +169,12 @@
|
||||
|
||||
- `ente-auth` now uses the name `enteauth` for its binary. The previous name was `ente_auth`.
|
||||
|
||||
- `foundationdb` was upgraded to 7.3.
|
||||
|
||||
- `fluxus` has been removed, as it depends on `racket_7_9` and had no updates in 9 years.
|
||||
|
||||
- `sm64ex-coop` has been removed as it was archived upstream. Consider migrating to `sm64coopdx`.
|
||||
|
||||
- `renovate` was updated to v39. See the [upstream release notes](https://docs.renovatebot.com/release-notes-for-major-versions/#version-39) for breaking changes.
|
||||
Like upstream's docker images, renovate now runs on NodeJS 22.
|
||||
|
||||
@@ -295,6 +317,10 @@
|
||||
|
||||
- `services.avahi.ipv6` now defaults to true.
|
||||
|
||||
- For matrix homeserver Synapse we are now following the upstream recommendation to enable jemalloc as the memory allocator by default.
|
||||
|
||||
- `services.kmonad` now creates a determinate symlink (in `/dev/input/by-id/`) to each of KMonad virtual devices.
|
||||
|
||||
- `bind.cacheNetworks` now only controls access for recursive queries, where it previously controlled access for all queries.
|
||||
|
||||
- Caddy can now be built with plugins by using `caddy.withPlugins`, a `passthru` function that accepts an attribute set as a parameter. The `plugins` argument represents a list of Caddy plugins, with each Caddy plugin being a versioned module. The `hash` argument represents the `vendorHash` of the resulting Caddy source code with the plugins added.
|
||||
@@ -329,10 +355,6 @@
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
## Nixpkgs Library {#sec-release-25.05-lib}
|
||||
|
||||
### Breaking changes {#sec-release-25.05-lib-breaking}
|
||||
|
||||
- Structure of the `functor` of some types has changed. `functor` is an implementation detail and should not be relied upon. If you did rely on it let us know in this [PR](https://github.com/NixOS/nixpkgs/pull/363565).
|
||||
- [`lib.types.enum`](https://nixos.org/manual/nixos/unstable/#sec-option-types-basic): Previously the `functor.payload` was the list of enum values directly. Now it is an attribute set containing the values in the `values` attribute.
|
||||
- [`lib.types.separatedString`](https://nixos.org/manual/nixos/unstable/#sec-option-types-string): Previously the `functor.payload` was the seperator directly. Now it is an attribute set containing the seperator in the `sep` attribute.
|
||||
```{=include=} sections
|
||||
../release-notes-nixpkgs/rl-2505.section.md
|
||||
```
|
||||
|
||||
@@ -65,6 +65,14 @@ let
|
||||
withWarnings = x:
|
||||
lib.warnIf (evalConfigArgs?extraArgs) "The extraArgs argument to eval-config.nix is deprecated. Please set config._module.args instead."
|
||||
lib.warnIf (evalConfigArgs?check) "The check argument to eval-config.nix is deprecated. Please set config._module.check instead."
|
||||
lib.warnIf (specialArgs?pkgs) ''
|
||||
You have set specialArgs.pkgs, which means that options like nixpkgs.config
|
||||
and nixpkgs.overlays will be ignored. If you wish to reuse an already created
|
||||
pkgs, which you know is configured correctly for this NixOS configuration,
|
||||
please import the `nixosModules.pkgsReadOnly` module from the nixpkgs flake or
|
||||
`(modulesPath + "/misc/nixpkgs/read-only.nix"), and set `{ nixpkgs.pkgs = <your pkgs>; }`.
|
||||
This properly disables the ignored options to prevent future surprises.
|
||||
''
|
||||
x;
|
||||
|
||||
legacyModules =
|
||||
|
||||
@@ -619,9 +619,6 @@ let format' = format; in let
|
||||
# __noChroot for example).
|
||||
export HOME=$TMPDIR
|
||||
NIXOS_INSTALL_BOOTLOADER=1 nixos-enter --root $mountPoint -- /nix/var/nix/profiles/system/bin/switch-to-configuration boot
|
||||
|
||||
# The above scripts will generate a random machine-id and we don't want to bake a single ID into all our images
|
||||
rm -f $mountPoint/etc/machine-id
|
||||
''}
|
||||
|
||||
# Set the ownerships of the contents. The modes are set in preVM.
|
||||
|
||||
@@ -14,22 +14,12 @@
|
||||
extraPythonPackages ? (_: [ ]),
|
||||
nixosTests,
|
||||
}:
|
||||
let
|
||||
fs = lib.fileset;
|
||||
in
|
||||
python3Packages.buildPythonApplication {
|
||||
pname = "nixos-test-driver";
|
||||
version = "1.1";
|
||||
pyproject = true;
|
||||
|
||||
src = fs.toSource {
|
||||
root = ./.;
|
||||
fileset = fs.unions [
|
||||
./pyproject.toml
|
||||
./test_driver
|
||||
./extract-docstrings.py
|
||||
];
|
||||
};
|
||||
src = ./src;
|
||||
|
||||
build-system = with python3Packages; [
|
||||
setuptools
|
||||
|
||||
@@ -11,6 +11,6 @@ in
|
||||
|
||||
runCommand "nixos-test-driver-docstrings" env ''
|
||||
mkdir $out
|
||||
python3 ${./extract-docstrings.py} ${./test_driver/machine.py} \
|
||||
python3 ${./src/extract-docstrings.py} ${./src/test_driver/machine.py} \
|
||||
> $out/machine-methods.md
|
||||
''
|
||||
|
||||
@@ -8,19 +8,35 @@ let
|
||||
|
||||
cfg = config.fonts.fontDir;
|
||||
|
||||
x11Fonts = pkgs.runCommand "X11-fonts" { preferLocalBuild = true; } ''
|
||||
mkdir -p "$out/share/X11/fonts"
|
||||
font_regexp='.*\.\(ttf\|ttc\|otb\|otf\|pcf\|pfa\|pfb\|bdf\)\(\.gz\)?'
|
||||
find ${toString config.fonts.packages} -regex "$font_regexp" \
|
||||
-exec ln -sf -t "$out/share/X11/fonts" '{}' \;
|
||||
cd "$out/share/X11/fonts"
|
||||
${lib.optionalString cfg.decompressFonts ''
|
||||
${pkgs.gzip}/bin/gunzip -f *.gz
|
||||
''}
|
||||
${pkgs.xorg.mkfontscale}/bin/mkfontscale
|
||||
${pkgs.xorg.mkfontdir}/bin/mkfontdir
|
||||
cat $(find ${pkgs.xorg.fontalias}/ -name fonts.alias) >fonts.alias
|
||||
'';
|
||||
x11Fonts = pkgs.callPackage (
|
||||
{
|
||||
runCommand,
|
||||
gzip,
|
||||
xorg,
|
||||
}:
|
||||
runCommand "X11-fonts"
|
||||
{
|
||||
preferLocalBuild = true;
|
||||
nativeBuildInputs = [
|
||||
gzip
|
||||
xorg.mkfontscale
|
||||
xorg.mkfontdir
|
||||
];
|
||||
}
|
||||
''
|
||||
mkdir -p "$out/share/X11/fonts"
|
||||
font_regexp='.*\.\(ttf\|ttc\|otb\|otf\|pcf\|pfa\|pfb\|bdf\)\(\.gz\)?'
|
||||
find ${toString config.fonts.packages} -regex "$font_regexp" \
|
||||
-exec ln -sf -t "$out/share/X11/fonts" '{}' \;
|
||||
cd "$out/share/X11/fonts"
|
||||
${lib.optionalString cfg.decompressFonts ''
|
||||
gunzip -f *.gz
|
||||
''}
|
||||
mkfontscale
|
||||
mkfontdir
|
||||
cat $(find ${pkgs.xorg.fontalias}/ -name fonts.alias) >fonts.alias
|
||||
''
|
||||
) { };
|
||||
|
||||
in
|
||||
|
||||
|
||||
@@ -1160,6 +1160,7 @@
|
||||
./services/networking/nats.nix
|
||||
./services/networking/nbd.nix
|
||||
./services/networking/ncdns.nix
|
||||
./services/networking/ncps.nix
|
||||
./services/networking/ndppd.nix
|
||||
./services/networking/nebula.nix
|
||||
./services/networking/netbird.nix
|
||||
@@ -1485,6 +1486,7 @@
|
||||
./services/web-apps/icingaweb2/module-monitoring.nix
|
||||
./services/web-apps/ifm.nix
|
||||
./services/web-apps/immich.nix
|
||||
./services/web-apps/immich-public-proxy.nix
|
||||
./services/web-apps/invidious.nix
|
||||
./services/web-apps/invoiceplane.nix
|
||||
./services/web-apps/isso.nix
|
||||
|
||||
@@ -1,40 +1,46 @@
|
||||
# This module defines a small NixOS configuration. It does not
|
||||
# contain any graphical stuff.
|
||||
|
||||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
documentation.enable = mkDefault false;
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) mkDefault;
|
||||
in
|
||||
{
|
||||
documentation = {
|
||||
enable = mkDefault false;
|
||||
doc.enable = mkDefault false;
|
||||
info.enable = mkDefault false;
|
||||
man.enable = mkDefault false;
|
||||
nixos.enable = mkDefault false;
|
||||
};
|
||||
|
||||
documentation.doc.enable = mkDefault false;
|
||||
environment = {
|
||||
# Perl is a default package.
|
||||
defaultPackages = mkDefault [ ];
|
||||
stub-ld.enable = mkDefault false;
|
||||
};
|
||||
|
||||
documentation.info.enable = mkDefault false;
|
||||
|
||||
documentation.man.enable = mkDefault false;
|
||||
|
||||
documentation.nixos.enable = mkDefault false;
|
||||
|
||||
# Perl is a default package.
|
||||
environment.defaultPackages = mkDefault [ ];
|
||||
|
||||
environment.stub-ld.enable = mkDefault false;
|
||||
|
||||
# The lessopen package pulls in Perl.
|
||||
programs.less.lessopen = mkDefault null;
|
||||
programs = {
|
||||
# The lessopen package pulls in Perl.
|
||||
less.lessopen = mkDefault null;
|
||||
command-not-found.enable = mkDefault false;
|
||||
};
|
||||
|
||||
# This pulls in nixos-containers which depends on Perl.
|
||||
boot.enableContainers = mkDefault false;
|
||||
|
||||
programs.command-not-found.enable = mkDefault false;
|
||||
services = {
|
||||
logrotate.enable = mkDefault false;
|
||||
udisks2.enable = mkDefault false;
|
||||
};
|
||||
|
||||
services.logrotate.enable = mkDefault false;
|
||||
|
||||
services.udisks2.enable = mkDefault false;
|
||||
|
||||
xdg.autostart.enable = mkDefault false;
|
||||
xdg.icons.enable = mkDefault false;
|
||||
xdg.mime.enable = mkDefault false;
|
||||
xdg.sounds.enable = mkDefault false;
|
||||
xdg = {
|
||||
autostart.enable = mkDefault false;
|
||||
icons.enable = mkDefault false;
|
||||
mime.enable = mkDefault false;
|
||||
sounds.enable = mkDefault false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ let
|
||||
{
|
||||
freeformType = attrsOf (either scalarType (listOf scalarType));
|
||||
# Client system-options file directives are explained here:
|
||||
# https://www.ibm.com/docs/en/storage-protect/8.1.24?topic=commands-processing-options
|
||||
# https://www.ibm.com/docs/en/storage-protect/8.1.25?topic=commands-processing-options
|
||||
options.servername = mkOption {
|
||||
type = servernameType;
|
||||
default = name;
|
||||
|
||||
@@ -45,6 +45,12 @@ in
|
||||
description = "Port to run Navidrome on.";
|
||||
type = port;
|
||||
};
|
||||
|
||||
EnableInsightsCollector = mkOption {
|
||||
default = false;
|
||||
description = "Enable anonymous usage data collection, see <https://www.navidrome.org/docs/getting-started/insights/> for details.";
|
||||
type = bool;
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
|
||||
@@ -44,8 +44,8 @@ let
|
||||
borgWrapper () {
|
||||
local result
|
||||
borg "$@" && result=$? || result=$?
|
||||
if [[ -z "${toString cfg.failOnWarnings}" ]] && [[ "$result" == 1 ]]; then
|
||||
echo "ignoring warning return value 1"
|
||||
if [[ -z "${toString cfg.failOnWarnings}" ]] && [[ "$result" == 1 || ("$result" -ge 100 && "$result" -le 127) ]]; then
|
||||
echo "ignoring warning return value $result"
|
||||
return 0
|
||||
else
|
||||
return "$result"
|
||||
|
||||
@@ -412,7 +412,7 @@ in
|
||||
]}
|
||||
PATH=${config.systemd.services."restic-backups-${name}".environment.PATH}:$PATH
|
||||
|
||||
exec ${resticCmd} $@
|
||||
exec ${resticCmd} "$@"
|
||||
'') (lib.filterAttrs (_: v: v.createWrapper) config.services.restic.backups);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ in
|
||||
environment.HOME = "/var/lib/tsm-backup";
|
||||
serviceConfig = {
|
||||
# for exit status description see
|
||||
# https://www.ibm.com/docs/en/storage-protect/8.1.24?topic=clients-client-return-codes
|
||||
# https://www.ibm.com/docs/en/storage-protect/8.1.25?topic=clients-client-return-codes
|
||||
SuccessExitStatus = "4 8";
|
||||
# The `-se` option must come after the command.
|
||||
# The `-optfile` option suppresses a `dsm.opt`-not-found warning.
|
||||
|
||||
@@ -80,9 +80,10 @@ in
|
||||
let
|
||||
args = lib.map lib.escapeShellArg (
|
||||
[
|
||||
"-l"
|
||||
"--verbose"
|
||||
"--user"
|
||||
cfg.username
|
||||
"-i"
|
||||
"--identity-file"
|
||||
cfg.identityFilePath
|
||||
cfg.host
|
||||
cfg.remoteFilesystem
|
||||
|
||||
@@ -205,9 +205,14 @@ in
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
description = "Kubernetes kubelet extra configuration file entries.";
|
||||
description = ''
|
||||
Kubernetes kubelet extra configuration file entries.
|
||||
|
||||
See also [Set Kubelet Parameters Via A Configuration File](https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/)
|
||||
and [Kubelet Configuration](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/).
|
||||
'';
|
||||
default = { };
|
||||
type = attrsOf attrs;
|
||||
type = attrsOf ((pkgs.formats.json { }).type);
|
||||
};
|
||||
|
||||
featureGates = mkOption {
|
||||
|
||||
@@ -515,12 +515,12 @@ in
|
||||
''
|
||||
set -eou pipefail
|
||||
compression=$(sed -nr 's/compress_build_logs_compression = ()/\1/p' ${baseDir}/hydra.conf)
|
||||
if [[ $compression == "" ]]; then
|
||||
compression="bzip2"
|
||||
if [[ $compression == "" || $compression == bzip2 ]]; then
|
||||
compressionCmd=(bzip2)
|
||||
elif [[ $compression == zstd ]]; then
|
||||
compression="zstd --rm"
|
||||
compressionCmd=(zstd --rm)
|
||||
fi
|
||||
find ${baseDir}/build-logs -type f -name "*.drv" -mtime +3 -size +0c -print0 | xargs -0 -r "$compression" --force --quiet
|
||||
find ${baseDir}/build-logs -type f -name "*.drv" -mtime +3 -size +0c -print0 | xargs -0 -r "''${compressionCmd[@]}" --force --quiet
|
||||
'';
|
||||
startAt = "Sun 01:45";
|
||||
serviceConfig.Slice = "system-hydra.slice";
|
||||
|
||||
@@ -18,7 +18,7 @@ To enable FoundationDB, add the following to your
|
||||
```nix
|
||||
{
|
||||
services.foundationdb.enable = true;
|
||||
services.foundationdb.package = pkgs.foundationdb71; # FoundationDB 7.1.x
|
||||
services.foundationdb.package = pkgs.foundationdb73; # FoundationDB 7.r3.x
|
||||
}
|
||||
```
|
||||
|
||||
@@ -68,7 +68,7 @@ necessary Python modules).
|
||||
```ShellSession
|
||||
a@link> cat fdb-status.py
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i python -p python pythonPackages.foundationdb71
|
||||
#! nix-shell -i python -p python pythonPackages.foundationdb73
|
||||
|
||||
import fdb
|
||||
import json
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
utils,
|
||||
...
|
||||
}:
|
||||
|
||||
@@ -15,6 +16,7 @@ let
|
||||
options = {
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = name;
|
||||
example = "laptop-internal";
|
||||
description = "Keyboard name.";
|
||||
};
|
||||
@@ -35,16 +37,16 @@ let
|
||||
Since KMonad runs as an unprivileged user, it may sometimes
|
||||
need extra permissions in order to read the keyboard device
|
||||
file. If your keyboard's device file isn't in the input
|
||||
group you'll need to list its group in this option.
|
||||
group, you'll need to list its group in this option.
|
||||
'';
|
||||
};
|
||||
|
||||
defcfg = {
|
||||
enable = lib.mkEnableOption ''
|
||||
Automatically generate the defcfg block.
|
||||
automatic generation of the defcfg block.
|
||||
|
||||
When this is option is set to true the config option for
|
||||
this keyboard should not include a defcfg block.
|
||||
When this option is set to true, the config option for
|
||||
this keyboard should not include a defcfg block
|
||||
'';
|
||||
|
||||
compose = {
|
||||
@@ -55,15 +57,15 @@ let
|
||||
};
|
||||
|
||||
delay = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
type = lib.types.ints.unsigned;
|
||||
default = 5;
|
||||
description = "The delay (in milliseconds) between compose key sequences.";
|
||||
};
|
||||
};
|
||||
|
||||
fallthrough = lib.mkEnableOption "Re-emit unhandled key events.";
|
||||
fallthrough = lib.mkEnableOption "re-emitting unhandled key events";
|
||||
|
||||
allowCommands = lib.mkEnableOption "Allow keys to run shell commands.";
|
||||
allowCommands = lib.mkEnableOption "keys to run shell commands";
|
||||
};
|
||||
|
||||
config = lib.mkOption {
|
||||
@@ -71,12 +73,10 @@ let
|
||||
description = "Keyboard configuration.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
name = lib.mkDefault name;
|
||||
};
|
||||
};
|
||||
|
||||
mkName = name: "kmonad-" + name;
|
||||
|
||||
# Create a complete KMonad configuration file:
|
||||
mkCfg =
|
||||
keyboard:
|
||||
@@ -84,7 +84,7 @@ let
|
||||
defcfg = ''
|
||||
(defcfg
|
||||
input (device-file "${keyboard.device}")
|
||||
output (uinput-sink "kmonad-${keyboard.name}")
|
||||
output (uinput-sink "${mkName keyboard.name}")
|
||||
${lib.optionalString (keyboard.defcfg.compose.key != null) ''
|
||||
cmp-seq ${keyboard.defcfg.compose.key}
|
||||
cmp-seq-delay ${toString keyboard.defcfg.compose.delay}
|
||||
@@ -95,9 +95,9 @@ let
|
||||
'';
|
||||
in
|
||||
pkgs.writeTextFile {
|
||||
name = "kmonad-${keyboard.name}.cfg";
|
||||
name = "${mkName keyboard.name}.kbd";
|
||||
text = lib.optionalString keyboard.defcfg.enable (defcfg + "\n") + keyboard.config;
|
||||
checkPhase = "${cfg.package}/bin/kmonad -d $out";
|
||||
checkPhase = "${lib.getExe cfg.package} -d $out";
|
||||
};
|
||||
|
||||
# Build a systemd path config that starts the service below when a
|
||||
@@ -105,7 +105,7 @@ let
|
||||
mkPath =
|
||||
keyboard:
|
||||
let
|
||||
name = "kmonad-${keyboard.name}";
|
||||
name = mkName keyboard.name;
|
||||
in
|
||||
lib.nameValuePair name {
|
||||
description = "KMonad trigger for ${keyboard.device}";
|
||||
@@ -119,19 +119,8 @@ let
|
||||
# Build a systemd service that starts KMonad:
|
||||
mkService =
|
||||
keyboard:
|
||||
let
|
||||
cmd =
|
||||
[
|
||||
(lib.getExe cfg.package)
|
||||
"--input"
|
||||
''device-file "${keyboard.device}"''
|
||||
]
|
||||
++ cfg.extraArgs
|
||||
++ [ "${mkCfg keyboard}" ];
|
||||
in
|
||||
lib.nameValuePair "kmonad-${keyboard.name}" {
|
||||
lib.nameValuePair (mkName keyboard.name) {
|
||||
description = "KMonad for ${keyboard.device}";
|
||||
script = lib.escapeShellArgs cmd;
|
||||
unitConfig = {
|
||||
# Control rate limiting.
|
||||
# Stop the restart logic if we restart more than
|
||||
@@ -140,6 +129,10 @@ let
|
||||
StartLimitBurst = 5;
|
||||
};
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${lib.getExe cfg.package} ${mkCfg keyboard} \
|
||||
${utils.escapeSystemdExecArgs cfg.extraArgs}
|
||||
'';
|
||||
Restart = "always";
|
||||
# Restart at increasing intervals from 2s to 1m
|
||||
RestartSec = 2;
|
||||
@@ -155,13 +148,26 @@ let
|
||||
config.users.groups.uinput.name
|
||||
] ++ keyboard.extraGroups;
|
||||
};
|
||||
# make sure the new config is used after nixos-rebuild switch
|
||||
# stopIfChanged controls[0] how a service is "restarted" during
|
||||
# nixos-rebuild switch. By default, stopIfChanged is true, which stops
|
||||
# the old service and then starts the new service after config updates.
|
||||
# Since we use path-based activation[1] here, the service unit will
|
||||
# immediately[2] be started by the path unit. Probably that start is
|
||||
# before config updates, whcih causes the service unit to use the old
|
||||
# config after nixos-rebuild switch. Setting stopIfChanged to false works
|
||||
# around this issue by restarting the service after config updates.
|
||||
# [0]: https://nixos.org/manual/nixos/unstable/#sec-switching-systems
|
||||
# [1]: man 7 daemon
|
||||
# [2]: man 5 systemd.path
|
||||
stopIfChanged = false;
|
||||
};
|
||||
in
|
||||
{
|
||||
options.services.kmonad = {
|
||||
enable = lib.mkEnableOption "KMonad: An advanced keyboard manager.";
|
||||
enable = lib.mkEnableOption "KMonad: an advanced keyboard manager";
|
||||
|
||||
package = lib.mkPackageOption pkgs "kmonad" { };
|
||||
package = lib.mkPackageOption pkgs "KMonad" { default = "kmonad"; };
|
||||
|
||||
keyboards = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule keyboard);
|
||||
@@ -183,9 +189,27 @@ in
|
||||
config = lib.mkIf cfg.enable {
|
||||
hardware.uinput.enable = true;
|
||||
|
||||
services.udev.extraRules =
|
||||
let
|
||||
mkRule = name: ''
|
||||
ACTION=="add", KERNEL=="event*", SUBSYSTEM=="input", ATTRS{name}=="${name}", ATTRS{id/product}=="5679", ATTRS{id/vendor}=="1235", SYMLINK+="input/by-id/${name}"
|
||||
'';
|
||||
in
|
||||
lib.foldlAttrs (
|
||||
rules: _: keyboard:
|
||||
rules + "\n" + mkRule (mkName keyboard.name)
|
||||
) "" cfg.keyboards;
|
||||
|
||||
systemd = {
|
||||
paths = lib.mapAttrs' (_: mkPath) cfg.keyboards;
|
||||
services = lib.mapAttrs' (_: mkService) cfg.keyboards;
|
||||
};
|
||||
};
|
||||
|
||||
meta = {
|
||||
maintainers = with lib.maintainers; [
|
||||
linj
|
||||
rvdp
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -705,7 +705,7 @@ in
|
||||
|
||||
withJemalloc = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to preload jemalloc to reduce memory fragmentation and overall usage.
|
||||
'';
|
||||
@@ -1462,6 +1462,7 @@ in
|
||||
baseServiceConfig = {
|
||||
environment = optionalAttrs (cfg.withJemalloc) {
|
||||
LD_PRELOAD = "${pkgs.jemalloc}/lib/libjemalloc.so";
|
||||
PYTHONMALLOC = "malloc";
|
||||
};
|
||||
serviceConfig = {
|
||||
Type = "notify";
|
||||
|
||||
@@ -49,7 +49,7 @@ in
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
services.upower.enable = lib.elem "battery" cfg.order;
|
||||
services.upower.enable = lib.mkIf (lib.elem "battery" cfg.order) true;
|
||||
|
||||
systemd.user.services.dwm-status = {
|
||||
description = "Highly performant and configurable DWM status service";
|
||||
|
||||
@@ -20,6 +20,12 @@ in
|
||||
default = 5055;
|
||||
description = ''The port which the Jellyseerr web UI should listen to.'';
|
||||
};
|
||||
|
||||
configDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/jellyseerr/config";
|
||||
description = "Config data directory";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
@@ -27,14 +33,15 @@ in
|
||||
description = "Jellyseerr, a requests manager for Jellyfin";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
environment.PORT = toString cfg.port;
|
||||
environment = {
|
||||
PORT = toString cfg.port;
|
||||
CONFIG_DIRECTORY = cfg.configDir;
|
||||
};
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
StateDirectory = "jellyseerr";
|
||||
WorkingDirectory = "${cfg.package}/libexec/jellyseerr/deps/jellyseerr";
|
||||
DynamicUser = true;
|
||||
ExecStart = lib.getExe cfg.package;
|
||||
BindPaths = [ "/var/lib/jellyseerr/:${cfg.package}/libexec/jellyseerr/deps/jellyseerr/config/" ];
|
||||
Restart = "on-failure";
|
||||
ProtectHome = true;
|
||||
ProtectSystem = "strict";
|
||||
|
||||
@@ -24,9 +24,12 @@ in
|
||||
description = "Whether to enable the PyKMS service.";
|
||||
};
|
||||
|
||||
package = lib.mkPackageOption pkgs "pykms" { };
|
||||
|
||||
listenAddress = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0.0.0.0";
|
||||
example = "::";
|
||||
description = "The IP address on which to listen.";
|
||||
};
|
||||
|
||||
@@ -78,13 +81,13 @@ in
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
# python programs with DynamicUser = true require HOME to be set
|
||||
environment.HOME = libDir;
|
||||
serviceConfig = with pkgs; {
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
StateDirectory = baseNameOf libDir;
|
||||
ExecStartPre = "${lib.getBin pykms}/libexec/create_pykms_db.sh ${libDir}/clients.db";
|
||||
ExecStartPre = "${lib.getBin cfg.package}/libexec/create_pykms_db.sh ${libDir}/clients.db";
|
||||
ExecStart = lib.concatStringsSep " " (
|
||||
[
|
||||
"${lib.getBin pykms}/bin/server"
|
||||
"${lib.getBin cfg.package}/bin/server"
|
||||
"--logfile=STDOUT"
|
||||
"--loglevel=${cfg.logLevel}"
|
||||
"--sqlite=${libDir}/clients.db"
|
||||
|
||||
@@ -31,7 +31,7 @@ let
|
||||
'';
|
||||
in
|
||||
{
|
||||
meta.maintainers = with lib.maintainers; [ ];
|
||||
meta.maintainers = with lib.maintainers; [ jvanbruegge ];
|
||||
|
||||
options.services.tandoor-recipes = {
|
||||
enable = lib.mkOption {
|
||||
|
||||
@@ -498,16 +498,16 @@ in
|
||||
ca.cert = if needToCreateCA then "${cfg.dataDir}/keys/ca.cert" else "${cfg.pki.manual.ca.cert}";
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${cfg.dataDir} 0770 ${cfg.user} ${cfg.group}"
|
||||
"z ${cfg.dataDir} 0770 ${cfg.user} ${cfg.group}"
|
||||
];
|
||||
|
||||
systemd.services.taskserver-init = {
|
||||
wantedBy = [ "taskserver.service" ];
|
||||
before = [ "taskserver.service" ];
|
||||
description = "Initialize Taskserver Data Directory";
|
||||
|
||||
preStart = ''
|
||||
mkdir -m 0770 -p "${cfg.dataDir}"
|
||||
chown "${cfg.user}:${cfg.group}" "${cfg.dataDir}"
|
||||
'';
|
||||
|
||||
script = ''
|
||||
${taskd} init
|
||||
touch "${cfg.dataDir}/.is_initialized"
|
||||
|
||||
@@ -36,8 +36,6 @@ let
|
||||
${lib.optionalString (cfg.cert != null) "cert=${cfg.cert}"}
|
||||
${lib.optionalString (cfg.pkey != null) "pkey=${cfg.pkey}"}
|
||||
${lib.optionalString (cfg.dh-file != null) "dh-file=${cfg.dh-file}"}
|
||||
no-stdout-log
|
||||
syslog
|
||||
pidfile=${pidfile}
|
||||
${lib.optionalString cfg.secure-stun "secure-stun"}
|
||||
${lib.optionalString cfg.no-cli "no-cli"}
|
||||
|
||||
@@ -153,6 +153,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
package = lib.mkPackageOption pkgs "keepalived" { };
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
@@ -334,7 +336,7 @@ in
|
||||
umask 077
|
||||
${pkgs.envsubst}/bin/envsubst -i "${keepalivedConf}" > ${finalConfigFile}
|
||||
'');
|
||||
ExecStart = "${pkgs.keepalived}/sbin/keepalived"
|
||||
ExecStart = "${lib.getExe cfg.package}"
|
||||
+ " -f ${finalConfigFile}"
|
||||
+ " -p ${pidFile}"
|
||||
+ optionalString cfg.snmp.enable " --snmp";
|
||||
|
||||
@@ -0,0 +1,326 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.ncps;
|
||||
|
||||
logLevels = [
|
||||
"trace"
|
||||
"debug"
|
||||
"info"
|
||||
"warn"
|
||||
"error"
|
||||
"fatal"
|
||||
"panic"
|
||||
];
|
||||
|
||||
globalFlags = lib.concatStringsSep " " (
|
||||
[ "--log-level='${cfg.logLevel}'" ]
|
||||
++ (lib.optionals cfg.openTelemetry.enable (
|
||||
[
|
||||
"--otel-enabled"
|
||||
]
|
||||
++ (lib.optional (
|
||||
cfg.openTelemetry.grpcURL != null
|
||||
) "--otel-grpc-url='${cfg.openTelemetry.grpcURL}'")
|
||||
))
|
||||
);
|
||||
|
||||
serveFlags = lib.concatStringsSep " " (
|
||||
[
|
||||
"--cache-hostname='${cfg.cache.hostName}'"
|
||||
"--cache-data-path='${cfg.cache.dataPath}'"
|
||||
"--cache-database-url='${cfg.cache.databaseURL}'"
|
||||
"--server-addr='${cfg.server.addr}'"
|
||||
]
|
||||
++ (lib.optional cfg.cache.allowDeleteVerb "--cache-allow-delete-verb")
|
||||
++ (lib.optional cfg.cache.allowPutVerb "--cache-allow-put-verb")
|
||||
++ (lib.optional (cfg.cache.maxSize != null) "--cache-max-size='${cfg.cache.maxSize}'")
|
||||
++ (lib.optionals (cfg.cache.lru.schedule != null) [
|
||||
"--cache-lru-schedule='${cfg.cache.lru.schedule}'"
|
||||
"--cache-lru-schedule-timezone='${cfg.cache.lru.scheduleTimeZone}'"
|
||||
])
|
||||
++ (lib.optional (cfg.cache.secretKeyPath != null) "--cache-secret-key-path='%d/secretKey'")
|
||||
++ (lib.forEach cfg.upstream.caches (url: "--upstream-cache='${url}'"))
|
||||
++ (lib.forEach cfg.upstream.publicKeys (pk: "--upstream-public-key='${pk}'"))
|
||||
);
|
||||
|
||||
isSqlite = lib.strings.hasPrefix "sqlite:" cfg.cache.databaseURL;
|
||||
|
||||
dbPath = lib.removePrefix "sqlite:" cfg.cache.databaseURL;
|
||||
dbDir = dirOf dbPath;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.ncps = {
|
||||
enable = lib.mkEnableOption "ncps: Nix binary cache proxy service implemented in Go";
|
||||
|
||||
package = lib.mkPackageOption pkgs "ncps" { };
|
||||
|
||||
dbmatePackage = lib.mkPackageOption pkgs "dbmate" { };
|
||||
|
||||
openTelemetry = {
|
||||
enable = lib.mkEnableOption "Enable OpenTelemetry logs, metrics, and tracing";
|
||||
|
||||
grpcURL = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Configure OpenTelemetry gRPC URL. Missing or "https" scheme enables
|
||||
secure gRPC, "insecure" otherwise. Omit to emit telemetry to
|
||||
stdout.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
logLevel = lib.mkOption {
|
||||
type = lib.types.enum logLevels;
|
||||
default = "info";
|
||||
description = ''
|
||||
Set the level for logging. Refer to
|
||||
<https://pkg.go.dev/github.com/rs/zerolog#readme-leveled-logging> for
|
||||
more information.
|
||||
'';
|
||||
};
|
||||
|
||||
cache = {
|
||||
allowDeleteVerb = lib.mkEnableOption ''
|
||||
Whether to allow the DELETE verb to delete narinfo and nar files from
|
||||
the cache.
|
||||
'';
|
||||
|
||||
allowPutVerb = lib.mkEnableOption ''
|
||||
Whether to allow the PUT verb to push narinfo and nar files directly
|
||||
to the cache.
|
||||
'';
|
||||
|
||||
hostName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
The hostname of the cache server. **This is used to generate the
|
||||
private key used for signing store paths (.narinfo)**
|
||||
'';
|
||||
};
|
||||
|
||||
dataPath = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/ncps";
|
||||
description = ''
|
||||
The local directory for storing configuration and cached store paths
|
||||
'';
|
||||
};
|
||||
|
||||
databaseURL = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "sqlite:${cfg.cache.dataPath}/db/db.sqlite";
|
||||
defaultText = "sqlite:/var/lib/ncps/db/db.sqlite";
|
||||
description = ''
|
||||
The URL of the database (currently only SQLite is supported)
|
||||
'';
|
||||
};
|
||||
|
||||
lru = {
|
||||
schedule = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "0 2 * * *";
|
||||
description = ''
|
||||
The cron spec for cleaning the store to keep it under
|
||||
config.ncps.cache.maxSize. Refer to
|
||||
https://pkg.go.dev/github.com/robfig/cron/v3#hdr-Usage for
|
||||
documentation.
|
||||
'';
|
||||
};
|
||||
|
||||
scheduleTimeZone = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Local";
|
||||
example = "America/Los_Angeles";
|
||||
description = ''
|
||||
The name of the timezone to use for the cron schedule. See
|
||||
<https://en.wikipedia.org/wiki/List_of_tz_database_time_zones>
|
||||
for a comprehensive list of possible values for this setting.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
maxSize = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "100G";
|
||||
description = ''
|
||||
The maximum size of the store. It can be given with units such as
|
||||
5K, 10G etc. Supported units: B, K, M, G, T.
|
||||
'';
|
||||
};
|
||||
|
||||
secretKeyPath = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
The path to load the secretKey for signing narinfos. Leave this
|
||||
empty to automatically generate a private/public key.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
server = {
|
||||
addr = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = ":8501";
|
||||
description = ''
|
||||
The address and port the server listens on.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
upstream = {
|
||||
caches = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
example = [ "https://cache.nixos.org" ];
|
||||
description = ''
|
||||
A list of URLs of upstream binary caches.
|
||||
'';
|
||||
};
|
||||
|
||||
publicKeys = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
example = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ];
|
||||
description = ''
|
||||
A list of public keys of upstream caches in the format
|
||||
`host[-[0-9]*]:public-key`. This flag is used to verify the
|
||||
signatures of store paths downloaded from upstream caches.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.cache.lru.schedule == null || cfg.cache.maxSize != null;
|
||||
message = "You must specify config.ncps.cache.lru.schedule when config.ncps.cache.maxSize is set";
|
||||
}
|
||||
|
||||
{
|
||||
assertion = cfg.cache.secretKeyPath == null || (builtins.pathExists cfg.cache.secretKeyPath);
|
||||
message = "config.ncps.cache.secresecretKeyPath=${cfg.cache.secretKeyPath} must exist but does not";
|
||||
}
|
||||
];
|
||||
|
||||
users.users.ncps = {
|
||||
isSystemUser = true;
|
||||
group = "ncps";
|
||||
};
|
||||
users.groups.ncps = { };
|
||||
|
||||
systemd.services.ncps-create-datadirs = {
|
||||
description = "Created required directories by ncps";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
UMask = "0066";
|
||||
};
|
||||
script =
|
||||
(lib.optionalString (cfg.cache.dataPath != "/var/lib/ncps") ''
|
||||
if ! test -d ${cfg.cache.dataPath}; then
|
||||
mkdir -p ${cfg.cache.dataPath}
|
||||
chown ncps:ncps ${cfg.cache.dataPath}
|
||||
fi
|
||||
'')
|
||||
+ (lib.optionalString isSqlite ''
|
||||
if ! test -d ${dbDir}; then
|
||||
mkdir -p ${dbDir}
|
||||
chown ncps:ncps ${dbDir}
|
||||
fi
|
||||
'');
|
||||
wantedBy = [ "ncps.service" ];
|
||||
before = [ "ncps.service" ];
|
||||
};
|
||||
|
||||
systemd.services.ncps = {
|
||||
description = "ncps binary cache proxy service";
|
||||
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
preStart = ''
|
||||
${lib.getExe cfg.dbmatePackage} --migrations-dir=${cfg.package}/share/ncps/db/migrations --url=${cfg.cache.databaseURL} up
|
||||
'';
|
||||
|
||||
serviceConfig = lib.mkMerge [
|
||||
{
|
||||
ExecStart = "${lib.getExe cfg.package} ${globalFlags} serve ${serveFlags}";
|
||||
User = "ncps";
|
||||
Group = "ncps";
|
||||
Restart = "on-failure";
|
||||
RuntimeDirectory = "ncps";
|
||||
}
|
||||
|
||||
# credentials
|
||||
(lib.mkIf (cfg.cache.secretKeyPath != null) {
|
||||
LoadCredential = "secretKey:${cfg.cache.secretKeyPath}";
|
||||
})
|
||||
|
||||
# ensure permissions on required directories
|
||||
(lib.mkIf (cfg.cache.dataPath != "/var/lib/ncps") {
|
||||
ReadWritePaths = [ cfg.cache.dataPath ];
|
||||
})
|
||||
(lib.mkIf (cfg.cache.dataPath == "/var/lib/ncps") {
|
||||
StateDirectory = "ncps";
|
||||
StateDirectoryMode = "0700";
|
||||
})
|
||||
(lib.mkIf (isSqlite && !lib.strings.hasPrefix "/var/lib/ncps" dbDir) {
|
||||
ReadWritePaths = [ dbDir ];
|
||||
})
|
||||
|
||||
# Hardening
|
||||
{
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
"~@resources"
|
||||
];
|
||||
CapabilityBoundingSet = "";
|
||||
PrivateUsers = true;
|
||||
DevicePolicy = "closed";
|
||||
DeviceAllow = [ "" ];
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
RestrictSUIDSGID = true;
|
||||
RestrictRealtime = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
ProcSubset = "pid";
|
||||
RestrictNamespaces = true;
|
||||
SystemCallArchitectures = "native";
|
||||
PrivateNetwork = false;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
PrivateMounts = true;
|
||||
NoNewPrivileges = true;
|
||||
LockPersonality = true;
|
||||
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
|
||||
LimitNOFILE = 65536;
|
||||
UMask = "0066";
|
||||
}
|
||||
];
|
||||
|
||||
unitConfig.RequiresMountsFor = lib.concatStringsSep " " (
|
||||
[ "${cfg.cache.dataPath}" ] ++ lib.optional (isSqlite) dbDir
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ kalbasit ];
|
||||
}
|
||||
@@ -143,10 +143,10 @@ in
|
||||
restartTriggers = [ cfg.unifiPackage cfg.mongodbPackage ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Type = "notify";
|
||||
ExecStart = "${cmd} start";
|
||||
ExecStop = "${cmd} stop";
|
||||
Restart = "on-failure";
|
||||
Restart = "always";
|
||||
TimeoutSec = "5min";
|
||||
User = "unifi";
|
||||
UMask = "0077";
|
||||
|
||||
@@ -419,7 +419,7 @@ in
|
||||
|
||||
${optionalString (containsGutenprint cfg.drivers) ''
|
||||
if [ -d /var/lib/cups/ppd ]; then
|
||||
${getGutenprint cfg.drivers}/bin/cups-genppdupdate -p /var/lib/cups/ppd
|
||||
${getGutenprint cfg.drivers}/bin/cups-genppdupdate -x -p /var/lib/cups/ppd
|
||||
fi
|
||||
''}
|
||||
'';
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.manticore;
|
||||
@@ -14,7 +11,7 @@ let
|
||||
|
||||
toSphinx =
|
||||
{
|
||||
mkKeyValue ? generators.mkKeyValueDefault { } "=",
|
||||
mkKeyValue ? lib.generators.mkKeyValueDefault { } "=",
|
||||
listsAsDuplicateKeys ? true,
|
||||
}:
|
||||
attrsOfAttrs:
|
||||
@@ -22,7 +19,7 @@ let
|
||||
# map function to string for each key val
|
||||
mapAttrsToStringsSep =
|
||||
sep: mapFn: attrs:
|
||||
concatStringsSep sep (mapAttrsToList mapFn attrs);
|
||||
lib.concatStringsSep sep (lib.mapAttrsToList mapFn attrs);
|
||||
mkSection =
|
||||
sectName: sectValues:
|
||||
''
|
||||
@@ -46,9 +43,9 @@ in
|
||||
options = {
|
||||
services.manticore = {
|
||||
|
||||
enable = mkEnableOption "Manticoresearch";
|
||||
enable = lib.mkEnableOption "Manticoresearch";
|
||||
|
||||
settings = mkOption {
|
||||
settings = lib.mkOption {
|
||||
default = {
|
||||
searchd = {
|
||||
listen = [
|
||||
@@ -67,10 +64,10 @@ in
|
||||
<https://manual.manticoresearch.com/Server%20settings>
|
||||
for more information.
|
||||
'';
|
||||
type = types.submodule {
|
||||
type = lib.types.submodule {
|
||||
freeformType = format.type;
|
||||
};
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
searchd = {
|
||||
listen = [
|
||||
@@ -90,7 +87,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
systemd = {
|
||||
packages = [ pkgs.manticoresearch ];
|
||||
|
||||
@@ -4,16 +4,13 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.meilisearch;
|
||||
|
||||
in
|
||||
{
|
||||
|
||||
meta.maintainers = with maintainers; [
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
Br1ght0ne
|
||||
happysalada
|
||||
];
|
||||
@@ -22,37 +19,37 @@ in
|
||||
###### interface
|
||||
|
||||
options.services.meilisearch = {
|
||||
enable = mkEnableOption "MeiliSearch - a RESTful search API";
|
||||
enable = lib.mkEnableOption "MeiliSearch - a RESTful search API";
|
||||
|
||||
package = mkPackageOption pkgs "meilisearch" {
|
||||
package = lib.mkPackageOption pkgs "meilisearch" {
|
||||
extraDescription = ''
|
||||
Use this if you require specific features to be enabled. The default package has no features.
|
||||
'';
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
listenAddress = lib.mkOption {
|
||||
description = "MeiliSearch listen address.";
|
||||
default = "127.0.0.1";
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
listenPort = mkOption {
|
||||
listenPort = lib.mkOption {
|
||||
description = "MeiliSearch port to listen on.";
|
||||
default = 7700;
|
||||
type = types.port;
|
||||
type = lib.types.port;
|
||||
};
|
||||
|
||||
environment = mkOption {
|
||||
environment = lib.mkOption {
|
||||
description = "Defines the running environment of MeiliSearch.";
|
||||
default = "development";
|
||||
type = types.enum [
|
||||
type = lib.types.enum [
|
||||
"development"
|
||||
"production"
|
||||
];
|
||||
};
|
||||
|
||||
# TODO change this to LoadCredentials once possible
|
||||
masterKeyEnvironmentFile = mkOption {
|
||||
masterKeyEnvironmentFile = lib.mkOption {
|
||||
description = ''
|
||||
Path to file which contains the master key.
|
||||
By doing so, all routes will be protected and will require a key to be accessed.
|
||||
@@ -61,10 +58,10 @@ in
|
||||
MEILI_MASTER_KEY=my_secret_key
|
||||
'';
|
||||
default = null;
|
||||
type = with types; nullOr path;
|
||||
type = with lib.types; nullOr path;
|
||||
};
|
||||
|
||||
noAnalytics = mkOption {
|
||||
noAnalytics = lib.mkOption {
|
||||
description = ''
|
||||
Deactivates analytics.
|
||||
Analytics allow MeiliSearch to know how many users are using MeiliSearch,
|
||||
@@ -72,10 +69,10 @@ in
|
||||
This process is entirely anonymous.
|
||||
'';
|
||||
default = true;
|
||||
type = types.bool;
|
||||
type = lib.types.bool;
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
logLevel = lib.mkOption {
|
||||
description = ''
|
||||
Defines how much detail should be present in MeiliSearch's logs.
|
||||
MeiliSearch currently supports four log levels, listed in order of increasing verbosity:
|
||||
@@ -86,10 +83,10 @@ in
|
||||
Useful when diagnosing issues and debugging
|
||||
'';
|
||||
default = "INFO";
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
maxIndexSize = mkOption {
|
||||
maxIndexSize = lib.mkOption {
|
||||
description = ''
|
||||
Sets the maximum size of the index.
|
||||
Value must be given in bytes or explicitly stating a base unit.
|
||||
@@ -97,10 +94,10 @@ in
|
||||
Default is 100 GiB
|
||||
'';
|
||||
default = "107374182400";
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
payloadSizeLimit = mkOption {
|
||||
payloadSizeLimit = lib.mkOption {
|
||||
description = ''
|
||||
Sets the maximum size of accepted JSON payloads.
|
||||
Value must be given in bytes or explicitly stating a base unit.
|
||||
@@ -108,14 +105,14 @@ in
|
||||
Default is ~ 100 MB
|
||||
'';
|
||||
default = "104857600";
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# used to restore dumps
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
@@ -127,7 +124,7 @@ in
|
||||
environment = {
|
||||
MEILI_DB_PATH = "/var/lib/meilisearch";
|
||||
MEILI_HTTP_ADDR = "${cfg.listenAddress}:${toString cfg.listenPort}";
|
||||
MEILI_NO_ANALYTICS = boolToString cfg.noAnalytics;
|
||||
MEILI_NO_ANALYTICS = lib.boolToString cfg.noAnalytics;
|
||||
MEILI_ENV = cfg.environment;
|
||||
MEILI_DUMP_DIR = "/var/lib/meilisearch/dumps";
|
||||
MEILI_LOG_LEVEL = cfg.logLevel;
|
||||
@@ -137,7 +134,7 @@ in
|
||||
ExecStart = "${cfg.package}/bin/meilisearch";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "meilisearch";
|
||||
EnvironmentFile = mkIf (cfg.masterKeyEnvironmentFile != null) cfg.masterKeyEnvironmentFile;
|
||||
EnvironmentFile = lib.mkIf (cfg.masterKeyEnvironmentFile != null) cfg.masterKeyEnvironmentFile;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.opensearch;
|
||||
|
||||
@@ -28,7 +25,7 @@ in
|
||||
{
|
||||
|
||||
options.services.opensearch = {
|
||||
enable = mkEnableOption "OpenSearch";
|
||||
enable = lib.mkEnableOption "OpenSearch";
|
||||
|
||||
package = lib.mkPackageOption pkgs "OpenSearch" {
|
||||
default = [ "opensearch" ];
|
||||
@@ -113,13 +110,13 @@ in
|
||||
rootLogger.level = info
|
||||
rootLogger.appenderRef.console.ref = console
|
||||
'';
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
};
|
||||
|
||||
dataDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/opensearch";
|
||||
apply = converge (removeSuffix "/");
|
||||
apply = lib.converge (lib.removeSuffix "/");
|
||||
description = ''
|
||||
Data directory for OpenSearch. If you change this, you need to
|
||||
manually create the directory. You also need to create the
|
||||
@@ -173,7 +170,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.opensearch = {
|
||||
description = "OpenSearch Daemon";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
@@ -194,7 +191,7 @@ in
|
||||
set -o errexit -o pipefail -o nounset -o errtrace
|
||||
shopt -s inherit_errexit
|
||||
''
|
||||
+ (optionalString (!config.boot.isContainer) ''
|
||||
+ (lib.optionalString (!config.boot.isContainer) ''
|
||||
# Only set vm.max_map_count if lower than ES required minimum
|
||||
# This avoids conflict if configured via boot.kernel.sysctl
|
||||
if [ $(${pkgs.procps}/bin/sysctl -n vm.max_map_count) -lt 262144 ]; then
|
||||
@@ -268,7 +265,7 @@ in
|
||||
TimeoutStartSec = "infinity";
|
||||
DynamicUser = usingDefaultUserAndGroup && usingDefaultDataDir;
|
||||
}
|
||||
// (optionalAttrs (usingDefaultDataDir) {
|
||||
// (lib.optionalAttrs (usingDefaultDataDir) {
|
||||
StateDirectory = "opensearch";
|
||||
StateDirectoryMode = "0700";
|
||||
});
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
let
|
||||
|
||||
cfg = config.services.qdrant;
|
||||
@@ -17,9 +15,9 @@ in
|
||||
|
||||
options = {
|
||||
services.qdrant = {
|
||||
enable = mkEnableOption "Vector Search Engine for the next generation of AI applications";
|
||||
enable = lib.mkEnableOption "Vector Search Engine for the next generation of AI applications";
|
||||
|
||||
settings = mkOption {
|
||||
settings = lib.mkOption {
|
||||
description = ''
|
||||
Configuration for Qdrant
|
||||
Refer to <https://github.com/qdrant/qdrant/blob/master/config/config.yaml> for details on supported values.
|
||||
@@ -43,7 +41,7 @@ in
|
||||
telemetry_disabled = true;
|
||||
};
|
||||
|
||||
defaultText = literalExpression ''
|
||||
defaultText = lib.literalExpression ''
|
||||
{
|
||||
storage = {
|
||||
storage_path = "/var/lib/qdrant/storage";
|
||||
@@ -64,41 +62,41 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.qdrant.settings = {
|
||||
service.static_content_dir = mkDefault pkgs.qdrant-web-ui;
|
||||
storage.storage_path = mkDefault "/var/lib/qdrant/storage";
|
||||
storage.snapshots_path = mkDefault "/var/lib/qdrant/snapshots";
|
||||
service.static_content_dir = lib.mkDefault pkgs.qdrant-web-ui;
|
||||
storage.storage_path = lib.mkDefault "/var/lib/qdrant/storage";
|
||||
storage.snapshots_path = lib.mkDefault "/var/lib/qdrant/snapshots";
|
||||
# The following default values are the same as in the default config,
|
||||
# they are just written here for convenience.
|
||||
storage.on_disk_payload = mkDefault true;
|
||||
storage.wal.wal_capacity_mb = mkDefault 32;
|
||||
storage.wal.wal_segments_ahead = mkDefault 0;
|
||||
storage.performance.max_search_threads = mkDefault 0;
|
||||
storage.performance.max_optimization_threads = mkDefault 1;
|
||||
storage.optimizers.deleted_threshold = mkDefault 0.2;
|
||||
storage.optimizers.vacuum_min_vector_number = mkDefault 1000;
|
||||
storage.optimizers.default_segment_number = mkDefault 0;
|
||||
storage.optimizers.max_segment_size_kb = mkDefault null;
|
||||
storage.optimizers.memmap_threshold_kb = mkDefault null;
|
||||
storage.optimizers.indexing_threshold_kb = mkDefault 20000;
|
||||
storage.optimizers.flush_interval_sec = mkDefault 5;
|
||||
storage.optimizers.max_optimization_threads = mkDefault 1;
|
||||
storage.hnsw_index.m = mkDefault 16;
|
||||
storage.hnsw_index.ef_construct = mkDefault 100;
|
||||
storage.hnsw_index.full_scan_threshold_kb = mkDefault 10000;
|
||||
storage.hnsw_index.max_indexing_threads = mkDefault 0;
|
||||
storage.hnsw_index.on_disk = mkDefault false;
|
||||
storage.hnsw_index.payload_m = mkDefault null;
|
||||
service.max_request_size_mb = mkDefault 32;
|
||||
service.max_workers = mkDefault 0;
|
||||
service.http_port = mkDefault 6333;
|
||||
service.grpc_port = mkDefault 6334;
|
||||
service.enable_cors = mkDefault true;
|
||||
cluster.enabled = mkDefault false;
|
||||
storage.on_disk_payload = lib.mkDefault true;
|
||||
storage.wal.wal_capacity_mb = lib.mkDefault 32;
|
||||
storage.wal.wal_segments_ahead = lib.mkDefault 0;
|
||||
storage.performance.max_search_threads = lib.mkDefault 0;
|
||||
storage.performance.max_optimization_threads = lib.mkDefault 1;
|
||||
storage.optimizers.deleted_threshold = lib.mkDefault 0.2;
|
||||
storage.optimizers.vacuum_min_vector_number = lib.mkDefault 1000;
|
||||
storage.optimizers.default_segment_number = lib.mkDefault 0;
|
||||
storage.optimizers.max_segment_size_kb = lib.mkDefault null;
|
||||
storage.optimizers.memmap_threshold_kb = lib.mkDefault null;
|
||||
storage.optimizers.indexing_threshold_kb = lib.mkDefault 20000;
|
||||
storage.optimizers.flush_interval_sec = lib.mkDefault 5;
|
||||
storage.optimizers.max_optimization_threads = lib.mkDefault 1;
|
||||
storage.hnsw_index.m = lib.mkDefault 16;
|
||||
storage.hnsw_index.ef_construct = lib.mkDefault 100;
|
||||
storage.hnsw_index.full_scan_threshold_kb = lib.mkDefault 10000;
|
||||
storage.hnsw_index.max_indexing_threads = lib.mkDefault 0;
|
||||
storage.hnsw_index.on_disk = lib.mkDefault false;
|
||||
storage.hnsw_index.payload_m = lib.mkDefault null;
|
||||
service.max_request_size_mb = lib.mkDefault 32;
|
||||
service.max_workers = lib.mkDefault 0;
|
||||
service.http_port = lib.mkDefault 6333;
|
||||
service.grpc_port = lib.mkDefault 6334;
|
||||
service.enable_cors = lib.mkDefault true;
|
||||
cluster.enabled = lib.mkDefault false;
|
||||
# the following have been altered for security
|
||||
service.host = mkDefault "127.0.0.1";
|
||||
telemetry_disabled = mkDefault true;
|
||||
service.host = lib.mkDefault "127.0.0.1";
|
||||
telemetry_disabled = lib.mkDefault true;
|
||||
};
|
||||
|
||||
systemd.services.qdrant = {
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.quickwit;
|
||||
|
||||
@@ -19,7 +16,7 @@ in
|
||||
{
|
||||
|
||||
options.services.quickwit = {
|
||||
enable = mkEnableOption "Quickwit";
|
||||
enable = lib.mkEnableOption "Quickwit";
|
||||
|
||||
package = lib.mkPackageOption pkgs "Quickwit" {
|
||||
default = [ "quickwit" ];
|
||||
@@ -83,7 +80,7 @@ in
|
||||
dataDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/quickwit";
|
||||
apply = converge (removeSuffix "/");
|
||||
apply = lib.converge (lib.removeSuffix "/");
|
||||
description = ''
|
||||
Data directory for Quickwit. If you change this, you need to
|
||||
manually create the directory. You also need to create the
|
||||
@@ -130,7 +127,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.quickwit = {
|
||||
description = "Quickwit";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
@@ -143,7 +140,7 @@ in
|
||||
{
|
||||
ExecStart = ''
|
||||
${cfg.package}/bin/quickwit run --config ${quickwitYml} \
|
||||
${escapeShellArgs cfg.extraFlags}
|
||||
${lib.escapeShellArgs cfg.extraFlags}
|
||||
'';
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
@@ -186,7 +183,7 @@ in
|
||||
"@chown"
|
||||
];
|
||||
}
|
||||
// (optionalAttrs (usingDefaultDataDir) {
|
||||
// (lib.optionalAttrs (usingDefaultDataDir) {
|
||||
StateDirectory = "quickwit";
|
||||
StateDirectoryMode = "0700";
|
||||
});
|
||||
|
||||
@@ -4,15 +4,12 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.certmgr;
|
||||
|
||||
specs = mapAttrsToList (n: v: rec {
|
||||
specs = lib.mapAttrsToList (n: v: rec {
|
||||
name = n + ".json";
|
||||
path = if isAttrs v then pkgs.writeText name (builtins.toJSON v) else v;
|
||||
path = if lib.isAttrs v then pkgs.writeText name (builtins.toJSON v) else v;
|
||||
}) cfg.specs;
|
||||
|
||||
allSpecs = pkgs.linkFarm "certmgr.d" specs;
|
||||
@@ -29,59 +26,59 @@ let
|
||||
);
|
||||
|
||||
specPaths = map dirOf (
|
||||
concatMap (
|
||||
lib.concatMap (
|
||||
spec:
|
||||
if isAttrs spec then
|
||||
collect isString (filterAttrsRecursive (n: v: isAttrs v || n == "path") spec)
|
||||
if lib.isAttrs spec then
|
||||
lib.collect lib.isString (lib.filterAttrsRecursive (n: v: lib.isAttrs v || n == "path") spec)
|
||||
else
|
||||
[ spec ]
|
||||
) (attrValues cfg.specs)
|
||||
) (lib.attrValues cfg.specs)
|
||||
);
|
||||
|
||||
preStart = ''
|
||||
${concatStringsSep " \\\n" ([ "mkdir -p" ] ++ map escapeShellArg specPaths)}
|
||||
${lib.concatStringsSep " \\\n" ([ "mkdir -p" ] ++ map lib.escapeShellArg specPaths)}
|
||||
${cfg.package}/bin/certmgr -f ${certmgrYaml} check
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.services.certmgr = {
|
||||
enable = mkEnableOption "certmgr";
|
||||
enable = lib.mkEnableOption "certmgr";
|
||||
|
||||
package = mkPackageOption pkgs "certmgr" { };
|
||||
package = lib.mkPackageOption pkgs "certmgr" { };
|
||||
|
||||
defaultRemote = mkOption {
|
||||
type = types.str;
|
||||
defaultRemote = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1:8888";
|
||||
description = "The default CA host:port to use.";
|
||||
};
|
||||
|
||||
validMin = mkOption {
|
||||
validMin = lib.mkOption {
|
||||
default = "72h";
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
description = "The interval before a certificate expires to start attempting to renew it.";
|
||||
};
|
||||
|
||||
renewInterval = mkOption {
|
||||
renewInterval = lib.mkOption {
|
||||
default = "30m";
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
description = "How often to check certificate expirations and how often to update the cert_next_expires metric.";
|
||||
};
|
||||
|
||||
metricsAddress = mkOption {
|
||||
metricsAddress = lib.mkOption {
|
||||
default = "127.0.0.1";
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
description = "The address for the Prometheus HTTP endpoint.";
|
||||
};
|
||||
|
||||
metricsPort = mkOption {
|
||||
metricsPort = lib.mkOption {
|
||||
default = 9488;
|
||||
type = types.ints.u16;
|
||||
type = lib.types.ints.u16;
|
||||
description = "The port for the Prometheus HTTP endpoint.";
|
||||
};
|
||||
|
||||
specs = mkOption {
|
||||
specs = lib.mkOption {
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
exampleCert =
|
||||
let
|
||||
@@ -119,21 +116,21 @@ in
|
||||
}
|
||||
'';
|
||||
type =
|
||||
with types;
|
||||
with lib.types;
|
||||
attrsOf (
|
||||
either path (submodule {
|
||||
options = {
|
||||
service = mkOption {
|
||||
service = lib.mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "The service on which to perform \<action\> after fetching.";
|
||||
};
|
||||
|
||||
action = mkOption {
|
||||
action = lib.mkOption {
|
||||
type = addCheck str (
|
||||
x:
|
||||
cfg.svcManager == "command"
|
||||
|| elem x [
|
||||
|| lib.elem x [
|
||||
"restart"
|
||||
"reload"
|
||||
"nop"
|
||||
@@ -144,22 +141,22 @@ in
|
||||
};
|
||||
|
||||
# These ought all to be specified according to certmgr spec def.
|
||||
authority = mkOption {
|
||||
authority = lib.mkOption {
|
||||
type = attrs;
|
||||
description = "certmgr spec authority object.";
|
||||
};
|
||||
|
||||
certificate = mkOption {
|
||||
certificate = lib.mkOption {
|
||||
type = nullOr attrs;
|
||||
description = "certmgr spec certificate object.";
|
||||
};
|
||||
|
||||
private_key = mkOption {
|
||||
private_key = lib.mkOption {
|
||||
type = nullOr attrs;
|
||||
description = "certmgr spec private_key object.";
|
||||
};
|
||||
|
||||
request = mkOption {
|
||||
request = lib.mkOption {
|
||||
type = nullOr attrs;
|
||||
description = "certmgr spec request object.";
|
||||
};
|
||||
@@ -173,9 +170,9 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
svcManager = mkOption {
|
||||
svcManager = lib.mkOption {
|
||||
default = "systemd";
|
||||
type = types.enum [
|
||||
type = lib.types.enum [
|
||||
"circus"
|
||||
"command"
|
||||
"dummy"
|
||||
@@ -193,7 +190,7 @@ in
|
||||
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.specs != { };
|
||||
@@ -201,10 +198,10 @@ in
|
||||
}
|
||||
{
|
||||
assertion =
|
||||
!any (hasAttrByPath [
|
||||
!lib.any (lib.hasAttrByPath [
|
||||
"authority"
|
||||
"auth_key"
|
||||
]) (attrValues cfg.specs);
|
||||
]) (lib.attrValues cfg.specs);
|
||||
message = ''
|
||||
Inline services.certmgr.specs are added to the Nix store rendering them world readable.
|
||||
Specify paths as specs, if you want to use include auth_key - or use the auth_key_file option."
|
||||
@@ -214,7 +211,7 @@ in
|
||||
|
||||
systemd.services.certmgr = {
|
||||
description = "certmgr";
|
||||
path = mkIf (cfg.svcManager == "command") [ pkgs.bash ];
|
||||
path = lib.mkIf (cfg.svcManager == "command") [ pkgs.bash ];
|
||||
wants = [ "network-online.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
@@ -5,19 +5,16 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.cfssl;
|
||||
in
|
||||
{
|
||||
options.services.cfssl = {
|
||||
enable = mkEnableOption "the CFSSL CA api-server";
|
||||
enable = lib.mkEnableOption "the CFSSL CA api-server";
|
||||
|
||||
dataDir = mkOption {
|
||||
dataDir = lib.mkOption {
|
||||
default = "/var/lib/cfssl";
|
||||
type = types.path;
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
The work directory for CFSSL.
|
||||
|
||||
@@ -30,51 +27,51 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
address = lib.mkOption {
|
||||
default = "127.0.0.1";
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
description = "Address to bind.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
port = lib.mkOption {
|
||||
default = 8888;
|
||||
type = types.port;
|
||||
type = lib.types.port;
|
||||
description = "Port to bind.";
|
||||
};
|
||||
|
||||
ca = mkOption {
|
||||
defaultText = literalExpression ''"''${cfg.dataDir}/ca.pem"'';
|
||||
type = types.str;
|
||||
ca = lib.mkOption {
|
||||
defaultText = lib.literalExpression ''"''${cfg.dataDir}/ca.pem"'';
|
||||
type = lib.types.str;
|
||||
description = "CA used to sign the new certificate -- accepts '[file:]fname' or 'env:varname'.";
|
||||
};
|
||||
|
||||
caKey = mkOption {
|
||||
defaultText = literalExpression ''"file:''${cfg.dataDir}/ca-key.pem"'';
|
||||
type = types.str;
|
||||
caKey = lib.mkOption {
|
||||
defaultText = lib.literalExpression ''"file:''${cfg.dataDir}/ca-key.pem"'';
|
||||
type = lib.types.str;
|
||||
description = "CA private key -- accepts '[file:]fname' or 'env:varname'.";
|
||||
};
|
||||
|
||||
caBundle = mkOption {
|
||||
caBundle = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = "Path to root certificate store.";
|
||||
};
|
||||
|
||||
intBundle = mkOption {
|
||||
intBundle = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = "Path to intermediate certificate store.";
|
||||
};
|
||||
|
||||
intDir = mkOption {
|
||||
intDir = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = "Intermediates directory.";
|
||||
};
|
||||
|
||||
metadata = mkOption {
|
||||
metadata = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = ''
|
||||
Metadata file for root certificate presence.
|
||||
The content of the file is a json dictionary (k,v): each key k is
|
||||
@@ -83,81 +80,81 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
remote = mkOption {
|
||||
remote = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
description = "Remote CFSSL server.";
|
||||
};
|
||||
|
||||
configFile = mkOption {
|
||||
configFile = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
description = "Path to configuration file. Do not put this in nix-store as it might contain secrets.";
|
||||
};
|
||||
|
||||
responder = mkOption {
|
||||
responder = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = "Certificate for OCSP responder.";
|
||||
};
|
||||
|
||||
responderKey = mkOption {
|
||||
responderKey = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
description = "Private key for OCSP responder certificate. Do not put this in nix-store.";
|
||||
};
|
||||
|
||||
tlsKey = mkOption {
|
||||
tlsKey = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
description = "Other endpoint's CA private key. Do not put this in nix-store.";
|
||||
};
|
||||
|
||||
tlsCert = mkOption {
|
||||
tlsCert = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = "Other endpoint's CA to set up TLS protocol.";
|
||||
};
|
||||
|
||||
mutualTlsCa = mkOption {
|
||||
mutualTlsCa = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = "Mutual TLS - require clients be signed by this CA.";
|
||||
};
|
||||
|
||||
mutualTlsCn = mkOption {
|
||||
mutualTlsCn = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
description = "Mutual TLS - regex for whitelist of allowed client CNs.";
|
||||
};
|
||||
|
||||
tlsRemoteCa = mkOption {
|
||||
tlsRemoteCa = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = "CAs to trust for remote TLS requests.";
|
||||
};
|
||||
|
||||
mutualTlsClientCert = mkOption {
|
||||
mutualTlsClientCert = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = "Mutual TLS - client certificate to call remote instance requiring client certs.";
|
||||
};
|
||||
|
||||
mutualTlsClientKey = mkOption {
|
||||
mutualTlsClientKey = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = "Mutual TLS - client key to call remote instance requiring client certs. Do not put this in nix-store.";
|
||||
};
|
||||
|
||||
dbConfig = mkOption {
|
||||
dbConfig = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = "Certificate db configuration file. Path must be writeable.";
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
logLevel = lib.mkOption {
|
||||
default = 1;
|
||||
type = types.enum [
|
||||
type = lib.types.enum [
|
||||
0
|
||||
1
|
||||
2
|
||||
@@ -169,7 +166,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.groups.cfssl = {
|
||||
gid = config.ids.gids.cfssl;
|
||||
};
|
||||
@@ -196,7 +193,7 @@ in
|
||||
ExecStart =
|
||||
with cfg;
|
||||
let
|
||||
opt = n: v: optionalString (v != null) ''-${n}="${v}"'';
|
||||
opt = n: v: lib.optionalString (v != null) ''-${n}="${v}"'';
|
||||
in
|
||||
lib.concatStringsSep " \\\n" [
|
||||
"${pkgs.cfssl}/bin/cfssl serve"
|
||||
@@ -223,7 +220,7 @@ in
|
||||
(opt "loglevel" (toString logLevel))
|
||||
];
|
||||
}
|
||||
(mkIf (cfg.dataDir == options.services.cfssl.dataDir.default) {
|
||||
(lib.mkIf (cfg.dataDir == options.services.cfssl.dataDir.default) {
|
||||
StateDirectory = baseNameOf cfg.dataDir;
|
||||
StateDirectoryMode = 700;
|
||||
})
|
||||
@@ -231,8 +228,8 @@ in
|
||||
};
|
||||
|
||||
services.cfssl = {
|
||||
ca = mkDefault "${cfg.dataDir}/ca.pem";
|
||||
caKey = mkDefault "${cfg.dataDir}/ca-key.pem";
|
||||
ca = lib.mkDefault "${cfg.dataDir}/ca.pem";
|
||||
caKey = lib.mkDefault "${cfg.dataDir}/ca-key.pem";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
let
|
||||
clamavUser = "clamav";
|
||||
stateDir = "/var/lib/clamav";
|
||||
clamavGroup = clamavUser;
|
||||
cfg = config.services.clamav;
|
||||
|
||||
toKeyValue = generators.toKeyValue {
|
||||
mkKeyValue = generators.mkKeyValueDefault { } " ";
|
||||
toKeyValue = lib.generators.toKeyValue {
|
||||
mkKeyValue = lib.generators.mkKeyValueDefault { } " ";
|
||||
listsAsDuplicateKeys = true;
|
||||
};
|
||||
|
||||
@@ -19,19 +18,19 @@ let
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
(mkRemovedOptionModule [ "services" "clamav" "updater" "config" ] "Use services.clamav.updater.settings instead.")
|
||||
(mkRemovedOptionModule [ "services" "clamav" "updater" "extraConfig" ] "Use services.clamav.updater.settings instead.")
|
||||
(mkRemovedOptionModule [ "services" "clamav" "daemon" "extraConfig" ] "Use services.clamav.daemon.settings instead.")
|
||||
(lib.mkRemovedOptionModule [ "services" "clamav" "updater" "config" ] "Use services.clamav.updater.settings instead.")
|
||||
(lib.mkRemovedOptionModule [ "services" "clamav" "updater" "extraConfig" ] "Use services.clamav.updater.settings instead.")
|
||||
(lib.mkRemovedOptionModule [ "services" "clamav" "daemon" "extraConfig" ] "Use services.clamav.daemon.settings instead.")
|
||||
];
|
||||
|
||||
options = {
|
||||
services.clamav = {
|
||||
package = mkPackageOption pkgs "clamav" { };
|
||||
package = lib.mkPackageOption pkgs "clamav" { };
|
||||
daemon = {
|
||||
enable = mkEnableOption "ClamAV clamd daemon";
|
||||
enable = lib.mkEnableOption "ClamAV clamd daemon";
|
||||
|
||||
settings = mkOption {
|
||||
type = with types; attrsOf (oneOf [ bool int str (listOf str) ]);
|
||||
settings = lib.mkOption {
|
||||
type = with lib.types; attrsOf (oneOf [ bool int str (listOf str) ]);
|
||||
default = { };
|
||||
description = ''
|
||||
ClamAV configuration. Refer to <https://linux.die.net/man/5/clamd.conf>,
|
||||
@@ -40,18 +39,18 @@ in
|
||||
};
|
||||
};
|
||||
updater = {
|
||||
enable = mkEnableOption "ClamAV freshclam updater";
|
||||
enable = lib.mkEnableOption "ClamAV freshclam updater";
|
||||
|
||||
frequency = mkOption {
|
||||
type = types.int;
|
||||
frequency = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 12;
|
||||
description = ''
|
||||
Number of database checks per day.
|
||||
'';
|
||||
};
|
||||
|
||||
interval = mkOption {
|
||||
type = types.str;
|
||||
interval = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "hourly";
|
||||
description = ''
|
||||
How often freshclam is invoked. See systemd.time(7) for more
|
||||
@@ -59,8 +58,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = with types; attrsOf (oneOf [ bool int str (listOf str) ]);
|
||||
settings = lib.mkOption {
|
||||
type = with lib.types; attrsOf (oneOf [ bool int str (listOf str) ]);
|
||||
default = { };
|
||||
description = ''
|
||||
freshclam configuration. Refer to <https://linux.die.net/man/5/freshclam.conf>,
|
||||
@@ -69,10 +68,10 @@ in
|
||||
};
|
||||
};
|
||||
fangfrisch = {
|
||||
enable = mkEnableOption "ClamAV fangfrisch updater";
|
||||
enable = lib.mkEnableOption "ClamAV fangfrisch updater";
|
||||
|
||||
interval = mkOption {
|
||||
type = types.str;
|
||||
interval = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "hourly";
|
||||
description = ''
|
||||
How often freshclam is invoked. See systemd.time(7) for more
|
||||
@@ -80,9 +79,9 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = with types; attrsOf (attrsOf (oneOf [ str int bool ]));
|
||||
freeformType = with lib.types; attrsOf (attrsOf (oneOf [ str int bool ]));
|
||||
};
|
||||
default = { };
|
||||
example = {
|
||||
@@ -100,10 +99,10 @@ in
|
||||
};
|
||||
|
||||
scanner = {
|
||||
enable = mkEnableOption "ClamAV scanner";
|
||||
enable = lib.mkEnableOption "ClamAV scanner";
|
||||
|
||||
interval = mkOption {
|
||||
type = types.str;
|
||||
interval = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "*-*-* 04:00:00";
|
||||
description = ''
|
||||
How often clamdscan is invoked. See systemd.time(7) for more
|
||||
@@ -112,8 +111,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
scanDirectories = mkOption {
|
||||
type = with types; listOf str;
|
||||
scanDirectories = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
default = [ "/home" "/var/lib" "/tmp" "/etc" "/var/tmp" ];
|
||||
description = ''
|
||||
List of directories to scan.
|
||||
@@ -124,7 +123,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.updater.enable || cfg.daemon.enable) {
|
||||
config = lib.mkIf (cfg.updater.enable || cfg.daemon.enable) {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
users.users.${clamavUser} = {
|
||||
@@ -153,12 +152,12 @@ in
|
||||
};
|
||||
|
||||
services.clamav.fangfrisch.settings = {
|
||||
DEFAULT.db_url = mkDefault "sqlite:////var/lib/clamav/fangfrisch_db.sqlite";
|
||||
DEFAULT.local_directory = mkDefault stateDir;
|
||||
DEFAULT.log_level = mkDefault "INFO";
|
||||
urlhaus.enabled = mkDefault "yes";
|
||||
urlhaus.max_size = mkDefault "2MB";
|
||||
sanesecurity.enabled = mkDefault "yes";
|
||||
DEFAULT.db_url = lib.mkDefault "sqlite:////var/lib/clamav/fangfrisch_db.sqlite";
|
||||
DEFAULT.local_directory = lib.mkDefault stateDir;
|
||||
DEFAULT.log_level = lib.mkDefault "INFO";
|
||||
urlhaus.enabled = lib.mkDefault "yes";
|
||||
urlhaus.max_size = lib.mkDefault "2MB";
|
||||
sanesecurity.enabled = lib.mkDefault "yes";
|
||||
};
|
||||
|
||||
environment.etc."clamav/freshclam.conf".source = freshclamConfigFile;
|
||||
@@ -168,10 +167,10 @@ in
|
||||
description = "ClamAV Antivirus Slice";
|
||||
};
|
||||
|
||||
systemd.services.clamav-daemon = mkIf cfg.daemon.enable {
|
||||
systemd.services.clamav-daemon = lib.mkIf cfg.daemon.enable {
|
||||
description = "ClamAV daemon (clamd)";
|
||||
after = optionals cfg.updater.enable [ "clamav-freshclam.service" ];
|
||||
wants = optionals cfg.updater.enable [ "clamav-freshclam.service" ];
|
||||
after = lib.optionals cfg.updater.enable [ "clamav-freshclam.service" ];
|
||||
wants = lib.optionals cfg.updater.enable [ "clamav-freshclam.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
restartTriggers = [ clamdConfigFile ];
|
||||
|
||||
@@ -189,7 +188,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.clamav-freshclam = mkIf cfg.updater.enable {
|
||||
systemd.timers.clamav-freshclam = lib.mkIf cfg.updater.enable {
|
||||
description = "Timer for ClamAV virus database updater (freshclam)";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
@@ -198,7 +197,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.clamav-freshclam = mkIf cfg.updater.enable {
|
||||
systemd.services.clamav-freshclam = lib.mkIf cfg.updater.enable {
|
||||
description = "ClamAV virus database updater (freshclam)";
|
||||
restartTriggers = [ freshclamConfigFile ];
|
||||
requires = [ "network-online.target" ];
|
||||
@@ -217,7 +216,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.clamav-fangfrisch-init = mkIf cfg.fangfrisch.enable {
|
||||
systemd.services.clamav-fangfrisch-init = lib.mkIf cfg.fangfrisch.enable {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
# if the sqlite file can be found assume the database has already been initialised
|
||||
script = ''
|
||||
@@ -239,7 +238,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.clamav-fangfrisch = mkIf cfg.fangfrisch.enable {
|
||||
systemd.timers.clamav-fangfrisch = lib.mkIf cfg.fangfrisch.enable {
|
||||
description = "Timer for ClamAV virus database updater (fangfrisch)";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
@@ -248,7 +247,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.clamav-fangfrisch = mkIf cfg.fangfrisch.enable {
|
||||
systemd.services.clamav-fangfrisch = lib.mkIf cfg.fangfrisch.enable {
|
||||
description = "ClamAV virus database updater (fangfrisch)";
|
||||
restartTriggers = [ fangfrischConfigFile ];
|
||||
requires = [ "network-online.target" ];
|
||||
@@ -266,7 +265,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.clamdscan = mkIf cfg.scanner.enable {
|
||||
systemd.timers.clamdscan = lib.mkIf cfg.scanner.enable {
|
||||
description = "Timer for ClamAV virus scanner";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
@@ -275,10 +274,10 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.clamdscan = mkIf cfg.scanner.enable {
|
||||
systemd.services.clamdscan = lib.mkIf cfg.scanner.enable {
|
||||
description = "ClamAV virus scanner";
|
||||
after = optionals cfg.updater.enable [ "clamav-freshclam.service" ];
|
||||
wants = optionals cfg.updater.enable [ "clamav-freshclam.service" ];
|
||||
after = lib.optionals cfg.updater.enable [ "clamav-freshclam.service" ];
|
||||
wants = lib.optionals cfg.updater.enable [ "clamav-freshclam.service" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
|
||||
@@ -4,20 +4,17 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.endlessh-go;
|
||||
in
|
||||
{
|
||||
options.services.endlessh-go = {
|
||||
enable = mkEnableOption "endlessh-go service";
|
||||
enable = lib.mkEnableOption "endlessh-go service";
|
||||
|
||||
package = mkPackageOption pkgs "endlessh-go" { };
|
||||
package = lib.mkPackageOption pkgs "endlessh-go" { };
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.str;
|
||||
listenAddress = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0.0.0.0";
|
||||
example = "[::]";
|
||||
description = ''
|
||||
@@ -25,8 +22,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 2222;
|
||||
example = 22;
|
||||
description = ''
|
||||
@@ -38,10 +35,10 @@ in
|
||||
};
|
||||
|
||||
prometheus = {
|
||||
enable = mkEnableOption "Prometheus integration";
|
||||
enable = lib.mkEnableOption "Prometheus integration";
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.str;
|
||||
listenAddress = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0.0.0.0";
|
||||
example = "[::]";
|
||||
description = ''
|
||||
@@ -50,8 +47,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 2112;
|
||||
example = 9119;
|
||||
description = ''
|
||||
@@ -61,8 +58,8 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
extraOptions = mkOption {
|
||||
type = with types; listOf str;
|
||||
extraOptions = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
default = [ ];
|
||||
example = [
|
||||
"-conn_type=tcp4"
|
||||
@@ -73,8 +70,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
openFirewall = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to open a firewall port for the SSH listener.
|
||||
@@ -82,7 +79,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.endlessh-go = {
|
||||
description = "SSH tarpit";
|
||||
requires = [ "network.target" ];
|
||||
@@ -90,21 +87,21 @@ in
|
||||
serviceConfig =
|
||||
let
|
||||
needsPrivileges = cfg.port < 1024 || cfg.prometheus.port < 1024;
|
||||
capabilities = [ "" ] ++ optionals needsPrivileges [ "CAP_NET_BIND_SERVICE" ];
|
||||
capabilities = [ "" ] ++ lib.optionals needsPrivileges [ "CAP_NET_BIND_SERVICE" ];
|
||||
rootDirectory = "/run/endlessh-go";
|
||||
in
|
||||
{
|
||||
Restart = "always";
|
||||
ExecStart =
|
||||
with cfg;
|
||||
concatStringsSep " " (
|
||||
lib.concatStringsSep " " (
|
||||
[
|
||||
(lib.getExe cfg.package)
|
||||
"-logtostderr"
|
||||
"-host=${listenAddress}"
|
||||
"-port=${toString port}"
|
||||
]
|
||||
++ optionals prometheus.enable [
|
||||
++ lib.optionals prometheus.enable [
|
||||
"-enable_prometheus"
|
||||
"-prometheus_host=${prometheus.listenAddress}"
|
||||
"-prometheus_port=${toString prometheus.port}"
|
||||
@@ -152,8 +149,8 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = with cfg; optionals openFirewall [ port ];
|
||||
networking.firewall.allowedTCPPorts = with cfg; lib.optionals openFirewall [ port ];
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ azahi ];
|
||||
meta.maintainers = with lib.maintainers; [ azahi ];
|
||||
}
|
||||
|
||||
@@ -4,18 +4,15 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.endlessh;
|
||||
in
|
||||
{
|
||||
options.services.endlessh = {
|
||||
enable = mkEnableOption "endlessh service";
|
||||
enable = lib.mkEnableOption "endlessh service";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 2222;
|
||||
example = 22;
|
||||
description = ''
|
||||
@@ -26,8 +23,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
extraOptions = mkOption {
|
||||
type = with types; listOf str;
|
||||
extraOptions = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
default = [ ];
|
||||
example = [
|
||||
"-6"
|
||||
@@ -39,8 +36,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
openFirewall = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to open a firewall port for the SSH listener.
|
||||
@@ -48,7 +45,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.endlessh = {
|
||||
description = "SSH tarpit";
|
||||
requires = [ "network.target" ];
|
||||
@@ -56,14 +53,14 @@ in
|
||||
serviceConfig =
|
||||
let
|
||||
needsPrivileges = cfg.port < 1024;
|
||||
capabilities = [ "" ] ++ optionals needsPrivileges [ "CAP_NET_BIND_SERVICE" ];
|
||||
capabilities = [ "" ] ++ lib.optionals needsPrivileges [ "CAP_NET_BIND_SERVICE" ];
|
||||
rootDirectory = "/run/endlessh";
|
||||
in
|
||||
{
|
||||
Restart = "always";
|
||||
ExecStart =
|
||||
with cfg;
|
||||
concatStringsSep " " (
|
||||
lib.concatStringsSep " " (
|
||||
[
|
||||
"${pkgs.endlessh}/bin/endlessh"
|
||||
"-p ${toString port}"
|
||||
@@ -112,8 +109,8 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = with cfg; optionals openFirewall [ port ];
|
||||
networking.firewall.allowedTCPPorts = with cfg; lib.optionals openFirewall [ port ];
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ azahi ];
|
||||
meta.maintainers = with lib.maintainers; [ azahi ];
|
||||
}
|
||||
|
||||
@@ -4,47 +4,44 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.fail2ban;
|
||||
|
||||
settingsFormat = pkgs.formats.keyValue { };
|
||||
|
||||
configFormat = pkgs.formats.ini {
|
||||
mkKeyValue = generators.mkKeyValueDefault { } " = ";
|
||||
mkKeyValue = lib.generators.mkKeyValueDefault { } " = ";
|
||||
};
|
||||
|
||||
mkJailConfig =
|
||||
name: attrs:
|
||||
optionalAttrs (name != "DEFAULT") { inherit (attrs) enabled; }
|
||||
// optionalAttrs (attrs.filter != null) {
|
||||
filter = if (builtins.isString filter) then filter else name;
|
||||
lib.optionalAttrs (name != "DEFAULT") { inherit (attrs) enabled; }
|
||||
// lib.optionalAttrs (attrs.filter != null) {
|
||||
filter = if (builtins.isString lib.filter) then lib.filter else name;
|
||||
}
|
||||
// attrs.settings;
|
||||
|
||||
mkFilter =
|
||||
name: attrs:
|
||||
nameValuePair "fail2ban/filter.d/${name}.conf" {
|
||||
lib.nameValuePair "fail2ban/filter.d/${name}.conf" {
|
||||
source = configFormat.generate "filter.d/${name}.conf" attrs.filter;
|
||||
};
|
||||
|
||||
fail2banConf = configFormat.generate "fail2ban.local" cfg.daemonSettings;
|
||||
|
||||
strJails = filterAttrs (_: builtins.isString) cfg.jails;
|
||||
attrsJails = filterAttrs (_: builtins.isAttrs) cfg.jails;
|
||||
strJails = lib.filterAttrs (_: builtins.isString) cfg.jails;
|
||||
attrsJails = lib.filterAttrs (_: builtins.isAttrs) cfg.jails;
|
||||
|
||||
jailConf =
|
||||
let
|
||||
configFile = configFormat.generate "jail.local" (
|
||||
{ INCLUDES.before = "paths-nixos.conf"; } // (mapAttrs mkJailConfig attrsJails)
|
||||
{ INCLUDES.before = "paths-nixos.conf"; } // (lib.mapAttrs mkJailConfig attrsJails)
|
||||
);
|
||||
extraConfig = concatStringsSep "\n" (
|
||||
attrValues (
|
||||
mapAttrs (
|
||||
extraConfig = lib.concatStringsSep "\n" (
|
||||
lib.attrValues (
|
||||
lib.mapAttrs (
|
||||
name: def:
|
||||
optionalString (def != "") ''
|
||||
lib.optionalString (def != "") ''
|
||||
[${name}]
|
||||
${def}
|
||||
''
|
||||
@@ -74,12 +71,12 @@ in
|
||||
{
|
||||
|
||||
imports = [
|
||||
(mkRemovedOptionModule [
|
||||
(lib.mkRemovedOptionModule [
|
||||
"services"
|
||||
"fail2ban"
|
||||
"daemonConfig"
|
||||
] "The daemon is now configured through the attribute set `services.fail2ban.daemonSettings`.")
|
||||
(mkRemovedOptionModule [ "services" "fail2ban" "extraSettings" ]
|
||||
(lib.mkRemovedOptionModule [ "services" "fail2ban" "extraSettings" ]
|
||||
"The extra default configuration can now be set using `services.fail2ban.jails.DEFAULT.settings`."
|
||||
)
|
||||
];
|
||||
@@ -88,9 +85,9 @@ in
|
||||
|
||||
options = {
|
||||
services.fail2ban = {
|
||||
enable = mkOption {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Whether to enable the fail2ban service.
|
||||
|
||||
@@ -99,20 +96,20 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkPackageOption pkgs "fail2ban" {
|
||||
package = lib.mkPackageOption pkgs "fail2ban" {
|
||||
example = "fail2ban_0_11";
|
||||
};
|
||||
|
||||
packageFirewall = mkOption {
|
||||
packageFirewall = lib.mkOption {
|
||||
default = config.networking.firewall.package;
|
||||
defaultText = literalExpression "config.networking.firewall.package";
|
||||
type = types.package;
|
||||
defaultText = lib.literalExpression "config.networking.firewall.package";
|
||||
type = lib.types.package;
|
||||
description = "The firewall package used by fail2ban service. Defaults to the package for your firewall (iptables or nftables).";
|
||||
};
|
||||
|
||||
extraPackages = mkOption {
|
||||
extraPackages = lib.mkOption {
|
||||
default = [ ];
|
||||
type = types.listOf types.package;
|
||||
type = lib.types.listOf lib.types.package;
|
||||
example = lib.literalExpression "[ pkgs.ipset ]";
|
||||
description = ''
|
||||
Extra packages to be made available to the fail2ban service. The example contains
|
||||
@@ -120,23 +117,23 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
bantime = mkOption {
|
||||
bantime = lib.mkOption {
|
||||
default = "10m";
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
example = "1h";
|
||||
description = "Number of seconds that a host is banned.";
|
||||
};
|
||||
|
||||
maxretry = mkOption {
|
||||
maxretry = lib.mkOption {
|
||||
default = 3;
|
||||
type = types.ints.unsigned;
|
||||
type = lib.types.ints.unsigned;
|
||||
description = "Number of failures before a host gets banned.";
|
||||
};
|
||||
|
||||
banaction = mkOption {
|
||||
banaction = lib.mkOption {
|
||||
default = if config.networking.nftables.enable then "nftables-multiport" else "iptables-multiport";
|
||||
defaultText = literalExpression ''if config.networking.nftables.enable then "nftables-multiport" else "iptables-multiport"'';
|
||||
type = types.str;
|
||||
defaultText = lib.literalExpression ''if config.networking.nftables.enable then "nftables-multiport" else "iptables-multiport"'';
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Default banning action (e.g. iptables, iptables-new, iptables-multiport,
|
||||
iptables-ipset-proto6-allports, shorewall, etc). It is used to
|
||||
@@ -145,10 +142,10 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
banaction-allports = mkOption {
|
||||
banaction-allports = lib.mkOption {
|
||||
default = if config.networking.nftables.enable then "nftables-allports" else "iptables-allports";
|
||||
defaultText = literalExpression ''if config.networking.nftables.enable then "nftables-allports" else "iptables-allports"'';
|
||||
type = types.str;
|
||||
defaultText = lib.literalExpression ''if config.networking.nftables.enable then "nftables-allports" else "iptables-allports"'';
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Default banning action (e.g. iptables, iptables-new, iptables-multiport,
|
||||
shorewall, etc) for "allports" jails. It is used to define action_* variables. Can be overridden
|
||||
@@ -156,18 +153,18 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.enable = mkOption {
|
||||
bantime-increment.enable = lib.mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
"bantime.increment" allows to use database for searching of previously banned ip's to increase
|
||||
a default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32 ...
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.rndtime = mkOption {
|
||||
bantime-increment.rndtime = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
example = "8m";
|
||||
description = ''
|
||||
"bantime.rndtime" is the max number of seconds using for mixing with random time
|
||||
@@ -175,18 +172,18 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.maxtime = mkOption {
|
||||
bantime-increment.maxtime = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
example = "48h";
|
||||
description = ''
|
||||
"bantime.maxtime" is the max number of seconds using the ban time can reach (don't grows further)
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.factor = mkOption {
|
||||
bantime-increment.factor = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
example = "4";
|
||||
description = ''
|
||||
"bantime.factor" is a coefficient to calculate exponent growing of the formula or common multiplier,
|
||||
@@ -194,9 +191,9 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.formula = mkOption {
|
||||
bantime-increment.formula = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
example = "ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)";
|
||||
description = ''
|
||||
"bantime.formula" used by default to calculate next value of ban time, default value below,
|
||||
@@ -204,9 +201,9 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.multipliers = mkOption {
|
||||
bantime-increment.multipliers = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
example = "1 2 4 8 16 32 64";
|
||||
description = ''
|
||||
"bantime.multipliers" used to calculate next value of ban time instead of formula, corresponding
|
||||
@@ -216,9 +213,9 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
bantime-increment.overalljails = mkOption {
|
||||
bantime-increment.overalljails = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.bool;
|
||||
type = lib.types.nullOr lib.types.bool;
|
||||
example = true;
|
||||
description = ''
|
||||
"bantime.overalljails" (if true) specifies the search of IP in the database will be executed
|
||||
@@ -226,9 +223,9 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
ignoreIP = mkOption {
|
||||
ignoreIP = lib.mkOption {
|
||||
default = [ ];
|
||||
type = types.listOf types.str;
|
||||
type = lib.types.listOf lib.types.str;
|
||||
example = [
|
||||
"192.168.0.0/16"
|
||||
"2001:DB8::42"
|
||||
@@ -239,10 +236,10 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
daemonSettings = mkOption {
|
||||
daemonSettings = lib.mkOption {
|
||||
inherit (configFormat) type;
|
||||
|
||||
defaultText = literalExpression ''
|
||||
defaultText = lib.literalExpression ''
|
||||
{
|
||||
Definition = {
|
||||
logtarget = "SYSLOG";
|
||||
@@ -258,9 +255,9 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
jails = mkOption {
|
||||
jails = lib.mkOption {
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
apache-nohome-iptables = {
|
||||
settings = {
|
||||
@@ -287,26 +284,26 @@ in
|
||||
};
|
||||
'';
|
||||
type =
|
||||
with types;
|
||||
with lib.types;
|
||||
attrsOf (
|
||||
either lines (
|
||||
submodule (
|
||||
{ name, ... }:
|
||||
{
|
||||
options = {
|
||||
enabled = mkEnableOption "this jail" // {
|
||||
enabled = lib.mkEnableOption "this jail" // {
|
||||
default = true;
|
||||
readOnly = name == "DEFAULT";
|
||||
};
|
||||
|
||||
filter = mkOption {
|
||||
filter = lib.mkOption {
|
||||
type = nullOr (either str configFormat.type);
|
||||
|
||||
default = null;
|
||||
description = "Content of the filter used for this jail.";
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
settings = lib.mkOption {
|
||||
inherit (settingsFormat) type;
|
||||
|
||||
default = { };
|
||||
@@ -344,7 +341,7 @@ in
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.bantime-increment.formula == null || cfg.bantime-increment.multipliers == null;
|
||||
@@ -354,7 +351,7 @@ in
|
||||
}
|
||||
];
|
||||
|
||||
warnings = mkIf (!config.networking.firewall.enable && !config.networking.nftables.enable) [
|
||||
warnings = lib.mkIf (!config.networking.firewall.enable && !config.networking.nftables.enable) [
|
||||
"fail2ban can not be used without a firewall"
|
||||
];
|
||||
|
||||
@@ -371,14 +368,14 @@ in
|
||||
"fail2ban/action.d".source = "${cfg.package}/etc/fail2ban/action.d/*.conf";
|
||||
"fail2ban/filter.d".source = "${cfg.package}/etc/fail2ban/filter.d/*.conf";
|
||||
}
|
||||
// (mapAttrs' mkFilter (
|
||||
filterAttrs (_: v: v.filter != null && !builtins.isString v.filter) attrsJails
|
||||
// (lib.mapAttrs' mkFilter (
|
||||
lib.filterAttrs (_: v: v.filter != null && !builtins.isString v.filter) attrsJails
|
||||
));
|
||||
|
||||
systemd.packages = [ cfg.package ];
|
||||
systemd.services.fail2ban = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
partOf = optional config.networking.firewall.enable "firewall.service";
|
||||
partOf = lib.optional config.networking.firewall.enable "firewall.service";
|
||||
|
||||
restartTriggers = [
|
||||
fail2banConf
|
||||
@@ -423,29 +420,29 @@ in
|
||||
|
||||
# Defaults for the daemon settings
|
||||
services.fail2ban.daemonSettings.Definition = {
|
||||
logtarget = mkDefault "SYSLOG";
|
||||
socket = mkDefault "/run/fail2ban/fail2ban.sock";
|
||||
pidfile = mkDefault "/run/fail2ban/fail2ban.pid";
|
||||
dbfile = mkDefault "/var/lib/fail2ban/fail2ban.sqlite3";
|
||||
logtarget = lib.mkDefault "SYSLOG";
|
||||
socket = lib.mkDefault "/run/fail2ban/fail2ban.sock";
|
||||
pidfile = lib.mkDefault "/run/fail2ban/fail2ban.pid";
|
||||
dbfile = lib.mkDefault "/var/lib/fail2ban/fail2ban.sqlite3";
|
||||
};
|
||||
|
||||
# Add some reasonable default jails. The special "DEFAULT" jail
|
||||
# sets default values for all other jails.
|
||||
services.fail2ban.jails = mkMerge [
|
||||
services.fail2ban.jails = lib.mkMerge [
|
||||
{
|
||||
DEFAULT.settings =
|
||||
(optionalAttrs cfg.bantime-increment.enable (
|
||||
(lib.optionalAttrs cfg.bantime-increment.enable (
|
||||
{
|
||||
"bantime.increment" = cfg.bantime-increment.enable;
|
||||
}
|
||||
// (mapAttrs' (name: nameValuePair "bantime.${name}") (
|
||||
filterAttrs (n: v: v != null && n != "enable") cfg.bantime-increment
|
||||
// (lib.mapAttrs' (name: lib.nameValuePair "bantime.${name}") (
|
||||
lib.filterAttrs (n: v: v != null && n != "enable") cfg.bantime-increment
|
||||
))
|
||||
))
|
||||
// {
|
||||
# Miscellaneous options
|
||||
inherit (cfg) banaction maxretry bantime;
|
||||
ignoreip = ''127.0.0.1/8 ${optionalString config.networking.enableIPv6 "::1"} ${concatStringsSep " " cfg.ignoreIP}'';
|
||||
ignoreip = ''127.0.0.1/8 ${lib.optionalString config.networking.enableIPv6 "::1"} ${lib.concatStringsSep " " cfg.ignoreIP}'';
|
||||
backend = "systemd";
|
||||
# Actions
|
||||
banaction_allports = cfg.banaction-allports;
|
||||
@@ -453,15 +450,15 @@ in
|
||||
}
|
||||
|
||||
# Block SSH if there are too many failing connection attempts.
|
||||
(mkIf config.services.openssh.enable {
|
||||
sshd.settings.port = mkDefault (
|
||||
concatMapStringsSep "," builtins.toString config.services.openssh.ports
|
||||
(lib.mkIf config.services.openssh.enable {
|
||||
sshd.settings.port = lib.mkDefault (
|
||||
lib.concatMapStringsSep "," builtins.toString config.services.openssh.ports
|
||||
);
|
||||
})
|
||||
];
|
||||
|
||||
# Benefits from verbose sshd logging to observe failed login attempts,
|
||||
# so we set that here unless the user overrode it.
|
||||
services.openssh.settings.LogLevel = mkDefault "VERBOSE";
|
||||
services.openssh.settings.LogLevel = lib.mkDefault "VERBOSE";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.fprintd;
|
||||
@@ -18,12 +15,12 @@ in
|
||||
|
||||
services.fprintd = {
|
||||
|
||||
enable = mkEnableOption "fprintd daemon and PAM module for fingerprint readers handling";
|
||||
enable = lib.mkEnableOption "fprintd daemon and PAM module for fingerprint readers handling";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = fprintdPkg;
|
||||
defaultText = literalExpression "if config.services.fprintd.tod.enable then pkgs.fprintd-tod else pkgs.fprintd";
|
||||
defaultText = lib.literalExpression "if config.services.fprintd.tod.enable then pkgs.fprintd-tod else pkgs.fprintd";
|
||||
description = ''
|
||||
fprintd package to use.
|
||||
'';
|
||||
@@ -31,11 +28,11 @@ in
|
||||
|
||||
tod = {
|
||||
|
||||
enable = mkEnableOption "Touch OEM Drivers library support";
|
||||
enable = lib.mkEnableOption "Touch OEM Drivers library support";
|
||||
|
||||
driver = mkOption {
|
||||
type = types.package;
|
||||
example = literalExpression "pkgs.libfprint-2-tod1-goodix";
|
||||
driver = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
example = lib.literalExpression "pkgs.libfprint-2-tod1-goodix";
|
||||
description = ''
|
||||
Touch OEM Drivers (TOD) package to use.
|
||||
'';
|
||||
@@ -47,7 +44,7 @@ in
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
services.dbus.packages = [ cfg.package ];
|
||||
|
||||
@@ -55,7 +52,7 @@ in
|
||||
|
||||
systemd.packages = [ cfg.package ];
|
||||
|
||||
systemd.services.fprintd.environment = mkIf cfg.tod.enable {
|
||||
systemd.services.fprintd.environment = lib.mkIf cfg.tod.enable {
|
||||
FP_TOD_DRIVERS_DIR = "${cfg.tod.driver}${cfg.tod.driver.driverPath}";
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
# This module defines global configuration for Haka.
|
||||
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.haka;
|
||||
@@ -23,14 +19,14 @@ let
|
||||
else
|
||||
"${haka}/share/haka/sample/${cfg.configFile}"
|
||||
}
|
||||
${optionalString (builtins.lessThan 0 cfg.threads) "thread = ${cfg.threads}"}
|
||||
${lib.optionalString (builtins.lessThan 0 cfg.threads) "thread = ${cfg.threads}"}
|
||||
|
||||
[packet]
|
||||
${optionalString cfg.pcap ''module = "packet/pcap"''}
|
||||
${optionalString cfg.nfqueue ''module = "packet/nqueue"''}
|
||||
${optionalString cfg.dump.enable ''dump = "yes"''}
|
||||
${optionalString cfg.dump.enable ''dump_input = "${cfg.dump.input}"''}
|
||||
${optionalString cfg.dump.enable ''dump_output = "${cfg.dump.output}"''}
|
||||
${lib.optionalString cfg.pcap ''module = "packet/pcap"''}
|
||||
${lib.optionalString cfg.nfqueue ''module = "packet/nqueue"''}
|
||||
${lib.optionalString cfg.dump.enable ''dump = "yes"''}
|
||||
${lib.optionalString cfg.dump.enable ''dump_input = "${cfg.dump.input}"''}
|
||||
${lib.optionalString cfg.dump.enable ''dump_output = "${cfg.dump.output}"''}
|
||||
|
||||
interfaces = "${lib.strings.concatStringsSep "," cfg.interfaces}"
|
||||
|
||||
@@ -62,14 +58,14 @@ in
|
||||
|
||||
services.haka = {
|
||||
|
||||
enable = mkEnableOption "Haka";
|
||||
enable = lib.mkEnableOption "Haka";
|
||||
|
||||
package = mkPackageOption pkgs "haka" { };
|
||||
package = lib.mkPackageOption pkgs "haka" { };
|
||||
|
||||
configFile = mkOption {
|
||||
configFile = lib.mkOption {
|
||||
default = "empty.lua";
|
||||
example = "/srv/haka/myfilter.lua";
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Specify which configuration file Haka uses.
|
||||
It can be absolute path or a path relative to the sample directory of
|
||||
@@ -77,46 +73,46 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
interfaces = mkOption {
|
||||
interfaces = lib.mkOption {
|
||||
default = [ "eth0" ];
|
||||
example = [ "any" ];
|
||||
type = with types; listOf str;
|
||||
type = with lib.types; listOf str;
|
||||
description = ''
|
||||
Specify which interface(s) Haka listens to.
|
||||
Use 'any' to listen to all interfaces.
|
||||
'';
|
||||
};
|
||||
|
||||
threads = mkOption {
|
||||
threads = lib.mkOption {
|
||||
default = 0;
|
||||
example = 4;
|
||||
type = types.int;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
The number of threads that will be used.
|
||||
All system threads are used by default.
|
||||
'';
|
||||
};
|
||||
|
||||
pcap = mkOption {
|
||||
pcap = lib.mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
type = lib.types.bool;
|
||||
description = "Whether to enable pcap";
|
||||
};
|
||||
|
||||
nfqueue = mkEnableOption "nfqueue";
|
||||
nfqueue = lib.mkEnableOption "nfqueue";
|
||||
|
||||
dump.enable = mkEnableOption "dump";
|
||||
dump.input = mkOption {
|
||||
dump.enable = lib.mkEnableOption "dump";
|
||||
dump.input = lib.mkOption {
|
||||
default = "/tmp/input.pcap";
|
||||
example = "/path/to/file.pcap";
|
||||
type = types.path;
|
||||
type = lib.types.path;
|
||||
description = "Path to file where incoming packets are dumped";
|
||||
};
|
||||
|
||||
dump.output = mkOption {
|
||||
dump.output = lib.mkOption {
|
||||
default = "/tmp/output.pcap";
|
||||
example = "/path/to/file.pcap";
|
||||
type = types.path;
|
||||
type = lib.types.path;
|
||||
description = "Path to file where outgoing packets are dumped";
|
||||
};
|
||||
};
|
||||
@@ -124,7 +120,7 @@ in
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
assertions = [
|
||||
{
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.haveged;
|
||||
|
||||
@@ -20,14 +17,14 @@ in
|
||||
|
||||
services.haveged = {
|
||||
|
||||
enable = mkEnableOption ''
|
||||
enable = lib.mkEnableOption ''
|
||||
haveged entropy daemon, which refills /dev/random when low.
|
||||
NOTE: does nothing on kernels newer than 5.6
|
||||
'';
|
||||
# source for the note https://github.com/jirka-h/haveged/issues/57
|
||||
|
||||
refill_threshold = mkOption {
|
||||
type = types.int;
|
||||
refill_threshold = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 1024;
|
||||
description = ''
|
||||
The number of bits of available entropy beneath which
|
||||
@@ -39,7 +36,7 @@ in
|
||||
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# https://github.com/jirka-h/haveged/blob/a4b69d65a8dfc5a9f52ff8505c7f58dcf8b9234f/contrib/Fedora/haveged.service
|
||||
systemd.services.haveged = {
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.hologram-agent;
|
||||
|
||||
@@ -19,20 +16,20 @@ in
|
||||
{
|
||||
options = {
|
||||
services.hologram-agent = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether to enable the Hologram agent for AWS instance credentials";
|
||||
};
|
||||
|
||||
dialAddress = mkOption {
|
||||
type = types.str;
|
||||
dialAddress = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "localhost:3100";
|
||||
description = "Hologram server and port.";
|
||||
};
|
||||
|
||||
httpPort = mkOption {
|
||||
type = types.str;
|
||||
httpPort = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "80";
|
||||
description = "Port for metadata service to listen on.";
|
||||
};
|
||||
@@ -40,7 +37,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
boot.kernelModules = [ "dummy" ];
|
||||
|
||||
networking.interfaces.dummy0.ipv4.addresses = [
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.hologram-server;
|
||||
|
||||
@@ -38,93 +35,93 @@ in
|
||||
{
|
||||
options = {
|
||||
services.hologram-server = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether to enable the Hologram server for AWS instance credentials";
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.str;
|
||||
listenAddress = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0.0.0.0:3100";
|
||||
description = "Address and port to listen on";
|
||||
};
|
||||
|
||||
ldapHost = mkOption {
|
||||
type = types.str;
|
||||
ldapHost = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Address of the LDAP server to use";
|
||||
};
|
||||
|
||||
ldapInsecure = mkOption {
|
||||
type = types.bool;
|
||||
ldapInsecure = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether to connect to LDAP over SSL or not";
|
||||
};
|
||||
|
||||
ldapUserAttr = mkOption {
|
||||
type = types.str;
|
||||
ldapUserAttr = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "cn";
|
||||
description = "The LDAP attribute for usernames";
|
||||
};
|
||||
|
||||
ldapBaseDN = mkOption {
|
||||
type = types.str;
|
||||
ldapBaseDN = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "The base DN for your Hologram users";
|
||||
};
|
||||
|
||||
ldapBindDN = mkOption {
|
||||
type = types.str;
|
||||
ldapBindDN = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "DN of account to use to query the LDAP server";
|
||||
};
|
||||
|
||||
ldapBindPassword = mkOption {
|
||||
type = types.str;
|
||||
ldapBindPassword = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Password of account to use to query the LDAP server";
|
||||
};
|
||||
|
||||
enableLdapRoles = mkOption {
|
||||
type = types.bool;
|
||||
enableLdapRoles = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether to assign user roles based on the user's LDAP group memberships";
|
||||
};
|
||||
|
||||
groupClassAttr = mkOption {
|
||||
type = types.str;
|
||||
groupClassAttr = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "groupOfNames";
|
||||
description = "The objectclass attribute to search for groups when enableLdapRoles is true";
|
||||
};
|
||||
|
||||
roleAttr = mkOption {
|
||||
type = types.str;
|
||||
roleAttr = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "businessCategory";
|
||||
description = "Which LDAP group attribute to search for authorized role ARNs";
|
||||
};
|
||||
|
||||
awsAccount = mkOption {
|
||||
type = types.str;
|
||||
awsAccount = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "AWS account number";
|
||||
};
|
||||
|
||||
awsDefaultRole = mkOption {
|
||||
type = types.str;
|
||||
awsDefaultRole = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "AWS default role";
|
||||
};
|
||||
|
||||
statsAddress = mkOption {
|
||||
type = types.str;
|
||||
statsAddress = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Address of statsd server";
|
||||
};
|
||||
|
||||
cacheTimeoutSeconds = mkOption {
|
||||
type = types.int;
|
||||
cacheTimeoutSeconds = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 3600;
|
||||
description = "How often (in seconds) to refresh the LDAP cache";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.hologram-server = {
|
||||
description = "Provide EC2 instance credentials to machines outside of EC2";
|
||||
after = [ "network.target" ];
|
||||
|
||||
@@ -4,38 +4,35 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.infnoise;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.infnoise = {
|
||||
enable = mkEnableOption "the Infinite Noise TRNG driver";
|
||||
enable = lib.mkEnableOption "the Infinite Noise TRNG driver";
|
||||
|
||||
fillDevRandom = mkOption {
|
||||
fillDevRandom = lib.mkOption {
|
||||
description = ''
|
||||
Whether to run the infnoise driver as a daemon to refill /dev/random.
|
||||
|
||||
If disabled, you can use the `infnoise` command-line tool to
|
||||
manually obtain randomness.
|
||||
'';
|
||||
type = types.bool;
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ pkgs.infnoise ];
|
||||
|
||||
services.udev.extraRules = ''
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", SYMLINK+="infnoise", TAG+="systemd", GROUP="dialout", MODE="0664", ENV{SYSTEMD_WANTS}="infnoise.service"
|
||||
'';
|
||||
|
||||
systemd.services.infnoise = mkIf cfg.fillDevRandom {
|
||||
systemd.services.infnoise = lib.mkIf cfg.fillDevRandom {
|
||||
description = "Infinite Noise TRNG driver";
|
||||
|
||||
bindsTo = [ "dev-infnoise.device" ];
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.munge;
|
||||
@@ -20,11 +17,11 @@ in
|
||||
options = {
|
||||
|
||||
services.munge = {
|
||||
enable = mkEnableOption "munge service";
|
||||
enable = lib.mkEnableOption "munge service";
|
||||
|
||||
password = mkOption {
|
||||
password = lib.mkOption {
|
||||
default = "/etc/munge/munge.key";
|
||||
type = types.path;
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
The path to a daemon's secret key.
|
||||
'';
|
||||
@@ -36,7 +33,7 @@ in
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ pkgs.munge ];
|
||||
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
{ config, lib, pkgs, utils, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.nginx.sso;
|
||||
format = pkgs.formats.yaml { };
|
||||
configPath = "/var/lib/nginx-sso/config.yaml";
|
||||
in {
|
||||
options.services.nginx.sso = {
|
||||
enable = mkEnableOption "nginx-sso service";
|
||||
enable = lib.mkEnableOption "nginx-sso service";
|
||||
|
||||
package = mkPackageOption pkgs "nginx-sso" { };
|
||||
package = lib.mkPackageOption pkgs "nginx-sso" { };
|
||||
|
||||
configuration = mkOption {
|
||||
configuration = lib.mkOption {
|
||||
type = format.type;
|
||||
default = {};
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
listen = { addr = "127.0.0.1"; port = 8080; };
|
||||
|
||||
@@ -48,7 +45,7 @@ in {
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.nginx-sso = {
|
||||
description = "Nginx SSO Backend";
|
||||
after = [ "network.target" ];
|
||||
|
||||
@@ -4,14 +4,11 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.opensnitch;
|
||||
format = pkgs.formats.json { };
|
||||
|
||||
predefinedRules = flip mapAttrs cfg.rules (
|
||||
predefinedRules = lib.flip lib.mapAttrs cfg.rules (
|
||||
name: cfg: {
|
||||
file = pkgs.writeText "rule" (builtins.toJSON cfg);
|
||||
}
|
||||
@@ -21,11 +18,11 @@ in
|
||||
{
|
||||
options = {
|
||||
services.opensnitch = {
|
||||
enable = mkEnableOption "Opensnitch application firewall";
|
||||
enable = lib.mkEnableOption "Opensnitch application firewall";
|
||||
|
||||
rules = mkOption {
|
||||
rules = lib.mkOption {
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
"tor" = {
|
||||
"name" = "tor";
|
||||
@@ -50,28 +47,28 @@ in
|
||||
for available options.
|
||||
'';
|
||||
|
||||
type = types.submodule {
|
||||
type = lib.types.submodule {
|
||||
freeformType = format.type;
|
||||
};
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = format.type;
|
||||
|
||||
options = {
|
||||
Server = {
|
||||
|
||||
Address = mkOption {
|
||||
type = types.str;
|
||||
Address = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Unix socket path (unix:///tmp/osui.sock, the "unix:///" part is
|
||||
mandatory) or TCP socket (192.168.1.100:50051).
|
||||
'';
|
||||
};
|
||||
|
||||
LogFile = mkOption {
|
||||
type = types.path;
|
||||
LogFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
File to write logs to (use /dev/stdout to write logs to standard
|
||||
output).
|
||||
@@ -80,8 +77,8 @@ in
|
||||
|
||||
};
|
||||
|
||||
DefaultAction = mkOption {
|
||||
type = types.enum [
|
||||
DefaultAction = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"allow"
|
||||
"deny"
|
||||
];
|
||||
@@ -91,15 +88,15 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
InterceptUnknown = mkOption {
|
||||
type = types.bool;
|
||||
InterceptUnknown = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Whether to intercept spare connections.
|
||||
'';
|
||||
};
|
||||
|
||||
ProcMonitorMethod = mkOption {
|
||||
type = types.enum [
|
||||
ProcMonitorMethod = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"ebpf"
|
||||
"proc"
|
||||
"ftrace"
|
||||
@@ -110,8 +107,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
LogLevel = mkOption {
|
||||
type = types.enum [
|
||||
LogLevel = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
0
|
||||
1
|
||||
2
|
||||
@@ -124,8 +121,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
Firewall = mkOption {
|
||||
type = types.enum [
|
||||
Firewall = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"iptables"
|
||||
"nftables"
|
||||
];
|
||||
@@ -136,15 +133,15 @@ in
|
||||
|
||||
Stats = {
|
||||
|
||||
MaxEvents = mkOption {
|
||||
type = types.int;
|
||||
MaxEvents = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
Max events to send to the GUI.
|
||||
'';
|
||||
};
|
||||
|
||||
MaxStats = mkOption {
|
||||
type = types.int;
|
||||
MaxStats = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
Max stats per item to keep in backlog.
|
||||
'';
|
||||
@@ -152,14 +149,14 @@ in
|
||||
|
||||
};
|
||||
|
||||
Ebpf.ModulesPath = mkOption {
|
||||
type = types.path;
|
||||
Ebpf.ModulesPath = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default =
|
||||
if cfg.settings.ProcMonitorMethod == "ebpf" then
|
||||
"${config.boot.kernelPackages.opensnitch-ebpf}/etc/opensnitchd"
|
||||
else
|
||||
null;
|
||||
defaultText = literalExpression ''
|
||||
defaultText = lib.literalExpression ''
|
||||
if cfg.settings.ProcMonitorMethod == "ebpf" then
|
||||
"\\$\\{config.boot.kernelPackages.opensnitch-ebpf\\}/etc/opensnitchd"
|
||||
else null;
|
||||
@@ -170,8 +167,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
Rules.Path = mkOption {
|
||||
type = types.path;
|
||||
Rules.Path = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/opensnitch/rules";
|
||||
description = ''
|
||||
Path to the directory where firewall rules can be found and will
|
||||
@@ -189,10 +186,10 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# pkg.opensnitch is referred to elsewhere in the module so we don't need to worry about it being garbage collected
|
||||
services.opensnitch.settings = mapAttrs (_: v: mkDefault v) (
|
||||
services.opensnitch.settings = lib.mapAttrs (_: v: lib.mkDefault v) (
|
||||
builtins.fromJSON (
|
||||
builtins.unsafeDiscardStringContext (
|
||||
builtins.readFile "${pkgs.opensnitch}/etc/opensnitchd/default-config.json"
|
||||
@@ -205,14 +202,20 @@ in
|
||||
services.opensnitchd = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = [
|
||||
""
|
||||
"${pkgs.opensnitch}/bin/opensnitchd --config-file ${format.generate "default-config.json" cfg.settings}"
|
||||
];
|
||||
ExecStart =
|
||||
let
|
||||
preparedSettings = removeAttrs cfg.settings (
|
||||
lib.optional (cfg.settings.ProcMonitorMethod != "ebpf") "Ebpf"
|
||||
);
|
||||
in
|
||||
[
|
||||
""
|
||||
"${pkgs.opensnitch}/bin/opensnitchd --config-file ${format.generate "default-config.json" preparedSettings}"
|
||||
];
|
||||
};
|
||||
preStart = mkIf (cfg.rules != { }) (
|
||||
preStart = lib.mkIf (cfg.rules != { }) (
|
||||
let
|
||||
rules = flip mapAttrsToList predefinedRules (
|
||||
rules = lib.flip lib.mapAttrsToList predefinedRules (
|
||||
file: content: {
|
||||
inherit (content) file;
|
||||
local = "${cfg.settings.Rules.Path}/${file}.json";
|
||||
@@ -225,11 +228,13 @@ in
|
||||
# declared in `cfg.rules` (i.e. all networks that were "removed" from
|
||||
# `cfg.rules`).
|
||||
find ${cfg.settings.Rules.Path} -type l -lname '${builtins.storeDir}/*' ${
|
||||
optionalString (rules != { }) ''
|
||||
-not \( ${concatMapStringsSep " -o " ({ local, ... }: "-name '${baseNameOf local}*'") rules} \) \
|
||||
lib.optionalString (rules != { }) ''
|
||||
-not \( ${
|
||||
lib.concatMapStringsSep " -o " ({ local, ... }: "-name '${baseNameOf local}*'") rules
|
||||
} \) \
|
||||
''
|
||||
} -delete
|
||||
${concatMapStrings (
|
||||
${lib.concatMapStrings (
|
||||
{ file, local }:
|
||||
''
|
||||
ln -sf '${file}' "${local}"
|
||||
|
||||
@@ -4,25 +4,22 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.passSecretService;
|
||||
in
|
||||
{
|
||||
options.services.passSecretService = {
|
||||
enable = mkEnableOption "pass secret service";
|
||||
enable = lib.mkEnableOption "pass secret service";
|
||||
|
||||
package = mkPackageOption pkgs "pass-secret-service" {
|
||||
package = lib.mkPackageOption pkgs "pass-secret-service" {
|
||||
example = "pass-secret-service.override { python3 = pkgs.python310 }";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.packages = [ cfg.package ];
|
||||
services.dbus.packages = [ cfg.package ];
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ aidalgol ];
|
||||
meta.maintainers = with lib.maintainers; [ aidalgol ];
|
||||
}
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.physlock;
|
||||
in
|
||||
@@ -19,8 +16,8 @@ in
|
||||
|
||||
services.physlock = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable the {command}`physlock` screen locking mechanism.
|
||||
@@ -35,8 +32,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
allowAnyUser = mkOption {
|
||||
type = types.bool;
|
||||
allowAnyUser = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to allow any user to lock the screen. This will install a
|
||||
@@ -46,24 +43,24 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
disableSysRq = mkOption {
|
||||
type = types.bool;
|
||||
disableSysRq = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to disable SysRq when locked with physlock.
|
||||
'';
|
||||
};
|
||||
|
||||
lockMessage = mkOption {
|
||||
type = types.str;
|
||||
lockMessage = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Message to show on physlock login terminal.
|
||||
'';
|
||||
};
|
||||
|
||||
muteKernelMessages = mkOption {
|
||||
type = types.bool;
|
||||
muteKernelMessages = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Disable kernel messages on console while physlock is running.
|
||||
@@ -72,24 +69,24 @@ in
|
||||
|
||||
lockOn = {
|
||||
|
||||
suspend = mkOption {
|
||||
type = types.bool;
|
||||
suspend = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to lock screen with physlock just before suspend.
|
||||
'';
|
||||
};
|
||||
|
||||
hibernate = mkOption {
|
||||
type = types.bool;
|
||||
hibernate = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to lock screen with physlock just before hibernate.
|
||||
'';
|
||||
};
|
||||
|
||||
extraTargets = mkOption {
|
||||
type = types.listOf types.str;
|
||||
extraTargets = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
example = [ "display-manager.service" ];
|
||||
description = ''
|
||||
@@ -110,46 +107,50 @@ in
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable (mkMerge [
|
||||
{
|
||||
config = lib.mkIf cfg.enable (
|
||||
lib.mkMerge [
|
||||
{
|
||||
|
||||
# for physlock -l and physlock -L
|
||||
environment.systemPackages = [ pkgs.physlock ];
|
||||
# for physlock -l and physlock -L
|
||||
environment.systemPackages = [ pkgs.physlock ];
|
||||
|
||||
systemd.services.physlock = {
|
||||
enable = true;
|
||||
description = "Physlock";
|
||||
wantedBy =
|
||||
optional cfg.lockOn.suspend "suspend.target"
|
||||
++ optional cfg.lockOn.hibernate "hibernate.target"
|
||||
++ cfg.lockOn.extraTargets;
|
||||
before =
|
||||
optional cfg.lockOn.suspend "systemd-suspend.service"
|
||||
++ optional cfg.lockOn.hibernate "systemd-hibernate.service"
|
||||
++ optional (cfg.lockOn.hibernate || cfg.lockOn.suspend) "systemd-suspend-then-hibernate.service"
|
||||
++ cfg.lockOn.extraTargets;
|
||||
serviceConfig = {
|
||||
Type = "forking";
|
||||
ExecStart = "${pkgs.physlock}/bin/physlock -d${optionalString cfg.muteKernelMessages "m"}${optionalString cfg.disableSysRq "s"}${
|
||||
optionalString (cfg.lockMessage != "") " -p \"${cfg.lockMessage}\""
|
||||
}";
|
||||
systemd.services.physlock = {
|
||||
enable = true;
|
||||
description = "Physlock";
|
||||
wantedBy =
|
||||
lib.optional cfg.lockOn.suspend "suspend.target"
|
||||
++ lib.optional cfg.lockOn.hibernate "hibernate.target"
|
||||
++ cfg.lockOn.extraTargets;
|
||||
before =
|
||||
lib.optional cfg.lockOn.suspend "systemd-suspend.service"
|
||||
++ lib.optional cfg.lockOn.hibernate "systemd-hibernate.service"
|
||||
++ lib.optional (
|
||||
cfg.lockOn.hibernate || cfg.lockOn.suspend
|
||||
) "systemd-suspend-then-hibernate.service"
|
||||
++ cfg.lockOn.extraTargets;
|
||||
serviceConfig = {
|
||||
Type = "forking";
|
||||
ExecStart = "${pkgs.physlock}/bin/physlock -d${lib.optionalString cfg.muteKernelMessages "m"}${lib.optionalString cfg.disableSysRq "s"}${
|
||||
lib.optionalString (cfg.lockMessage != "") " -p \"${cfg.lockMessage}\""
|
||||
}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
security.pam.services.physlock = { };
|
||||
security.pam.services.physlock = { };
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
(mkIf cfg.allowAnyUser {
|
||||
(lib.mkIf cfg.allowAnyUser {
|
||||
|
||||
security.wrappers.physlock = {
|
||||
setuid = true;
|
||||
owner = "root";
|
||||
group = "root";
|
||||
source = "${pkgs.physlock}/bin/physlock";
|
||||
};
|
||||
security.wrappers.physlock = {
|
||||
setuid = true;
|
||||
owner = "root";
|
||||
group = "root";
|
||||
source = "${pkgs.physlock}/bin/physlock";
|
||||
};
|
||||
|
||||
})
|
||||
]);
|
||||
})
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.sks;
|
||||
sksPkg = cfg.package;
|
||||
@@ -16,7 +13,7 @@ let
|
||||
|
||||
in
|
||||
{
|
||||
meta.maintainers = with maintainers; [
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
calbrecht
|
||||
jcumming
|
||||
];
|
||||
@@ -25,15 +22,15 @@ in
|
||||
|
||||
services.sks = {
|
||||
|
||||
enable = mkEnableOption ''
|
||||
enable = lib.mkEnableOption ''
|
||||
SKS (synchronizing key server for OpenPGP) and start the database
|
||||
server. You need to create "''${dataDir}/dump/*.gpg" for the initial
|
||||
import'';
|
||||
|
||||
package = mkPackageOption pkgs "sks" { };
|
||||
package = lib.mkPackageOption pkgs "sks" { };
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
dataDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/db/sks";
|
||||
example = "/var/lib/sks";
|
||||
# TODO: The default might change to "/var/lib/sks" as this is more
|
||||
@@ -46,8 +43,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
extraDbConfig = mkOption {
|
||||
type = types.str;
|
||||
extraDbConfig = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Set contents of the files "KDB/DB_CONFIG" and "PTree/DB_CONFIG" within
|
||||
@@ -60,28 +57,28 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
hkpAddress = mkOption {
|
||||
hkpAddress = lib.mkOption {
|
||||
default = [
|
||||
"127.0.0.1"
|
||||
"::1"
|
||||
];
|
||||
type = types.listOf types.str;
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = ''
|
||||
Domain names, IPv4 and/or IPv6 addresses to listen on for HKP
|
||||
requests.
|
||||
'';
|
||||
};
|
||||
|
||||
hkpPort = mkOption {
|
||||
hkpPort = lib.mkOption {
|
||||
default = 11371;
|
||||
type = types.ints.u16;
|
||||
type = lib.types.ints.u16;
|
||||
description = "HKP port to listen on.";
|
||||
};
|
||||
|
||||
webroot = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
webroot = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = "${sksPkg.webSamples}/OpenPKG";
|
||||
defaultText = literalExpression ''"''${package.webSamples}/OpenPKG"'';
|
||||
defaultText = lib.literalExpression ''"''${package.webSamples}/OpenPKG"'';
|
||||
description = ''
|
||||
Source directory (will be symlinked, if not null) for the files the
|
||||
built-in webserver should serve. SKS (''${pkgs.sks.webSamples})
|
||||
@@ -96,7 +93,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
users = {
|
||||
users.sks = {
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.sshguard;
|
||||
|
||||
@@ -19,7 +16,7 @@ let
|
||||
"-o cat"
|
||||
"-n1"
|
||||
]
|
||||
++ (map (name: "-t ${escapeShellArg name}") cfg.services)
|
||||
++ (map (name: "-t ${lib.escapeShellArg name}") cfg.services)
|
||||
);
|
||||
backend = if config.networking.nftables.enable then "sshg-fw-nft-sets" else "sshg-fw-ipset";
|
||||
in
|
||||
@@ -36,40 +33,40 @@ in
|
||||
options = {
|
||||
|
||||
services.sshguard = {
|
||||
enable = mkOption {
|
||||
enable = lib.mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
type = lib.types.bool;
|
||||
description = "Whether to enable the sshguard service.";
|
||||
};
|
||||
|
||||
attack_threshold = mkOption {
|
||||
attack_threshold = lib.mkOption {
|
||||
default = 30;
|
||||
type = types.int;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
Block attackers when their cumulative attack score exceeds threshold. Most attacks have a score of 10.
|
||||
'';
|
||||
};
|
||||
|
||||
blacklist_threshold = mkOption {
|
||||
blacklist_threshold = lib.mkOption {
|
||||
default = null;
|
||||
example = 120;
|
||||
type = types.nullOr types.int;
|
||||
type = lib.types.nullOr lib.types.int;
|
||||
description = ''
|
||||
Blacklist an attacker when its score exceeds threshold. Blacklisted addresses are loaded from and added to blacklist-file.
|
||||
'';
|
||||
};
|
||||
|
||||
blacklist_file = mkOption {
|
||||
blacklist_file = lib.mkOption {
|
||||
default = "/var/lib/sshguard/blacklist.db";
|
||||
type = types.path;
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
Blacklist an attacker when its score exceeds threshold. Blacklisted addresses are loaded from and added to blacklist-file.
|
||||
'';
|
||||
};
|
||||
|
||||
blocktime = mkOption {
|
||||
blocktime = lib.mkOption {
|
||||
default = 120;
|
||||
type = types.int;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
Block attackers for initially blocktime seconds after exceeding threshold. Subsequent blocks increase by a factor of 1.5.
|
||||
|
||||
@@ -77,33 +74,33 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
detection_time = mkOption {
|
||||
detection_time = lib.mkOption {
|
||||
default = 1800;
|
||||
type = types.int;
|
||||
type = lib.types.int;
|
||||
description = ''
|
||||
Remember potential attackers for up to detection_time seconds before resetting their score.
|
||||
'';
|
||||
};
|
||||
|
||||
whitelist = mkOption {
|
||||
whitelist = lib.mkOption {
|
||||
default = [ ];
|
||||
example = [
|
||||
"198.51.100.56"
|
||||
"198.51.100.2"
|
||||
];
|
||||
type = types.listOf types.str;
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = ''
|
||||
Whitelist a list of addresses, hostnames, or address blocks.
|
||||
'';
|
||||
};
|
||||
|
||||
services = mkOption {
|
||||
services = lib.mkOption {
|
||||
default = [ "sshd" ];
|
||||
example = [
|
||||
"sshd"
|
||||
"exim"
|
||||
];
|
||||
type = types.listOf types.str;
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = ''
|
||||
Systemd services sshguard should receive logs of.
|
||||
'';
|
||||
@@ -113,7 +110,7 @@ in
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
environment.etc."sshguard.conf".source = configFile;
|
||||
|
||||
@@ -122,7 +119,7 @@ in
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
partOf = optional config.networking.firewall.enable "firewall.service";
|
||||
partOf = lib.optional config.networking.firewall.enable "firewall.service";
|
||||
|
||||
restartTriggers = [ configFile ];
|
||||
|
||||
@@ -149,21 +146,21 @@ in
|
||||
# of the ipsets. So instead, we create both the ipsets and
|
||||
# firewall rules before sshguard starts.
|
||||
preStart =
|
||||
optionalString config.networking.firewall.enable ''
|
||||
lib.optionalString config.networking.firewall.enable ''
|
||||
${pkgs.ipset}/bin/ipset -quiet create -exist sshguard4 hash:net family inet
|
||||
${pkgs.iptables}/bin/iptables -I INPUT -m set --match-set sshguard4 src -j DROP
|
||||
''
|
||||
+ optionalString (config.networking.firewall.enable && config.networking.enableIPv6) ''
|
||||
+ lib.optionalString (config.networking.firewall.enable && config.networking.enableIPv6) ''
|
||||
${pkgs.ipset}/bin/ipset -quiet create -exist sshguard6 hash:net family inet6
|
||||
${pkgs.iptables}/bin/ip6tables -I INPUT -m set --match-set sshguard6 src -j DROP
|
||||
'';
|
||||
|
||||
postStop =
|
||||
optionalString config.networking.firewall.enable ''
|
||||
lib.optionalString config.networking.firewall.enable ''
|
||||
${pkgs.iptables}/bin/iptables -D INPUT -m set --match-set sshguard4 src -j DROP
|
||||
${pkgs.ipset}/bin/ipset -quiet destroy sshguard4
|
||||
''
|
||||
+ optionalString (config.networking.firewall.enable && config.networking.enableIPv6) ''
|
||||
+ lib.optionalString (config.networking.firewall.enable && config.networking.enableIPv6) ''
|
||||
${pkgs.iptables}/bin/ip6tables -D INPUT -m set --match-set sshguard6 src -j DROP
|
||||
${pkgs.ipset}/bin/ipset -quiet destroy sshguard6
|
||||
'';
|
||||
@@ -179,11 +176,11 @@ in
|
||||
"-a ${toString cfg.attack_threshold}"
|
||||
"-p ${toString cfg.blocktime}"
|
||||
"-s ${toString cfg.detection_time}"
|
||||
(optionalString (
|
||||
(lib.optionalString (
|
||||
cfg.blacklist_threshold != null
|
||||
) "-b ${toString cfg.blacklist_threshold}:${cfg.blacklist_file}")
|
||||
]
|
||||
++ (map (name: "-w ${escapeShellArg name}") cfg.whitelist)
|
||||
++ (map (name: "-w ${lib.escapeShellArg name}") cfg.whitelist)
|
||||
);
|
||||
in
|
||||
"${pkgs.sshguard}/bin/sshguard ${args}";
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.sslmate-agent;
|
||||
|
||||
@@ -16,11 +13,11 @@ in
|
||||
|
||||
options = {
|
||||
services.sslmate-agent = {
|
||||
enable = mkEnableOption "sslmate-agent, a daemon for managing SSL/TLS certificates on a server";
|
||||
enable = lib.mkEnableOption "sslmate-agent, a daemon for managing SSL/TLS certificates on a server";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = with pkgs; [ sslmate-agent ];
|
||||
|
||||
systemd = {
|
||||
|
||||
@@ -4,23 +4,22 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.tang;
|
||||
in
|
||||
{
|
||||
options.services.tang = {
|
||||
enable = mkEnableOption "tang";
|
||||
enable = lib.mkEnableOption "tang";
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.tang;
|
||||
defaultText = literalExpression "pkgs.tang";
|
||||
defaultText = lib.literalExpression "pkgs.tang";
|
||||
description = "The tang package to use.";
|
||||
};
|
||||
|
||||
listenStream = mkOption {
|
||||
type = with types; listOf str;
|
||||
listenStream = lib.mkOption {
|
||||
type = with lib.types; listOf str;
|
||||
default = [ "7654" ];
|
||||
example = [
|
||||
"198.168.100.1:7654"
|
||||
@@ -33,9 +32,9 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
ipAddressAllow = mkOption {
|
||||
ipAddressAllow = lib.mkOption {
|
||||
example = [ "192.168.1.0/24" ];
|
||||
type = types.listOf types.str;
|
||||
type = lib.types.listOf lib.types.str;
|
||||
description = ''
|
||||
Whitelist a list of address prefixes.
|
||||
Preferably, internal addresses should be used.
|
||||
@@ -43,7 +42,7 @@ in
|
||||
};
|
||||
|
||||
};
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
systemd.services."tangd@" = {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,6 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
|
||||
cfg = config.services.tor;
|
||||
@@ -29,8 +28,8 @@ in
|
||||
|
||||
services.tor.tsocks = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to build tsocks wrapper script to relay application traffic via Tor.
|
||||
@@ -45,8 +44,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
server = mkOption {
|
||||
type = types.str;
|
||||
server = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "localhost:9050";
|
||||
example = "192.168.0.20";
|
||||
description = ''
|
||||
@@ -54,8 +53,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
type = types.lines;
|
||||
config = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra configuration. Contents will be added verbatim to TSocks
|
||||
@@ -69,13 +68,13 @@ in
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.tsocks.enable {
|
||||
config = lib.mkIf cfg.tsocks.enable {
|
||||
|
||||
environment.systemPackages = [ torify ]; # expose it to the users
|
||||
|
||||
services.tor.tsocks.config = ''
|
||||
server = ${toString (head (splitString ":" cfg.tsocks.server))}
|
||||
server_port = ${toString (tail (splitString ":" cfg.tsocks.server))}
|
||||
server = ${toString (lib.head (lib.splitString ":" cfg.tsocks.server))}
|
||||
server_port = ${toString (lib.tail (lib.splitString ":" cfg.tsocks.server))}
|
||||
|
||||
local = 127.0.0.0/255.128.0.0
|
||||
local = 127.128.0.0/255.192.0.0
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.tor.torsocks;
|
||||
optionalNullStr = b: v: optionalString (b != null) v;
|
||||
optionalNullStr = b: v: lib.optionalString (b != null) v;
|
||||
|
||||
configFile = server: ''
|
||||
TorAddress ${toString (head (splitString ":" server))}
|
||||
TorPort ${toString (tail (splitString ":" server))}
|
||||
TorAddress ${toString (lib.head (lib.splitString ":" server))}
|
||||
TorPort ${toString (lib.tail (lib.splitString ":" server))}
|
||||
|
||||
OnionAddrRange ${cfg.onionAddrRange}
|
||||
|
||||
@@ -34,18 +31,18 @@ in
|
||||
{
|
||||
options = {
|
||||
services.tor.torsocks = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = config.services.tor.enable && config.services.tor.client.enable;
|
||||
defaultText = literalExpression "config.services.tor.enable && config.services.tor.client.enable";
|
||||
defaultText = lib.literalExpression "config.services.tor.enable && config.services.tor.client.enable";
|
||||
description = ''
|
||||
Whether to build `/etc/tor/torsocks.conf`
|
||||
containing the specified global torsocks configuration.
|
||||
'';
|
||||
};
|
||||
|
||||
server = mkOption {
|
||||
type = types.str;
|
||||
server = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1:9050";
|
||||
example = "192.168.0.20:1234";
|
||||
description = ''
|
||||
@@ -54,8 +51,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
fasterServer = mkOption {
|
||||
type = types.str;
|
||||
fasterServer = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1:9063";
|
||||
example = "192.168.0.20:1234";
|
||||
description = ''
|
||||
@@ -64,8 +61,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
onionAddrRange = mkOption {
|
||||
type = types.str;
|
||||
onionAddrRange = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.42.42.0/24";
|
||||
description = ''
|
||||
Tor hidden sites do not have real IP addresses. This
|
||||
@@ -77,8 +74,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
socks5Username = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
socks5Username = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "bob";
|
||||
description = ''
|
||||
@@ -87,8 +84,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
socks5Password = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
socks5Password = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "sekret";
|
||||
description = ''
|
||||
@@ -97,8 +94,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
allowInbound = mkOption {
|
||||
type = types.bool;
|
||||
allowInbound = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Set Torsocks to accept inbound connections. If set to
|
||||
@@ -110,7 +107,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ pkgs.torsocks (wrapTorsocks "torsocks-faster" cfg.fasterServer) ];
|
||||
|
||||
environment.etc."tor/torsocks.conf" =
|
||||
|
||||
@@ -4,14 +4,12 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.usbguard;
|
||||
|
||||
# valid policy options
|
||||
policy = (
|
||||
types.enum [
|
||||
lib.types.enum [
|
||||
"allow"
|
||||
"block"
|
||||
"reject"
|
||||
@@ -30,13 +28,13 @@ let
|
||||
PresentDevicePolicy=${cfg.presentDevicePolicy}
|
||||
PresentControllerPolicy=${cfg.presentControllerPolicy}
|
||||
InsertedDevicePolicy=${cfg.insertedDevicePolicy}
|
||||
RestoreControllerDeviceState=${boolToString cfg.restoreControllerDeviceState}
|
||||
RestoreControllerDeviceState=${lib.boolToString cfg.restoreControllerDeviceState}
|
||||
# this does not seem useful for endusers to change
|
||||
DeviceManagerBackend=uevent
|
||||
IPCAllowedUsers=${concatStringsSep " " cfg.IPCAllowedUsers}
|
||||
IPCAllowedGroups=${concatStringsSep " " cfg.IPCAllowedGroups}
|
||||
IPCAllowedUsers=${lib.concatStringsSep " " cfg.IPCAllowedUsers}
|
||||
IPCAllowedGroups=${lib.concatStringsSep " " cfg.IPCAllowedGroups}
|
||||
IPCAccessControlFiles=/var/lib/usbguard/IPCAccessControl.d/
|
||||
DeviceRulesWithPort=${boolToString cfg.deviceRulesWithPort}
|
||||
DeviceRulesWithPort=${lib.boolToString cfg.deviceRulesWithPort}
|
||||
# HACK: that way audit logs still land in the journal
|
||||
AuditFilePath=/dev/null
|
||||
'';
|
||||
@@ -50,16 +48,16 @@ in
|
||||
|
||||
options = {
|
||||
services.usbguard = {
|
||||
enable = mkEnableOption "USBGuard daemon";
|
||||
enable = lib.mkEnableOption "USBGuard daemon";
|
||||
|
||||
package = mkPackageOption pkgs "usbguard" {
|
||||
package = lib.mkPackageOption pkgs "usbguard" {
|
||||
extraDescription = ''
|
||||
If you do not need the Qt GUI, use `pkgs.usbguard-nox` to save disk space.
|
||||
'';
|
||||
};
|
||||
|
||||
ruleFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
ruleFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = "/var/lib/usbguard/rules.conf";
|
||||
example = "/run/secrets/usbguard-rules";
|
||||
description = ''
|
||||
@@ -71,8 +69,8 @@ in
|
||||
'';
|
||||
|
||||
};
|
||||
rules = mkOption {
|
||||
type = types.nullOr types.lines;
|
||||
rules = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.lines;
|
||||
default = null;
|
||||
example = ''
|
||||
allow with-interface equals { 08:*:* }
|
||||
@@ -92,8 +90,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
implicitPolicyTarget = mkOption {
|
||||
type = types.enum [
|
||||
implicitPolicyTarget = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"allow"
|
||||
"block"
|
||||
"reject"
|
||||
@@ -106,7 +104,7 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
presentDevicePolicy = mkOption {
|
||||
presentDevicePolicy = lib.mkOption {
|
||||
type = policy;
|
||||
default = "apply-policy";
|
||||
description = ''
|
||||
@@ -117,7 +115,7 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
presentControllerPolicy = mkOption {
|
||||
presentControllerPolicy = lib.mkOption {
|
||||
type = policy;
|
||||
default = "keep";
|
||||
description = ''
|
||||
@@ -126,8 +124,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
insertedDevicePolicy = mkOption {
|
||||
type = types.enum [
|
||||
insertedDevicePolicy = lib.mkOption {
|
||||
type = lib.types.enum [
|
||||
"block"
|
||||
"reject"
|
||||
"apply-policy"
|
||||
@@ -139,8 +137,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
restoreControllerDeviceState = mkOption {
|
||||
type = types.bool;
|
||||
restoreControllerDeviceState = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
The USBGuard daemon modifies some attributes of controller
|
||||
@@ -151,8 +149,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
IPCAllowedUsers = mkOption {
|
||||
type = types.listOf types.str;
|
||||
IPCAllowedUsers = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ "root" ];
|
||||
example = [
|
||||
"root"
|
||||
@@ -163,8 +161,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
IPCAllowedGroups = mkOption {
|
||||
type = types.listOf types.str;
|
||||
IPCAllowedGroups = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
example = [ "wheel" ];
|
||||
description = ''
|
||||
@@ -173,21 +171,21 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
deviceRulesWithPort = mkOption {
|
||||
type = types.bool;
|
||||
deviceRulesWithPort = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Generate device specific rules including the "via-port" attribute.
|
||||
'';
|
||||
};
|
||||
|
||||
dbus.enable = mkEnableOption "USBGuard dbus daemon";
|
||||
dbus.enable = lib.mkEnableOption "USBGuard dbus daemon";
|
||||
};
|
||||
};
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
@@ -239,7 +237,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
usbguard-dbus = mkIf cfg.dbus.enable {
|
||||
usbguard-dbus = lib.mkIf cfg.dbus.enable {
|
||||
description = "USBGuard D-Bus Service";
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
@@ -261,7 +259,7 @@ in
|
||||
groupCheck =
|
||||
(lib.concatStrings (map (g: "subject.isInGroup(\"${g}\") || ") cfg.IPCAllowedGroups)) + "false";
|
||||
in
|
||||
optionalString cfg.dbus.enable ''
|
||||
lib.optionalString cfg.dbus.enable ''
|
||||
polkit.addRule(function(action, subject) {
|
||||
if ((action.id == "org.usbguard.Policy1.listRules" ||
|
||||
action.id == "org.usbguard.Policy1.appendRule" ||
|
||||
@@ -278,15 +276,15 @@ in
|
||||
'';
|
||||
};
|
||||
imports = [
|
||||
(mkRemovedOptionModule [ "services" "usbguard" "IPCAccessControlFiles" ]
|
||||
(lib.mkRemovedOptionModule [ "services" "usbguard" "IPCAccessControlFiles" ]
|
||||
"The usbguard module now hardcodes IPCAccessControlFiles to /var/lib/usbguard/IPCAccessControl.d."
|
||||
)
|
||||
(mkRemovedOptionModule [
|
||||
(lib.mkRemovedOptionModule [
|
||||
"services"
|
||||
"usbguard"
|
||||
"auditFilePath"
|
||||
] "Removed usbguard module audit log files. Audit logs can be found in the systemd journal.")
|
||||
(mkRenamedOptionModule
|
||||
(lib.mkRenamedOptionModule
|
||||
[ "services" "usbguard" "implictPolicyTarget" ]
|
||||
[ "services" "usbguard" "implicitPolicyTarget" ]
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user