commit
48ee6e1663
@ -0,0 +1,31 @@ |
||||
{ lib, ... }: |
||||
let |
||||
inherit (lib) types; |
||||
in { |
||||
options = { |
||||
name = lib.mkOption { |
||||
type = types.str; |
||||
}; |
||||
email = lib.mkOption { |
||||
type = types.str; |
||||
}; |
||||
matrix = lib.mkOption { |
||||
type = types.nullOr types.str; |
||||
default = null; |
||||
}; |
||||
github = lib.mkOption { |
||||
type = types.nullOr types.str; |
||||
default = null; |
||||
}; |
||||
githubId = lib.mkOption { |
||||
type = types.nullOr types.ints.unsigned; |
||||
default = null; |
||||
}; |
||||
keys = lib.mkOption { |
||||
type = types.listOf (types.submodule { |
||||
options.fingerprint = lib.mkOption { type = types.str; }; |
||||
}); |
||||
default = []; |
||||
}; |
||||
}; |
||||
} |
@ -0,0 +1,50 @@ |
||||
# to run these tests: |
||||
# nix-build nixpkgs/lib/tests/teams.nix |
||||
# If it builds, all tests passed |
||||
{ pkgs ? import ../.. {}, lib ? pkgs.lib }: |
||||
|
||||
let |
||||
inherit (lib) types; |
||||
|
||||
teamModule = { config, ... }: { |
||||
options = { |
||||
shortName = lib.mkOption { |
||||
type = types.str; |
||||
}; |
||||
scope = lib.mkOption { |
||||
type = types.str; |
||||
}; |
||||
enableFeatureFreezePing = lib.mkOption { |
||||
type = types.bool; |
||||
default = false; |
||||
}; |
||||
members = lib.mkOption { |
||||
type = types.listOf (types.submodule |
||||
(import ./maintainer-module.nix { inherit lib; }) |
||||
); |
||||
default = []; |
||||
}; |
||||
githubTeams = lib.mkOption { |
||||
type = types.listOf types.str; |
||||
default = []; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
checkTeam = team: uncheckedAttrs: |
||||
let |
||||
prefix = [ "lib" "maintainer-team" team ]; |
||||
checkedAttrs = (lib.modules.evalModules { |
||||
inherit prefix; |
||||
modules = [ |
||||
teamModule |
||||
{ |
||||
_file = toString ../../maintainers/team-list.nix; |
||||
config = uncheckedAttrs; |
||||
} |
||||
]; |
||||
}).config; |
||||
in checkedAttrs; |
||||
|
||||
checkedTeams = lib.mapAttrs checkTeam lib.teams; |
||||
in pkgs.writeTextDir "maintainer-teams.json" (builtins.toJSON checkedTeams) |
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,63 @@ |
||||
{ evalMinimalConfig, pkgs, lib, stdenv }: |
||||
let |
||||
eval = mod: evalMinimalConfig { |
||||
imports = [ ../nixpkgs.nix mod ]; |
||||
}; |
||||
withHost = eval { |
||||
nixpkgs.hostPlatform = "aarch64-linux"; |
||||
}; |
||||
withHostAndBuild = eval { |
||||
nixpkgs.hostPlatform = "aarch64-linux"; |
||||
nixpkgs.buildPlatform = "aarch64-darwin"; |
||||
}; |
||||
ambiguous = { |
||||
_file = "ambiguous.nix"; |
||||
nixpkgs.hostPlatform = "aarch64-linux"; |
||||
nixpkgs.buildPlatform = "aarch64-darwin"; |
||||
nixpkgs.system = "x86_64-linux"; |
||||
nixpkgs.localSystem.system = "x86_64-darwin"; |
||||
nixpkgs.crossSystem.system = "i686-linux"; |
||||
imports = [ |
||||
{ _file = "repeat.nix"; |
||||
nixpkgs.hostPlatform = "aarch64-linux"; |
||||
} |
||||
]; |
||||
}; |
||||
getErrors = module: |
||||
let |
||||
uncheckedEval = lib.evalModules { modules = [ ../nixpkgs.nix module ]; }; |
||||
in map (ass: ass.message) (lib.filter (ass: !ass.assertion) uncheckedEval.config.assertions); |
||||
in |
||||
lib.recurseIntoAttrs { |
||||
invokeNixpkgsSimple = |
||||
(evalMinimalConfig ({ config, modulesPath, ... }: { |
||||
imports = [ (modulesPath + "/misc/nixpkgs.nix") ]; |
||||
(eval { |
||||
nixpkgs.system = stdenv.hostPlatform.system; |
||||
}))._module.args.pkgs.hello; |
||||
})._module.args.pkgs.hello; |
||||
assertions = |
||||
assert withHost._module.args.pkgs.stdenv.hostPlatform.system == "aarch64-linux"; |
||||
assert withHost._module.args.pkgs.stdenv.buildPlatform.system == "aarch64-linux"; |
||||
assert withHostAndBuild._module.args.pkgs.stdenv.hostPlatform.system == "aarch64-linux"; |
||||
assert withHostAndBuild._module.args.pkgs.stdenv.buildPlatform.system == "aarch64-darwin"; |
||||
assert builtins.trace (lib.head (getErrors ambiguous)) |
||||
getErrors ambiguous == |
||||
['' |
||||
Your system configures nixpkgs with the platform parameters: |
||||
nixpkgs.hostPlatform, with values defined in: |
||||
- repeat.nix |
||||
- ambiguous.nix |
||||
nixpkgs.buildPlatform, with values defined in: |
||||
- ambiguous.nix |
||||
|
||||
However, it also defines the legacy options: |
||||
nixpkgs.system, with values defined in: |
||||
- ambiguous.nix |
||||
nixpkgs.localSystem, with values defined in: |
||||
- ambiguous.nix |
||||
nixpkgs.crossSystem, with values defined in: |
||||
- ambiguous.nix |
||||
|
||||
For a future proof system configuration, we recommend to remove |
||||
the legacy definitions. |
||||
'']; |
||||
pkgs.emptyFile; |
||||
} |
||||
|
@ -1,21 +0,0 @@ |
||||
{ config, lib, pkgs, ... }: |
||||
|
||||
{ |
||||
|
||||
options.programs.clickshare-csc1.enable = |
||||
lib.options.mkEnableOption '' |
||||
Barco ClickShare CSC-1 driver/client. |
||||
This allows users in the <literal>clickshare</literal> |
||||
group to access and use a ClickShare USB dongle |
||||
that is connected to the machine |
||||
''; |
||||
|
||||
config = lib.modules.mkIf config.programs.clickshare-csc1.enable { |
||||
environment.systemPackages = [ pkgs.clickshare-csc1 ]; |
||||
services.udev.packages = [ pkgs.clickshare-csc1 ]; |
||||
users.groups.clickshare = {}; |
||||
}; |
||||
|
||||
meta.maintainers = [ lib.maintainers.yarny ]; |
||||
|
||||
} |
@ -1,162 +0,0 @@ |
||||
{ config, lib, pkgs, ... }: |
||||
|
||||
with lib; |
||||
|
||||
let |
||||
|
||||
cfg = config.services.riak; |
||||
|
||||
in |
||||
|
||||
{ |
||||
|
||||
###### interface |
||||
|
||||
options = { |
||||
|
||||
services.riak = { |
||||
|
||||
enable = mkEnableOption "riak"; |
||||
|
||||
package = mkOption { |
||||
type = types.package; |
||||
default = pkgs.riak; |
||||
defaultText = literalExpression "pkgs.riak"; |
||||
description = '' |
||||
Riak package to use. |
||||
''; |
||||
}; |
||||
|
||||
nodeName = mkOption { |
||||
type = types.str; |
||||
default = "riak@127.0.0.1"; |
||||
description = '' |
||||
Name of the Erlang node. |
||||
''; |
||||
}; |
||||
|
||||
distributedCookie = mkOption { |
||||
type = types.str; |
||||
default = "riak"; |
||||
description = '' |
||||
Cookie for distributed node communication. All nodes in the |
||||
same cluster should use the same cookie or they will not be able to |
||||
communicate. |
||||
''; |
||||
}; |
||||
|
||||
dataDir = mkOption { |
||||
type = types.path; |
||||
default = "/var/db/riak"; |
||||
description = '' |
||||
Data directory for Riak. |
||||
''; |
||||
}; |
||||
|
||||
logDir = mkOption { |
||||
type = types.path; |
||||
default = "/var/log/riak"; |
||||
description = '' |
||||
Log directory for Riak. |
||||
''; |
||||
}; |
||||
|
||||
extraConfig = mkOption { |
||||
type = types.lines; |
||||
default = ""; |
||||
description = '' |
||||
Additional text to be appended to <filename>riak.conf</filename>. |
||||
''; |
||||
}; |
||||
|
||||
extraAdvancedConfig = mkOption { |
||||
type = types.lines; |
||||
default = ""; |
||||
description = '' |
||||
Additional text to be appended to <filename>advanced.config</filename>. |
||||
''; |
||||
}; |
||||
|
||||
}; |
||||
|
||||
}; |
||||
|
||||
###### implementation |
||||
|
||||
config = mkIf cfg.enable { |
||||
|
||||
environment.systemPackages = [ cfg.package ]; |
||||
environment.etc."riak/riak.conf".text = '' |
||||
nodename = ${cfg.nodeName} |
||||
distributed_cookie = ${cfg.distributedCookie} |
||||
|
||||
platform_log_dir = ${cfg.logDir} |
||||
platform_etc_dir = /etc/riak |
||||
platform_data_dir = ${cfg.dataDir} |
||||
|
||||
${cfg.extraConfig} |
||||
''; |
||||
|
||||
environment.etc."riak/advanced.config".text = '' |
||||
${cfg.extraAdvancedConfig} |
||||
''; |
||||
|
||||
users.users.riak = { |
||||
name = "riak"; |
||||
uid = config.ids.uids.riak; |
||||
group = "riak"; |
||||
description = "Riak server user"; |
||||
}; |
||||
|
||||
users.groups.riak.gid = config.ids.gids.riak; |
||||
|
||||
systemd.services.riak = { |
||||
description = "Riak Server"; |
||||
|
||||
wantedBy = [ "multi-user.target" ]; |
||||
after = [ "network.target" ]; |
||||
|
||||
path = [ |
||||
pkgs.util-linux # for `logger` |
||||
pkgs.bash |
||||
]; |
||||
|
||||
environment.HOME = "${cfg.dataDir}"; |
||||
environment.RIAK_DATA_DIR = "${cfg.dataDir}"; |
||||
environment.RIAK_LOG_DIR = "${cfg.logDir}"; |
||||
environment.RIAK_ETC_DIR = "/etc/riak"; |
||||
|
||||
preStart = '' |
||||
if ! test -e ${cfg.logDir}; then |
||||
mkdir -m 0755 -p ${cfg.logDir} |
||||
chown -R riak ${cfg.logDir} |
||||
fi |
||||
|
||||
if ! test -e ${cfg.dataDir}; then |
||||
mkdir -m 0700 -p ${cfg.dataDir} |
||||
chown -R riak ${cfg.dataDir} |
||||
fi |
||||
''; |
||||
|
||||
serviceConfig = { |
||||
ExecStart = "${cfg.package}/bin/riak console"; |
||||
ExecStop = "${cfg.package}/bin/riak stop"; |
||||
StandardInput = "tty"; |
||||
User = "riak"; |
||||
Group = "riak"; |
||||
PermissionsStartOnly = true; |
||||
# Give Riak a decent amount of time to clean up. |
||||
TimeoutStopSec = 120; |
||||
LimitNOFILE = 65536; |
||||
}; |
||||
|
||||
unitConfig.RequiresMountsFor = [ |
||||
"${cfg.dataDir}" |
||||
"${cfg.logDir}" |
||||
"/etc/riak" |
||||
]; |
||||
}; |
||||
|
||||
}; |
||||
|
||||
} |
@ -0,0 +1,58 @@ |
||||
{ config, lib, pkgs, ... }: |
||||
|
||||
let |
||||
cfg = config.services.hardware.argonone; |
||||
in |
||||
{ |
||||
options.services.hardware.argonone = { |
||||
enable = lib.mkEnableOption "the driver for Argon One Raspberry Pi case fan and power button"; |
||||
package = lib.mkOption { |
||||
type = lib.types.package; |
||||
default = pkgs.argononed; |
||||
defaultText = "pkgs.argononed"; |
||||
description = '' |
||||
The package implementing the Argon One driver |
||||
''; |
||||
}; |
||||
}; |
||||
|
||||
config = lib.mkIf cfg.enable { |
||||
hardware.i2c.enable = true; |
||||
hardware.deviceTree.overlays = [ |
||||
{ |
||||
name = "argononed"; |
||||
dtboFile = "${cfg.package}/boot/overlays/argonone.dtbo"; |
||||
} |
||||
{ |
||||
name = "i2c1-okay-overlay"; |
||||
dtsText = '' |
||||
/dts-v1/; |
||||
/plugin/; |
||||
/ { |
||||
compatible = "brcm,bcm2711"; |
||||
fragment@0 { |
||||
target = <&i2c1>; |
||||
__overlay__ { |
||||
status = "okay"; |
||||
}; |
||||
}; |
||||
}; |
||||
''; |
||||
} |
||||
]; |
||||
environment.systemPackages = [ cfg.package ]; |
||||
systemd.services.argononed = { |
||||
description = "Argon One Raspberry Pi case Daemon Service"; |
||||
wantedBy = [ "multi-user.target" ]; |
||||
serviceConfig = { |
||||
Type = "forking"; |
||||
ExecStart = "${cfg.package}/bin/argononed"; |
||||
PIDFile = "/run/argononed.pid"; |
||||
Restart = "on-failure"; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
meta.maintainers = with lib.maintainers; [ misterio77 ]; |
||||
|
||||
} |
@ -0,0 +1,162 @@ |
||||
{ config, pkgs, lib, ... }: |
||||
let |
||||
cfg = config.services.schleuder; |
||||
settingsFormat = pkgs.formats.yaml { }; |
||||
postfixMap = entries: lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: "${name} ${value}") entries); |
||||
writePostfixMap = name: entries: pkgs.writeText name (postfixMap entries); |
||||
configScript = pkgs.writeScript "schleuder-cfg" '' |
||||
#!${pkgs.runtimeShell} |
||||
set -exuo pipefail |
||||
umask 0077 |
||||
${pkgs.yq}/bin/yq \ |
||||
--slurpfile overrides <(${pkgs.yq}/bin/yq . <${lib.escapeShellArg cfg.extraSettingsFile}) \ |
||||
< ${settingsFormat.generate "schleuder.yml" cfg.settings} \ |
||||
'. * $overrides[0]' \ |
||||
> /etc/schleuder/schleuder.yml |
||||
chown schleuder: /etc/schleuder/schleuder.yml |
||||
''; |
||||
in |
||||
{ |
||||
options.services.schleuder = { |
||||
enable = lib.mkEnableOption "Schleuder secure remailer"; |
||||
enablePostfix = lib.mkEnableOption "automatic postfix integration" // { default = true; }; |
||||
lists = lib.mkOption { |
||||
description = '' |
||||
List of list addresses that should be handled by Schleuder. |
||||
|
||||
Note that this is only handled by the postfix integration, and |
||||
the setup of the lists, their members and their keys has to be |
||||
performed separately via schleuder's API, using a tool such as |
||||
schleuder-cli. |
||||
''; |
||||
type = lib.types.listOf lib.types.str; |
||||
default = [ ]; |
||||
example = [ "widget-team@example.com" "security@example.com" ]; |
||||
}; |
||||
/* maybe one day.... |
||||
domains = lib.mkOption { |
||||
description = "Domains for which all mail should be handled by Schleuder."; |
||||
type = lib.types.listOf lib.types.str; |
||||
default = []; |
||||
example = ["securelists.example.com"]; |
||||
}; |
||||
*/ |
||||
settings = lib.mkOption { |
||||
description = '' |
||||
Settings for schleuder.yml. |
||||
|
||||
Check the <link xlink:href="https://0xacab.org/schleuder/schleuder/blob/master/etc/schleuder.yml">example configuration</link> for possible values. |
||||
''; |
||||
type = lib.types.submodule { |
||||
freeformType = settingsFormat.type; |
||||
options.keyserver = lib.mkOption { |
||||
type = lib.types.str; |
||||
description = '' |
||||
Key server from which to fetch and update keys. |
||||
|
||||
Note that NixOS uses a different default from upstream, since the upstream default sks-keyservers.net is deprecated. |
||||
''; |
||||
default = "keys.openpgp.org"; |
||||
}; |
||||
}; |
||||
default = { }; |
||||
}; |
||||
extraSettingsFile = lib.mkOption { |
||||
description = "YAML file to merge into the schleuder config at runtime. This can be used for secrets such as API keys."; |
||||
type = lib.types.nullOr lib.types.path; |
||||
default = null; |
||||
}; |
||||
listDefaults = lib.mkOption { |
||||
description = '' |
||||
Default settings for lists (list-defaults.yml). |
||||
|
||||
Check the <link xlink:href="https://0xacab.org/schleuder/schleuder/-/blob/master/etc/list-defaults.yml">example configuration</link> for possible values. |
||||
''; |
||||
type = settingsFormat.type; |
||||
default = { }; |
||||
}; |
||||
}; |
||||
config = lib.mkIf cfg.enable { |
||||
assertions = [ |
||||
{ |
||||
assertion = !(cfg.settings.api ? valid_api_keys); |
||||
message = '' |
||||
services.schleuder.settings.api.valid_api_keys is set. Defining API keys via NixOS config results in them being copied to the world-readable Nix store. Please use the extraSettingsFile option to store API keys in a non-public location. |
||||
''; |
||||
} |
||||
{ |
||||
assertion = !(lib.any (db: db ? password) (lib.attrValues cfg.settings.database or {})); |
||||
message = '' |
||||
A password is defined for at least one database in services.schleuder.settings.database. Defining passwords via NixOS config results in them being copied to the world-readable Nix store. Please use the extraSettingsFile option to store database passwords in a non-public location. |
||||
''; |
||||
} |
||||
]; |
||||
users.users.schleuder.isSystemUser = true; |
||||
users.users.schleuder.group = "schleuder"; |
||||
users.groups.schleuder = {}; |
||||
environment.systemPackages = [ |
||||
pkgs.schleuder-cli |
||||
]; |
||||
services.postfix = lib.mkIf cfg.enablePostfix { |
||||
extraMasterConf = '' |
||||
schleuder unix - n n - - pipe |
||||
flags=DRhu user=schleuder argv=/${pkgs.schleuder}/bin/schleuder work ''${recipient} |
||||
''; |
||||
transport = lib.mkIf (cfg.lists != [ ]) (postfixMap (lib.genAttrs cfg.lists (_: "schleuder:"))); |
||||
extraConfig = '' |
||||
schleuder_destination_recipient_limit = 1 |
||||
''; |
||||
# review: does this make sense? |
||||
localRecipients = lib.mkIf (cfg.lists != [ ]) cfg.lists; |
||||
}; |
||||
systemd.services = let commonServiceConfig = { |
||||
# We would have liked to use DynamicUser, but since the default |
||||
# database is SQLite and lives in StateDirectory, and that same |
||||
# database needs to be readable from the postfix service, this |
||||
# isn't trivial to do. |
||||
User = "schleuder"; |
||||
StateDirectory = "schleuder"; |
||||
StateDirectoryMode = "0700"; |
||||
}; in |
||||
{ |
||||
schleuder-init = { |
||||
serviceConfig = commonServiceConfig // { |
||||
ExecStartPre = lib.mkIf (cfg.extraSettingsFile != null) [ |
||||
"+${configScript}" |
||||
]; |
||||
ExecStart = [ "${pkgs.schleuder}/bin/schleuder install" ]; |
||||
Type = "oneshot"; |
||||
}; |
||||
}; |
||||
schleuder-api-daemon = { |
||||
after = [ "local-fs.target" "network.target" "schleuder-init.service" ]; |
||||
wantedBy = [ "multi-user.target" ]; |
||||
requires = [ "schleuder-init.service" ]; |
||||
serviceConfig = commonServiceConfig // { |
||||
ExecStart = [ "${pkgs.schleuder}/bin/schleuder-api-daemon" ]; |
||||
}; |
||||
}; |
||||
schleuder-weekly-key-maintenance = { |
||||
after = [ "local-fs.target" "network.target" ]; |
||||
startAt = "weekly"; |
||||
serviceConfig = commonServiceConfig // { |
||||
ExecStart = [ |
||||
"${pkgs.schleuder}/bin/schleuder refresh_keys" |
||||
"${pkgs.schleuder}/bin/schleuder check_keys" |
||||
]; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
environment.etc."schleuder/schleuder.yml" = lib.mkIf (cfg.extraSettingsFile == null) { |
||||
source = settingsFormat.generate "schleuder.yml" cfg.settings; |
||||
}; |
||||
environment.etc."schleuder/list-defaults.yml".source = settingsFormat.generate "list-defaults.yml" cfg.listDefaults; |
||||
|
||||
services.schleuder = { |
||||
#lists_dir = "/var/lib/schleuder.lists"; |
||||
settings.filters_dir = lib.mkDefault "/var/lib/schleuder/filters"; |
||||
settings.keyword_handlers_dir = lib.mkDefault "/var/lib/schleuder/keyword_handlers"; |
||||
}; |
||||
}; |
||||
} |
@ -0,0 +1,84 @@ |
||||
{ config |
||||
, lib |
||||
, pkgs |
||||
, ... |
||||
}: |
||||
|
||||
with lib; |
||||
|
||||
let |
||||
cfg = config.services.routedns; |
||||
settingsFormat = pkgs.formats.toml { }; |
||||
in |
||||
{ |
||||
options.services.routedns = { |
||||
enable = mkEnableOption "RouteDNS - DNS stub resolver, proxy and router"; |
||||
|
||||
settings = mkOption { |
||||
type = settingsFormat.type; |
||||
example = literalExpression '' |
||||
{ |
||||
resolvers.cloudflare-dot = { |
||||
address = "1.1.1.1:853"; |
||||
protocol = "dot"; |
||||
}; |
||||
groups.cloudflare-cached = { |
||||
type = "cache"; |
||||
resolvers = ["cloudflare-dot"]; |
||||
}; |
||||
listeners.local-udp = { |
||||
address = "127.0.0.1:53"; |
||||
protocol = "udp"; |
||||
resolver = "cloudflare-cached"; |
||||
}; |
||||
listeners.local-tcp = { |
||||
address = "127.0.0.1:53"; |
||||
protocol = "tcp"; |
||||
resolver = "cloudflare-cached"; |
||||
}; |
||||
} |
||||
''; |
||||
description = '' |
||||
Configuration for RouteDNS, see <link xlink:href="https://github.com/folbricht/routedns/blob/master/doc/configuration.md"/> |
||||
for more information. |
||||
''; |
||||
}; |
||||
|
||||
configFile = mkOption { |
||||
default = settingsFormat.generate "routedns.toml" cfg.settings; |
||||
defaultText = "A RouteDNS configuration file automatically generated by values from services.routedns.*"; |
||||
type = types.path; |
||||
example = literalExpression ''"''${pkgs.routedns}/cmd/routedns/example-config/use-case-1.toml"''; |
||||
description = "Path to RouteDNS TOML configuration file."; |
||||
}; |
||||
|
||||
package = mkOption { |
||||
default = pkgs.routedns; |
||||
defaultText = literalExpression "pkgs.routedns"; |
||||
type = types.package; |
||||
description = "RouteDNS package to use."; |
||||
}; |
||||
}; |
||||
|
||||
config = mkIf cfg.enable { |
||||
systemd.services.routedns = { |
||||
description = "RouteDNS - DNS stub resolver, proxy and router"; |
||||
after = [ "network.target" ]; # in case a bootstrap resolver is used, this might fail a few times until the respective server is actually reachable |
||||
wantedBy = [ "multi-user.target" ]; |
||||
wants = [ "network.target" ]; |
||||
startLimitIntervalSec = 30; |
||||
startLimitBurst = 5; |
||||
serviceConfig = { |
||||
Restart = "on-failure"; |
||||
RestartSec = "5s"; |
||||
LimitNPROC = 512; |
||||
LimitNOFILE = 1048576; |
||||
DynamicUser = true; |
||||
AmbientCapabilities = "CAP_NET_BIND_SERVICE"; |
||||
NoNewPrivileges = true; |
||||
ExecStart = "${getBin cfg.package}/bin/routedns -l 4 ${cfg.configFile}"; |
||||
}; |
||||
}; |
||||
}; |
||||
meta.maintainers = with maintainers; [ jsimonetti ]; |
||||
} |
@ -1,18 +0,0 @@ |
||||
import ./make-test-python.nix ({ lib, pkgs, ... }: { |
||||
name = "riak"; |
||||
meta = with lib.maintainers; { |
||||
maintainers = [ Br1ght0ne ]; |
||||
}; |
||||
|
||||
nodes.machine = { |
||||
services.riak.enable = true; |
||||
services.riak.package = pkgs.riak; |
||||
}; |
||||
|
||||
testScript = '' |
||||
machine.start() |
||||
|
||||
machine.wait_for_unit("riak") |
||||
machine.wait_until_succeeds("riak ping 2>&1") |
||||
''; |
||||
}) |
@ -0,0 +1,128 @@ |
||||
let |
||||
certs = import ./common/acme/server/snakeoil-certs.nix; |
||||
domain = certs.domain; |
||||
in |
||||
import ./make-test-python.nix { |
||||
name = "schleuder"; |
||||
nodes.machine = { pkgs, ... }: { |
||||
imports = [ ./common/user-account.nix ]; |
||||
services.postfix = { |
||||
enable = true; |
||||
enableSubmission = true; |
||||
tlsTrustedAuthorities = "${certs.ca.cert}"; |
||||
sslCert = "${certs.${domain}.cert}"; |
||||
sslKey = "${certs.${domain}.key}"; |
||||
inherit domain; |
||||
destination = [ domain ]; |
||||
localRecipients = [ "root" "alice" "bob" ]; |
||||
}; |
||||
services.schleuder = { |
||||
enable = true; |
||||
# Don't do it like this in production! The point of this setting |
||||
# is to allow loading secrets from _outside_ the world-readable |
||||
# Nix store. |
||||
extraSettingsFile = pkgs.writeText "schleuder-api-keys.yml" '' |
||||
api: |
||||
valid_api_keys: |
||||
- fnord |
||||
''; |
||||
lists = [ "security@${domain}" ]; |
||||
settings.api = { |
||||
tls_cert_file = "${certs.${domain}.cert}"; |
||||
tls_key_file = "${certs.${domain}.key}"; |
||||
}; |
||||
}; |
||||
|
||||
environment.systemPackages = [ |
||||
pkgs.gnupg |
||||
pkgs.msmtp |
||||
(pkgs.writeScriptBin "do-test" '' |
||||
#!${pkgs.runtimeShell} |
||||
set -exuo pipefail |
||||
|
||||
# Generate a GPG key with no passphrase and export it |
||||
sudo -u alice gpg --passphrase-fd 0 --batch --yes --quick-generate-key 'alice@${domain}' rsa4096 sign,encr < <(echo) |
||||
sudo -u alice gpg --armor --export alice@${domain} > alice.asc |
||||
# Create a new mailing list with alice as the owner, and alice's key |
||||
schleuder-cli list new security@${domain} alice@${domain} alice.asc |
||||
|
||||
# Send an email from a non-member of the list. Use --auto-from so we don't have to specify who it's from twice. |
||||
msmtp --auto-from security@${domain} --host=${domain} --port=25 --tls --tls-starttls <<EOF |
||||
Subject: really big security issue!! |
||||
From: root@${domain} |
||||
|
||||
I found a big security problem! |
||||
EOF |
||||
|
||||
# Wait for delivery |
||||
(set +o pipefail; journalctl -f -n 1000 -u postfix | grep -m 1 'delivered to maildir') |
||||
|
||||
# There should be exactly one email |
||||
mail=(/var/spool/mail/alice/new/*) |
||||
[[ "''${#mail[@]}" = 1 ]] |
||||
|
||||
# Find the fingerprint of the mailing list key |
||||
read list_key_fp address < <(schleuder-cli keys list security@${domain} | grep security@) |
||||
schleuder-cli keys export security@${domain} $list_key_fp > list.asc |
||||
|
||||
# Import the key into alice's keyring, so we can verify it as well as decrypting |
||||
sudo -u alice gpg --import <list.asc |
||||
# And perform the decryption. |
||||
sudo -u alice gpg -d $mail >decrypted |
||||
# And check that the text matches. |
||||
grep "big security problem" decrypted |
||||
'') |
||||
|
||||
# For debugging: |
||||
# pkgs.vim pkgs.openssl pkgs.sqliteinteractive |
||||
]; |
||||
|
||||
security.pki.certificateFiles = [ certs.ca.cert ]; |
||||
|
||||
# Since we don't have internet here, use dnsmasq to provide MX records from /etc/hosts |
||||
services.dnsmasq = { |
||||
enable = true; |
||||
extraConfig = '' |
||||
selfmx |
||||
''; |
||||
}; |
||||
|
||||
networking.extraHosts = '' |
||||
127.0.0.1 ${domain} |
||||
''; |
||||
|
||||
# schleuder-cli's config is not quite optimal in several ways: |
||||
# - A fingerprint _must_ be pinned, it doesn't even have an option |
||||
# to trust the PKI |
||||
# - It compares certificate fingerprints rather than key |
||||
# fingerprints, so renewals break the pin (though that's not |
||||
# relevant for this test) |
||||
# - It compares them as strings, which means we need to match the |
||||
# expected format exactly. This means removing the :s and |
||||
# lowercasing it. |
||||
# Refs: |
||||
# https://0xacab.org/schleuder/schleuder-cli/-/issues/16 |
||||
# https://0xacab.org/schleuder/schleuder-cli/-/blob/f8895b9f47083d8c7b99a2797c93f170f3c6a3c0/lib/schleuder-cli/helper.rb#L230-238 |
||||
systemd.tmpfiles.rules = let cliconfig = pkgs.runCommand "schleuder-cli.yml" |
||||
{ |
||||
nativeBuildInputs = [ pkgs.jq pkgs.openssl ]; |
||||
} '' |
||||
fp=$(openssl x509 -in ${certs.${domain}.cert} -noout -fingerprint -sha256 | cut -d = -f 2 | tr -d : | tr 'A-Z' 'a-z') |
||||
cat > $out <<EOF |
||||
host: localhost |
||||
port: 4443 |
||||
tls_fingerprint: "$fp" |
||||
api_key: fnord |
||||
EOF |
||||
''; in |
||||
[ |
||||
"L+ /root/.schleuder-cli/schleuder-cli.yml - - - - ${cliconfig}" |
||||
]; |
||||
}; |
||||
|
||||
testScript = '' |
||||
machine.wait_for_unit("multi-user.target") |
||||
machine.wait_until_succeeds("nc -z localhost 4443") |
||||
machine.succeed("do-test") |
||||
''; |
||||
} |
@ -0,0 +1,119 @@ |
||||
{ lib |
||||
, stdenv |
||||
, fetchurl |
||||
, autoPatchelfHook |
||||
, dpkg |
||||
, makeWrapper |
||||
, alsa-lib |
||||
, at-spi2-atk |
||||
, at-spi2-core |
||||
, atk |
||||
, cairo |
||||
, cups |
||||
, dbus |
||||
, expat |
||||
, ffmpeg |
||||
, fontconfig |
||||
, freetype |
||||
, gdk-pixbuf |
||||
, glib |
||||
, gtk3 |
||||
, libappindicator-gtk3 |
||||
, libdbusmenu |
||||
, libdrm |
||||
, libnotify |
||||
, libpulseaudio |
||||
, libsecret |
||||
, libuuid |
||||
, libxkbcommon |
||||
, mesa |
||||
, nss |
||||
, pango |
||||
, systemd |
||||
, xdg-utils |
||||
, xorg |
||||
}: |
||||
|
||||
stdenv.mkDerivation rec { |
||||
pname = "tidal-hifi"; |
||||
version = "4.0.1"; |
||||
|
||||
src = fetchurl { |
||||
url = "https://github.com/Mastermindzh/tidal-hifi/releases/download/${version}/tidal-hifi_${version}_amd64.deb"; |
||||
sha256 = "1azxdr2m84ci6ppzy0j17wmza7prlnw055fks6s4i77sjw45rhlq"; |
||||
}; |
||||
|
||||
nativeBuildInputs = [ autoPatchelfHook dpkg makeWrapper ]; |
||||
|
||||
buildInputs = [ |
||||
alsa-lib |
||||
at-spi2-atk |
||||
at-spi2-core |
||||
atk |
||||
cairo |
||||
cups |
||||
dbus |
||||
expat |
||||
ffmpeg |
||||
fontconfig |
||||
freetype |
||||
gdk-pixbuf |
||||
glib |
||||
gtk3 |
||||
pango |
||||
systemd |
||||
mesa # for libgbm |
||||
nss |
||||
libuuid |
||||
libdrm |
||||
libnotify |
||||
libsecret |
||||
libpulseaudio |
||||
libxkbcommon |
||||
libappindicator-gtk3 |
||||
xorg.libX11 |
||||
xorg.libxcb |
||||
xorg.libXcomposite |
||||
xorg.libXcursor |
||||
xorg.libXdamage |
||||
xorg.libXext |
||||
xorg.libXfixes |
||||
xorg.libXi |
||||
xorg.libXrandr |
||||
xorg.libXrender |
||||
xorg.libXScrnSaver |
||||
xorg.libxshmfence |
||||
xorg.libXtst |
||||
]; |
||||
|
||||
runtimeDependencies = |
||||
[ (lib.getLib systemd) libnotify libdbusmenu xdg-utils ]; |
||||
|
||||
unpackPhase = "dpkg-deb -x $src ."; |
||||
|
||||
installPhase = '' |
||||
runHook preInstall |
||||
|
||||
mkdir -p "$out/bin" |
||||
cp -R "opt" "$out" |
||||
cp -R "usr/share" "$out/share" |
||||
chmod -R g-w "$out" |
||||
|
||||
runHook postInstall |
||||
''; |
||||
|
||||
postFixup = '' |
||||
makeWrapper $out/opt/tidal-hifi/tidal-hifi $out/bin/tidal-hifi \ |
||||
--prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath buildInputs}" \ |
||||
"''${gappsWrapperArgs[@]}" |
||||
''; |
||||
|
||||
meta = with lib; { |
||||
description = "The web version of Tidal running in electron with hifi support thanks to widevine"; |
||||
homepage = "https://github.com/Mastermindzh/tidal-hifi"; |
||||
changelog = "https://github.com/Mastermindzh/tidal-hifi/releases/tag/${version}"; |
||||
license = licenses.mit; |
||||
maintainers = with maintainers; [ alternateved ]; |
||||
platforms = [ "x86_64-linux" ]; |
||||
}; |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue