mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-04-14 19:27:53 +00:00
Merge master into haskell-updates
This commit is contained in:
commit
6cdc8ac1f7
@ -533,7 +533,6 @@ writeScript "my-file"
|
||||
Contents of File
|
||||
''
|
||||
```
|
||||
:::
|
||||
|
||||
This is equivalent to:
|
||||
|
||||
@ -546,6 +545,7 @@ writeTextFile {
|
||||
executable = true;
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
### `writeScriptBin` {#trivial-builder-writeScriptBin}
|
||||
|
||||
|
@ -13173,6 +13173,13 @@
|
||||
githubId = 191622;
|
||||
name = "Denys Pavlov";
|
||||
};
|
||||
meator = {
|
||||
email = "meator.dev@gmail.com";
|
||||
github = "meator";
|
||||
githubId = 67633081;
|
||||
name = "meator";
|
||||
keys = [ { fingerprint = "7B0F 58A5 E0F1 A2EA 1157 8A73 1A14 CB34 64CB E5BF"; } ];
|
||||
};
|
||||
meditans = {
|
||||
email = "meditans@gmail.com";
|
||||
github = "meditans";
|
||||
@ -21170,6 +21177,12 @@
|
||||
githubId = 16036882;
|
||||
name = "Thibault Gagnaux";
|
||||
};
|
||||
tri-ler = {
|
||||
github = "tri-ler";
|
||||
githubId = 47867303;
|
||||
email = "tylerh689@gmail.com";
|
||||
name = "Tyler Hong";
|
||||
};
|
||||
trino = {
|
||||
email = "muehlhans.hubert@ekodia.de";
|
||||
github = "hmuehlhans";
|
||||
|
@ -43,6 +43,8 @@
|
||||
|
||||
- [Flood](https://flood.js.org/), a beautiful WebUI for various torrent clients. Available as [services.flood](options.html#opt-services.flood).
|
||||
|
||||
- [Firefly-iii Data Importer](https://github.com/firefly-iii/data-importer), a data importer for Firefly-III. Available as [services.firefly-iii-data-importer](options.html#opt-services.firefly-iii-data-importer)
|
||||
|
||||
- [QGroundControl], a ground station support and configuration manager for the PX4 and APM Flight Stacks. Available as [programs.qgroundcontrol](options.html#opt-programs.qgroundcontrol.enable).
|
||||
|
||||
- [Eintopf](https://eintopf.info), community event and calendar web application. Available as [services.eintopf](options.html#opt-services.eintopf).
|
||||
@ -96,6 +98,10 @@
|
||||
- [chromadb](https://www.trychroma.com/), an open-source AI application
|
||||
database. Batteries included. Available as [services.chromadb](options.html#opt-services.chromadb.enable).
|
||||
|
||||
- [Wakapi](https://wakapi.dev/), a time tracking software for programmers. Available as [services.wakapi](#opt-services.wakapi.enable).
|
||||
|
||||
- [foot](https://codeberg.org/dnkl/foot), a fast, lightweight and minimalistic Wayland terminal emulator. Available as [programs.foot](#opt-programs.foot.enable).
|
||||
|
||||
## Backward Incompatibilities {#sec-release-24.11-incompatibilities}
|
||||
|
||||
- `transmission` package has been aliased with a `trace` warning to `transmission_3`. Since [Transmission 4 has been released last year](https://github.com/transmission/transmission/releases/tag/4.0.0), and Transmission 3 will eventually go away, it was decided perform this warning alias to make people aware of the new version. The `services.transmission.package` defaults to `transmission_3` as well because the upgrade can cause data loss in certain specific usage patterns (examples: [#5153](https://github.com/transmission/transmission/issues/5153), [#6796](https://github.com/transmission/transmission/issues/6796)). Please make sure to back up to your data directory per your usage:
|
||||
@ -399,10 +405,8 @@
|
||||
|
||||
- The hooks `yarnConfigHook` and `yarnBuildHook` were added. These should replace `yarn2nix.mkYarnPackage` and other `yarn2nix` related tools. The motivation to get rid of `yarn2nix` tools is the fact that they are too complex and hard to maintain, and they rely upon too much Nix evaluation which is problematic if import-from-derivation is not allowed (see more details at [#296856](https://github.com/NixOS/nixpkgs/issues/296856). The transition from `mkYarnPackage` to `yarn{Config,Build}Hook` is tracked at [#324246](https://github.com/NixOS/nixpkgs/issues/324246).
|
||||
|
||||
- Cinnamon has been updated to 6.2.
|
||||
- Following Mint 22 defaults, the Cinnamon module no longer ships geary and hexchat by default.
|
||||
- Nemo is now built with gtk-layer-shell support, note that for now it will be expected to see nemo-desktop
|
||||
listed as a regular entry in Cinnamon Wayland session's window list applet.
|
||||
- Cinnamon has been updated to 6.2, please check [upstream announcement](https://www.linuxmint.com/rel_wilma_whatsnew.php) for more details.
|
||||
Following Mint 22 defaults, the Cinnamon module no longer ships geary and hexchat by default.
|
||||
|
||||
- The `shadowstack` hardening flag has been added, though disabled by default.
|
||||
|
||||
|
@ -58,10 +58,18 @@ pkgs.stdenv.mkDerivation {
|
||||
# Make a crude approximation of the size of the target image.
|
||||
# If the script starts failing, increase the fudge factors here.
|
||||
numInodes=$(find ./rootImage | wc -l)
|
||||
numDataBlocks=$(du -s -c -B 4096 --apparent-size ./rootImage | tail -1 | awk '{ print int($1 * 1.10) }')
|
||||
numDataBlocks=$(du -s -c -B 4096 --apparent-size ./rootImage | tail -1 | awk '{ print int($1 * 1.20) }')
|
||||
bytes=$((2 * 4096 * $numInodes + 4096 * $numDataBlocks))
|
||||
echo "Creating an EXT4 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks)"
|
||||
|
||||
mebibyte=$(( 1024 * 1024 ))
|
||||
# Round up to the nearest mebibyte.
|
||||
# This ensures whole 512 bytes sector sizes in the disk image
|
||||
# and helps towards aligning partitions optimally.
|
||||
if (( bytes % mebibyte )); then
|
||||
bytes=$(( ( bytes / mebibyte + 1) * mebibyte ))
|
||||
fi
|
||||
|
||||
truncate -s $bytes $img
|
||||
|
||||
faketime -f "1970-01-01 00:00:01" fakeroot mkfs.ext4 -L ${volumeLabel} -U ${uuid} -d ./rootImage $img
|
||||
|
@ -63,7 +63,7 @@ with lib;
|
||||
# Firefox for reading the manual.
|
||||
firefox
|
||||
|
||||
glxinfo
|
||||
mesa-demos
|
||||
];
|
||||
|
||||
}
|
||||
|
@ -193,6 +193,7 @@
|
||||
./programs/fish.nix
|
||||
./programs/flashrom.nix
|
||||
./programs/flexoptix-app.nix
|
||||
./programs/foot
|
||||
./programs/freetds.nix
|
||||
./programs/fuse.nix
|
||||
./programs/fzf.nix
|
||||
@ -286,6 +287,7 @@
|
||||
./programs/ssh.nix
|
||||
./programs/starship.nix
|
||||
./programs/steam.nix
|
||||
./programs/streamcontroller.nix
|
||||
./programs/streamdeck-ui.nix
|
||||
./programs/sysdig.nix
|
||||
./programs/system-config-printer.nix
|
||||
@ -1401,6 +1403,7 @@
|
||||
./services/web-apps/ethercalc.nix
|
||||
./services/web-apps/filesender.nix
|
||||
./services/web-apps/firefly-iii.nix
|
||||
./services/web-apps/firefly-iii-data-importer.nix
|
||||
./services/web-apps/flarum.nix
|
||||
./services/web-apps/fluidd.nix
|
||||
./services/web-apps/freshrss.nix
|
||||
@ -1489,6 +1492,7 @@
|
||||
./services/web-apps/trilium.nix
|
||||
./services/web-apps/tt-rss.nix
|
||||
./services/web-apps/vikunja.nix
|
||||
./services/web-apps/wakapi.nix
|
||||
./services/web-apps/weblate.nix
|
||||
./services/web-apps/whitebophir.nix
|
||||
./services/web-apps/wiki-js.nix
|
||||
|
@ -17,5 +17,5 @@
|
||||
# Enable sound in virtualbox appliances.
|
||||
hardware.pulseaudio.enable = true;
|
||||
|
||||
environment.systemPackages = [ pkgs.glxinfo pkgs.firefox ];
|
||||
environment.systemPackages = [ pkgs.mesa-demos pkgs.firefox ];
|
||||
}
|
||||
|
27
nixos/modules/programs/foot/bashrc
Normal file
27
nixos/modules/programs/foot/bashrc
Normal file
@ -0,0 +1,27 @@
|
||||
osc7_cwd() {
|
||||
local strlen=${#PWD}
|
||||
local encoded=""
|
||||
local pos c o
|
||||
for (( pos=0; pos<strlen; pos++ )); do
|
||||
c=${PWD:$pos:1}
|
||||
case "$c" in
|
||||
[-/:_.!\'\(\)~[:alnum:]] ) o="${c}" ;;
|
||||
* ) printf -v o '%%%02X' "'${c}" ;;
|
||||
esac
|
||||
encoded+="${o}"
|
||||
done
|
||||
printf '\e]7;file://%s%s\e\\' "${HOSTNAME}" "${encoded}"
|
||||
}
|
||||
PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND; }osc7_cwd
|
||||
|
||||
prompt_marker() {
|
||||
printf '\e]133;A\e\\'
|
||||
}
|
||||
PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND; }prompt_marker
|
||||
|
||||
PS0+='\e]133;C\e\\'
|
||||
|
||||
command_done() {
|
||||
printf '\e]133;D\e\\'
|
||||
}
|
||||
PROMPT_COMMAND=${PROMPT_COMMAND:+$PROMPT_COMMAND; }command_done
|
20
nixos/modules/programs/foot/config.fish
Normal file
20
nixos/modules/programs/foot/config.fish
Normal file
@ -0,0 +1,20 @@
|
||||
function update_cwd_osc --on-variable PWD --description 'Notify terminals when $PWD changes'
|
||||
if status --is-command-substitution || set -q INSIDE_EMACS
|
||||
return
|
||||
end
|
||||
printf \e\]7\;file://%s%s\e\\ $hostname (string escape --style=url $PWD)
|
||||
end
|
||||
|
||||
update_cwd_osc # Run once since we might have inherited PWD from a parent shell
|
||||
|
||||
function mark_prompt_start --on-event fish_prompt
|
||||
echo -en "\e]133;A\e\\"
|
||||
end
|
||||
|
||||
function foot_cmd_start --on-event fish_preexec
|
||||
echo -en "\e]133;C\e\\"
|
||||
end
|
||||
|
||||
function foot_cmd_end --on-event fish_postexec
|
||||
echo -en "\e]133;D\e\\"
|
||||
end
|
92
nixos/modules/programs/foot/default.nix
Normal file
92
nixos/modules/programs/foot/default.nix
Normal file
@ -0,0 +1,92 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.programs.foot;
|
||||
|
||||
settingsFormat = pkgs.formats.ini {
|
||||
listsAsDuplicateKeys = true;
|
||||
mkKeyValue =
|
||||
with lib.generators;
|
||||
mkKeyValueDefault {
|
||||
mkValueString =
|
||||
v:
|
||||
mkValueStringDefault { } (
|
||||
if v == true then
|
||||
"yes"
|
||||
else if v == false then
|
||||
"no"
|
||||
else if v == null then
|
||||
"none"
|
||||
else
|
||||
v
|
||||
);
|
||||
} "=";
|
||||
};
|
||||
in
|
||||
{
|
||||
options.programs.foot = {
|
||||
enable = lib.mkEnableOption "foot terminal emulator";
|
||||
|
||||
package = lib.mkPackageOption pkgs "foot" { };
|
||||
|
||||
settings = lib.mkOption {
|
||||
inherit (settingsFormat) type;
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration for foot terminal emulator. Further information can be found in {command}`man 5 foot.ini`.
|
||||
|
||||
Global configuration has to be written under the [main] section.
|
||||
'';
|
||||
example = {
|
||||
main.font = "FreeMono:size=12";
|
||||
scrollback.lines = 100000;
|
||||
};
|
||||
};
|
||||
|
||||
theme = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
Theme name. Check <https://codeberg.org/dnkl/foot/src/branch/master/themes> for available themes.
|
||||
'';
|
||||
example = "aeroroot";
|
||||
};
|
||||
|
||||
enableBashIntegration = lib.mkEnableOption "foot bash integration" // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
enableFishIntegration = lib.mkEnableOption "foot fish integration" // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
enableZshIntegration = lib.mkEnableOption "foot zsh integration" // {
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment = {
|
||||
systemPackages = [ cfg.package ];
|
||||
etc."xdg/foot/foot.ini".source = settingsFormat.generate "foot.ini" cfg.settings;
|
||||
};
|
||||
programs = {
|
||||
foot.settings.main.include = lib.optionals (cfg.theme != null) [
|
||||
"${pkgs.foot.themes}/share/foot/themes/${cfg.theme}"
|
||||
];
|
||||
# https://codeberg.org/dnkl/foot/wiki#user-content-shell-integration
|
||||
bash.interactiveShellInit = lib.mkIf cfg.enableBashIntegration ". ${./bashrc} # enable shell integration for foot terminal";
|
||||
fish.interactiveShellInit = lib.mkIf cfg.enableFishIntegration "source ${./config.fish} # enable shell integration for foot terminal";
|
||||
zsh.interactiveShellInit = lib.mkIf cfg.enableZshIntegration ". ${./zshrc} # enable shell integration for foot terminal";
|
||||
};
|
||||
};
|
||||
|
||||
meta = {
|
||||
maintainers = with lib.maintainers; [ linsui ];
|
||||
};
|
||||
}
|
25
nixos/modules/programs/foot/zshrc
Normal file
25
nixos/modules/programs/foot/zshrc
Normal file
@ -0,0 +1,25 @@
|
||||
function osc7-pwd() {
|
||||
emulate -L zsh # also sets localoptions for us
|
||||
setopt extendedglob
|
||||
local LC_ALL=C
|
||||
printf '\e]7;file://%s%s\e\' $HOST ${PWD//(#m)([^@-Za-z&-;_~])/%${(l:2::0:)$(([##16]#MATCH))}}
|
||||
}
|
||||
|
||||
function chpwd-osc7-pwd() {
|
||||
(( ZSH_SUBSHELL )) || osc7-pwd
|
||||
}
|
||||
add-zsh-hook -Uz chpwd chpwd-osc7-pwd
|
||||
|
||||
precmd() {
|
||||
print -Pn "\e]133;A\e\\"
|
||||
}
|
||||
|
||||
function precmd {
|
||||
if ! builtin zle; then
|
||||
print -n "\e]133;D\e\\"
|
||||
fi
|
||||
}
|
||||
|
||||
function preexec {
|
||||
print -n "\e]133;C\e\\"
|
||||
}
|
22
nixos/modules/programs/streamcontroller.nix
Normal file
22
nixos/modules/programs/streamcontroller.nix
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.programs.streamcontroller;
|
||||
in
|
||||
{
|
||||
options.programs.streamcontroller = {
|
||||
enable = lib.mkEnableOption "StreamController";
|
||||
package = lib.mkPackageOption pkgs "streamcontroller" { default = [ "streamcontroller" ]; };
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
services.udev.packages = [ cfg.package ];
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ sifmelcara ];
|
||||
}
|
@ -1,7 +1,4 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.postfix;
|
||||
@ -17,32 +14,32 @@ let
|
||||
haveLocalRecipients = cfg.localRecipients != null;
|
||||
|
||||
clientAccess =
|
||||
optional (cfg.dnsBlacklistOverrides != "")
|
||||
lib.optional (cfg.dnsBlacklistOverrides != "")
|
||||
"check_client_access hash:/etc/postfix/client_access";
|
||||
|
||||
dnsBl =
|
||||
optionals (cfg.dnsBlacklists != [])
|
||||
lib.optionals (cfg.dnsBlacklists != [])
|
||||
(map (s: "reject_rbl_client " + s) cfg.dnsBlacklists);
|
||||
|
||||
clientRestrictions = concatStringsSep ", " (clientAccess ++ dnsBl);
|
||||
clientRestrictions = lib.concatStringsSep ", " (clientAccess ++ dnsBl);
|
||||
|
||||
mainCf = let
|
||||
escape = replaceStrings ["$"] ["$$"];
|
||||
mkList = items: "\n " + concatStringsSep ",\n " items;
|
||||
escape = lib.replaceStrings ["$"] ["$$"];
|
||||
mkList = items: "\n " + lib.concatStringsSep ",\n " items;
|
||||
mkVal = value:
|
||||
if isList value then mkList value
|
||||
if lib.isList value then mkList value
|
||||
else " " + (if value == true then "yes"
|
||||
else if value == false then "no"
|
||||
else toString value);
|
||||
mkEntry = name: value: "${escape name} =${mkVal value}";
|
||||
in
|
||||
concatStringsSep "\n" (mapAttrsToList mkEntry cfg.config)
|
||||
lib.concatStringsSep "\n" (lib.mapAttrsToList mkEntry cfg.config)
|
||||
+ "\n" + cfg.extraConfig;
|
||||
|
||||
masterCfOptions = { options, config, name, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = name;
|
||||
example = "smtp";
|
||||
description = ''
|
||||
@ -50,15 +47,15 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
type = mkOption {
|
||||
type = types.enum [ "inet" "unix" "unix-dgram" "fifo" "pass" ];
|
||||
type = lib.mkOption {
|
||||
type = lib.types.enum [ "inet" "unix" "unix-dgram" "fifo" "pass" ];
|
||||
default = "unix";
|
||||
example = "inet";
|
||||
description = "The type of the service";
|
||||
};
|
||||
|
||||
private = mkOption {
|
||||
type = types.bool;
|
||||
private = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
example = false;
|
||||
description = ''
|
||||
Whether the service's sockets and storage directory is restricted to
|
||||
@ -67,14 +64,14 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
privileged = mkOption {
|
||||
type = types.bool;
|
||||
privileged = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
example = true;
|
||||
description = "";
|
||||
};
|
||||
|
||||
chroot = mkOption {
|
||||
type = types.bool;
|
||||
chroot = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
example = true;
|
||||
description = ''
|
||||
Whether the service is chrooted to have only access to the
|
||||
@ -83,8 +80,8 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
wakeup = mkOption {
|
||||
type = types.int;
|
||||
wakeup = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
example = 60;
|
||||
description = ''
|
||||
Automatically wake up the service after the specified number of
|
||||
@ -93,8 +90,8 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
wakeupUnusedComponent = mkOption {
|
||||
type = types.bool;
|
||||
wakeupUnusedComponent = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
example = false;
|
||||
description = ''
|
||||
If set to `false` the component will only be woken
|
||||
@ -104,8 +101,8 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
maxproc = mkOption {
|
||||
type = types.int;
|
||||
maxproc = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
example = 1;
|
||||
description = ''
|
||||
The maximum number of processes to spawn for this service. If the
|
||||
@ -115,8 +112,8 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
command = mkOption {
|
||||
type = types.str;
|
||||
command = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = name;
|
||||
example = "smtpd";
|
||||
description = ''
|
||||
@ -125,8 +122,8 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
args = mkOption {
|
||||
type = types.listOf types.str;
|
||||
args = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
example = [ "-o" "smtp_helo_timeout=5" ];
|
||||
description = ''
|
||||
@ -136,8 +133,8 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
rawEntry = mkOption {
|
||||
type = types.listOf types.str;
|
||||
rawEntry = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
internal = true;
|
||||
description = ''
|
||||
@ -148,7 +145,7 @@ let
|
||||
|
||||
config.rawEntry = let
|
||||
mkBool = bool: if bool then "y" else "n";
|
||||
mkArg = arg: "${optionalString (hasPrefix "-" arg) "\n "}${arg}";
|
||||
mkArg = arg: "${lib.optionalString (lib.hasPrefix "-" arg) "\n "}${arg}";
|
||||
|
||||
maybeOption = fun: option:
|
||||
if options.${option}.isDefined then fun config.${option} else "-";
|
||||
@ -158,7 +155,7 @@ let
|
||||
wakeupDefined = options.wakeup.isDefined;
|
||||
wakeupUCDefined = options.wakeupUnusedComponent.isDefined;
|
||||
finalValue = toString config.wakeup
|
||||
+ optionalString (wakeupUCDefined && !config.wakeupUnusedComponent) "?";
|
||||
+ lib.optionalString (wakeupUCDefined && !config.wakeupUnusedComponent) "?";
|
||||
in if wakeupDefined then finalValue else "-";
|
||||
|
||||
in [
|
||||
@ -169,7 +166,7 @@ let
|
||||
(maybeOption mkBool "chroot")
|
||||
wakeup
|
||||
(maybeOption toString "maxproc")
|
||||
(config.command + " " + concatMapStringsSep " " mkArg config.args)
|
||||
(config.command + " " + lib.concatMapStringsSep " " mkArg config.args)
|
||||
];
|
||||
};
|
||||
|
||||
@ -184,47 +181,47 @@ let
|
||||
"# " "" "(yes)" "(yes)" "(no)" "(never)" "(100)" "" ""
|
||||
];
|
||||
|
||||
masterCf = mapAttrsToList (const (getAttr "rawEntry")) cfg.masterConfig;
|
||||
masterCf = lib.mapAttrsToList (lib.const (lib.getAttr "rawEntry")) cfg.masterConfig;
|
||||
|
||||
# A list of the maximum width of the columns across all lines and labels
|
||||
maxWidths = let
|
||||
foldLine = line: acc: let
|
||||
columnLengths = map stringLength line;
|
||||
in zipListsWith max acc columnLengths;
|
||||
columnLengths = map lib.stringLength line;
|
||||
in lib.zipListsWith lib.max acc columnLengths;
|
||||
# We need to handle the last column specially here, because it's
|
||||
# open-ended (command + args).
|
||||
lines = [ labels labelDefaults ] ++ (map (l: init l ++ [""]) masterCf);
|
||||
in foldr foldLine (genList (const 0) (length labels)) lines;
|
||||
lines = [ labels labelDefaults ] ++ (map (l: lib.init l ++ [""]) masterCf);
|
||||
in lib.foldr foldLine (lib.genList (lib.const 0) (lib.length labels)) lines;
|
||||
|
||||
# Pad a string with spaces from the right (opposite of fixedWidthString).
|
||||
pad = width: str: let
|
||||
padWidth = width - stringLength str;
|
||||
padding = concatStrings (genList (const " ") padWidth);
|
||||
in str + optionalString (padWidth > 0) padding;
|
||||
padWidth = width - lib.stringLength str;
|
||||
padding = lib.concatStrings (lib.genList (lib.const " ") padWidth);
|
||||
in str + lib.optionalString (padWidth > 0) padding;
|
||||
|
||||
# It's + 2 here, because that's the amount of spacing between columns.
|
||||
fullWidth = foldr (width: acc: acc + width + 2) 0 maxWidths;
|
||||
fullWidth = lib.foldr (width: acc: acc + width + 2) 0 maxWidths;
|
||||
|
||||
formatLine = line: concatStringsSep " " (zipListsWith pad maxWidths line);
|
||||
formatLine = line: lib.concatStringsSep " " (lib.zipListsWith pad maxWidths line);
|
||||
|
||||
formattedLabels = let
|
||||
sep = "# " + concatStrings (genList (const "=") (fullWidth + 5));
|
||||
sep = "# " + lib.concatStrings (lib.genList (lib.const "=") (fullWidth + 5));
|
||||
lines = [ sep (formatLine labels) (formatLine labelDefaults) sep ];
|
||||
in concatStringsSep "\n" lines;
|
||||
in lib.concatStringsSep "\n" lines;
|
||||
|
||||
in formattedLabels + "\n" + concatMapStringsSep "\n" formatLine masterCf + "\n" + cfg.extraMasterConf;
|
||||
in formattedLabels + "\n" + lib.concatMapStringsSep "\n" formatLine masterCf + "\n" + cfg.extraMasterConf;
|
||||
|
||||
headerCheckOptions = { ... }:
|
||||
{
|
||||
options = {
|
||||
pattern = mkOption {
|
||||
type = types.str;
|
||||
pattern = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/^.*/";
|
||||
example = "/^X-Mailer:/";
|
||||
description = "A regexp pattern matching the header";
|
||||
};
|
||||
action = mkOption {
|
||||
type = types.str;
|
||||
action = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "DUNNO";
|
||||
example = "BCC mail@example.com";
|
||||
description = "The action to be executed when the pattern is matched";
|
||||
@ -232,13 +229,13 @@ let
|
||||
};
|
||||
};
|
||||
|
||||
headerChecks = concatStringsSep "\n" (map (x: "${x.pattern} ${x.action}") cfg.headerChecks) + cfg.extraHeaderChecks;
|
||||
headerChecks = lib.concatStringsSep "\n" (map (x: "${x.pattern} ${x.action}") cfg.headerChecks) + cfg.extraHeaderChecks;
|
||||
|
||||
aliases = let separator = optionalString (cfg.aliasMapType == "hash") ":"; in
|
||||
optionalString (cfg.postmasterAlias != "") ''
|
||||
aliases = let separator = lib.optionalString (cfg.aliasMapType == "hash") ":"; in
|
||||
lib.optionalString (cfg.postmasterAlias != "") ''
|
||||
postmaster${separator} ${cfg.postmasterAlias}
|
||||
''
|
||||
+ optionalString (cfg.rootAlias != "") ''
|
||||
+ lib.optionalString (cfg.rootAlias != "") ''
|
||||
root${separator} ${cfg.rootAlias}
|
||||
''
|
||||
+ cfg.extraAliases
|
||||
@ -247,7 +244,7 @@ let
|
||||
aliasesFile = pkgs.writeText "postfix-aliases" aliases;
|
||||
canonicalFile = pkgs.writeText "postfix-canonical" cfg.canonical;
|
||||
virtualFile = pkgs.writeText "postfix-virtual" cfg.virtual;
|
||||
localRecipientMapFile = pkgs.writeText "postfix-local-recipient-map" (concatMapStrings (x: x + " ACCEPT\n") cfg.localRecipients);
|
||||
localRecipientMapFile = pkgs.writeText "postfix-local-recipient-map" (lib.concatMapStrings (x: x + " ACCEPT\n") cfg.localRecipients);
|
||||
checkClientAccessFile = pkgs.writeText "postfix-check-client-access" cfg.dnsBlacklistOverrides;
|
||||
mainCfFile = pkgs.writeText "postfix-main.cf" mainCf;
|
||||
masterCfFile = pkgs.writeText "postfix-master.cf" masterCfContent;
|
||||
@ -264,26 +261,26 @@ in
|
||||
|
||||
services.postfix = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether to run the Postfix mail server.";
|
||||
};
|
||||
|
||||
enableSmtp = mkOption {
|
||||
type = types.bool;
|
||||
enableSmtp = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Whether to enable smtp in master.cf.";
|
||||
};
|
||||
|
||||
enableSubmission = mkOption {
|
||||
type = types.bool;
|
||||
enableSubmission = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether to enable smtp submission.";
|
||||
};
|
||||
|
||||
enableSubmissions = mkOption {
|
||||
type = types.bool;
|
||||
enableSubmissions = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable smtp submission via smtps.
|
||||
@ -293,8 +290,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
submissionOptions = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
submissionOptions = lib.mkOption {
|
||||
type = with lib.types; attrsOf str;
|
||||
default = {
|
||||
smtpd_tls_security_level = "encrypt";
|
||||
smtpd_sasl_auth_enable = "yes";
|
||||
@ -311,8 +308,8 @@ in
|
||||
description = "Options for the submission config in master.cf";
|
||||
};
|
||||
|
||||
submissionsOptions = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
submissionsOptions = lib.mkOption {
|
||||
type = with lib.types; attrsOf str;
|
||||
default = {
|
||||
smtpd_sasl_auth_enable = "yes";
|
||||
smtpd_client_restrictions = "permit_sasl_authenticated,reject";
|
||||
@ -334,26 +331,26 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
setSendmail = mkOption {
|
||||
type = types.bool;
|
||||
setSendmail = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Whether to set the system sendmail to postfix's.";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "postfix";
|
||||
description = "What to call the Postfix user (must be used only for postfix).";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "postfix";
|
||||
description = "What to call the Postfix group (must be used only for postfix).";
|
||||
};
|
||||
|
||||
setgidGroup = mkOption {
|
||||
type = types.str;
|
||||
setgidGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "postdrop";
|
||||
description = ''
|
||||
How to call postfix setgid group (for postdrop). Should
|
||||
@ -361,8 +358,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
networks = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
networks = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.listOf lib.types.str);
|
||||
default = null;
|
||||
example = ["192.168.0.1/24"];
|
||||
description = ''
|
||||
@ -372,8 +369,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
networksStyle = mkOption {
|
||||
type = types.str;
|
||||
networksStyle = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Name of standard way of trusted network specification to use,
|
||||
@ -382,8 +379,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
hostname = mkOption {
|
||||
type = types.str;
|
||||
hostname = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Hostname to use. Leave blank to use just the hostname of machine.
|
||||
@ -391,24 +388,24 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
type = types.str;
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Domain to use. Leave blank to use hostname minus first component.
|
||||
'';
|
||||
};
|
||||
|
||||
origin = mkOption {
|
||||
type = types.str;
|
||||
origin = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Origin to use in outgoing e-mail. Leave blank to use hostname.
|
||||
'';
|
||||
};
|
||||
|
||||
destination = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
destination = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.listOf lib.types.str);
|
||||
default = null;
|
||||
example = ["localhost"];
|
||||
description = ''
|
||||
@ -417,8 +414,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
relayDomains = mkOption {
|
||||
type = types.nullOr (types.listOf types.str);
|
||||
relayDomains = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.listOf lib.types.str);
|
||||
default = null;
|
||||
example = ["localdomain"];
|
||||
description = ''
|
||||
@ -426,32 +423,32 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
relayHost = mkOption {
|
||||
type = types.str;
|
||||
relayHost = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Mail relay for outbound mail.
|
||||
'';
|
||||
};
|
||||
|
||||
relayPort = mkOption {
|
||||
type = types.int;
|
||||
relayPort = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 25;
|
||||
description = ''
|
||||
SMTP port for relay mail relay.
|
||||
'';
|
||||
};
|
||||
|
||||
lookupMX = mkOption {
|
||||
type = types.bool;
|
||||
lookupMX = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether relay specified is just domain whose MX must be used.
|
||||
'';
|
||||
};
|
||||
|
||||
postmasterAlias = mkOption {
|
||||
type = types.str;
|
||||
postmasterAlias = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "root";
|
||||
description = ''
|
||||
Who should receive postmaster e-mail. Multiple values can be added by
|
||||
@ -459,8 +456,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
rootAlias = mkOption {
|
||||
type = types.str;
|
||||
rootAlias = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
Who should receive root e-mail. Blank for no redirection.
|
||||
@ -468,23 +465,23 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
extraAliases = mkOption {
|
||||
type = types.lines;
|
||||
extraAliases = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Additional entries to put verbatim into aliases file, cf. man-page aliases(8).
|
||||
'';
|
||||
};
|
||||
|
||||
aliasMapType = mkOption {
|
||||
type = with types; enum [ "hash" "regexp" "pcre" ];
|
||||
aliasMapType = lib.mkOption {
|
||||
type = with lib.types; enum [ "hash" "regexp" "pcre" ];
|
||||
default = "hash";
|
||||
example = "regexp";
|
||||
description = "The format the alias map should have. Use regexp if you want to use regular expressions.";
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
type = with types; attrsOf (oneOf [ bool int str (listOf str) ]);
|
||||
config = lib.mkOption {
|
||||
type = with lib.types; attrsOf (oneOf [ bool int str (listOf str) ]);
|
||||
description = ''
|
||||
The main.cf configuration file as key value set.
|
||||
'';
|
||||
@ -494,37 +491,37 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
extraConfig = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Extra lines to be added verbatim to the main.cf configuration file.
|
||||
'';
|
||||
};
|
||||
|
||||
tlsTrustedAuthorities = mkOption {
|
||||
type = types.str;
|
||||
tlsTrustedAuthorities = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
|
||||
defaultText = literalExpression ''"''${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"'';
|
||||
defaultText = lib.literalExpression ''"''${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"'';
|
||||
description = ''
|
||||
File containing trusted certification authorities (CA) to verify certificates of mailservers contacted for mail delivery. This basically sets smtp_tls_CAfile and enables opportunistic tls. Defaults to NixOS trusted certification authorities.
|
||||
'';
|
||||
};
|
||||
|
||||
sslCert = mkOption {
|
||||
type = types.str;
|
||||
sslCert = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "SSL certificate to use.";
|
||||
};
|
||||
|
||||
sslKey = mkOption {
|
||||
type = types.str;
|
||||
sslKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "SSL key to use.";
|
||||
};
|
||||
|
||||
recipientDelimiter = mkOption {
|
||||
type = types.str;
|
||||
recipientDelimiter = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
example = "+";
|
||||
description = ''
|
||||
@ -532,32 +529,32 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
canonical = mkOption {
|
||||
type = types.lines;
|
||||
canonical = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Entries for the {manpage}`canonical(5)` table.
|
||||
'';
|
||||
};
|
||||
|
||||
virtual = mkOption {
|
||||
type = types.lines;
|
||||
virtual = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Entries for the virtual alias map, cf. man-page virtual(5).
|
||||
'';
|
||||
};
|
||||
|
||||
virtualMapType = mkOption {
|
||||
type = types.enum ["hash" "regexp" "pcre"];
|
||||
virtualMapType = lib.mkOption {
|
||||
type = lib.types.enum ["hash" "regexp" "pcre"];
|
||||
default = "hash";
|
||||
description = ''
|
||||
What type of virtual alias map file to use. Use `"regexp"` for regular expressions.
|
||||
'';
|
||||
};
|
||||
|
||||
localRecipients = mkOption {
|
||||
type = with types; nullOr (listOf str);
|
||||
localRecipients = lib.mkOption {
|
||||
type = with lib.types; nullOr (listOf str);
|
||||
default = null;
|
||||
description = ''
|
||||
List of accepted local users. Specify a bare username, an
|
||||
@ -569,28 +566,28 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
transport = mkOption {
|
||||
transport = lib.mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
type = lib.types.lines;
|
||||
description = ''
|
||||
Entries for the transport map, cf. man-page transport(8).
|
||||
'';
|
||||
};
|
||||
|
||||
dnsBlacklists = mkOption {
|
||||
dnsBlacklists = lib.mkOption {
|
||||
default = [];
|
||||
type = with types; listOf str;
|
||||
type = with lib.types; listOf str;
|
||||
description = "dns blacklist servers to use with smtpd_client_restrictions";
|
||||
};
|
||||
|
||||
dnsBlacklistOverrides = mkOption {
|
||||
dnsBlacklistOverrides = lib.mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
type = lib.types.lines;
|
||||
description = "contents of check_client_access for overriding dnsBlacklists";
|
||||
};
|
||||
|
||||
masterConfig = mkOption {
|
||||
type = types.attrsOf (types.submodule masterCfOptions);
|
||||
masterConfig = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule masterCfOptions);
|
||||
default = {};
|
||||
example =
|
||||
{ submission = {
|
||||
@ -605,48 +602,48 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
extraMasterConf = mkOption {
|
||||
type = types.lines;
|
||||
extraMasterConf = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
example = "submission inet n - n - - smtpd";
|
||||
description = "Extra lines to append to the generated master.cf file.";
|
||||
};
|
||||
|
||||
enableHeaderChecks = mkOption {
|
||||
type = types.bool;
|
||||
enableHeaderChecks = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
example = true;
|
||||
description = "Whether to enable postfix header checks";
|
||||
};
|
||||
|
||||
headerChecks = mkOption {
|
||||
type = types.listOf (types.submodule headerCheckOptions);
|
||||
headerChecks = lib.mkOption {
|
||||
type = lib.types.listOf (lib.types.submodule headerCheckOptions);
|
||||
default = [];
|
||||
example = [ { pattern = "/^X-Spam-Flag:/"; action = "REDIRECT spam@example.com"; } ];
|
||||
description = "Postfix header checks.";
|
||||
};
|
||||
|
||||
extraHeaderChecks = mkOption {
|
||||
type = types.lines;
|
||||
extraHeaderChecks = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
example = "/^X-Spam-Flag:/ REDIRECT spam@example.com";
|
||||
description = "Extra lines to /etc/postfix/header_checks file.";
|
||||
};
|
||||
|
||||
aliasFiles = mkOption {
|
||||
type = types.attrsOf types.path;
|
||||
aliasFiles = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.path;
|
||||
default = {};
|
||||
description = "Aliases' tables to be compiled and placed into /var/lib/postfix/conf.";
|
||||
};
|
||||
|
||||
mapFiles = mkOption {
|
||||
type = types.attrsOf types.path;
|
||||
mapFiles = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.path;
|
||||
default = {};
|
||||
description = "Maps to be compiled and placed into /var/lib/postfix/conf.";
|
||||
};
|
||||
|
||||
useSrs = mkOption {
|
||||
type = types.bool;
|
||||
useSrs = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether to enable sender rewriting scheme";
|
||||
};
|
||||
@ -658,7 +655,7 @@ in
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf config.services.postfix.enable (mkMerge [
|
||||
config = lib.mkIf config.services.postfix.enable (lib.mkMerge [
|
||||
{
|
||||
|
||||
environment = {
|
||||
@ -670,7 +667,7 @@ in
|
||||
|
||||
services.pfix-srsd.enable = config.services.postfix.useSrs;
|
||||
|
||||
services.mail.sendmailSetuidWrapper = mkIf config.services.postfix.setSendmail {
|
||||
services.mail.sendmailSetuidWrapper = lib.mkIf config.services.postfix.setSendmail {
|
||||
program = "sendmail";
|
||||
source = "${pkgs.postfix}/bin/sendmail";
|
||||
owner = "root";
|
||||
@ -706,7 +703,7 @@ in
|
||||
setgid = true;
|
||||
};
|
||||
|
||||
users.users = optionalAttrs (user == "postfix")
|
||||
users.users = lib.optionalAttrs (user == "postfix")
|
||||
{ postfix = {
|
||||
description = "Postfix mail server user";
|
||||
uid = config.ids.uids.postfix;
|
||||
@ -715,10 +712,10 @@ in
|
||||
};
|
||||
|
||||
users.groups =
|
||||
optionalAttrs (group == "postfix")
|
||||
lib.optionalAttrs (group == "postfix")
|
||||
{ ${group}.gid = config.ids.gids.postfix;
|
||||
}
|
||||
// optionalAttrs (setgidGroup == "postdrop")
|
||||
// lib.optionalAttrs (setgidGroup == "postdrop")
|
||||
{ ${setgidGroup}.gid = config.ids.gids.postdrop;
|
||||
};
|
||||
|
||||
@ -745,11 +742,11 @@ in
|
||||
ln -sf ${mainCfFile} /var/lib/postfix/conf/main.cf
|
||||
ln -sf ${masterCfFile} /var/lib/postfix/conf/master.cf
|
||||
|
||||
${concatStringsSep "\n" (mapAttrsToList (to: from: ''
|
||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList (to: from: ''
|
||||
ln -sf ${from} /var/lib/postfix/conf/${to}
|
||||
${pkgs.postfix}/bin/postalias -o -p /var/lib/postfix/conf/${to}
|
||||
'') cfg.aliasFiles)}
|
||||
${concatStringsSep "\n" (mapAttrsToList (to: from: ''
|
||||
${lib.concatStringsSep "\n" (lib.mapAttrsToList (to: from: ''
|
||||
ln -sf ${from} /var/lib/postfix/conf/${to}
|
||||
${pkgs.postfix}/bin/postmap /var/lib/postfix/conf/${to}
|
||||
'') cfg.mapFiles)}
|
||||
@ -795,7 +792,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
services.postfix.config = (mapAttrs (_: v: mkDefault v) {
|
||||
services.postfix.config = (lib.mapAttrs (_: v: lib.mkDefault v) {
|
||||
compatibility_level = pkgs.postfix.version;
|
||||
mail_owner = cfg.user;
|
||||
default_privs = "nobody";
|
||||
@ -819,39 +816,39 @@ in
|
||||
mail_spool_directory = "/var/spool/mail/";
|
||||
setgid_group = cfg.setgidGroup;
|
||||
})
|
||||
// optionalAttrs (cfg.relayHost != "") { relayhost = if cfg.lookupMX
|
||||
// lib.optionalAttrs (cfg.relayHost != "") { relayhost = if cfg.lookupMX
|
||||
then "${cfg.relayHost}:${toString cfg.relayPort}"
|
||||
else "[${cfg.relayHost}]:${toString cfg.relayPort}"; }
|
||||
// optionalAttrs (!config.networking.enableIPv6) { inet_protocols = mkDefault "ipv4"; }
|
||||
// optionalAttrs (cfg.networks != null) { mynetworks = cfg.networks; }
|
||||
// optionalAttrs (cfg.networksStyle != "") { mynetworks_style = cfg.networksStyle; }
|
||||
// optionalAttrs (cfg.hostname != "") { myhostname = cfg.hostname; }
|
||||
// optionalAttrs (cfg.domain != "") { mydomain = cfg.domain; }
|
||||
// optionalAttrs (cfg.origin != "") { myorigin = cfg.origin; }
|
||||
// optionalAttrs (cfg.destination != null) { mydestination = cfg.destination; }
|
||||
// optionalAttrs (cfg.relayDomains != null) { relay_domains = cfg.relayDomains; }
|
||||
// optionalAttrs (cfg.recipientDelimiter != "") { recipient_delimiter = cfg.recipientDelimiter; }
|
||||
// optionalAttrs haveAliases { alias_maps = [ "${cfg.aliasMapType}:/etc/postfix/aliases" ]; }
|
||||
// optionalAttrs haveTransport { transport_maps = [ "hash:/etc/postfix/transport" ]; }
|
||||
// optionalAttrs haveVirtual { virtual_alias_maps = [ "${cfg.virtualMapType}:/etc/postfix/virtual" ]; }
|
||||
// optionalAttrs haveLocalRecipients { local_recipient_maps = [ "hash:/etc/postfix/local_recipients" ] ++ optional haveAliases "$alias_maps"; }
|
||||
// optionalAttrs (cfg.dnsBlacklists != []) { smtpd_client_restrictions = clientRestrictions; }
|
||||
// optionalAttrs cfg.useSrs {
|
||||
// lib.optionalAttrs (!config.networking.enableIPv6) { inet_protocols = lib.mkDefault "ipv4"; }
|
||||
// lib.optionalAttrs (cfg.networks != null) { mynetworks = cfg.networks; }
|
||||
// lib.optionalAttrs (cfg.networksStyle != "") { mynetworks_style = cfg.networksStyle; }
|
||||
// lib.optionalAttrs (cfg.hostname != "") { myhostname = cfg.hostname; }
|
||||
// lib.optionalAttrs (cfg.domain != "") { mydomain = cfg.domain; }
|
||||
// lib.optionalAttrs (cfg.origin != "") { myorigin = cfg.origin; }
|
||||
// lib.optionalAttrs (cfg.destination != null) { mydestination = cfg.destination; }
|
||||
// lib.optionalAttrs (cfg.relayDomains != null) { relay_domains = cfg.relayDomains; }
|
||||
// lib.optionalAttrs (cfg.recipientDelimiter != "") { recipient_delimiter = cfg.recipientDelimiter; }
|
||||
// lib.optionalAttrs haveAliases { alias_maps = [ "${cfg.aliasMapType}:/etc/postfix/aliases" ]; }
|
||||
// lib.optionalAttrs haveTransport { transport_maps = [ "hash:/etc/postfix/transport" ]; }
|
||||
// lib.optionalAttrs haveVirtual { virtual_alias_maps = [ "${cfg.virtualMapType}:/etc/postfix/virtual" ]; }
|
||||
// lib.optionalAttrs haveLocalRecipients { local_recipient_maps = [ "hash:/etc/postfix/local_recipients" ] ++ lib.optional haveAliases "$alias_maps"; }
|
||||
// lib.optionalAttrs (cfg.dnsBlacklists != []) { smtpd_client_restrictions = clientRestrictions; }
|
||||
// lib.optionalAttrs cfg.useSrs {
|
||||
sender_canonical_maps = [ "tcp:127.0.0.1:10001" ];
|
||||
sender_canonical_classes = [ "envelope_sender" ];
|
||||
recipient_canonical_maps = [ "tcp:127.0.0.1:10002" ];
|
||||
recipient_canonical_classes = [ "envelope_recipient" ];
|
||||
}
|
||||
// optionalAttrs cfg.enableHeaderChecks { header_checks = [ "regexp:/etc/postfix/header_checks" ]; }
|
||||
// optionalAttrs (cfg.tlsTrustedAuthorities != "") {
|
||||
// lib.optionalAttrs cfg.enableHeaderChecks { header_checks = [ "regexp:/etc/postfix/header_checks" ]; }
|
||||
// lib.optionalAttrs (cfg.tlsTrustedAuthorities != "") {
|
||||
smtp_tls_CAfile = cfg.tlsTrustedAuthorities;
|
||||
smtp_tls_security_level = mkDefault "may";
|
||||
smtp_tls_security_level = lib.mkDefault "may";
|
||||
}
|
||||
// optionalAttrs (cfg.sslCert != "") {
|
||||
// lib.optionalAttrs (cfg.sslCert != "") {
|
||||
smtp_tls_cert_file = cfg.sslCert;
|
||||
smtp_tls_key_file = cfg.sslKey;
|
||||
|
||||
smtp_tls_security_level = mkDefault "may";
|
||||
smtp_tls_security_level = lib.mkDefault "may";
|
||||
|
||||
smtpd_tls_cert_file = cfg.sslCert;
|
||||
smtpd_tls_key_file = cfg.sslKey;
|
||||
@ -931,16 +928,16 @@ in
|
||||
scache = {
|
||||
maxproc = 1;
|
||||
};
|
||||
} // optionalAttrs cfg.enableSubmission {
|
||||
} // lib.optionalAttrs cfg.enableSubmission {
|
||||
submission = {
|
||||
type = "inet";
|
||||
private = false;
|
||||
command = "smtpd";
|
||||
args = let
|
||||
mkKeyVal = opt: val: [ "-o" (opt + "=" + val) ];
|
||||
in concatLists (mapAttrsToList mkKeyVal cfg.submissionOptions);
|
||||
in lib.concatLists (lib.mapAttrsToList mkKeyVal cfg.submissionOptions);
|
||||
};
|
||||
} // optionalAttrs cfg.enableSmtp {
|
||||
} // lib.optionalAttrs cfg.enableSmtp {
|
||||
smtp_inet = {
|
||||
name = "smtp";
|
||||
type = "inet";
|
||||
@ -952,7 +949,7 @@ in
|
||||
command = "smtp";
|
||||
args = [ "-o" "smtp_fallback_relay=" ];
|
||||
};
|
||||
} // optionalAttrs cfg.enableSubmissions {
|
||||
} // lib.optionalAttrs cfg.enableSubmissions {
|
||||
submissions = {
|
||||
type = "inet";
|
||||
private = false;
|
||||
@ -964,43 +961,43 @@ in
|
||||
cfg.submissionsOptions.smtpd_tls_security_level == "may";
|
||||
submissionsOptions = cfg.submissionsOptions // {
|
||||
smtpd_tls_wrappermode = "yes";
|
||||
} // optionalAttrs adjustSmtpTlsSecurityLevel {
|
||||
} // lib.optionalAttrs adjustSmtpTlsSecurityLevel {
|
||||
smtpd_tls_security_level = "encrypt";
|
||||
};
|
||||
in concatLists (mapAttrsToList mkKeyVal submissionsOptions);
|
||||
in lib.concatLists (lib.mapAttrsToList mkKeyVal submissionsOptions);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
(mkIf haveAliases {
|
||||
(lib.mkIf haveAliases {
|
||||
services.postfix.aliasFiles.aliases = aliasesFile;
|
||||
})
|
||||
(mkIf haveCanonical {
|
||||
(lib.mkIf haveCanonical {
|
||||
services.postfix.mapFiles.canonical = canonicalFile;
|
||||
})
|
||||
(mkIf haveTransport {
|
||||
(lib.mkIf haveTransport {
|
||||
services.postfix.mapFiles.transport = transportFile;
|
||||
})
|
||||
(mkIf haveVirtual {
|
||||
(lib.mkIf haveVirtual {
|
||||
services.postfix.mapFiles.virtual = virtualFile;
|
||||
})
|
||||
(mkIf haveLocalRecipients {
|
||||
(lib.mkIf haveLocalRecipients {
|
||||
services.postfix.mapFiles.local_recipients = localRecipientMapFile;
|
||||
})
|
||||
(mkIf cfg.enableHeaderChecks {
|
||||
(lib.mkIf cfg.enableHeaderChecks {
|
||||
services.postfix.mapFiles.header_checks = headerChecksFile;
|
||||
})
|
||||
(mkIf (cfg.dnsBlacklists != []) {
|
||||
(lib.mkIf (cfg.dnsBlacklists != []) {
|
||||
services.postfix.mapFiles.client_access = checkClientAccessFile;
|
||||
})
|
||||
]);
|
||||
|
||||
imports = [
|
||||
(mkRemovedOptionModule [ "services" "postfix" "sslCACert" ]
|
||||
(lib.mkRemovedOptionModule [ "services" "postfix" "sslCACert" ]
|
||||
"services.postfix.sslCACert was replaced by services.postfix.tlsTrustedAuthorities. In case you intend that your server should validate requested client certificates use services.postfix.extraConfig.")
|
||||
|
||||
(mkChangedOptionModule [ "services" "postfix" "useDane" ]
|
||||
(lib.mkChangedOptionModule [ "services" "postfix" "useDane" ]
|
||||
[ "services" "postfix" "config" "smtp_tls_security_level" ]
|
||||
(config: mkIf config.services.postfix.useDane "dane"))
|
||||
(config: lib.mkIf config.services.postfix.useDane "dane"))
|
||||
];
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.sympa;
|
||||
dataDir = "/var/lib/sympa";
|
||||
user = "sympa";
|
||||
group = "sympa";
|
||||
pkg = pkgs.sympa;
|
||||
fqdns = attrNames cfg.domains;
|
||||
fqdns = lib.attrNames cfg.domains;
|
||||
usingNginx = cfg.web.enable && cfg.web.server == "nginx";
|
||||
mysqlLocal = cfg.database.createLocally && cfg.database.type == "MySQL";
|
||||
pgsqlLocal = cfg.database.createLocally && cfg.database.type == "PostgreSQL";
|
||||
@ -42,15 +39,15 @@ let
|
||||
} // commonServiceConfig;
|
||||
|
||||
configVal = value:
|
||||
if isBool value then
|
||||
if lib.isBool value then
|
||||
if value then "on" else "off"
|
||||
else toString value;
|
||||
configGenerator = c: concatStrings (flip mapAttrsToList c (key: val: "${key}\t${configVal val}\n"));
|
||||
configGenerator = c: lib.concatStrings (lib.flip lib.mapAttrsToList c (key: val: "${key}\t${configVal val}\n"));
|
||||
|
||||
mainConfig = pkgs.writeText "sympa.conf" (configGenerator cfg.settings);
|
||||
robotConfig = fqdn: domain: pkgs.writeText "${fqdn}-robot.conf" (configGenerator domain.settings);
|
||||
|
||||
transport = pkgs.writeText "transport.sympa" (concatStringsSep "\n" (flip map fqdns (domain: ''
|
||||
transport = pkgs.writeText "transport.sympa" (lib.concatStringsSep "\n" (lib.flip map fqdns (domain: ''
|
||||
${domain} error:User unknown in recipient table
|
||||
sympa@${domain} sympa:sympa@${domain}
|
||||
listmaster@${domain} sympa:listmaster@${domain}
|
||||
@ -58,7 +55,7 @@ let
|
||||
abuse-feedback-report@${domain} sympabounce:sympa@${domain}
|
||||
'')));
|
||||
|
||||
virtual = pkgs.writeText "virtual.sympa" (concatStringsSep "\n" (flip map fqdns (domain: ''
|
||||
virtual = pkgs.writeText "virtual.sympa" (lib.concatStringsSep "\n" (lib.flip map fqdns (domain: ''
|
||||
sympa-request@${domain} postmaster@localhost
|
||||
sympa-owner@${domain} postmaster@localhost
|
||||
'')));
|
||||
@ -73,16 +70,16 @@ let
|
||||
[% list.name %][% return_path_suffix %]@[% list.domain %] sympabounce:[% list.name %]@[% list.domain %]
|
||||
'';
|
||||
|
||||
enabledFiles = filterAttrs (n: v: v.enable) cfg.settingsFile;
|
||||
enabledFiles = lib.filterAttrs (n: v: v.enable) cfg.settingsFile;
|
||||
in
|
||||
{
|
||||
|
||||
###### interface
|
||||
options.services.sympa = with types; {
|
||||
options.services.sympa = with lib.types; {
|
||||
|
||||
enable = mkEnableOption "Sympa mailing list manager";
|
||||
enable = lib.mkEnableOption "Sympa mailing list manager";
|
||||
|
||||
lang = mkOption {
|
||||
lang = lib.mkOption {
|
||||
type = str;
|
||||
default = "en_US";
|
||||
example = "cs";
|
||||
@ -93,7 +90,7 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
listMasters = mkOption {
|
||||
listMasters = lib.mkOption {
|
||||
type = listOf str;
|
||||
example = [ "postmaster@sympa.example.org" ];
|
||||
description = ''
|
||||
@ -102,7 +99,7 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
mainDomain = mkOption {
|
||||
mainDomain = lib.mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
example = "lists.example.org";
|
||||
@ -112,10 +109,10 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
domains = mkOption {
|
||||
domains = lib.mkOption {
|
||||
type = attrsOf (submodule ({ name, config, ... }: {
|
||||
options = {
|
||||
webHost = mkOption {
|
||||
webHost = lib.mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
example = "archive.example.org";
|
||||
@ -124,13 +121,13 @@ in
|
||||
DNS record of type A (or AAAA or CNAME) has to exist with this value.
|
||||
'';
|
||||
};
|
||||
webLocation = mkOption {
|
||||
webLocation = lib.mkOption {
|
||||
type = str;
|
||||
default = "/";
|
||||
example = "/sympa";
|
||||
description = "URL path part of the web interface.";
|
||||
};
|
||||
settings = mkOption {
|
||||
settings = lib.mkOption {
|
||||
type = attrsOf (oneOf [ str int bool ]);
|
||||
default = {};
|
||||
example = {
|
||||
@ -144,8 +141,8 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
config.settings = mkIf (cfg.web.enable && config.webHost != null) {
|
||||
wwsympa_url = mkDefault "https://${config.webHost}${strings.removeSuffix "/" config.webLocation}";
|
||||
config.settings = lib.mkIf (cfg.web.enable && config.webHost != null) {
|
||||
wwsympa_url = lib.mkDefault "https://${config.webHost}${lib.removeSuffix "/" config.webLocation}";
|
||||
};
|
||||
}));
|
||||
|
||||
@ -153,7 +150,7 @@ in
|
||||
Email domains handled by this instance. There have
|
||||
to be MX records for keys of this attribute set.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
"lists.example.org" = {
|
||||
webHost = "lists.example.org";
|
||||
@ -168,14 +165,14 @@ in
|
||||
};
|
||||
|
||||
database = {
|
||||
type = mkOption {
|
||||
type = lib.mkOption {
|
||||
type = enum [ "SQLite" "PostgreSQL" "MySQL" ];
|
||||
default = "SQLite";
|
||||
example = "MySQL";
|
||||
description = "Database engine to use.";
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
host = lib.mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
@ -191,29 +188,29 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
port = lib.mkOption {
|
||||
type = nullOr port;
|
||||
default = null;
|
||||
description = "Database port. Use `null` for default port.";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
name = lib.mkOption {
|
||||
type = str;
|
||||
default = if cfg.database.type == "SQLite" then "${dataDir}/sympa.sqlite" else "sympa";
|
||||
defaultText = literalExpression ''if database.type == "SQLite" then "${dataDir}/sympa.sqlite" else "sympa"'';
|
||||
defaultText = lib.literalExpression ''if database.type == "SQLite" then "${dataDir}/sympa.sqlite" else "sympa"'';
|
||||
description = ''
|
||||
Database name. When using SQLite this must be an absolute
|
||||
path to the database file.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
user = lib.mkOption {
|
||||
type = nullOr str;
|
||||
default = user;
|
||||
description = "Database user. The system user name is used as a default.";
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
passwordFile = lib.mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
example = "/run/keys/sympa-dbpassword";
|
||||
@ -222,7 +219,7 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
createLocally = mkOption {
|
||||
createLocally = lib.mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
description = "Whether to create a local database automatically.";
|
||||
@ -230,13 +227,13 @@ in
|
||||
};
|
||||
|
||||
web = {
|
||||
enable = mkOption {
|
||||
enable = lib.mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
description = "Whether to enable Sympa web interface.";
|
||||
};
|
||||
|
||||
server = mkOption {
|
||||
server = lib.mkOption {
|
||||
type = enum [ "nginx" "none" ];
|
||||
default = "nginx";
|
||||
description = ''
|
||||
@ -246,7 +243,7 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
https = mkOption {
|
||||
https = lib.mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
description = ''
|
||||
@ -255,7 +252,7 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
fcgiProcs = mkOption {
|
||||
fcgiProcs = lib.mkOption {
|
||||
type = ints.positive;
|
||||
default = 2;
|
||||
description = "Number of FastCGI processes to fork.";
|
||||
@ -263,7 +260,7 @@ in
|
||||
};
|
||||
|
||||
mta = {
|
||||
type = mkOption {
|
||||
type = lib.mkOption {
|
||||
type = enum [ "postfix" "none" ];
|
||||
default = "postfix";
|
||||
description = ''
|
||||
@ -276,10 +273,10 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
settings = lib.mkOption {
|
||||
type = attrsOf (oneOf [ str int bool ]);
|
||||
default = {};
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
default_home = "lists";
|
||||
viewlogs_page_size = 50;
|
||||
@ -292,29 +289,29 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
settingsFile = mkOption {
|
||||
settingsFile = lib.mkOption {
|
||||
type = attrsOf (submodule ({ name, config, ... }: {
|
||||
options = {
|
||||
enable = mkOption {
|
||||
enable = lib.mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
description = "Whether this file should be generated. This option allows specific files to be disabled.";
|
||||
};
|
||||
text = mkOption {
|
||||
text = lib.mkOption {
|
||||
default = null;
|
||||
type = nullOr lines;
|
||||
description = "Text of the file.";
|
||||
};
|
||||
source = mkOption {
|
||||
source = lib.mkOption {
|
||||
type = path;
|
||||
description = "Path of the source file.";
|
||||
};
|
||||
};
|
||||
|
||||
config.source = mkIf (config.text != null) (mkDefault (pkgs.writeText "sympa-${baseNameOf name}" config.text));
|
||||
config.source = lib.mkIf (config.text != null) (lib.mkDefault (pkgs.writeText "sympa-${baseNameOf name}" config.text));
|
||||
}));
|
||||
default = {};
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
"list_data/lists.example.org/help" = {
|
||||
text = "subject This list provides help to users";
|
||||
@ -327,11 +324,11 @@ in
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
services.sympa.settings = (mapAttrs (_: v: mkDefault v) {
|
||||
domain = if cfg.mainDomain != null then cfg.mainDomain else head fqdns;
|
||||
listmaster = concatStringsSep "," cfg.listMasters;
|
||||
services.sympa.settings = (lib.mapAttrs (_: v: lib.mkDefault v) {
|
||||
domain = if cfg.mainDomain != null then cfg.mainDomain else lib.head fqdns;
|
||||
listmaster = lib.concatStringsSep "," cfg.listMasters;
|
||||
lang = cfg.lang;
|
||||
|
||||
home = "${dataDir}/list_data";
|
||||
@ -344,24 +341,24 @@ in
|
||||
db_name = cfg.database.name;
|
||||
db_user = cfg.database.name;
|
||||
}
|
||||
// (optionalAttrs (cfg.database.host != null) {
|
||||
// (lib.optionalAttrs (cfg.database.host != null) {
|
||||
db_host = cfg.database.host;
|
||||
})
|
||||
// (optionalAttrs mysqlLocal {
|
||||
// (lib.optionalAttrs mysqlLocal {
|
||||
db_host = "localhost"; # use unix domain socket
|
||||
})
|
||||
// (optionalAttrs pgsqlLocal {
|
||||
// (lib.optionalAttrs pgsqlLocal {
|
||||
db_host = "/run/postgresql"; # use unix domain socket
|
||||
})
|
||||
// (optionalAttrs (cfg.database.port != null) {
|
||||
// (lib.optionalAttrs (cfg.database.port != null) {
|
||||
db_port = cfg.database.port;
|
||||
})
|
||||
// (optionalAttrs (cfg.mta.type == "postfix") {
|
||||
// (lib.optionalAttrs (cfg.mta.type == "postfix") {
|
||||
sendmail_aliases = "${dataDir}/sympa_transport";
|
||||
aliases_program = "${pkgs.postfix}/bin/postmap";
|
||||
aliases_db_type = "hash";
|
||||
})
|
||||
// (optionalAttrs cfg.web.enable {
|
||||
// (lib.optionalAttrs cfg.web.enable {
|
||||
static_content_path = "${dataDir}/static_content";
|
||||
css_path = "${dataDir}/static_content/css";
|
||||
pictures_path = "${dataDir}/static_content/pictures";
|
||||
@ -369,12 +366,12 @@ in
|
||||
}));
|
||||
|
||||
services.sympa.settingsFile = {
|
||||
"virtual.sympa" = mkDefault { source = virtual; };
|
||||
"transport.sympa" = mkDefault { source = transport; };
|
||||
"etc/list_aliases.tt2" = mkDefault { source = listAliases; };
|
||||
"virtual.sympa" = lib.mkDefault { source = virtual; };
|
||||
"transport.sympa" = lib.mkDefault { source = transport; };
|
||||
"etc/list_aliases.tt2" = lib.mkDefault { source = listAliases; };
|
||||
}
|
||||
// (flip mapAttrs' cfg.domains (fqdn: domain:
|
||||
nameValuePair "etc/${fqdn}/robot.conf" (mkDefault { source = robotConfig fqdn domain; })));
|
||||
// (lib.flip lib.mapAttrs' cfg.domains (fqdn: domain:
|
||||
lib.nameValuePair "etc/${fqdn}/robot.conf" (lib.mkDefault { source = robotConfig fqdn domain; })));
|
||||
|
||||
environment = {
|
||||
systemPackages = [ pkg ];
|
||||
@ -416,14 +413,14 @@ in
|
||||
|
||||
"d /run/sympa 0755 ${user} ${group} - -"
|
||||
]
|
||||
++ (flip concatMap fqdns (fqdn: [
|
||||
++ (lib.flip lib.concatMap fqdns (fqdn: [
|
||||
"d ${dataDir}/etc/${fqdn} 0700 ${user} ${group} - -"
|
||||
"d ${dataDir}/list_data/${fqdn} 0700 ${user} ${group} - -"
|
||||
]))
|
||||
#++ (flip mapAttrsToList enabledFiles (k: v:
|
||||
#++ (lib.flip lib.mapAttrsToList enabledFiles (k: v:
|
||||
# "L+ ${dataDir}/${k} - - - - ${v.source}"
|
||||
#))
|
||||
++ (concatLists (flip mapAttrsToList enabledFiles (k: v: [
|
||||
++ (lib.concatLists (lib.flip lib.mapAttrsToList enabledFiles (k: v: [
|
||||
# sympa doesn't handle symlinks well (e.g. fails to create locks)
|
||||
# force-copy instead
|
||||
"R ${dataDir}/${k} - - - - -"
|
||||
@ -443,13 +440,13 @@ in
|
||||
umask 0077
|
||||
|
||||
cp -f ${mainConfig} ${dataDir}/etc/sympa.conf
|
||||
${optionalString (cfg.database.passwordFile != null) ''
|
||||
${lib.optionalString (cfg.database.passwordFile != null) ''
|
||||
chmod u+w ${dataDir}/etc/sympa.conf
|
||||
echo -n "db_passwd " >> ${dataDir}/etc/sympa.conf
|
||||
cat ${cfg.database.passwordFile} >> ${dataDir}/etc/sympa.conf
|
||||
''}
|
||||
|
||||
${optionalString (cfg.mta.type == "postfix") ''
|
||||
${lib.optionalString (cfg.mta.type == "postfix") ''
|
||||
${pkgs.postfix}/bin/postmap hash:${dataDir}/virtual.sympa
|
||||
${pkgs.postfix}/bin/postmap hash:${dataDir}/transport.sympa
|
||||
''}
|
||||
@ -478,7 +475,7 @@ in
|
||||
serviceConfig = sympaServiceConfig "task_manager";
|
||||
};
|
||||
|
||||
systemd.services.wwsympa = mkIf usingNginx {
|
||||
systemd.services.wwsympa = lib.mkIf usingNginx {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "sympa.service" ];
|
||||
serviceConfig = {
|
||||
@ -499,14 +496,14 @@ in
|
||||
} // commonServiceConfig;
|
||||
};
|
||||
|
||||
services.nginx.enable = mkIf usingNginx true;
|
||||
services.nginx.virtualHosts = mkIf usingNginx (let
|
||||
vHosts = unique (remove null (mapAttrsToList (_k: v: v.webHost) cfg.domains));
|
||||
hostLocations = host: map (v: v.webLocation) (filter (v: v.webHost == host) (attrValues cfg.domains));
|
||||
httpsOpts = optionalAttrs cfg.web.https { forceSSL = mkDefault true; enableACME = mkDefault true; };
|
||||
services.nginx.enable = lib.mkIf usingNginx true;
|
||||
services.nginx.virtualHosts = lib.mkIf usingNginx (let
|
||||
vHosts = lib.unique (lib.remove null (lib.mapAttrsToList (_k: v: v.webHost) cfg.domains));
|
||||
hostLocations = host: map (v: v.webLocation) (lib.filter (v: v.webHost == host) (lib.attrValues cfg.domains));
|
||||
httpsOpts = lib.optionalAttrs cfg.web.https { forceSSL = lib.mkDefault true; enableACME = lib.mkDefault true; };
|
||||
in
|
||||
genAttrs vHosts (host: {
|
||||
locations = genAttrs (hostLocations host) (loc: {
|
||||
lib.genAttrs vHosts (host: {
|
||||
locations = lib.genAttrs (hostLocations host) (loc: {
|
||||
extraConfig = ''
|
||||
include ${config.services.nginx.package}/conf/fastcgi_params;
|
||||
|
||||
@ -517,7 +514,7 @@ in
|
||||
};
|
||||
} // httpsOpts));
|
||||
|
||||
services.postfix = mkIf (cfg.mta.type == "postfix") {
|
||||
services.postfix = lib.mkIf (cfg.mta.type == "postfix") {
|
||||
enable = true;
|
||||
recipientDelimiter = "+";
|
||||
config = {
|
||||
@ -561,9 +558,9 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
services.mysql = optionalAttrs mysqlLocal {
|
||||
services.mysql = lib.optionalAttrs mysqlLocal {
|
||||
enable = true;
|
||||
package = mkDefault pkgs.mariadb;
|
||||
package = lib.mkDefault pkgs.mariadb;
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
ensureUsers = [
|
||||
{ name = cfg.database.user;
|
||||
@ -572,7 +569,7 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
services.postgresql = optionalAttrs pgsqlLocal {
|
||||
services.postgresql = lib.optionalAttrs pgsqlLocal {
|
||||
enable = true;
|
||||
ensureDatabases = [ cfg.database.name ];
|
||||
ensureUsers = [
|
||||
@ -584,5 +581,5 @@ in
|
||||
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ mmilata sorki ];
|
||||
meta.maintainers = with lib.maintainers; [ mmilata sorki ];
|
||||
}
|
||||
|
@ -1,32 +1,29 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.services.autorandr;
|
||||
hookType = types.lines;
|
||||
hookType = lib.types.lines;
|
||||
|
||||
matrixOf = n: m: elemType:
|
||||
mkOptionType rec {
|
||||
lib.mkOptionType rec {
|
||||
name = "matrixOf";
|
||||
description =
|
||||
"${toString n}×${toString m} matrix of ${elemType.description}s";
|
||||
check = xss:
|
||||
let listOfSize = l: xs: isList xs && length xs == l;
|
||||
let listOfSize = l: xs: lib.isList xs && lib.length xs == l;
|
||||
in listOfSize n xss
|
||||
&& all (xs: listOfSize m xs && all elemType.check xs) xss;
|
||||
merge = mergeOneOption;
|
||||
&& lib.all (xs: listOfSize m xs && lib.all elemType.check xs) xss;
|
||||
merge = lib.mergeOneOption;
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "*" "*" ]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = mod: matrixOf n m (elemType.substSubModules mod);
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
functor = (lib.defaultFunctor name) // { wrapped = elemType; };
|
||||
};
|
||||
|
||||
profileModule = types.submodule {
|
||||
profileModule = lib.types.submodule {
|
||||
options = {
|
||||
fingerprint = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
fingerprint = lib.mkOption {
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
description = ''
|
||||
Output name to EDID mapping.
|
||||
Use `autorandr --fingerprint` to get current setup values.
|
||||
@ -34,13 +31,13 @@ let
|
||||
default = { };
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
type = types.attrsOf configModule;
|
||||
config = lib.mkOption {
|
||||
type = lib.types.attrsOf configModule;
|
||||
description = "Per output profile configuration.";
|
||||
default = { };
|
||||
};
|
||||
|
||||
hooks = mkOption {
|
||||
hooks = lib.mkOption {
|
||||
type = hooksModule;
|
||||
description = "Profile hook scripts.";
|
||||
default = { };
|
||||
@ -48,66 +45,66 @@ let
|
||||
};
|
||||
};
|
||||
|
||||
configModule = types.submodule {
|
||||
configModule = lib.types.submodule {
|
||||
options = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = "Whether to enable the output.";
|
||||
default = true;
|
||||
};
|
||||
|
||||
crtc = mkOption {
|
||||
type = types.nullOr types.ints.unsigned;
|
||||
crtc = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.ints.unsigned;
|
||||
description = "Output video display controller.";
|
||||
default = null;
|
||||
example = 0;
|
||||
};
|
||||
|
||||
primary = mkOption {
|
||||
type = types.bool;
|
||||
primary = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = "Whether output should be marked as primary";
|
||||
default = false;
|
||||
};
|
||||
|
||||
position = mkOption {
|
||||
type = types.str;
|
||||
position = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Output position";
|
||||
default = "";
|
||||
example = "5760x0";
|
||||
};
|
||||
|
||||
mode = mkOption {
|
||||
type = types.str;
|
||||
mode = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Output resolution.";
|
||||
default = "";
|
||||
example = "3840x2160";
|
||||
};
|
||||
|
||||
rate = mkOption {
|
||||
type = types.str;
|
||||
rate = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Output framerate.";
|
||||
default = "";
|
||||
example = "60.00";
|
||||
};
|
||||
|
||||
gamma = mkOption {
|
||||
type = types.str;
|
||||
gamma = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Output gamma configuration.";
|
||||
default = "";
|
||||
example = "1.0:0.909:0.833";
|
||||
};
|
||||
|
||||
rotate = mkOption {
|
||||
type = types.nullOr (types.enum [ "normal" "left" "right" "inverted" ]);
|
||||
rotate = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.enum [ "normal" "left" "right" "inverted" ]);
|
||||
description = "Output rotate configuration.";
|
||||
default = null;
|
||||
example = "left";
|
||||
};
|
||||
|
||||
transform = mkOption {
|
||||
type = types.nullOr (matrixOf 3 3 types.float);
|
||||
transform = lib.mkOption {
|
||||
type = lib.types.nullOr (matrixOf 3 3 lib.types.float);
|
||||
default = null;
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
[
|
||||
[ 0.6 0.0 0.0 ]
|
||||
[ 0.0 0.6 0.0 ]
|
||||
@ -121,30 +118,30 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
dpi = mkOption {
|
||||
type = types.nullOr types.ints.positive;
|
||||
dpi = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.ints.positive;
|
||||
description = "Output DPI configuration.";
|
||||
default = null;
|
||||
example = 96;
|
||||
};
|
||||
|
||||
scale = mkOption {
|
||||
type = types.nullOr (types.submodule {
|
||||
scale = lib.mkOption {
|
||||
type = lib.types.nullOr (lib.types.submodule {
|
||||
options = {
|
||||
method = mkOption {
|
||||
type = types.enum [ "factor" "pixel" ];
|
||||
method = lib.mkOption {
|
||||
type = lib.types.enum [ "factor" "pixel" ];
|
||||
description = "Output scaling method.";
|
||||
default = "factor";
|
||||
example = "pixel";
|
||||
};
|
||||
|
||||
x = mkOption {
|
||||
type = types.either types.float types.ints.positive;
|
||||
x = lib.mkOption {
|
||||
type = lib.types.either lib.types.float lib.types.ints.positive;
|
||||
description = "Horizontal scaling factor/pixels.";
|
||||
};
|
||||
|
||||
y = mkOption {
|
||||
type = types.either types.float types.ints.positive;
|
||||
y = lib.mkOption {
|
||||
type = lib.types.either lib.types.float lib.types.ints.positive;
|
||||
description = "Vertical scaling factor/pixels.";
|
||||
};
|
||||
};
|
||||
@ -164,7 +161,7 @@ let
|
||||
exclusive.
|
||||
'';
|
||||
default = null;
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
x = 1.25;
|
||||
y = 1.25;
|
||||
@ -174,22 +171,22 @@ let
|
||||
};
|
||||
};
|
||||
|
||||
hooksModule = types.submodule {
|
||||
hooksModule = lib.types.submodule {
|
||||
options = {
|
||||
postswitch = mkOption {
|
||||
type = types.attrsOf hookType;
|
||||
postswitch = lib.mkOption {
|
||||
type = lib.types.attrsOf hookType;
|
||||
description = "Postswitch hook executed after mode switch.";
|
||||
default = { };
|
||||
};
|
||||
|
||||
preswitch = mkOption {
|
||||
type = types.attrsOf hookType;
|
||||
preswitch = lib.mkOption {
|
||||
type = lib.types.attrsOf hookType;
|
||||
description = "Preswitch hook executed before mode switch.";
|
||||
default = { };
|
||||
};
|
||||
|
||||
predetect = mkOption {
|
||||
type = types.attrsOf hookType;
|
||||
predetect = lib.mkOption {
|
||||
type = lib.types.attrsOf hookType;
|
||||
description = ''
|
||||
Predetect hook executed before autorandr attempts to run xrandr.
|
||||
'';
|
||||
@ -199,37 +196,37 @@ let
|
||||
};
|
||||
|
||||
hookToFile = folder: name: hook:
|
||||
nameValuePair "xdg/autorandr/${folder}/${name}" {
|
||||
lib.nameValuePair "xdg/autorandr/${folder}/${name}" {
|
||||
source = "${pkgs.writeShellScriptBin "hook" hook}/bin/hook";
|
||||
};
|
||||
profileToFiles = name: profile:
|
||||
with profile;
|
||||
mkMerge ([
|
||||
lib.mkMerge ([
|
||||
{
|
||||
"xdg/autorandr/${name}/setup".text = concatStringsSep "\n"
|
||||
(mapAttrsToList fingerprintToString fingerprint);
|
||||
"xdg/autorandr/${name}/setup".text = lib.concatStringsSep "\n"
|
||||
(lib.mapAttrsToList fingerprintToString fingerprint);
|
||||
"xdg/autorandr/${name}/config".text =
|
||||
concatStringsSep "\n" (mapAttrsToList configToString profile.config);
|
||||
lib.concatStringsSep "\n" (lib.mapAttrsToList configToString profile.config);
|
||||
}
|
||||
(mapAttrs' (hookToFile "${name}/postswitch.d") hooks.postswitch)
|
||||
(mapAttrs' (hookToFile "${name}/preswitch.d") hooks.preswitch)
|
||||
(mapAttrs' (hookToFile "${name}/predetect.d") hooks.predetect)
|
||||
(lib.mapAttrs' (hookToFile "${name}/postswitch.d") hooks.postswitch)
|
||||
(lib.mapAttrs' (hookToFile "${name}/preswitch.d") hooks.preswitch)
|
||||
(lib.mapAttrs' (hookToFile "${name}/predetect.d") hooks.predetect)
|
||||
]);
|
||||
fingerprintToString = name: edid: "${name} ${edid}";
|
||||
configToString = name: config:
|
||||
if config.enable then
|
||||
concatStringsSep "\n" ([ "output ${name}" ]
|
||||
++ optional (config.position != "") "pos ${config.position}"
|
||||
++ optional (config.crtc != null) "crtc ${toString config.crtc}"
|
||||
++ optional config.primary "primary"
|
||||
++ optional (config.dpi != null) "dpi ${toString config.dpi}"
|
||||
++ optional (config.gamma != "") "gamma ${config.gamma}"
|
||||
++ optional (config.mode != "") "mode ${config.mode}"
|
||||
++ optional (config.rate != "") "rate ${config.rate}"
|
||||
++ optional (config.rotate != null) "rotate ${config.rotate}"
|
||||
++ optional (config.transform != null) ("transform "
|
||||
+ concatMapStringsSep "," toString (flatten config.transform))
|
||||
++ optional (config.scale != null)
|
||||
lib.concatStringsSep "\n" ([ "output ${name}" ]
|
||||
++ lib.optional (config.position != "") "pos ${config.position}"
|
||||
++ lib.optional (config.crtc != null) "crtc ${toString config.crtc}"
|
||||
++ lib.optional config.primary "primary"
|
||||
++ lib.optional (config.dpi != null) "dpi ${toString config.dpi}"
|
||||
++ lib.optional (config.gamma != "") "gamma ${config.gamma}"
|
||||
++ lib.optional (config.mode != "") "mode ${config.mode}"
|
||||
++ lib.optional (config.rate != "") "rate ${config.rate}"
|
||||
++ lib.optional (config.rotate != null) "rotate ${config.rotate}"
|
||||
++ lib.optional (config.transform != null) ("transform "
|
||||
+ lib.concatMapStringsSep "," toString (lib.flatten config.transform))
|
||||
++ lib.optional (config.scale != null)
|
||||
((if config.scale.method == "factor" then "scale" else "scale-from")
|
||||
+ " ${toString config.scale.x}x${toString config.scale.y}"))
|
||||
else ''
|
||||
@ -242,11 +239,11 @@ in {
|
||||
options = {
|
||||
|
||||
services.autorandr = {
|
||||
enable = mkEnableOption "handling of hotplug and sleep events by autorandr";
|
||||
enable = lib.mkEnableOption "handling of hotplug and sleep events by autorandr";
|
||||
|
||||
defaultTarget = mkOption {
|
||||
defaultTarget = lib.mkOption {
|
||||
default = "default";
|
||||
type = types.str;
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Fallback if no monitor layout can be detected. See the docs
|
||||
(https://github.com/phillipberndt/autorandr/blob/v1.0/README.md#how-to-use)
|
||||
@ -254,23 +251,23 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
ignoreLid = mkOption {
|
||||
ignoreLid = lib.mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
type = lib.types.bool;
|
||||
description = "Treat outputs as connected even if their lids are closed";
|
||||
};
|
||||
|
||||
matchEdid = mkOption {
|
||||
matchEdid = lib.mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
type = lib.types.bool;
|
||||
description = "Match displays based on edid instead of name";
|
||||
};
|
||||
|
||||
hooks = mkOption {
|
||||
hooks = lib.mkOption {
|
||||
type = hooksModule;
|
||||
description = "Global hook scripts";
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
postswitch = {
|
||||
"notify-i3" = "''${pkgs.i3}/bin/i3-msg restart";
|
||||
@ -296,11 +293,11 @@ in {
|
||||
}
|
||||
'';
|
||||
};
|
||||
profiles = mkOption {
|
||||
type = types.attrsOf profileModule;
|
||||
profiles = lib.mkOption {
|
||||
type = lib.types.attrsOf profileModule;
|
||||
description = "Autorandr profiles specification.";
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
"work" = {
|
||||
fingerprint = {
|
||||
@ -330,17 +327,17 @@ in {
|
||||
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
services.udev.packages = [ pkgs.autorandr ];
|
||||
|
||||
environment = {
|
||||
systemPackages = [ pkgs.autorandr ];
|
||||
etc = mkMerge ([
|
||||
(mapAttrs' (hookToFile "postswitch.d") cfg.hooks.postswitch)
|
||||
(mapAttrs' (hookToFile "preswitch.d") cfg.hooks.preswitch)
|
||||
(mapAttrs' (hookToFile "predetect.d") cfg.hooks.predetect)
|
||||
(mkMerge (mapAttrsToList profileToFiles cfg.profiles))
|
||||
etc = lib.mkMerge ([
|
||||
(lib.mapAttrs' (hookToFile "postswitch.d") cfg.hooks.postswitch)
|
||||
(lib.mapAttrs' (hookToFile "preswitch.d") cfg.hooks.preswitch)
|
||||
(lib.mapAttrs' (hookToFile "predetect.d") cfg.hooks.predetect)
|
||||
(lib.mkMerge (lib.mapAttrsToList profileToFiles cfg.profiles))
|
||||
]);
|
||||
};
|
||||
|
||||
@ -357,8 +354,8 @@ in {
|
||||
--batch \
|
||||
--change \
|
||||
--default ${cfg.defaultTarget} \
|
||||
${optionalString cfg.ignoreLid "--ignore-lid"} \
|
||||
${optionalString cfg.matchEdid "--match-edid"}
|
||||
${lib.optionalString cfg.ignoreLid "--ignore-lid"} \
|
||||
${lib.optionalString cfg.matchEdid "--match-edid"}
|
||||
'';
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = false;
|
||||
@ -368,5 +365,5 @@ in {
|
||||
|
||||
};
|
||||
|
||||
meta.maintainers = with maintainers; [ alexnortung ];
|
||||
meta.maintainers = with lib.maintainers; [ alexnortung ];
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
{ pkgs, lib, config, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.services.gammu-smsd;
|
||||
|
||||
@ -10,7 +8,7 @@ let
|
||||
Connection = ${cfg.device.connection}
|
||||
SynchronizeTime = ${if cfg.device.synchronizeTime then "yes" else "no"}
|
||||
LogFormat = ${cfg.log.format}
|
||||
${optionalString (cfg.device.pin != null) "PIN = ${cfg.device.pin}"}
|
||||
${lib.optionalString (cfg.device.pin != null) "PIN = ${cfg.device.pin}"}
|
||||
${cfg.extraConfig.gammu}
|
||||
|
||||
|
||||
@ -18,25 +16,25 @@ let
|
||||
LogFile = ${cfg.log.file}
|
||||
Service = ${cfg.backend.service}
|
||||
|
||||
${optionalString (cfg.backend.service == "files") ''
|
||||
${lib.optionalString (cfg.backend.service == "files") ''
|
||||
InboxPath = ${cfg.backend.files.inboxPath}
|
||||
OutboxPath = ${cfg.backend.files.outboxPath}
|
||||
SentSMSPath = ${cfg.backend.files.sentSMSPath}
|
||||
ErrorSMSPath = ${cfg.backend.files.errorSMSPath}
|
||||
''}
|
||||
|
||||
${optionalString (cfg.backend.service == "sql" && cfg.backend.sql.driver == "sqlite") ''
|
||||
${lib.optionalString (cfg.backend.service == "sql" && cfg.backend.sql.driver == "sqlite") ''
|
||||
Driver = ${cfg.backend.sql.driver}
|
||||
DBDir = ${cfg.backend.sql.database}
|
||||
''}
|
||||
|
||||
${optionalString (cfg.backend.service == "sql" && cfg.backend.sql.driver == "native_pgsql") (
|
||||
${lib.optionalString (cfg.backend.service == "sql" && cfg.backend.sql.driver == "native_pgsql") (
|
||||
with cfg.backend; ''
|
||||
Driver = ${sql.driver}
|
||||
${optionalString (sql.database!= null) "Database = ${sql.database}"}
|
||||
${optionalString (sql.host != null) "Host = ${sql.host}"}
|
||||
${optionalString (sql.user != null) "User = ${sql.user}"}
|
||||
${optionalString (sql.password != null) "Password = ${sql.password}"}
|
||||
${lib.optionalString (sql.database!= null) "Database = ${sql.database}"}
|
||||
${lib.optionalString (sql.host != null) "Host = ${sql.host}"}
|
||||
${lib.optionalString (sql.user != null) "User = ${sql.user}"}
|
||||
${lib.optionalString (sql.password != null) "Password = ${sql.password}"}
|
||||
'')}
|
||||
|
||||
${cfg.extraConfig.smsd}
|
||||
@ -53,42 +51,42 @@ in {
|
||||
options = {
|
||||
services.gammu-smsd = {
|
||||
|
||||
enable = mkEnableOption "gammu-smsd daemon";
|
||||
enable = lib.mkEnableOption "gammu-smsd daemon";
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "smsd";
|
||||
description = "User that has access to the device";
|
||||
};
|
||||
|
||||
device = {
|
||||
path = mkOption {
|
||||
type = types.path;
|
||||
path = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = "Device node or address of the phone";
|
||||
example = "/dev/ttyUSB2";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "root";
|
||||
description = "Owner group of the device";
|
||||
example = "dialout";
|
||||
};
|
||||
|
||||
connection = mkOption {
|
||||
type = types.str;
|
||||
connection = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "at";
|
||||
description = "Protocol which will be used to talk to the phone";
|
||||
};
|
||||
|
||||
synchronizeTime = mkOption {
|
||||
type = types.bool;
|
||||
synchronizeTime = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Whether to set time from computer to the phone during starting connection";
|
||||
};
|
||||
|
||||
pin = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
pin = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "PIN code for the simcard";
|
||||
};
|
||||
@ -96,14 +94,14 @@ in {
|
||||
|
||||
|
||||
log = {
|
||||
file = mkOption {
|
||||
type = types.str;
|
||||
file = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "syslog";
|
||||
description = "Path to file where information about communication will be stored";
|
||||
};
|
||||
|
||||
format = mkOption {
|
||||
type = types.enum [ "nothing" "text" "textall" "textalldate" "errors" "errorsdate" "binary" ];
|
||||
format = lib.mkOption {
|
||||
type = lib.types.enum [ "nothing" "text" "textall" "textalldate" "errors" "errorsdate" "binary" ];
|
||||
default = "errors";
|
||||
description = "Determines what will be logged to the LogFile";
|
||||
};
|
||||
@ -111,15 +109,15 @@ in {
|
||||
|
||||
|
||||
extraConfig = {
|
||||
gammu = mkOption {
|
||||
type = types.lines;
|
||||
gammu = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
description = "Extra config lines to be added into [gammu] section";
|
||||
};
|
||||
|
||||
|
||||
smsd = mkOption {
|
||||
type = types.lines;
|
||||
smsd = lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
description = "Extra config lines to be added into [smsd] section";
|
||||
};
|
||||
@ -127,70 +125,70 @@ in {
|
||||
|
||||
|
||||
backend = {
|
||||
service = mkOption {
|
||||
type = types.enum [ "null" "files" "sql" ];
|
||||
service = lib.mkOption {
|
||||
type = lib.types.enum [ "null" "files" "sql" ];
|
||||
default = "null";
|
||||
description = "Service to use to store sms data.";
|
||||
};
|
||||
|
||||
files = {
|
||||
inboxPath = mkOption {
|
||||
type = types.path;
|
||||
inboxPath = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/spool/sms/inbox/";
|
||||
description = "Where the received SMSes are stored";
|
||||
};
|
||||
|
||||
outboxPath = mkOption {
|
||||
type = types.path;
|
||||
outboxPath = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/spool/sms/outbox/";
|
||||
description = "Where SMSes to be sent should be placed";
|
||||
};
|
||||
|
||||
sentSMSPath = mkOption {
|
||||
type = types.path;
|
||||
sentSMSPath = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/spool/sms/sent/";
|
||||
description = "Where the transmitted SMSes are placed";
|
||||
};
|
||||
|
||||
errorSMSPath = mkOption {
|
||||
type = types.path;
|
||||
errorSMSPath = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/spool/sms/error/";
|
||||
description = "Where SMSes with error in transmission is placed";
|
||||
};
|
||||
};
|
||||
|
||||
sql = {
|
||||
driver = mkOption {
|
||||
type = types.enum [ "native_mysql" "native_pgsql" "odbc" "dbi" ];
|
||||
driver = lib.mkOption {
|
||||
type = lib.types.enum [ "native_mysql" "native_pgsql" "odbc" "dbi" ];
|
||||
description = "DB driver to use";
|
||||
};
|
||||
|
||||
sqlDialect = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
sqlDialect = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "SQL dialect to use (odbc driver only)";
|
||||
};
|
||||
|
||||
database = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
database = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "Database name to store sms data";
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "localhost";
|
||||
description = "Database server address";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
user = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "User name used for connection to the database";
|
||||
};
|
||||
|
||||
password = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
password = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = "User password used for connection to the database";
|
||||
};
|
||||
@ -199,7 +197,7 @@ in {
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
users.users.${cfg.user} = {
|
||||
description = "gammu-smsd user";
|
||||
isSystemUser = true;
|
||||
@ -207,7 +205,7 @@ in {
|
||||
};
|
||||
|
||||
environment.systemPackages = with cfg.backend; [ gammuPackage ]
|
||||
++ optionals (service == "sql" && sql.driver == "sqlite") [ pkgs.sqlite ];
|
||||
++ lib.optionals (service == "sql" && sql.driver == "sqlite") [ pkgs.sqlite ];
|
||||
|
||||
systemd.services.gammu-smsd = {
|
||||
description = "gammu-smsd daemon";
|
||||
@ -215,29 +213,29 @@ in {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
wants = with cfg.backend; [ ]
|
||||
++ optionals (service == "sql" && sql.driver == "native_pgsql") [ "postgresql.service" ];
|
||||
++ lib.optionals (service == "sql" && sql.driver == "native_pgsql") [ "postgresql.service" ];
|
||||
|
||||
preStart = with cfg.backend;
|
||||
|
||||
optionalString (service == "files") (with files; ''
|
||||
lib.optionalString (service == "files") (with files; ''
|
||||
mkdir -m 755 -p ${inboxPath} ${outboxPath} ${sentSMSPath} ${errorSMSPath}
|
||||
chown ${cfg.user} -R ${inboxPath}
|
||||
chown ${cfg.user} -R ${outboxPath}
|
||||
chown ${cfg.user} -R ${sentSMSPath}
|
||||
chown ${cfg.user} -R ${errorSMSPath}
|
||||
'')
|
||||
+ optionalString (service == "sql" && sql.driver == "sqlite") ''
|
||||
+ lib.optionalString (service == "sql" && sql.driver == "sqlite") ''
|
||||
cat "${gammuPackage}/${initDBDir}/sqlite.sql" \
|
||||
| ${pkgs.sqlite.bin}/bin/sqlite3 ${sql.database}
|
||||
''
|
||||
+ (let execPsql = extraArgs: concatStringsSep " " [
|
||||
(optionalString (sql.password != null) "PGPASSWORD=${sql.password}")
|
||||
+ (let execPsql = extraArgs: lib.concatStringsSep " " [
|
||||
(lib.optionalString (sql.password != null) "PGPASSWORD=${sql.password}")
|
||||
"${config.services.postgresql.package}/bin/psql"
|
||||
(optionalString (sql.host != null) "-h ${sql.host}")
|
||||
(optionalString (sql.user != null) "-U ${sql.user}")
|
||||
(lib.optionalString (sql.host != null) "-h ${sql.host}")
|
||||
(lib.optionalString (sql.user != null) "-U ${sql.user}")
|
||||
"$extraArgs"
|
||||
"${sql.database}"
|
||||
]; in optionalString (service == "sql" && sql.driver == "native_pgsql") ''
|
||||
]; in lib.optionalString (service == "sql" && sql.driver == "native_pgsql") ''
|
||||
echo '\i '"${gammuPackage}/${initDBDir}/pgsql.sql" | ${execPsql ""}
|
||||
'');
|
||||
|
||||
|
@ -222,6 +222,7 @@ in
|
||||
|
||||
environment = {
|
||||
HOMEPAGE_CONFIG_DIR = configDir;
|
||||
HOMEPAGE_CACHE_DIR = "/var/cache/homepage-dashboard";
|
||||
PORT = toString cfg.listenPort;
|
||||
LOG_TARGETS = lib.mkIf managedConfig "stdout";
|
||||
};
|
||||
@ -231,6 +232,7 @@ in
|
||||
DynamicUser = true;
|
||||
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
||||
StateDirectory = lib.mkIf (!managedConfig) "homepage-dashboard";
|
||||
CacheDirectory = "homepage-dashboard";
|
||||
ExecStart = lib.getExe cfg.package;
|
||||
Restart = "on-failure";
|
||||
};
|
||||
|
@ -1,7 +1,4 @@
|
||||
{ config, lib, options, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
gid = config.ids.gids.mediatomb;
|
||||
@ -13,19 +10,19 @@ let
|
||||
# configuration on media directory
|
||||
mediaDirectory = {
|
||||
options = {
|
||||
path = mkOption {
|
||||
type = types.str;
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Absolute directory path to the media directory to index.
|
||||
'';
|
||||
};
|
||||
recursive = mkOption {
|
||||
type = types.bool;
|
||||
recursive = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Whether the indexation must take place recursively or not.";
|
||||
};
|
||||
hidden-files = mkOption {
|
||||
type = types.bool;
|
||||
hidden-files = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Whether to index the hidden files or not.";
|
||||
};
|
||||
@ -66,7 +63,7 @@ let
|
||||
</transcoding>
|
||||
'';
|
||||
|
||||
configText = optionalString (! cfg.customCfg) ''
|
||||
configText = lib.optionalString (! cfg.customCfg) ''
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config version="2" xmlns="http://mediatomb.cc/config/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://mediatomb.cc/config/2 http://mediatomb.cc/config/2.xsd">
|
||||
<server>
|
||||
@ -87,7 +84,7 @@ let
|
||||
</sqlite3>
|
||||
</storage>
|
||||
<protocolInfo extend="${optionYesNo cfg.ps3Support}"/>
|
||||
${optionalString cfg.dsmSupport ''
|
||||
${lib.optionalString cfg.dsmSupport ''
|
||||
<custom-http-headers>
|
||||
<add header="X-User-Agent: redsonic"/>
|
||||
</custom-http-headers>
|
||||
@ -95,7 +92,7 @@ let
|
||||
<manufacturerURL>redsonic.com</manufacturerURL>
|
||||
<modelNumber>105</modelNumber>
|
||||
''}
|
||||
${optionalString cfg.tg100Support ''
|
||||
${lib.optionalString cfg.tg100Support ''
|
||||
<upnp-string-limit>101</upnp-string-limit>
|
||||
''}
|
||||
<extended-runtime-options>
|
||||
@ -109,7 +106,7 @@ let
|
||||
</server>
|
||||
<import hidden-files="no">
|
||||
<autoscan use-inotify="auto">
|
||||
${concatMapStrings toMediaDirectory cfg.mediaDirectories}
|
||||
${lib.concatMapStrings toMediaDirectory cfg.mediaDirectories}
|
||||
</autoscan>
|
||||
<scripting script-charset="UTF-8">
|
||||
<common-script>${pkg}/share/${name}/js/common.js</common-script>
|
||||
@ -139,10 +136,10 @@ let
|
||||
<map from="flv" to="video/x-flv"/>
|
||||
<map from="mkv" to="video/x-matroska"/>
|
||||
<map from="mka" to="audio/x-matroska"/>
|
||||
${optionalString cfg.ps3Support ''
|
||||
${lib.optionalString cfg.ps3Support ''
|
||||
<map from="avi" to="video/divx"/>
|
||||
''}
|
||||
${optionalString cfg.dsmSupport ''
|
||||
${lib.optionalString cfg.dsmSupport ''
|
||||
<map from="avi" to="video/avi"/>
|
||||
''}
|
||||
</extension-mimetype>
|
||||
@ -199,26 +196,26 @@ in {
|
||||
|
||||
services.mediatomb = {
|
||||
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable the Gerbera/Mediatomb DLNA server.
|
||||
'';
|
||||
};
|
||||
|
||||
serverName = mkOption {
|
||||
type = types.str;
|
||||
serverName = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Gerbera (Mediatomb)";
|
||||
description = ''
|
||||
How to identify the server on the network.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkPackageOption pkgs "gerbera" { };
|
||||
package = lib.mkPackageOption pkgs "gerbera" { };
|
||||
|
||||
ps3Support = mkOption {
|
||||
type = types.bool;
|
||||
ps3Support = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable ps3 specific tweaks.
|
||||
@ -226,8 +223,8 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
dsmSupport = mkOption {
|
||||
type = types.bool;
|
||||
dsmSupport = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable D-Link DSM 320 specific tweaks.
|
||||
@ -235,69 +232,69 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
tg100Support = mkOption {
|
||||
type = types.bool;
|
||||
tg100Support = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable Telegent TG100 specific tweaks.
|
||||
'';
|
||||
};
|
||||
|
||||
transcoding = mkOption {
|
||||
type = types.bool;
|
||||
transcoding = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable transcoding.
|
||||
'';
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
dataDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/${name}";
|
||||
defaultText = literalExpression ''"/var/lib/''${config.${opt.package}.pname}"'';
|
||||
defaultText = lib.literalExpression ''"/var/lib/''${config.${opt.package}.pname}"'';
|
||||
description = ''
|
||||
The directory where Gerbera/Mediatomb stores its state, data, etc.
|
||||
'';
|
||||
};
|
||||
|
||||
pcDirectoryHide = mkOption {
|
||||
type = types.bool;
|
||||
pcDirectoryHide = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to list the top-level directory or not (from upnp client standpoint).
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "mediatomb";
|
||||
description = "User account under which the service runs.";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "mediatomb";
|
||||
description = "Group account under which the service runs.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 49152;
|
||||
description = ''
|
||||
The network port to listen on.
|
||||
'';
|
||||
};
|
||||
|
||||
interface = mkOption {
|
||||
type = types.str;
|
||||
interface = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = ''
|
||||
A specific interface to bind to.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
openFirewall = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If false (the default), this is up to the user to declare the firewall rules.
|
||||
@ -310,16 +307,16 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
uuid = mkOption {
|
||||
type = types.str;
|
||||
uuid = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "fdfc8a4e-a3ad-4c1d-b43d-a2eedb03a687";
|
||||
description = ''
|
||||
A unique (on your network) to identify the server by.
|
||||
'';
|
||||
};
|
||||
|
||||
mediaDirectories = mkOption {
|
||||
type = with types; listOf (submodule mediaDirectory);
|
||||
mediaDirectories = lib.mkOption {
|
||||
type = with lib.types; listOf (submodule mediaDirectory);
|
||||
default = [];
|
||||
description = ''
|
||||
Declare media directories to index.
|
||||
@ -330,8 +327,8 @@ in {
|
||||
];
|
||||
};
|
||||
|
||||
customCfg = mkOption {
|
||||
type = types.bool;
|
||||
customCfg = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Allow the service to create and use its own config file inside the `dataDir` as
|
||||
@ -350,9 +347,9 @@ in {
|
||||
###### implementation
|
||||
|
||||
config = let binaryCommand = "${pkg}/bin/${name}";
|
||||
interfaceFlag = optionalString ( cfg.interface != "") "--interface ${cfg.interface}";
|
||||
configFlag = optionalString (! cfg.customCfg) "--config ${pkgs.writeText "config.xml" configText}";
|
||||
in mkIf cfg.enable {
|
||||
interfaceFlag = lib.optionalString ( cfg.interface != "") "--interface ${cfg.interface}";
|
||||
configFlag = lib.optionalString (! cfg.customCfg) "--config ${pkgs.writeText "config.xml" configText}";
|
||||
in lib.mkIf cfg.enable {
|
||||
systemd.services.mediatomb = {
|
||||
description = "${cfg.serverName} media Server";
|
||||
# Gerbera might fail if the network interface is not available on startup
|
||||
@ -365,11 +362,11 @@ in {
|
||||
serviceConfig.Group = cfg.group;
|
||||
};
|
||||
|
||||
users.groups = optionalAttrs (cfg.group == "mediatomb") {
|
||||
users.groups = lib.optionalAttrs (cfg.group == "mediatomb") {
|
||||
mediatomb.gid = gid;
|
||||
};
|
||||
|
||||
users.users = optionalAttrs (cfg.user == "mediatomb") {
|
||||
users.users = lib.optionalAttrs (cfg.user == "mediatomb") {
|
||||
mediatomb = {
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
@ -380,11 +377,11 @@ in {
|
||||
};
|
||||
|
||||
# Open firewall only if users enable it
|
||||
networking.firewall = mkMerge [
|
||||
(mkIf (cfg.openFirewall && cfg.interface != "") {
|
||||
networking.firewall = lib.mkMerge [
|
||||
(lib.mkIf (cfg.openFirewall && cfg.interface != "") {
|
||||
interfaces."${cfg.interface}" = defaultFirewallRules;
|
||||
})
|
||||
(mkIf (cfg.openFirewall && cfg.interface == "") defaultFirewallRules)
|
||||
(lib.mkIf (cfg.openFirewall && cfg.interface == "") defaultFirewallRules)
|
||||
];
|
||||
};
|
||||
}
|
||||
|
@ -4,12 +4,9 @@
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.mqtt2influxdb;
|
||||
filterNull = filterAttrsRecursive (n: v: v != null);
|
||||
filterNull = lib.filterAttrsRecursive (n: v: v != null);
|
||||
configFile = (pkgs.formats.yaml {}).generate "mqtt2influxdb.config.yaml" (
|
||||
filterNull {
|
||||
inherit (cfg) mqtt influxdb;
|
||||
@ -17,26 +14,26 @@ let
|
||||
}
|
||||
);
|
||||
|
||||
pointType = types.submodule {
|
||||
pointType = lib.types.submodule {
|
||||
options = {
|
||||
measurement = mkOption {
|
||||
type = types.str;
|
||||
measurement = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Name of the measurement";
|
||||
};
|
||||
topic = mkOption {
|
||||
type = types.str;
|
||||
topic = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "MQTT topic to subscribe to.";
|
||||
};
|
||||
fields = mkOption {
|
||||
type = types.submodule {
|
||||
fields = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
options = {
|
||||
value = mkOption {
|
||||
type = types.str;
|
||||
value = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "$.payload";
|
||||
description = "Value to be picked up";
|
||||
};
|
||||
type = mkOption {
|
||||
type = with types; nullOr str;
|
||||
type = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = null;
|
||||
description = "Type to be picked up";
|
||||
};
|
||||
@ -44,8 +41,8 @@ let
|
||||
};
|
||||
description = "Field selector.";
|
||||
};
|
||||
tags = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
tags = lib.mkOption {
|
||||
type = with lib.types; attrsOf str;
|
||||
default = {};
|
||||
description = "Tags applied";
|
||||
};
|
||||
@ -124,10 +121,10 @@ let
|
||||
in {
|
||||
options = {
|
||||
services.mqtt2influxdb = {
|
||||
enable = mkEnableOption "BigClown MQTT to InfluxDB bridge";
|
||||
package = mkPackageOption pkgs ["python3Packages" "mqtt2influxdb"] {};
|
||||
environmentFiles = mkOption {
|
||||
type = types.listOf types.path;
|
||||
enable = lib.mkEnableOption "BigClown MQTT to InfluxDB bridge";
|
||||
package = lib.mkPackageOption pkgs ["python3Packages" "mqtt2influxdb"] {};
|
||||
environmentFiles = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.path;
|
||||
default = [];
|
||||
example = [ "/run/keys/mqtt2influxdb.env" ];
|
||||
description = ''
|
||||
@ -138,23 +135,23 @@ in {
|
||||
'';
|
||||
};
|
||||
mqtt = {
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "Host where MQTT server is running.";
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 1883;
|
||||
description = "MQTT server port.";
|
||||
};
|
||||
username = mkOption {
|
||||
type = with types; nullOr str;
|
||||
username = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = null;
|
||||
description = "Username used to connect to the MQTT server.";
|
||||
};
|
||||
password = mkOption {
|
||||
type = with types; nullOr str;
|
||||
password = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
MQTT password.
|
||||
@ -164,44 +161,44 @@ in {
|
||||
the store.
|
||||
'';
|
||||
};
|
||||
cafile = mkOption {
|
||||
type = with types; nullOr path;
|
||||
cafile = lib.mkOption {
|
||||
type = with lib.types; nullOr path;
|
||||
default = null;
|
||||
description = "Certification Authority file for MQTT";
|
||||
};
|
||||
certfile = mkOption {
|
||||
type = with types; nullOr path;
|
||||
certfile = lib.mkOption {
|
||||
type = with lib.types; nullOr path;
|
||||
default = null;
|
||||
description = "Certificate file for MQTT";
|
||||
};
|
||||
keyfile = mkOption {
|
||||
type = with types; nullOr path;
|
||||
keyfile = lib.mkOption {
|
||||
type = with lib.types; nullOr path;
|
||||
default = null;
|
||||
description = "Key file for MQTT";
|
||||
};
|
||||
};
|
||||
influxdb = {
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "Host where InfluxDB server is running.";
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8086;
|
||||
description = "InfluxDB server port";
|
||||
};
|
||||
database = mkOption {
|
||||
type = types.str;
|
||||
database = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Name of the InfluxDB database.";
|
||||
};
|
||||
username = mkOption {
|
||||
type = with types; nullOr str;
|
||||
username = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = null;
|
||||
description = "Username for InfluxDB login.";
|
||||
};
|
||||
password = mkOption {
|
||||
type = with types; nullOr str;
|
||||
password = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
Password for InfluxDB login.
|
||||
@ -211,26 +208,26 @@ in {
|
||||
the store.
|
||||
'';
|
||||
};
|
||||
ssl = mkOption {
|
||||
type = types.bool;
|
||||
ssl = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Use SSL to connect to the InfluxDB server.";
|
||||
};
|
||||
verify_ssl = mkOption {
|
||||
type = types.bool;
|
||||
verify_ssl = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Verify SSL certificate when connecting to the InfluxDB server.";
|
||||
};
|
||||
};
|
||||
points = mkOption {
|
||||
type = types.listOf pointType;
|
||||
points = lib.mkOption {
|
||||
type = lib.types.listOf pointType;
|
||||
default = defaultPoints;
|
||||
description = "Points to bridge from MQTT to InfluxDB.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services.bigclown-mqtt2influxdb = let
|
||||
envConfig = cfg.environmentFiles != [];
|
||||
finalConfig = if envConfig
|
||||
@ -239,7 +236,7 @@ in {
|
||||
in {
|
||||
description = "BigClown MQTT to InfluxDB bridge";
|
||||
wantedBy = ["multi-user.target"];
|
||||
wants = mkIf config.services.mosquitto.enable ["mosquitto.service"];
|
||||
wants = lib.mkIf config.services.mosquitto.enable ["mosquitto.service"];
|
||||
preStart = ''
|
||||
umask 077
|
||||
${pkgs.envsubst}/bin/envsubst -i "${configFile}" -o "${finalConfig}"
|
||||
|
@ -1,16 +1,13 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.nitter;
|
||||
configFile = pkgs.writeText "nitter.conf" ''
|
||||
${generators.toINI {
|
||||
${lib.generators.toINI {
|
||||
# String values need to be quoted
|
||||
mkKeyValue = generators.mkKeyValueDefault {
|
||||
mkKeyValue = lib.generators.mkKeyValueDefault {
|
||||
mkValueString = v:
|
||||
if isString v then "\"" + (strings.escape ["\""] (toString v)) + "\""
|
||||
else generators.mkValueStringDefault {} v;
|
||||
if lib.isString v then "\"" + (lib.escape ["\""] (toString v)) + "\""
|
||||
else lib.generators.mkValueStringDefault {} v;
|
||||
} " = ";
|
||||
} (lib.recursiveUpdate {
|
||||
Server = cfg.server;
|
||||
@ -47,57 +44,57 @@ in
|
||||
{
|
||||
imports = [
|
||||
# https://github.com/zedeus/nitter/pull/772
|
||||
(mkRemovedOptionModule [ "services" "nitter" "replaceInstagram" ] "Nitter no longer supports this option as Bibliogram has been discontinued.")
|
||||
(lib.mkRemovedOptionModule [ "services" "nitter" "replaceInstagram" ] "Nitter no longer supports this option as Bibliogram has been discontinued.")
|
||||
];
|
||||
|
||||
options = {
|
||||
services.nitter = {
|
||||
enable = mkEnableOption "Nitter, an alternative Twitter front-end";
|
||||
enable = lib.mkEnableOption "Nitter, an alternative Twitter front-end";
|
||||
|
||||
package = mkPackageOption pkgs "nitter" { };
|
||||
package = lib.mkPackageOption pkgs "nitter" { };
|
||||
|
||||
server = {
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
address = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0.0.0.0";
|
||||
example = "127.0.0.1";
|
||||
description = "The address to listen on.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8080;
|
||||
example = 8000;
|
||||
description = "The port to listen on.";
|
||||
};
|
||||
|
||||
https = mkOption {
|
||||
type = types.bool;
|
||||
https = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Set secure attribute on cookies. Keep it disabled to enable cookies when not using HTTPS.";
|
||||
};
|
||||
|
||||
httpMaxConnections = mkOption {
|
||||
type = types.int;
|
||||
httpMaxConnections = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 100;
|
||||
description = "Maximum number of HTTP connections.";
|
||||
};
|
||||
|
||||
staticDir = mkOption {
|
||||
type = types.path;
|
||||
staticDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "${cfg.package}/share/nitter/public";
|
||||
defaultText = literalExpression ''"''${config.services.nitter.package}/share/nitter/public"'';
|
||||
defaultText = lib.literalExpression ''"''${config.services.nitter.package}/share/nitter/public"'';
|
||||
description = "Path to the static files directory.";
|
||||
};
|
||||
|
||||
title = mkOption {
|
||||
type = types.str;
|
||||
title = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "nitter";
|
||||
description = "Title of the instance.";
|
||||
};
|
||||
|
||||
hostname = mkOption {
|
||||
type = types.str;
|
||||
hostname = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "localhost";
|
||||
example = "nitter.net";
|
||||
description = "Hostname of the instance.";
|
||||
@ -105,38 +102,38 @@ in
|
||||
};
|
||||
|
||||
cache = {
|
||||
listMinutes = mkOption {
|
||||
type = types.int;
|
||||
listMinutes = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 240;
|
||||
description = "How long to cache list info (not the tweets, so keep it high).";
|
||||
};
|
||||
|
||||
rssMinutes = mkOption {
|
||||
type = types.int;
|
||||
rssMinutes = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 10;
|
||||
description = "How long to cache RSS queries.";
|
||||
};
|
||||
|
||||
redisHost = mkOption {
|
||||
type = types.str;
|
||||
redisHost = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "localhost";
|
||||
description = "Redis host.";
|
||||
};
|
||||
|
||||
redisPort = mkOption {
|
||||
type = types.port;
|
||||
redisPort = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 6379;
|
||||
description = "Redis port.";
|
||||
};
|
||||
|
||||
redisConnections = mkOption {
|
||||
type = types.int;
|
||||
redisConnections = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 20;
|
||||
description = "Redis connection pool size.";
|
||||
};
|
||||
|
||||
redisMaxConnections = mkOption {
|
||||
type = types.int;
|
||||
redisMaxConnections = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 30;
|
||||
description = ''
|
||||
Maximum number of connections to Redis.
|
||||
@ -149,30 +146,30 @@ in
|
||||
};
|
||||
|
||||
config = {
|
||||
base64Media = mkOption {
|
||||
type = types.bool;
|
||||
base64Media = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Use base64 encoding for proxied media URLs.";
|
||||
};
|
||||
|
||||
enableRSS = mkEnableOption "RSS feeds" // { default = true; };
|
||||
enableRSS = lib.mkEnableOption "RSS feeds" // { default = true; };
|
||||
|
||||
enableDebug = mkEnableOption "request logs and debug endpoints";
|
||||
enableDebug = lib.mkEnableOption "request logs and debug endpoints";
|
||||
|
||||
proxy = mkOption {
|
||||
type = types.str;
|
||||
proxy = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "URL to a HTTP/HTTPS proxy.";
|
||||
};
|
||||
|
||||
proxyAuth = mkOption {
|
||||
type = types.str;
|
||||
proxyAuth = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
description = "Credentials for proxy.";
|
||||
};
|
||||
|
||||
tokenCount = mkOption {
|
||||
type = types.int;
|
||||
tokenCount = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 10;
|
||||
description = ''
|
||||
Minimum amount of usable tokens.
|
||||
@ -187,114 +184,114 @@ in
|
||||
};
|
||||
|
||||
preferences = {
|
||||
replaceTwitter = mkOption {
|
||||
type = types.str;
|
||||
replaceTwitter = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
example = "nitter.net";
|
||||
description = "Replace Twitter links with links to this instance (blank to disable).";
|
||||
};
|
||||
|
||||
replaceYouTube = mkOption {
|
||||
type = types.str;
|
||||
replaceYouTube = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
example = "piped.kavin.rocks";
|
||||
description = "Replace YouTube links with links to this instance (blank to disable).";
|
||||
};
|
||||
|
||||
replaceReddit = mkOption {
|
||||
type = types.str;
|
||||
replaceReddit = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
example = "teddit.net";
|
||||
description = "Replace Reddit links with links to this instance (blank to disable).";
|
||||
};
|
||||
|
||||
mp4Playback = mkOption {
|
||||
type = types.bool;
|
||||
mp4Playback = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Enable MP4 video playback.";
|
||||
};
|
||||
|
||||
hlsPlayback = mkOption {
|
||||
type = types.bool;
|
||||
hlsPlayback = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Enable HLS video streaming (requires JavaScript).";
|
||||
};
|
||||
|
||||
proxyVideos = mkOption {
|
||||
type = types.bool;
|
||||
proxyVideos = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Proxy video streaming through the server (might be slow).";
|
||||
};
|
||||
|
||||
muteVideos = mkOption {
|
||||
type = types.bool;
|
||||
muteVideos = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Mute videos by default.";
|
||||
};
|
||||
|
||||
autoplayGifs = mkOption {
|
||||
type = types.bool;
|
||||
autoplayGifs = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Autoplay GIFs.";
|
||||
};
|
||||
|
||||
theme = mkOption {
|
||||
type = types.str;
|
||||
theme = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "Nitter";
|
||||
description = "Instance theme.";
|
||||
};
|
||||
|
||||
infiniteScroll = mkOption {
|
||||
type = types.bool;
|
||||
infiniteScroll = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Infinite scrolling (requires JavaScript, experimental!).";
|
||||
};
|
||||
|
||||
stickyProfile = mkOption {
|
||||
type = types.bool;
|
||||
stickyProfile = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Make profile sidebar stick to top.";
|
||||
};
|
||||
|
||||
bidiSupport = mkOption {
|
||||
type = types.bool;
|
||||
bidiSupport = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Support bidirectional text (makes clicking on tweets harder).";
|
||||
};
|
||||
|
||||
hideTweetStats = mkOption {
|
||||
type = types.bool;
|
||||
hideTweetStats = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Hide tweet stats (replies, retweets, likes).";
|
||||
};
|
||||
|
||||
hideBanner = mkOption {
|
||||
type = types.bool;
|
||||
hideBanner = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Hide profile banner.";
|
||||
};
|
||||
|
||||
hidePins = mkOption {
|
||||
type = types.bool;
|
||||
hidePins = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Hide pinned tweets.";
|
||||
};
|
||||
|
||||
hideReplies = mkOption {
|
||||
type = types.bool;
|
||||
hideReplies = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Hide tweet replies.";
|
||||
};
|
||||
|
||||
squareAvatars = mkOption {
|
||||
type = types.bool;
|
||||
squareAvatars = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Square profile pictures.";
|
||||
};
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = types.attrs;
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.attrs;
|
||||
default = {};
|
||||
description = ''
|
||||
Add settings here to override NixOS module generated settings.
|
||||
@ -304,8 +301,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
guestAccounts = mkOption {
|
||||
type = types.path;
|
||||
guestAccounts = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/nitter/guest_accounts.jsonl";
|
||||
description = ''
|
||||
Path to the guest accounts file.
|
||||
@ -321,21 +318,21 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
redisCreateLocally = mkOption {
|
||||
type = types.bool;
|
||||
redisCreateLocally = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Configure local Redis server for Nitter.";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
openFirewall = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Open ports in the firewall for Nitter web interface.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = !cfg.redisCreateLocally || (cfg.cache.redisHost == "localhost" && cfg.cache.redisPort == 6379);
|
||||
@ -397,7 +394,7 @@ in
|
||||
port = cfg.cache.redisPort;
|
||||
};
|
||||
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
networking.firewall = lib.mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.server.port ];
|
||||
};
|
||||
};
|
||||
|
@ -1,39 +1,36 @@
|
||||
{ config, lib, pkgs, ...}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.mosquitto;
|
||||
|
||||
# note that mosquitto config parsing is very simplistic as of may 2021.
|
||||
# often times they'll e.g. strtok() a line, check the first two tokens, and ignore the rest.
|
||||
# there's no escaping available either, so we have to prevent any being necessary.
|
||||
str = types.strMatching "[^\r\n]*" // {
|
||||
str = lib.types.strMatching "[^\r\n]*" // {
|
||||
description = "single-line string";
|
||||
};
|
||||
path = types.addCheck types.path (p: str.check "${p}");
|
||||
configKey = types.strMatching "[^\r\n\t ]+";
|
||||
optionType = with types; oneOf [ str path bool int ] // {
|
||||
path = lib.types.addCheck lib.types.path (p: str.check "${p}");
|
||||
configKey = lib.types.strMatching "[^\r\n\t ]+";
|
||||
optionType = with lib.types; oneOf [ str path bool int ] // {
|
||||
description = "string, path, bool, or integer";
|
||||
};
|
||||
optionToString = v:
|
||||
if isBool v then boolToString v
|
||||
if lib.isBool v then lib.boolToString v
|
||||
else if path.check v then "${v}"
|
||||
else toString v;
|
||||
|
||||
assertKeysValid = prefix: valid: config:
|
||||
mapAttrsToList
|
||||
lib.mapAttrsToList
|
||||
(n: _: {
|
||||
assertion = valid ? ${n};
|
||||
message = "Invalid config key ${prefix}.${n}.";
|
||||
})
|
||||
config;
|
||||
|
||||
formatFreeform = { prefix ? "" }: mapAttrsToList (n: v: "${prefix}${n} ${optionToString v}");
|
||||
formatFreeform = { prefix ? "" }: lib.mapAttrsToList (n: v: "${prefix}${n} ${optionToString v}");
|
||||
|
||||
userOptions = with types; submodule {
|
||||
userOptions = with lib.types; submodule {
|
||||
options = {
|
||||
password = mkOption {
|
||||
password = lib.mkOption {
|
||||
type = uniq (nullOr str);
|
||||
default = null;
|
||||
description = ''
|
||||
@ -41,7 +38,7 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
passwordFile = lib.mkOption {
|
||||
type = uniq (nullOr path);
|
||||
example = "/path/to/file";
|
||||
default = null;
|
||||
@ -54,7 +51,7 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
hashedPassword = mkOption {
|
||||
hashedPassword = lib.mkOption {
|
||||
type = uniq (nullOr str);
|
||||
default = null;
|
||||
description = ''
|
||||
@ -66,7 +63,7 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
hashedPasswordFile = mkOption {
|
||||
hashedPasswordFile = lib.mkOption {
|
||||
type = uniq (nullOr path);
|
||||
example = "/path/to/file";
|
||||
default = null;
|
||||
@ -82,7 +79,7 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
acl = mkOption {
|
||||
acl = lib.mkOption {
|
||||
type = listOf str;
|
||||
example = [ "read A/B" "readwrite A/#" ];
|
||||
default = [];
|
||||
@ -94,15 +91,15 @@ let
|
||||
};
|
||||
|
||||
userAsserts = prefix: users:
|
||||
mapAttrsToList
|
||||
lib.mapAttrsToList
|
||||
(n: _: {
|
||||
assertion = builtins.match "[^:\r\n]+" n != null;
|
||||
message = "Invalid user name ${n} in ${prefix}";
|
||||
})
|
||||
users
|
||||
++ mapAttrsToList
|
||||
++ lib.mapAttrsToList
|
||||
(n: u: {
|
||||
assertion = count (s: s != null) [
|
||||
assertion = lib.count (s: s != null) [
|
||||
u.password u.passwordFile u.hashedPassword u.hashedPasswordFile
|
||||
] <= 1;
|
||||
message = "Cannot set more than one password option for user ${n} in ${prefix}";
|
||||
@ -112,26 +109,26 @@ let
|
||||
userScope = prefix: index: "${prefix}-user-${toString index}";
|
||||
credentialID = prefix: credential: "${prefix}-${credential}";
|
||||
|
||||
toScopedUsers = listenerScope: users: pipe users [
|
||||
attrNames
|
||||
(imap0 (index: user: nameValuePair user
|
||||
toScopedUsers = listenerScope: users: lib.pipe users [
|
||||
lib.attrNames
|
||||
(lib.imap0 (index: user: lib.nameValuePair user
|
||||
(users.${user} // { scope = userScope listenerScope index; })
|
||||
))
|
||||
listToAttrs
|
||||
lib.listToAttrs
|
||||
];
|
||||
|
||||
userCredentials = user: credentials: pipe credentials [
|
||||
(filter (credential: user.${credential} != null))
|
||||
userCredentials = user: credentials: lib.pipe credentials [
|
||||
(lib.filter (credential: user.${credential} != null))
|
||||
(map (credential: "${credentialID user.scope credential}:${user.${credential}}"))
|
||||
];
|
||||
usersCredentials = listenerScope: users: credentials: pipe users [
|
||||
usersCredentials = listenerScope: users: credentials: lib.pipe users [
|
||||
(toScopedUsers listenerScope)
|
||||
(mapAttrsToList (_: user: userCredentials user credentials))
|
||||
concatLists
|
||||
(lib.mapAttrsToList (_: user: userCredentials user credentials))
|
||||
lib.concatLists
|
||||
];
|
||||
systemdCredentials = listeners: listenerCredentials: pipe listeners [
|
||||
(imap0 (index: listener: listenerCredentials (listenerScope index) listener))
|
||||
concatLists
|
||||
systemdCredentials = listeners: listenerCredentials: lib.pipe listeners [
|
||||
(lib.imap0 (index: listener: listenerCredentials (listenerScope index) listener))
|
||||
lib.concatLists
|
||||
];
|
||||
|
||||
makePasswordFile = listenerScope: users: path:
|
||||
@ -139,12 +136,12 @@ let
|
||||
makeLines = store: file: let
|
||||
scopedUsers = toScopedUsers listenerScope users;
|
||||
in
|
||||
mapAttrsToList
|
||||
(name: user: ''addLine ${escapeShellArg name} "''$(systemd-creds cat ${credentialID user.scope store})"'')
|
||||
(filterAttrs (_: user: user.${store} != null) scopedUsers)
|
||||
++ mapAttrsToList
|
||||
(name: user: ''addFile ${escapeShellArg name} "''${CREDENTIALS_DIRECTORY}/${credentialID user.scope file}"'')
|
||||
(filterAttrs (_: user: user.${file} != null) scopedUsers);
|
||||
lib.mapAttrsToList
|
||||
(name: user: ''addLine ${lib.escapeShellArg name} "''$(systemd-creds cat ${credentialID user.scope store})"'')
|
||||
(lib.filterAttrs (_: user: user.${store} != null) scopedUsers)
|
||||
++ lib.mapAttrsToList
|
||||
(name: user: ''addFile ${lib.escapeShellArg name} "''${CREDENTIALS_DIRECTORY}/${credentialID user.scope file}"'')
|
||||
(lib.filterAttrs (_: user: user.${file} != null) scopedUsers);
|
||||
plainLines = makeLines "password" "passwordFile";
|
||||
hashedLines = makeLines "hashedPassword" "hashedPasswordFile";
|
||||
in
|
||||
@ -154,7 +151,7 @@ let
|
||||
|
||||
set -eu
|
||||
|
||||
file=${escapeShellArg path}
|
||||
file=${lib.escapeShellArg path}
|
||||
|
||||
rm -f "$file"
|
||||
touch "$file"
|
||||
@ -170,23 +167,23 @@ let
|
||||
echo "$1:$(cat "$2")" >> "$file"
|
||||
}
|
||||
''
|
||||
+ concatStringsSep "\n"
|
||||
+ lib.concatStringsSep "\n"
|
||||
(plainLines
|
||||
++ optional (plainLines != []) ''
|
||||
++ lib.optional (plainLines != []) ''
|
||||
${cfg.package}/bin/mosquitto_passwd -U "$file"
|
||||
''
|
||||
++ hashedLines));
|
||||
|
||||
authPluginOptions = with types; submodule {
|
||||
authPluginOptions = with lib.types; submodule {
|
||||
options = {
|
||||
plugin = mkOption {
|
||||
plugin = lib.mkOption {
|
||||
type = path;
|
||||
description = ''
|
||||
Plugin path to load, should be a `.so` file.
|
||||
'';
|
||||
};
|
||||
|
||||
denySpecialChars = mkOption {
|
||||
denySpecialChars = lib.mkOption {
|
||||
type = bool;
|
||||
description = ''
|
||||
Automatically disallow all clients using `#`
|
||||
@ -195,7 +192,7 @@ let
|
||||
default = true;
|
||||
};
|
||||
|
||||
options = mkOption {
|
||||
options = lib.mkOption {
|
||||
type = attrsOf optionType;
|
||||
description = ''
|
||||
Options for the auth plugin. Each key turns into a `auth_opt_*`
|
||||
@ -207,7 +204,7 @@ let
|
||||
};
|
||||
|
||||
authAsserts = prefix: auth:
|
||||
mapAttrsToList
|
||||
lib.mapAttrsToList
|
||||
(n: _: {
|
||||
assertion = configKey.check n;
|
||||
message = "Invalid auth plugin key ${prefix}.${n}";
|
||||
@ -253,9 +250,9 @@ let
|
||||
use_username_as_clientid = 1;
|
||||
};
|
||||
|
||||
listenerOptions = with types; submodule {
|
||||
listenerOptions = with lib.types; submodule {
|
||||
options = {
|
||||
port = mkOption {
|
||||
port = lib.mkOption {
|
||||
type = port;
|
||||
description = ''
|
||||
Port to listen on. Must be set to 0 to listen on a unix domain socket.
|
||||
@ -263,7 +260,7 @@ let
|
||||
default = 1883;
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
address = lib.mkOption {
|
||||
type = nullOr str;
|
||||
description = ''
|
||||
Address to listen on. Listen on `0.0.0.0`/`::`
|
||||
@ -272,7 +269,7 @@ let
|
||||
default = null;
|
||||
};
|
||||
|
||||
authPlugins = mkOption {
|
||||
authPlugins = lib.mkOption {
|
||||
type = listOf authPluginOptions;
|
||||
description = ''
|
||||
Authentication plugin to attach to this listener.
|
||||
@ -282,7 +279,7 @@ let
|
||||
default = [];
|
||||
};
|
||||
|
||||
users = mkOption {
|
||||
users = lib.mkOption {
|
||||
type = attrsOf userOptions;
|
||||
example = { john = { password = "123456"; acl = [ "readwrite john/#" ]; }; };
|
||||
description = ''
|
||||
@ -291,7 +288,7 @@ let
|
||||
default = {};
|
||||
};
|
||||
|
||||
omitPasswordAuth = mkOption {
|
||||
omitPasswordAuth = lib.mkOption {
|
||||
type = bool;
|
||||
description = ''
|
||||
Omits password checking, allowing anyone to log in with any user name unless
|
||||
@ -300,7 +297,7 @@ let
|
||||
default = false;
|
||||
};
|
||||
|
||||
acl = mkOption {
|
||||
acl = lib.mkOption {
|
||||
type = listOf str;
|
||||
description = ''
|
||||
Additional ACL items to prepend to the generated ACL file.
|
||||
@ -309,7 +306,7 @@ let
|
||||
default = [];
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
settings = lib.mkOption {
|
||||
type = submodule {
|
||||
freeformType = attrsOf optionType;
|
||||
};
|
||||
@ -324,7 +321,7 @@ let
|
||||
listenerAsserts = prefix: listener:
|
||||
assertKeysValid "${prefix}.settings" freeformListenerKeys listener.settings
|
||||
++ userAsserts prefix listener.users
|
||||
++ imap0
|
||||
++ lib.imap0
|
||||
(i: v: authAsserts "${prefix}.authPlugins.${toString i}" v)
|
||||
listener.authPlugins;
|
||||
|
||||
@ -333,9 +330,9 @@ let
|
||||
"listener ${toString listener.port} ${toString listener.address}"
|
||||
"acl_file /etc/mosquitto/acl-${toString idx}.conf"
|
||||
]
|
||||
++ optional (! listener.omitPasswordAuth) "password_file ${cfg.dataDir}/passwd-${toString idx}"
|
||||
++ lib.optional (! listener.omitPasswordAuth) "password_file ${cfg.dataDir}/passwd-${toString idx}"
|
||||
++ formatFreeform {} listener.settings
|
||||
++ concatMap formatAuthPlugin listener.authPlugins;
|
||||
++ lib.concatMap formatAuthPlugin listener.authPlugins;
|
||||
|
||||
freeformBridgeKeys = {
|
||||
bridge_alpn = 1;
|
||||
@ -373,19 +370,19 @@ let
|
||||
try_private = 1;
|
||||
};
|
||||
|
||||
bridgeOptions = with types; submodule {
|
||||
bridgeOptions = with lib.types; submodule {
|
||||
options = {
|
||||
addresses = mkOption {
|
||||
addresses = lib.mkOption {
|
||||
type = listOf (submodule {
|
||||
options = {
|
||||
address = mkOption {
|
||||
address = lib.mkOption {
|
||||
type = str;
|
||||
description = ''
|
||||
Address of the remote MQTT broker.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
port = lib.mkOption {
|
||||
type = port;
|
||||
description = ''
|
||||
Port of the remote MQTT broker.
|
||||
@ -400,7 +397,7 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
topics = mkOption {
|
||||
topics = lib.mkOption {
|
||||
type = listOf str;
|
||||
description = ''
|
||||
Topic patterns to be shared between the two brokers.
|
||||
@ -411,7 +408,7 @@ let
|
||||
example = [ "# both 2 local/topic/ remote/topic/" ];
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
settings = lib.mkOption {
|
||||
type = submodule {
|
||||
freeformType = attrsOf optionType;
|
||||
};
|
||||
@ -426,14 +423,14 @@ let
|
||||
bridgeAsserts = prefix: bridge:
|
||||
assertKeysValid "${prefix}.settings" freeformBridgeKeys bridge.settings
|
||||
++ [ {
|
||||
assertion = length bridge.addresses > 0;
|
||||
assertion = lib.length bridge.addresses > 0;
|
||||
message = "Bridge ${prefix} needs remote broker addresses";
|
||||
} ];
|
||||
|
||||
formatBridge = name: bridge:
|
||||
[
|
||||
"connection ${name}"
|
||||
"addresses ${concatMapStringsSep " " (a: "${a.address}:${toString a.port}") bridge.addresses}"
|
||||
"addresses ${lib.concatMapStringsSep " " (a: "${a.address}:${toString a.port}") bridge.addresses}"
|
||||
]
|
||||
++ map (t: "topic ${t}") bridge.topics
|
||||
++ formatFreeform {} bridge.settings;
|
||||
@ -468,12 +465,12 @@ let
|
||||
websockets_log_level = 1;
|
||||
};
|
||||
|
||||
globalOptions = with types; {
|
||||
enable = mkEnableOption "the MQTT Mosquitto broker";
|
||||
globalOptions = with lib.types; {
|
||||
enable = lib.mkEnableOption "the MQTT Mosquitto broker";
|
||||
|
||||
package = mkPackageOption pkgs "mosquitto" { };
|
||||
package = lib.mkPackageOption pkgs "mosquitto" { };
|
||||
|
||||
bridges = mkOption {
|
||||
bridges = lib.mkOption {
|
||||
type = attrsOf bridgeOptions;
|
||||
default = {};
|
||||
description = ''
|
||||
@ -481,7 +478,7 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
listeners = mkOption {
|
||||
listeners = lib.mkOption {
|
||||
type = listOf listenerOptions;
|
||||
default = [];
|
||||
description = ''
|
||||
@ -489,7 +486,7 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
includeDirs = mkOption {
|
||||
includeDirs = lib.mkOption {
|
||||
type = listOf path;
|
||||
description = ''
|
||||
Directories to be scanned for further config files to include.
|
||||
@ -500,7 +497,7 @@ let
|
||||
default = [];
|
||||
};
|
||||
|
||||
logDest = mkOption {
|
||||
logDest = lib.mkOption {
|
||||
type = listOf (either path (enum [ "stdout" "stderr" "syslog" "topic" "dlt" ]));
|
||||
description = ''
|
||||
Destinations to send log messages to.
|
||||
@ -508,7 +505,7 @@ let
|
||||
default = [ "stderr" ];
|
||||
};
|
||||
|
||||
logType = mkOption {
|
||||
logType = lib.mkOption {
|
||||
type = listOf (enum [ "debug" "error" "warning" "notice" "information"
|
||||
"subscribe" "unsubscribe" "websockets" "none" "all" ]);
|
||||
description = ''
|
||||
@ -517,7 +514,7 @@ let
|
||||
default = [];
|
||||
};
|
||||
|
||||
persistence = mkOption {
|
||||
persistence = lib.mkOption {
|
||||
type = bool;
|
||||
description = ''
|
||||
Enable persistent storage of subscriptions and messages.
|
||||
@ -525,15 +522,15 @@ let
|
||||
default = true;
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
dataDir = lib.mkOption {
|
||||
default = "/var/lib/mosquitto";
|
||||
type = types.path;
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
The data directory.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
settings = lib.mkOption {
|
||||
type = submodule {
|
||||
freeformType = attrsOf optionType;
|
||||
};
|
||||
@ -545,10 +542,10 @@ let
|
||||
};
|
||||
|
||||
globalAsserts = prefix: cfg:
|
||||
flatten [
|
||||
lib.flatten [
|
||||
(assertKeysValid "${prefix}.settings" freeformGlobalKeys cfg.settings)
|
||||
(imap0 (n: l: listenerAsserts "${prefix}.listener.${toString n}" l) cfg.listeners)
|
||||
(mapAttrsToList (n: b: bridgeAsserts "${prefix}.bridge.${n}" b) cfg.bridges)
|
||||
(lib.imap0 (n: l: listenerAsserts "${prefix}.listener.${toString n}" l) cfg.listeners)
|
||||
(lib.mapAttrsToList (n: b: bridgeAsserts "${prefix}.bridge.${n}" b) cfg.bridges)
|
||||
];
|
||||
|
||||
formatGlobal = cfg:
|
||||
@ -561,12 +558,12 @@ let
|
||||
cfg.logDest
|
||||
++ map (t: "log_type ${t}") cfg.logType
|
||||
++ formatFreeform {} cfg.settings
|
||||
++ concatLists (imap0 formatListener cfg.listeners)
|
||||
++ concatLists (mapAttrsToList formatBridge cfg.bridges)
|
||||
++ lib.concatLists (lib.imap0 formatListener cfg.listeners)
|
||||
++ lib.concatLists (lib.mapAttrsToList formatBridge cfg.bridges)
|
||||
++ map (d: "include_dir ${d}") cfg.includeDirs;
|
||||
|
||||
configFile = pkgs.writeText "mosquitto.conf"
|
||||
(concatStringsSep "\n" (formatGlobal cfg));
|
||||
(lib.concatStringsSep "\n" (formatGlobal cfg));
|
||||
|
||||
in
|
||||
|
||||
@ -578,7 +575,7 @@ in
|
||||
|
||||
###### Implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
assertions = globalAsserts "services.mosquitto" cfg;
|
||||
|
||||
@ -633,13 +630,13 @@ in
|
||||
ReadWritePaths = [
|
||||
cfg.dataDir
|
||||
"/tmp" # mosquitto_passwd creates files in /tmp before moving them
|
||||
] ++ filter path.check cfg.logDest;
|
||||
] ++ lib.filter path.check cfg.logDest;
|
||||
ReadOnlyPaths =
|
||||
map (p: "${p}")
|
||||
(cfg.includeDirs
|
||||
++ filter
|
||||
++ lib.filter
|
||||
(v: v != null)
|
||||
(flatten [
|
||||
(lib.flatten [
|
||||
(map
|
||||
(l: [
|
||||
(l.settings.psk_file or null)
|
||||
@ -652,7 +649,7 @@ in
|
||||
(l.settings.keyfile or null)
|
||||
])
|
||||
cfg.listeners)
|
||||
(mapAttrsToList
|
||||
(lib.mapAttrsToList
|
||||
(_: b: [
|
||||
(b.settings.bridge_cafile or null)
|
||||
(b.settings.bridge_capath or null)
|
||||
@ -680,26 +677,26 @@ in
|
||||
UMask = "0077";
|
||||
};
|
||||
preStart =
|
||||
concatStringsSep
|
||||
lib.concatStringsSep
|
||||
"\n"
|
||||
(imap0
|
||||
(lib.imap0
|
||||
(idx: listener: makePasswordFile (listenerScope idx) listener.users "${cfg.dataDir}/passwd-${toString idx}")
|
||||
cfg.listeners);
|
||||
};
|
||||
|
||||
environment.etc = listToAttrs (
|
||||
imap0
|
||||
environment.etc = lib.listToAttrs (
|
||||
lib.imap0
|
||||
(idx: listener: {
|
||||
name = "mosquitto/acl-${toString idx}.conf";
|
||||
value = {
|
||||
user = config.users.users.mosquitto.name;
|
||||
group = config.users.users.mosquitto.group;
|
||||
mode = "0400";
|
||||
text = (concatStringsSep
|
||||
text = (lib.concatStringsSep
|
||||
"\n"
|
||||
(flatten [
|
||||
(lib.flatten [
|
||||
listener.acl
|
||||
(mapAttrsToList
|
||||
(lib.mapAttrsToList
|
||||
(n: u: [ "user ${n}" ] ++ map (t: "topic ${t}") u.acl)
|
||||
listener.users)
|
||||
]));
|
||||
|
@ -1,7 +1,8 @@
|
||||
{ config
|
||||
, lib
|
||||
, pkgs
|
||||
, ...
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
@ -29,10 +30,9 @@ let
|
||||
|
||||
package = lib.mkPackageOption pkgs "wstunnel" { };
|
||||
|
||||
autoStart =
|
||||
lib.mkEnableOption "starting this wstunnel instance automatically" // {
|
||||
default = true;
|
||||
};
|
||||
autoStart = lib.mkEnableOption "starting this wstunnel instance automatically" // {
|
||||
default = true;
|
||||
};
|
||||
|
||||
extraArgs = lib.mkOption {
|
||||
description = ''
|
||||
@ -75,192 +75,198 @@ let
|
||||
};
|
||||
};
|
||||
|
||||
serverSubmodule = { config, ... }: {
|
||||
options = commonOptions // {
|
||||
listen = lib.mkOption {
|
||||
description = ''
|
||||
Address and port to listen on.
|
||||
Setting the port to a value below 1024 will also give the process
|
||||
the required `CAP_NET_BIND_SERVICE` capability.
|
||||
'';
|
||||
type = lib.types.submodule hostPortSubmodule;
|
||||
default = {
|
||||
host = "0.0.0.0";
|
||||
port = if config.enableHTTPS then 443 else 80;
|
||||
};
|
||||
defaultText = lib.literalExpression ''
|
||||
{
|
||||
serverSubmodule =
|
||||
{ config, ... }:
|
||||
{
|
||||
options = commonOptions // {
|
||||
listen = lib.mkOption {
|
||||
description = ''
|
||||
Address and port to listen on.
|
||||
Setting the port to a value below 1024 will also give the process
|
||||
the required `CAP_NET_BIND_SERVICE` capability.
|
||||
'';
|
||||
type = lib.types.submodule hostPortSubmodule;
|
||||
default = {
|
||||
host = "0.0.0.0";
|
||||
port = if enableHTTPS then 443 else 80;
|
||||
}
|
||||
'';
|
||||
};
|
||||
port = if config.enableHTTPS then 443 else 80;
|
||||
};
|
||||
defaultText = lib.literalExpression ''
|
||||
{
|
||||
host = "0.0.0.0";
|
||||
port = if enableHTTPS then 443 else 80;
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
restrictTo = lib.mkOption {
|
||||
description = ''
|
||||
Accepted traffic will be forwarded only to this service.
|
||||
'';
|
||||
type = lib.types.listOf (lib.types.submodule hostPortSubmodule);
|
||||
default = [ ];
|
||||
example = [{
|
||||
host = "127.0.0.1";
|
||||
port = 51820;
|
||||
}];
|
||||
};
|
||||
restrictTo = lib.mkOption {
|
||||
description = ''
|
||||
Accepted traffic will be forwarded only to this service.
|
||||
'';
|
||||
type = lib.types.listOf (lib.types.submodule hostPortSubmodule);
|
||||
default = [ ];
|
||||
example = [
|
||||
{
|
||||
host = "127.0.0.1";
|
||||
port = 51820;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
enableHTTPS = lib.mkOption {
|
||||
description = "Use HTTPS for the tunnel server.";
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
enableHTTPS = lib.mkOption {
|
||||
description = "Use HTTPS for the tunnel server.";
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
tlsCertificate = lib.mkOption {
|
||||
description = ''
|
||||
TLS certificate to use instead of the hardcoded one in case of HTTPS connections.
|
||||
Use together with `tlsKey`.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
example = "/var/lib/secrets/cert.pem";
|
||||
};
|
||||
tlsCertificate = lib.mkOption {
|
||||
description = ''
|
||||
TLS certificate to use instead of the hardcoded one in case of HTTPS connections.
|
||||
Use together with `tlsKey`.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
example = "/var/lib/secrets/cert.pem";
|
||||
};
|
||||
|
||||
tlsKey = lib.mkOption {
|
||||
description = ''
|
||||
TLS key to use instead of the hardcoded on in case of HTTPS connections.
|
||||
Use together with `tlsCertificate`.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
example = "/var/lib/secrets/key.pem";
|
||||
};
|
||||
tlsKey = lib.mkOption {
|
||||
description = ''
|
||||
TLS key to use instead of the hardcoded on in case of HTTPS connections.
|
||||
Use together with `tlsCertificate`.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
example = "/var/lib/secrets/key.pem";
|
||||
};
|
||||
|
||||
useACMEHost = lib.mkOption {
|
||||
description = ''
|
||||
Use a certificate generated by the NixOS ACME module for the given host.
|
||||
Note that this will not generate a new certificate - you will need to do so with `security.acme.certs`.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "example.com";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
clientSubmodule = { config, ... }: {
|
||||
options = commonOptions // {
|
||||
connectTo = lib.mkOption {
|
||||
description = "Server address and port to connect to.";
|
||||
type = lib.types.str;
|
||||
example = "https://wstunnel.server.com:8443";
|
||||
};
|
||||
|
||||
localToRemote = lib.mkOption {
|
||||
description = ''Listen on local and forwards traffic from remote.'';
|
||||
type = lib.types.listOf (lib.types.str);
|
||||
default = [ ];
|
||||
example = [
|
||||
"tcp://1212:google.com:443"
|
||||
"unix:///tmp/wstunnel.sock:g.com:443"
|
||||
];
|
||||
};
|
||||
|
||||
remoteToLocal = lib.mkOption {
|
||||
description = "Listen on remote and forwards traffic from local. Only tcp is supported";
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
example = [
|
||||
"tcp://1212:google.com:443"
|
||||
"unix://wstunnel.sock:g.com:443"
|
||||
];
|
||||
};
|
||||
|
||||
addNetBind = lib.mkEnableOption "Whether add CAP_NET_BIND_SERVICE to the tunnel service, this should be enabled if you want to bind port < 1024";
|
||||
|
||||
httpProxy = lib.mkOption {
|
||||
description = ''
|
||||
Proxy to use to connect to the wstunnel server (`USER:PASS@HOST:PORT`).
|
||||
|
||||
::: {.warning}
|
||||
Passwords specified here will be world-readable in the Nix store!
|
||||
To pass a password to the service, point the `environmentFile` option
|
||||
to a file containing `PROXY_PASSWORD=<your-password-here>` and set
|
||||
this option to `<user>:$PROXY_PASSWORD@<host>:<port>`.
|
||||
Note however that this will also locally leak the passwords at
|
||||
runtime via e.g. /proc/<pid>/cmdline.
|
||||
:::
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
};
|
||||
|
||||
soMark = lib.mkOption {
|
||||
description = ''
|
||||
Mark network packets with the SO_MARK sockoption with the specified value.
|
||||
Setting this option will also enable the required `CAP_NET_ADMIN` capability
|
||||
for the systemd service.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.ints.unsigned;
|
||||
default = null;
|
||||
};
|
||||
|
||||
upgradePathPrefix = lib.mkOption {
|
||||
description = ''
|
||||
Use a specific HTTP path prefix that will show up in the upgrade
|
||||
request to the `wstunnel` server.
|
||||
Useful when running `wstunnel` behind a reverse proxy.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "wstunnel";
|
||||
};
|
||||
|
||||
tlsSNI = lib.mkOption {
|
||||
description = "Use this as the SNI while connecting via TLS. Useful for circumventing hostname-based firewalls.";
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
};
|
||||
|
||||
tlsVerifyCertificate = lib.mkOption {
|
||||
description = "Whether to verify the TLS certificate of the server. It might be useful to set this to `false` when working with the `tlsSNI` option.";
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
# The original argument name `websocketPingFrequency` is a misnomer, as the frequency is the inverse of the interval.
|
||||
websocketPingInterval = lib.mkOption {
|
||||
description = "Frequency at which the client will send websocket ping to the server.";
|
||||
type = lib.types.nullOr lib.types.ints.unsigned;
|
||||
default = null;
|
||||
};
|
||||
|
||||
upgradeCredentials = lib.mkOption {
|
||||
description = ''
|
||||
Use these credentials to authenticate during the HTTP upgrade request
|
||||
(Basic authorization type, `USER:[PASS]`).
|
||||
|
||||
::: {.warning}
|
||||
Passwords specified here will be world-readable in the Nix store!
|
||||
To pass a password to the service, point the `environmentFile` option
|
||||
to a file containing `HTTP_PASSWORD=<your-password-here>` and set this
|
||||
option to `<user>:$HTTP_PASSWORD`.
|
||||
Note however that this will also locally leak the passwords at runtime
|
||||
via e.g. /proc/<pid>/cmdline.
|
||||
:::
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
};
|
||||
|
||||
customHeaders = lib.mkOption {
|
||||
description = "Custom HTTP headers to send during the upgrade request.";
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = { };
|
||||
example = {
|
||||
"X-Some-Header" = "some-value";
|
||||
useACMEHost = lib.mkOption {
|
||||
description = ''
|
||||
Use a certificate generated by the NixOS ACME module for the given host.
|
||||
Note that this will not generate a new certificate - you will need to do so with `security.acme.certs`.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "example.com";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
clientSubmodule =
|
||||
{ config, ... }:
|
||||
{
|
||||
options = commonOptions // {
|
||||
connectTo = lib.mkOption {
|
||||
description = "Server address and port to connect to.";
|
||||
type = lib.types.str;
|
||||
example = "https://wstunnel.server.com:8443";
|
||||
};
|
||||
|
||||
localToRemote = lib.mkOption {
|
||||
description = ''Listen on local and forwards traffic from remote.'';
|
||||
type = lib.types.listOf (lib.types.str);
|
||||
default = [ ];
|
||||
example = [
|
||||
"tcp://1212:google.com:443"
|
||||
"unix:///tmp/wstunnel.sock:g.com:443"
|
||||
];
|
||||
};
|
||||
|
||||
remoteToLocal = lib.mkOption {
|
||||
description = "Listen on remote and forwards traffic from local. Only tcp is supported";
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
example = [
|
||||
"tcp://1212:google.com:443"
|
||||
"unix://wstunnel.sock:g.com:443"
|
||||
];
|
||||
};
|
||||
|
||||
addNetBind = lib.mkEnableOption "Whether add CAP_NET_BIND_SERVICE to the tunnel service, this should be enabled if you want to bind port < 1024";
|
||||
|
||||
httpProxy = lib.mkOption {
|
||||
description = ''
|
||||
Proxy to use to connect to the wstunnel server (`USER:PASS@HOST:PORT`).
|
||||
|
||||
::: {.warning}
|
||||
Passwords specified here will be world-readable in the Nix store!
|
||||
To pass a password to the service, point the `environmentFile` option
|
||||
to a file containing `PROXY_PASSWORD=<your-password-here>` and set
|
||||
this option to `<user>:$PROXY_PASSWORD@<host>:<port>`.
|
||||
Note however that this will also locally leak the passwords at
|
||||
runtime via e.g. /proc/<pid>/cmdline.
|
||||
:::
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
};
|
||||
|
||||
soMark = lib.mkOption {
|
||||
description = ''
|
||||
Mark network packets with the SO_MARK sockoption with the specified value.
|
||||
Setting this option will also enable the required `CAP_NET_ADMIN` capability
|
||||
for the systemd service.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.ints.unsigned;
|
||||
default = null;
|
||||
};
|
||||
|
||||
upgradePathPrefix = lib.mkOption {
|
||||
description = ''
|
||||
Use a specific HTTP path prefix that will show up in the upgrade
|
||||
request to the `wstunnel` server.
|
||||
Useful when running `wstunnel` behind a reverse proxy.
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "wstunnel";
|
||||
};
|
||||
|
||||
tlsSNI = lib.mkOption {
|
||||
description = "Use this as the SNI while connecting via TLS. Useful for circumventing hostname-based firewalls.";
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
};
|
||||
|
||||
tlsVerifyCertificate = lib.mkOption {
|
||||
description = "Whether to verify the TLS certificate of the server. It might be useful to set this to `false` when working with the `tlsSNI` option.";
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
# The original argument name `websocketPingFrequency` is a misnomer, as the frequency is the inverse of the interval.
|
||||
websocketPingInterval = lib.mkOption {
|
||||
description = "Frequency at which the client will send websocket ping to the server.";
|
||||
type = lib.types.nullOr lib.types.ints.unsigned;
|
||||
default = null;
|
||||
};
|
||||
|
||||
upgradeCredentials = lib.mkOption {
|
||||
description = ''
|
||||
Use these credentials to authenticate during the HTTP upgrade request
|
||||
(Basic authorization type, `USER:[PASS]`).
|
||||
|
||||
::: {.warning}
|
||||
Passwords specified here will be world-readable in the Nix store!
|
||||
To pass a password to the service, point the `environmentFile` option
|
||||
to a file containing `HTTP_PASSWORD=<your-password-here>` and set this
|
||||
option to `<user>:$HTTP_PASSWORD`.
|
||||
Note however that this will also locally leak the passwords at runtime
|
||||
via e.g. /proc/<pid>/cmdline.
|
||||
:::
|
||||
'';
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
};
|
||||
|
||||
customHeaders = lib.mkOption {
|
||||
description = "Custom HTTP headers to send during the upgrade request.";
|
||||
type = lib.types.attrsOf lib.types.str;
|
||||
default = { };
|
||||
example = {
|
||||
"X-Some-Header" = "some-value";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
generateServerUnit = name: serverCfg: {
|
||||
name = "wstunnel-server-${name}";
|
||||
@ -270,22 +276,25 @@ let
|
||||
in
|
||||
{
|
||||
description = "wstunnel server - ${name}";
|
||||
requires = [ "network.target" "network-online.target" ];
|
||||
after = [ "network.target" "network-online.target" ];
|
||||
requires = [
|
||||
"network.target"
|
||||
"network-online.target"
|
||||
];
|
||||
after = [
|
||||
"network.target"
|
||||
"network-online.target"
|
||||
];
|
||||
wantedBy = lib.optional serverCfg.autoStart "multi-user.target";
|
||||
|
||||
environment.RUST_LOG = serverCfg.loggingLevel;
|
||||
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
EnvironmentFile =
|
||||
lib.optional (serverCfg.environmentFile != null) serverCfg.environmentFile;
|
||||
EnvironmentFile = lib.optional (serverCfg.environmentFile != null) serverCfg.environmentFile;
|
||||
DynamicUser = true;
|
||||
SupplementaryGroups =
|
||||
lib.optional (serverCfg.useACMEHost != null) certConfig.group;
|
||||
SupplementaryGroups = lib.optional (serverCfg.useACMEHost != null) certConfig.group;
|
||||
PrivateTmp = true;
|
||||
AmbientCapabilities =
|
||||
lib.optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
|
||||
AmbientCapabilities = lib.optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
|
||||
NoNewPrivileges = true;
|
||||
RestrictNamespaces = "uts ipc pid user cgroup";
|
||||
ProtectSystem = "strict";
|
||||
@ -305,19 +314,16 @@ let
|
||||
script = with serverCfg; ''
|
||||
${lib.getExe package} \
|
||||
server \
|
||||
${lib.cli.toGNUCommandLineShell { } (
|
||||
lib.recursiveUpdate
|
||||
{
|
||||
restrict-to = map hostPortToString restrictTo;
|
||||
tls-certificate = if useACMEHost != null
|
||||
then "${certConfig.directory}/fullchain.pem"
|
||||
else "${tlsCertificate}";
|
||||
tls-private-key = if useACMEHost != null
|
||||
then "${certConfig.directory}/key.pem"
|
||||
else "${tlsKey}";
|
||||
}
|
||||
extraArgs
|
||||
)} \
|
||||
${
|
||||
lib.cli.toGNUCommandLineShell { } (
|
||||
lib.recursiveUpdate {
|
||||
restrict-to = map hostPortToString restrictTo;
|
||||
tls-certificate =
|
||||
if useACMEHost != null then "${certConfig.directory}/fullchain.pem" else "${tlsCertificate}";
|
||||
tls-private-key = if useACMEHost != null then "${certConfig.directory}/key.pem" else "${tlsKey}";
|
||||
} extraArgs
|
||||
)
|
||||
} \
|
||||
${lib.escapeShellArg "${if enableHTTPS then "wss" else "ws"}://${hostPortToString listen}"}
|
||||
'';
|
||||
};
|
||||
@ -327,21 +333,26 @@ let
|
||||
name = "wstunnel-client-${name}";
|
||||
value = {
|
||||
description = "wstunnel client - ${name}";
|
||||
requires = [ "network.target" "network-online.target" ];
|
||||
after = [ "network.target" "network-online.target" ];
|
||||
requires = [
|
||||
"network.target"
|
||||
"network-online.target"
|
||||
];
|
||||
after = [
|
||||
"network.target"
|
||||
"network-online.target"
|
||||
];
|
||||
wantedBy = lib.optional clientCfg.autoStart "multi-user.target";
|
||||
|
||||
environment.RUST_LOG = clientCfg.loggingLevel;
|
||||
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
EnvironmentFile =
|
||||
lib.optional (clientCfg.environmentFile != null) clientCfg.environmentFile;
|
||||
EnvironmentFile = lib.optional (clientCfg.environmentFile != null) clientCfg.environmentFile;
|
||||
DynamicUser = true;
|
||||
PrivateTmp = true;
|
||||
AmbientCapabilities =
|
||||
(lib.optionals clientCfg.addNetBind [ "CAP_NET_BIND_SERVICE" ]) ++
|
||||
(lib.optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]);
|
||||
(lib.optionals clientCfg.addNetBind [ "CAP_NET_BIND_SERVICE" ])
|
||||
++ (lib.optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]);
|
||||
NoNewPrivileges = true;
|
||||
RestrictNamespaces = "uts ipc pid user cgroup";
|
||||
ProtectSystem = "strict";
|
||||
@ -361,22 +372,22 @@ let
|
||||
script = with clientCfg; ''
|
||||
${lib.getExe package} \
|
||||
client \
|
||||
${lib.cli.toGNUCommandLineShell { } (
|
||||
lib.recursiveUpdate
|
||||
{
|
||||
local-to-remote = localToRemote;
|
||||
remote-to-local = remoteToLocal;
|
||||
http-headers = lib.mapAttrsToList (n: v: "${n}:${v}") customHeaders;
|
||||
http-proxy = httpProxy;
|
||||
socket-so-mark = soMark;
|
||||
http-upgrade-path-prefix = upgradePathPrefix;
|
||||
tls-sni-override = tlsSNI;
|
||||
tls-verify-certificate = tlsVerifyCertificate;
|
||||
websocket-ping-frequency-sec = websocketPingInterval;
|
||||
http-upgrade-credentials = upgradeCredentials;
|
||||
}
|
||||
extraArgs
|
||||
)} \
|
||||
${
|
||||
lib.cli.toGNUCommandLineShell { } (
|
||||
lib.recursiveUpdate {
|
||||
local-to-remote = localToRemote;
|
||||
remote-to-local = remoteToLocal;
|
||||
http-headers = lib.mapAttrsToList (n: v: "${n}:${v}") customHeaders;
|
||||
http-proxy = httpProxy;
|
||||
socket-so-mark = soMark;
|
||||
http-upgrade-path-prefix = upgradePathPrefix;
|
||||
tls-sni-override = tlsSNI;
|
||||
tls-verify-certificate = tlsVerifyCertificate;
|
||||
websocket-ping-frequency-sec = websocketPingInterval;
|
||||
http-upgrade-credentials = upgradeCredentials;
|
||||
} extraArgs
|
||||
)
|
||||
} \
|
||||
${lib.escapeShellArg connectTo}
|
||||
'';
|
||||
};
|
||||
@ -399,10 +410,12 @@ in
|
||||
enableHTTPS = true;
|
||||
tlsCertificate = "/var/lib/secrets/fullchain.pem";
|
||||
tlsKey = "/var/lib/secrets/key.pem";
|
||||
restrictTo = [{
|
||||
host = "127.0.0.1";
|
||||
port = 51820;
|
||||
}];
|
||||
restrictTo = [
|
||||
{
|
||||
host = "127.0.0.1";
|
||||
port = 51820;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -429,40 +442,39 @@ in
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
systemd.services =
|
||||
(lib.mapAttrs' generateServerUnit (lib.filterAttrs (n: v: v.enable) cfg.servers)) //
|
||||
(lib.mapAttrs' generateClientUnit (lib.filterAttrs (n: v: v.enable) cfg.clients));
|
||||
(lib.mapAttrs' generateServerUnit (lib.filterAttrs (n: v: v.enable) cfg.servers))
|
||||
// (lib.mapAttrs' generateClientUnit (lib.filterAttrs (n: v: v.enable) cfg.clients));
|
||||
|
||||
assertions =
|
||||
(lib.mapAttrsToList
|
||||
(name: serverCfg: {
|
||||
assertion =
|
||||
!(serverCfg.useACMEHost != null && serverCfg.tlsCertificate != null);
|
||||
message = ''
|
||||
Options services.wstunnel.servers."${name}".useACMEHost and services.wstunnel.servers."${name}".{tlsCertificate, tlsKey} are mutually exclusive.
|
||||
'';
|
||||
})
|
||||
cfg.servers) ++
|
||||
(lib.mapAttrsToList (name: serverCfg: {
|
||||
assertion = !(serverCfg.useACMEHost != null && serverCfg.tlsCertificate != null);
|
||||
message = ''
|
||||
Options services.wstunnel.servers."${name}".useACMEHost and services.wstunnel.servers."${name}".{tlsCertificate, tlsKey} are mutually exclusive.
|
||||
'';
|
||||
}) cfg.servers)
|
||||
++
|
||||
|
||||
(lib.mapAttrsToList
|
||||
(name: serverCfg: {
|
||||
(lib.mapAttrsToList (name: serverCfg: {
|
||||
assertion =
|
||||
(serverCfg.tlsCertificate == null && serverCfg.tlsKey == null) ||
|
||||
(serverCfg.tlsCertificate != null && serverCfg.tlsKey != null);
|
||||
(serverCfg.tlsCertificate == null && serverCfg.tlsKey == null)
|
||||
|| (serverCfg.tlsCertificate != null && serverCfg.tlsKey != null);
|
||||
message = ''
|
||||
services.wstunnel.servers."${name}".tlsCertificate and services.wstunnel.servers."${name}".tlsKey need to be set together.
|
||||
'';
|
||||
})
|
||||
cfg.servers) ++
|
||||
}) cfg.servers)
|
||||
++
|
||||
|
||||
(lib.mapAttrsToList
|
||||
(name: clientCfg: {
|
||||
(lib.mapAttrsToList (name: clientCfg: {
|
||||
assertion = !(clientCfg.localToRemote == [ ] && clientCfg.remoteToLocal == [ ]);
|
||||
message = ''
|
||||
Either one of services.wstunnel.clients."${name}".localToRemote or services.wstunnel.clients."${name}".remoteToLocal must be set.
|
||||
'';
|
||||
})
|
||||
cfg.clients);
|
||||
}) cfg.clients);
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ alyaeanyx rvdp neverbehave ];
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
alyaeanyx
|
||||
rvdp
|
||||
neverbehave
|
||||
];
|
||||
}
|
||||
|
301
nixos/modules/services/web-apps/firefly-iii-data-importer.nix
Normal file
301
nixos/modules/services/web-apps/firefly-iii-data-importer.nix
Normal file
@ -0,0 +1,301 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.firefly-iii-data-importer;
|
||||
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
|
||||
defaultUser = "firefly-iii-data-importer";
|
||||
defaultGroup = "firefly-iii-data-importer";
|
||||
|
||||
artisan = "${cfg.package}/artisan";
|
||||
|
||||
env-file-values = lib.attrsets.mapAttrs' (
|
||||
n: v: lib.attrsets.nameValuePair (lib.strings.removeSuffix "_FILE" n) v
|
||||
) (lib.attrsets.filterAttrs (n: v: lib.strings.hasSuffix "_FILE" n) cfg.settings);
|
||||
env-nonfile-values = lib.attrsets.filterAttrs (n: v: !lib.strings.hasSuffix "_FILE" n) cfg.settings;
|
||||
|
||||
data-importer-maintenance = pkgs.writeShellScript "data-importer-maintenance.sh" ''
|
||||
set -a
|
||||
${lib.strings.toShellVars env-nonfile-values}
|
||||
${lib.strings.concatLines (
|
||||
lib.attrsets.mapAttrsToList (n: v: "${n}=\"$(< ${v})\"") env-file-values
|
||||
)}
|
||||
set +a
|
||||
${artisan} package:discover
|
||||
${artisan} cache:clear
|
||||
${artisan} config:cache
|
||||
'';
|
||||
|
||||
commonServiceConfig = {
|
||||
Type = "oneshot";
|
||||
User = user;
|
||||
Group = group;
|
||||
StateDirectory = "firefly-iii-data-importer";
|
||||
ReadWritePaths = [ cfg.dataDir ];
|
||||
WorkingDirectory = cfg.package;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
CapabilityBoundingSet = "";
|
||||
AmbientCapabilities = "";
|
||||
ProtectSystem = "strict";
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectClock = true;
|
||||
ProtectHostname = true;
|
||||
ProtectHome = "tmpfs";
|
||||
ProtectKernelLogs = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
PrivateNetwork = false;
|
||||
RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX";
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service @resources"
|
||||
"~@obsolete @privileged"
|
||||
];
|
||||
RestrictSUIDSGID = true;
|
||||
RemoveIPC = true;
|
||||
NoNewPrivileges = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictNamespaces = true;
|
||||
LockPersonality = true;
|
||||
PrivateUsers = true;
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
|
||||
options.services.firefly-iii-data-importer = {
|
||||
enable = lib.mkEnableOption "Firefly III Data Importer";
|
||||
|
||||
user = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = defaultUser;
|
||||
description = "User account under which firefly-iii-data-importer runs.";
|
||||
};
|
||||
|
||||
group = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = if cfg.enableNginx then "nginx" else defaultGroup;
|
||||
defaultText = "If `services.firefly-iii-data-importer.enableNginx` is true then `nginx` else ${defaultGroup}";
|
||||
description = ''
|
||||
Group under which firefly-iii-data-importer runs. It is best to set this to the group
|
||||
of whatever webserver is being used as the frontend.
|
||||
'';
|
||||
};
|
||||
|
||||
dataDir = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/var/lib/firefly-iii-data-importer";
|
||||
description = ''
|
||||
The place where firefly-iii data importer stores its state.
|
||||
'';
|
||||
};
|
||||
|
||||
package = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.firefly-iii-data-importer;
|
||||
defaultText = lib.literalExpression "pkgs.firefly-iii-data-importer";
|
||||
description = ''
|
||||
The firefly-iii-data-importer package served by php-fpm and the webserver of choice.
|
||||
This option can be used to point the webserver to the correct root. It
|
||||
may also be used to set the package to a different version, say a
|
||||
development version.
|
||||
'';
|
||||
apply =
|
||||
firefly-iii-data-importer:
|
||||
firefly-iii-data-importer.override (prev: {
|
||||
dataDir = cfg.dataDir;
|
||||
});
|
||||
};
|
||||
|
||||
enableNginx = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable nginx or not. If enabled, an nginx virtual host will
|
||||
be created for access to firefly-iii data importer. If not enabled, then you may use
|
||||
`''${config.services.firefly-iii-data-importer.package}` as your document root in
|
||||
whichever webserver you wish to setup.
|
||||
'';
|
||||
};
|
||||
|
||||
virtualHost = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "localhost";
|
||||
description = ''
|
||||
The hostname at which you wish firefly-iii-data-importer to be served. If you have
|
||||
enabled nginx using `services.firefly-iii-data-importer.enableNginx` then this will
|
||||
be used.
|
||||
'';
|
||||
};
|
||||
|
||||
poolConfig = lib.mkOption {
|
||||
type = lib.types.attrsOf (
|
||||
lib.types.oneOf [
|
||||
lib.types.str
|
||||
lib.types.int
|
||||
lib.types.bool
|
||||
]
|
||||
);
|
||||
default = { };
|
||||
defaultText = lib.literalExpression ''
|
||||
{
|
||||
"pm" = "dynamic";
|
||||
"pm.max_children" = 32;
|
||||
"pm.start_servers" = 2;
|
||||
"pm.min_spare_servers" = 2;
|
||||
"pm.max_spare_servers" = 4;
|
||||
"pm.max_requests" = 500;
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
Options for the Firefly III Data Importer PHP pool. See the documentation on <literal>php-fpm.conf</literal>
|
||||
for details on configuration directives.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
default = { };
|
||||
description = ''
|
||||
Options for firefly-iii data importer configuration. Refer to
|
||||
<https://github.com/firefly-iii/data-importer/blob/main/.env.example> for
|
||||
details on supported values. All <option>_FILE values supported by
|
||||
upstream are supported here.
|
||||
|
||||
APP_URL will be the same as `services.firefly-iii-data-importer.virtualHost` if the
|
||||
former is unset in `services.firefly-iii-data-importer.settings`.
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
APP_ENV = "local";
|
||||
LOG_CHANNEL = "syslog";
|
||||
FIREFLY_III_ACCESS_TOKEN= = "/var/secrets/firefly-iii-access-token.txt";
|
||||
}
|
||||
'';
|
||||
type = lib.types.submodule {
|
||||
freeformType = lib.types.attrsOf (
|
||||
lib.types.oneOf [
|
||||
lib.types.str
|
||||
lib.types.int
|
||||
lib.types.bool
|
||||
]
|
||||
);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.phpfpm.pools.firefly-iii-data-importer = {
|
||||
inherit user group;
|
||||
phpPackage = cfg.package.phpPackage;
|
||||
phpOptions = ''
|
||||
log_errors = on
|
||||
'';
|
||||
settings = {
|
||||
"listen.mode" = "0660";
|
||||
"listen.owner" = user;
|
||||
"listen.group" = group;
|
||||
"pm" = lib.mkDefault "dynamic";
|
||||
"pm.max_children" = lib.mkDefault 32;
|
||||
"pm.start_servers" = lib.mkDefault 2;
|
||||
"pm.min_spare_servers" = lib.mkDefault 2;
|
||||
"pm.max_spare_servers" = lib.mkDefault 4;
|
||||
"pm.max_requests" = lib.mkDefault 500;
|
||||
} // cfg.poolConfig;
|
||||
};
|
||||
|
||||
systemd.services.firefly-iii-data-importer-setup = {
|
||||
requiredBy = [ "phpfpm-firefly-iii-data-importer.service" ];
|
||||
before = [ "phpfpm-firefly-iii-data-importer.service" ];
|
||||
serviceConfig = {
|
||||
ExecStart = data-importer-maintenance;
|
||||
RemainAfterExit = true;
|
||||
} // commonServiceConfig;
|
||||
unitConfig.JoinsNamespaceOf = "phpfpm-firefly-iii-data-importer.service";
|
||||
restartTriggers = [ cfg.package ];
|
||||
};
|
||||
|
||||
services.nginx = lib.mkIf cfg.enableNginx {
|
||||
enable = true;
|
||||
recommendedTlsSettings = lib.mkDefault true;
|
||||
recommendedOptimisation = lib.mkDefault true;
|
||||
recommendedGzipSettings = lib.mkDefault true;
|
||||
virtualHosts.${cfg.virtualHost} = {
|
||||
root = "${cfg.package}/public";
|
||||
locations = {
|
||||
"/" = {
|
||||
tryFiles = "$uri $uri/ /index.php?$query_string";
|
||||
index = "index.php";
|
||||
extraConfig = ''
|
||||
sendfile off;
|
||||
'';
|
||||
};
|
||||
"~ \.php$" = {
|
||||
extraConfig = ''
|
||||
include ${config.services.nginx.package}/conf/fastcgi_params ;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
fastcgi_param modHeadersAvailable true;
|
||||
fastcgi_pass unix:${config.services.phpfpm.pools.firefly-iii-data-importer.socket};
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.settings."10-firefly-iii-data-importer" =
|
||||
lib.attrsets.genAttrs
|
||||
[
|
||||
"${cfg.dataDir}/storage"
|
||||
"${cfg.dataDir}/storage/app"
|
||||
"${cfg.dataDir}/storage/app/public"
|
||||
"${cfg.dataDir}/storage/configurations"
|
||||
"${cfg.dataDir}/storage/conversion-routines"
|
||||
"${cfg.dataDir}/storage/debugbar"
|
||||
"${cfg.dataDir}/storage/framework"
|
||||
"${cfg.dataDir}/storage/framework/cache"
|
||||
"${cfg.dataDir}/storage/framework/sessions"
|
||||
"${cfg.dataDir}/storage/framework/testing"
|
||||
"${cfg.dataDir}/storage/framework/views"
|
||||
"${cfg.dataDir}/storage/jobs"
|
||||
"${cfg.dataDir}/storage/logs"
|
||||
"${cfg.dataDir}/storage/submission-routines"
|
||||
"${cfg.dataDir}/storage/uploads"
|
||||
"${cfg.dataDir}/cache"
|
||||
]
|
||||
(n: {
|
||||
d = {
|
||||
group = group;
|
||||
mode = "0710";
|
||||
user = user;
|
||||
};
|
||||
})
|
||||
// {
|
||||
"${cfg.dataDir}".d = {
|
||||
group = group;
|
||||
mode = "0700";
|
||||
user = user;
|
||||
};
|
||||
};
|
||||
|
||||
users = {
|
||||
users = lib.mkIf (user == defaultUser) {
|
||||
${defaultUser} = {
|
||||
description = "Firefly-iii Data Importer service user";
|
||||
inherit group;
|
||||
isSystemUser = true;
|
||||
home = cfg.dataDir;
|
||||
};
|
||||
};
|
||||
groups = lib.mkIf (group == defaultGroup) { ${defaultGroup} = { }; };
|
||||
};
|
||||
};
|
||||
}
|
@ -135,6 +135,8 @@ in
|
||||
default = "freshrss";
|
||||
description = ''
|
||||
Name of the nginx virtualhost to use and setup. If null, do not setup any virtualhost.
|
||||
You may need to configure the virtualhost further through services.nginx.virtualHosts.<virtualhost>,
|
||||
for example to enable SSL.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -47,18 +47,20 @@ in
|
||||
environment = lib.mapAttrs (_: toString) cfg.environment;
|
||||
|
||||
# following https://github.com/Stirling-Tools/Stirling-PDF#locally
|
||||
path = with pkgs; [
|
||||
unpaper
|
||||
libreoffice
|
||||
ocrmypdf
|
||||
poppler_utils
|
||||
unoconv
|
||||
opencv
|
||||
pngquant
|
||||
tesseract
|
||||
python3Packages.weasyprint
|
||||
calibre
|
||||
];
|
||||
path =
|
||||
with pkgs;
|
||||
[
|
||||
unpaper
|
||||
libreoffice
|
||||
ocrmypdf
|
||||
poppler_utils
|
||||
unoconv
|
||||
opencv
|
||||
pngquant
|
||||
tesseract
|
||||
python3Packages.weasyprint
|
||||
]
|
||||
++ lib.optional (cfg.environment.INSTALL_BOOK_AND_ADVANCED_HTML_OPS or "false" == "true") calibre;
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
|
164
nixos/modules/services/web-apps/wakapi.nix
Normal file
164
nixos/modules/services/web-apps/wakapi.nix
Normal file
@ -0,0 +1,164 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.wakapi;
|
||||
|
||||
settingsFormat = pkgs.formats.yaml { };
|
||||
settingsFile = settingsFormat.generate "wakapi-settings" cfg.settings;
|
||||
|
||||
inherit (lib)
|
||||
getExe
|
||||
mkOption
|
||||
mkEnableOption
|
||||
mkPackageOption
|
||||
types
|
||||
mkIf
|
||||
optional
|
||||
mkMerge
|
||||
singleton
|
||||
;
|
||||
in
|
||||
{
|
||||
options.services.wakapi = {
|
||||
enable = mkEnableOption "Wakapi";
|
||||
package = mkPackageOption pkgs "wakapi" { };
|
||||
|
||||
settings = mkOption {
|
||||
inherit (settingsFormat) type;
|
||||
default = { };
|
||||
description = ''
|
||||
Settings for Wakapi.
|
||||
|
||||
See [config.default.yml](https://github.com/muety/wakapi/blob/master/config.default.yml) for a list of all possible options.
|
||||
'';
|
||||
};
|
||||
|
||||
passwordSalt = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
The password salt to use for Wakapi.
|
||||
'';
|
||||
};
|
||||
passwordSaltFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
The path to a file containing the password salt to use for Wakapi.
|
||||
'';
|
||||
};
|
||||
|
||||
smtpPassword = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
The password used for the smtp mailed to used by Wakapi.
|
||||
'';
|
||||
};
|
||||
smtpPasswordFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
The path to a file containing the password for the smtp mailer used by Wakapi.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.wakapi = {
|
||||
description = "Wakapi (self-hosted WakaTime-compatible backend)";
|
||||
wants = [
|
||||
"network-online.target"
|
||||
] ++ optional (cfg.settings.db.dialect == "postgres") "postgresql.service";
|
||||
after = [
|
||||
"network-online.target"
|
||||
] ++ optional (cfg.settings.db.dialect == "postgres") "postgresql.service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
script = ''
|
||||
exec ${getExe cfg.package} -config ${settingsFile}
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
Environment = mkMerge [
|
||||
(mkIf (cfg.passwordSalt != null) "WAKAPI_PASSWORD_SALT=${cfg.passwordSalt}")
|
||||
(mkIf (cfg.smtpPassword != null) "WAKAPI_MAIL_SMTP_PASS=${cfg.smtpPassword}")
|
||||
];
|
||||
EnvironmentFile = [
|
||||
(optional (cfg.passwordSaltFile != null) cfg.passwordSaltFile)
|
||||
(optional (cfg.smtpPasswordFile != null) cfg.smtpPasswordFile)
|
||||
];
|
||||
|
||||
User = config.users.users.wakapi.name;
|
||||
Group = config.users.users.wakapi.group;
|
||||
|
||||
DynamicUser = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_UNIX"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
StateDirectoryMode = "0700";
|
||||
Restart = "always";
|
||||
};
|
||||
};
|
||||
|
||||
services.wakapi.settings = {
|
||||
env = lib.mkDefault "production";
|
||||
};
|
||||
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.passwordSalt != null || cfg.passwordSaltFile != null;
|
||||
message = "Either `services.wakapi.passwordSalt` or `services.wakapi.passwordSaltFile` must be set.";
|
||||
}
|
||||
{
|
||||
assertion = cfg.passwordSalt != null -> cfg.passwordSaltFile != null;
|
||||
message = "Both `services.wakapi.passwordSalt` `services.wakapi.passwordSaltFile` should not be set at the same time.";
|
||||
}
|
||||
{
|
||||
assertion = cfg.smtpPassword != null -> cfg.smtpPasswordFile != null;
|
||||
message = "Both `services.wakapi.smtpPassword` `services.wakapi.smtpPasswordFile` should not be set at the same time.";
|
||||
}
|
||||
];
|
||||
|
||||
users = {
|
||||
users.wakapi = {
|
||||
group = "wakapi";
|
||||
createHome = false;
|
||||
isSystemUser = true;
|
||||
};
|
||||
groups.wakapi = { };
|
||||
};
|
||||
|
||||
services.postgresql = mkIf (cfg.settings.db.dialect == "postgres") {
|
||||
enable = true;
|
||||
|
||||
ensureDatabases = singleton cfg.settings.db.name;
|
||||
ensureUsers = singleton {
|
||||
name = cfg.settings.db.user;
|
||||
ensureDBOwnership = true;
|
||||
};
|
||||
|
||||
authentication = ''
|
||||
host ${cfg.settings.db.name} ${cfg.settings.db.user} 127.0.0.1/32 trust
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ isabelroses ];
|
||||
}
|
@ -33,6 +33,7 @@ CAN_TOUCH_EFI_VARIABLES = "@canTouchEfiVariables@"
|
||||
GRACEFUL = "@graceful@"
|
||||
COPY_EXTRA_FILES = "@copyExtraFiles@"
|
||||
CHECK_MOUNTPOINTS = "@checkMountpoints@"
|
||||
STORE_DIR = "@storeDir@"
|
||||
|
||||
@dataclass
|
||||
class BootSpec:
|
||||
@ -106,7 +107,7 @@ def write_loader_conf(profile: str | None, generation: int, specialisation: str
|
||||
if not EDITOR:
|
||||
f.write("editor 0\n")
|
||||
if REBOOT_FOR_BITLOCKER:
|
||||
f.write("reboot-for-bitlocker yes\n");
|
||||
f.write("reboot-for-bitlocker yes\n")
|
||||
f.write(f"console-mode {CONSOLE_MODE}\n")
|
||||
f.flush()
|
||||
os.fsync(f.fileno())
|
||||
@ -150,12 +151,13 @@ def bootspec_from_json(bootspec_json: dict[str, Any]) -> BootSpec:
|
||||
def copy_from_file(file: str, dry_run: bool = False) -> str:
|
||||
store_file_path = os.path.realpath(file)
|
||||
suffix = os.path.basename(store_file_path)
|
||||
store_dir = os.path.basename(os.path.dirname(store_file_path))
|
||||
efi_file_path = f"{NIXOS_DIR}/{store_dir}-{suffix}.efi"
|
||||
store_subdir = os.path.relpath(store_file_path, start=STORE_DIR).split(os.path.sep)[0]
|
||||
efi_file_path = f"{NIXOS_DIR}/{suffix}.efi" if suffix == store_subdir else f"{NIXOS_DIR}/{store_subdir}-{suffix}.efi"
|
||||
if not dry_run:
|
||||
copy_if_not_exists(store_file_path, f"{BOOT_MOUNT_POINT}{efi_file_path}")
|
||||
return efi_file_path
|
||||
|
||||
|
||||
def write_entry(profile: str | None, generation: int, specialisation: str | None,
|
||||
machine_id: str, bootspec: BootSpec, current: bool) -> None:
|
||||
if specialisation:
|
||||
|
@ -28,6 +28,8 @@ let
|
||||
|
||||
isExecutable = true;
|
||||
|
||||
inherit (builtins) storeDir;
|
||||
|
||||
inherit (pkgs) python3;
|
||||
|
||||
systemd = config.systemd.package;
|
||||
|
@ -23,6 +23,8 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
unprivilegedContainers = lib.mkEnableOption "support for unprivileged users to launch containers";
|
||||
|
||||
systemConfig =
|
||||
lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
@ -53,6 +55,15 @@ in
|
||||
administration access in LXC. See {manpage}`lxc-usernet(5)`.
|
||||
'';
|
||||
};
|
||||
|
||||
bridgeConfig =
|
||||
lib.mkOption {
|
||||
type = lib.types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
This is the config file for override lxc-net bridge default settings.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
###### implementation
|
||||
@ -62,6 +73,8 @@ in
|
||||
environment.etc."lxc/lxc.conf".text = cfg.systemConfig;
|
||||
environment.etc."lxc/lxc-usernet".text = cfg.usernetConfig;
|
||||
environment.etc."lxc/default.conf".text = cfg.defaultConfig;
|
||||
environment.etc."lxc/lxc-net".text = cfg.bridgeConfig;
|
||||
environment.pathsToLink = [ "/share/lxc" ];
|
||||
systemd.tmpfiles.rules = [ "d /var/lib/lxc/rootfs 0755 root root -" ];
|
||||
|
||||
security.apparmor.packages = [ cfg.package ];
|
||||
@ -73,5 +86,30 @@ in
|
||||
include ${cfg.package}/etc/apparmor.d/lxc-containers
|
||||
'';
|
||||
};
|
||||
|
||||
# We don't need the `lxc-user` group, unless the unprivileged containers are enabled.
|
||||
users.groups = lib.mkIf cfg.unprivilegedContainers { lxc-user = {}; };
|
||||
|
||||
# `lxc-user-nic` needs suid to attach to bridge for unpriv containers.
|
||||
security.wrappers = lib.mkIf cfg.unprivilegedContainers {
|
||||
lxcUserNet = {
|
||||
source = "${pkgs.lxc}/libexec/lxc/lxc-user-nic";
|
||||
setuid = true;
|
||||
owner = "root";
|
||||
group = "lxc-user";
|
||||
program = "lxc-user-nic";
|
||||
permissions = "u+rx,g+x,o-rx";
|
||||
};
|
||||
};
|
||||
|
||||
# Add lxc-net service if unpriv mode is enabled.
|
||||
systemd.packages = lib.mkIf cfg.unprivilegedContainers [ pkgs.lxc ];
|
||||
systemd.services = lib.mkIf cfg.unprivilegedContainers {
|
||||
lxc-net = {
|
||||
enable = true;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ pkgs.iproute2 pkgs.iptables pkgs.getent pkgs.dnsmasq ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -326,6 +326,7 @@ in {
|
||||
filesender = handleTest ./filesender.nix {};
|
||||
filesystems-overlayfs = runTest ./filesystems-overlayfs.nix;
|
||||
firefly-iii = handleTest ./firefly-iii.nix {};
|
||||
firefly-iii-data-importer = handleTest ./firefly-iii-data-importer.nix {};
|
||||
firefox = handleTest ./firefox.nix { firefoxPackage = pkgs.firefox; };
|
||||
firefox-beta = handleTest ./firefox.nix { firefoxPackage = pkgs.firefox-beta; };
|
||||
firefox-devedition = handleTest ./firefox.nix { firefoxPackage = pkgs.firefox-devedition; };
|
||||
@ -538,6 +539,7 @@ in {
|
||||
loki = handleTest ./loki.nix {};
|
||||
luks = handleTest ./luks.nix {};
|
||||
lvm2 = handleTest ./lvm2 {};
|
||||
lxc = handleTest ./lxc {};
|
||||
lxd = pkgs.recurseIntoAttrs (handleTest ./lxd { inherit handleTestOn; });
|
||||
lxd-image-server = handleTest ./lxd-image-server.nix {};
|
||||
#logstash = handleTest ./logstash.nix {};
|
||||
|
27
nixos/tests/firefly-iii-data-importer.nix
Normal file
27
nixos/tests/firefly-iii-data-importer.nix
Normal file
@ -0,0 +1,27 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
name = "firefly-iii-data-importer";
|
||||
meta.maintainers = [ lib.maintainers.savyajha ];
|
||||
|
||||
nodes.dataImporter =
|
||||
{ ... }:
|
||||
{
|
||||
services.firefly-iii-data-importer = {
|
||||
enable = true;
|
||||
enableNginx = true;
|
||||
settings = {
|
||||
LOG_CHANNEL = "stdout";
|
||||
USE_CACHE = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
dataImporter.wait_for_unit("phpfpm-firefly-iii-data-importer.service")
|
||||
dataImporter.wait_for_unit("nginx.service")
|
||||
dataImporter.succeed("curl -fvvv -Ls http://localhost/token | grep 'Firefly III Data Import Tool'")
|
||||
'';
|
||||
}
|
||||
)
|
@ -11,8 +11,8 @@ let
|
||||
extra;
|
||||
};
|
||||
|
||||
container-image-metadata = releases.incusContainerMeta.${pkgs.stdenv.hostPlatform.system};
|
||||
container-image-rootfs = releases.incusContainerImage.${pkgs.stdenv.hostPlatform.system};
|
||||
container-image-metadata = "${releases.incusContainerMeta.${pkgs.stdenv.hostPlatform.system}}/tarball/nixos-system-${pkgs.stdenv.hostPlatform.system}.tar.xz";
|
||||
container-image-rootfs = "${releases.incusContainerImage.${pkgs.stdenv.hostPlatform.system}}/nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}.squashfs";
|
||||
in
|
||||
{
|
||||
inherit name;
|
||||
@ -61,7 +61,7 @@ in
|
||||
machine.succeed("incus admin init --minimal")
|
||||
|
||||
with subtest("Container image can be imported"):
|
||||
machine.succeed("incus image import ${container-image-metadata}/*/*.tar.xz ${container-image-rootfs} --alias nixos")
|
||||
machine.succeed("incus image import ${container-image-metadata} ${container-image-rootfs} --alias nixos")
|
||||
|
||||
with subtest("Container can be launched and managed"):
|
||||
machine.succeed("incus launch nixos container")
|
||||
|
@ -16,8 +16,12 @@ import ../make-test-python.nix (
|
||||
};
|
||||
};
|
||||
|
||||
container-image-metadata = releases.incusContainerMeta.${pkgs.stdenv.hostPlatform.system};
|
||||
container-image-rootfs = releases.incusContainerImage.${pkgs.stdenv.hostPlatform.system};
|
||||
container-image-metadata = "${
|
||||
releases.incusContainerMeta.${pkgs.stdenv.hostPlatform.system}
|
||||
}/tarball/nixos-system-${pkgs.stdenv.hostPlatform.system}.tar.xz";
|
||||
container-image-rootfs = "${
|
||||
releases.incusContainerImage.${pkgs.stdenv.hostPlatform.system}
|
||||
}/nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}.squashfs";
|
||||
in
|
||||
{
|
||||
name = "incusd-options";
|
||||
@ -87,7 +91,7 @@ import ../make-test-python.nix (
|
||||
machine.wait_for_unit("incus-preseed.service")
|
||||
|
||||
with subtest("Container image can be imported"):
|
||||
machine.succeed("incus image import ${container-image-metadata}/*/*.tar.xz ${container-image-rootfs} --alias nixos")
|
||||
machine.succeed("incus image import ${container-image-metadata} ${container-image-rootfs} --alias nixos")
|
||||
|
||||
with subtest("Container can be launched and managed"):
|
||||
machine.succeed("incus launch nixos container")
|
||||
|
124
nixos/tests/lxc/default.nix
Normal file
124
nixos/tests/lxc/default.nix
Normal file
@ -0,0 +1,124 @@
|
||||
import ../make-test-python.nix (
|
||||
{ pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
releases = import ../../release.nix {
|
||||
configuration = {
|
||||
# Building documentation makes the test unnecessarily take a longer time:
|
||||
documentation.enable = lib.mkForce false;
|
||||
};
|
||||
};
|
||||
|
||||
lxc-image-metadata = releases.lxdContainerMeta.${pkgs.stdenv.hostPlatform.system};
|
||||
lxc-image-rootfs = releases.lxdContainerImage.${pkgs.stdenv.hostPlatform.system};
|
||||
|
||||
in
|
||||
{
|
||||
name = "lxc-container-unprivileged";
|
||||
|
||||
meta = {
|
||||
maintainers = lib.teams.lxc.members;
|
||||
};
|
||||
|
||||
nodes.machine =
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
virtualisation = {
|
||||
diskSize = 6144;
|
||||
cores = 2;
|
||||
memorySize = 512;
|
||||
writableStore = true;
|
||||
|
||||
lxc = {
|
||||
enable = true;
|
||||
unprivilegedContainers = true;
|
||||
systemConfig = ''
|
||||
lxc.lxcpath = /tmp/lxc
|
||||
'';
|
||||
defaultConfig = ''
|
||||
lxc.net.0.type = veth
|
||||
lxc.net.0.link = lxcbr0
|
||||
lxc.net.0.flags = up
|
||||
lxc.net.0.hwaddr = 00:16:3e:xx:xx:xx
|
||||
lxc.idmap = u 0 100000 65536
|
||||
lxc.idmap = g 0 100000 65536
|
||||
'';
|
||||
# Permit user alice to connect to bridge
|
||||
usernetConfig = ''
|
||||
@lxc-user veth lxcbr0 10
|
||||
'';
|
||||
bridgeConfig = ''
|
||||
LXC_IPV6_ADDR=""
|
||||
LXC_IPV6_MASK=""
|
||||
LXC_IPV6_NETWORK=""
|
||||
LXC_IPV6_NAT="false"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# Needed for lxc
|
||||
environment.systemPackages = with pkgs; [
|
||||
pkgs.wget
|
||||
pkgs.dnsmasq
|
||||
];
|
||||
|
||||
# Create user for test
|
||||
users.users.alice = {
|
||||
isNormalUser = true;
|
||||
password = "test";
|
||||
description = "Lxc unprivileged user with access to lxcbr0";
|
||||
extraGroups = [ "lxc-user" ];
|
||||
subGidRanges = [
|
||||
{
|
||||
startGid = 100000;
|
||||
count = 65536;
|
||||
}
|
||||
];
|
||||
subUidRanges = [
|
||||
{
|
||||
startUid = 100000;
|
||||
count = 65536;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
users.users.bob = {
|
||||
isNormalUser = true;
|
||||
password = "test";
|
||||
description = "Lxc unprivileged user without access to lxcbr0";
|
||||
subGidRanges = [
|
||||
{
|
||||
startGid = 100000;
|
||||
count = 65536;
|
||||
}
|
||||
];
|
||||
subUidRanges = [
|
||||
{
|
||||
startUid = 100000;
|
||||
count = 65536;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("lxc-net.service")
|
||||
|
||||
# Copy config files for alice
|
||||
machine.execute("su -- alice -c 'mkdir -p ~/.config/lxc'")
|
||||
machine.execute("su -- alice -c 'cp /etc/lxc/default.conf ~/.config/lxc/'")
|
||||
machine.execute("su -- alice -c 'cp /etc/lxc/lxc.conf ~/.config/lxc/'")
|
||||
|
||||
machine.succeed("su -- alice -c 'lxc-create -t local -n test -- --metadata ${lxc-image-metadata}/*/*.tar.xz --fstree ${lxc-image-rootfs}/*/*.tar.xz'")
|
||||
machine.succeed("su -- alice -c 'lxc-start test'")
|
||||
machine.succeed("su -- alice -c 'lxc-stop test'")
|
||||
|
||||
# Copy config files for bob
|
||||
machine.execute("su -- bob -c 'mkdir -p ~/.config/lxc'")
|
||||
machine.execute("su -- bob -c 'cp /etc/lxc/default.conf ~/.config/lxc/'")
|
||||
machine.execute("su -- bob -c 'cp /etc/lxc/lxc.conf ~/.config/lxc/'")
|
||||
|
||||
machine.fail("su -- bob -c 'lxc-start test'")
|
||||
'';
|
||||
}
|
||||
)
|
@ -64,7 +64,7 @@ in {
|
||||
|
||||
with subtest("Squashfs image is functional"):
|
||||
machine.succeed(
|
||||
"lxc image import ${lxd-image-metadata}/*/*.tar.xz ${lxd-image-rootfs-squashfs} --alias nixos-squashfs"
|
||||
"lxc image import ${lxd-image-metadata}/*/*.tar.xz ${lxd-image-rootfs-squashfs}/nixos-lxc-image-${pkgs.stdenv.hostPlatform.system}.squashfs --alias nixos-squashfs"
|
||||
)
|
||||
machine.succeed("lxc launch nixos-squashfs container")
|
||||
with machine.nested("Waiting for instance to start and be usable"):
|
||||
|
@ -200,7 +200,7 @@ in
|
||||
)
|
||||
'' + pkgs.lib.optionalString pkgs.stdenv.hostPlatform.isAarch64 ''
|
||||
machine.succeed(
|
||||
"grep 'devicetree .*dummy' /boot/loader/entries/nixos-generation-1-specialisation-something.conf"
|
||||
r"grep 'devicetree /EFI/nixos/[a-z0-9]\{32\}.*dummy' /boot/loader/entries/nixos-generation-1-specialisation-something.conf"
|
||||
)
|
||||
'';
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }: {
|
||||
nodes.machine = { pkgs, ... }: {
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
glxinfo
|
||||
mesa-demos
|
||||
procps # for `pkill`, `pidof` in the test
|
||||
scrot # for screenshotting Xorg
|
||||
turbovnc
|
||||
|
@ -60,37 +60,34 @@ in
|
||||
clients.my-client = {
|
||||
autoStart = false;
|
||||
connectTo = "wss://${domain}:443";
|
||||
localToRemote = [
|
||||
"tcp://8080:localhost:2080"
|
||||
];
|
||||
remoteToLocal = [
|
||||
"tcp://2081:localhost:8081"
|
||||
];
|
||||
localToRemote = [ "tcp://8080:localhost:2080" ];
|
||||
remoteToLocal = [ "tcp://2081:localhost:8081" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = /* python */ ''
|
||||
start_all()
|
||||
server.wait_for_unit("wstunnel-server-my-server.service")
|
||||
client.wait_for_open_port(443, "10.0.0.1")
|
||||
testScript = # python
|
||||
''
|
||||
start_all()
|
||||
server.wait_for_unit("wstunnel-server-my-server.service")
|
||||
client.wait_for_open_port(443, "10.0.0.1")
|
||||
|
||||
client.systemctl("start wstunnel-client-my-client.service")
|
||||
client.wait_for_unit("wstunnel-client-my-client.service")
|
||||
client.systemctl("start wstunnel-client-my-client.service")
|
||||
client.wait_for_unit("wstunnel-client-my-client.service")
|
||||
|
||||
with subtest("connection from client to server"):
|
||||
server.succeed("nc -l 2080 >/tmp/msg &")
|
||||
client.sleep(1)
|
||||
client.succeed('nc -w1 localhost 8080 <<<"Hello from client"')
|
||||
server.succeed('grep "Hello from client" /tmp/msg')
|
||||
with subtest("connection from client to server"):
|
||||
server.succeed("nc -l 2080 >/tmp/msg &")
|
||||
client.sleep(1)
|
||||
client.succeed('nc -w1 localhost 8080 <<<"Hello from client"')
|
||||
server.succeed('grep "Hello from client" /tmp/msg')
|
||||
|
||||
with subtest("connection from server to client"):
|
||||
client.succeed("nc -l 8081 >/tmp/msg &")
|
||||
server.sleep(1)
|
||||
server.succeed('nc -w1 localhost 2081 <<<"Hello from server"')
|
||||
client.succeed('grep "Hello from server" /tmp/msg')
|
||||
with subtest("connection from server to client"):
|
||||
client.succeed("nc -l 8081 >/tmp/msg &")
|
||||
server.sleep(1)
|
||||
server.succeed('nc -w1 localhost 2081 <<<"Hello from server"')
|
||||
client.succeed('grep "Hello from server" /tmp/msg')
|
||||
|
||||
client.systemctl("stop wstunnel-client-my-client.service")
|
||||
'';
|
||||
client.systemctl("stop wstunnel-client-my-client.service")
|
||||
'';
|
||||
}
|
||||
|
@ -33,13 +33,13 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
ELECTRON_SKIP_BINARY_DOWNLOAD = 1;
|
||||
|
||||
postBuild = lib.optionalString stdenv.isDarwin ''
|
||||
cp -R ${electron}/Applications/Electron.app Electron.app
|
||||
cp -R ${electron.dist}/Electron.app Electron.app
|
||||
chmod -R u+w Electron.app
|
||||
'' + ''
|
||||
pnpm build
|
||||
./node_modules/.bin/electron-builder \
|
||||
--dir \
|
||||
-c.electronDist=${if stdenv.isDarwin then "." else "${electron}/libexec/electron"} \
|
||||
-c.electronDist=${if stdenv.isDarwin then "." else electron.dist} \
|
||||
-c.electronVersion=${electron.version}
|
||||
'';
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
, file
|
||||
, fontsConf
|
||||
, git
|
||||
, glxinfo
|
||||
, gnugrep
|
||||
, gnused
|
||||
, gnutar
|
||||
@ -30,6 +29,7 @@
|
||||
, libX11
|
||||
, libxcb
|
||||
, libxkbcommon
|
||||
, mesa-demos
|
||||
, xcbutilwm
|
||||
, xcbutilrenderutil
|
||||
, xcbutilkeysyms
|
||||
@ -107,7 +107,7 @@ let
|
||||
|
||||
# For Android emulator
|
||||
file
|
||||
glxinfo
|
||||
mesa-demos
|
||||
pciutils
|
||||
setxkbmap
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
lib,
|
||||
consult,
|
||||
embark,
|
||||
embark-consult,
|
||||
fetchFromGitHub,
|
||||
forge,
|
||||
gh,
|
||||
@ -12,24 +12,26 @@
|
||||
|
||||
melpaBuild {
|
||||
pname = "consult-gh";
|
||||
version = "1.0-unstable-2024-08-11";
|
||||
version = "1.0-unstable-2024-08-24";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "armindarvish";
|
||||
repo = "consult-gh";
|
||||
rev = "640d4b9c71aa6dfff4f29c0207cc02316f1d61c8";
|
||||
hash = "sha256-hFHex4cUAP1U5aK1bfa+va1jiWS8tRqtnMGxr17NWio=";
|
||||
rev = "b1d85d179438e4b6469e1b78906a7dde8f07c822";
|
||||
hash = "sha256-VmxuXvO0nl0h9IKU+XWfjW90KG/1B+qHoOVhvYJ8XTs=";
|
||||
};
|
||||
|
||||
packageRequires = [
|
||||
consult
|
||||
embark
|
||||
embark-consult
|
||||
forge
|
||||
markdown-mode
|
||||
];
|
||||
|
||||
propagatedUserEnvPkgs = [ gh ];
|
||||
|
||||
ignoreCompilationError = false;
|
||||
|
||||
passthru.updateScript = unstableGitUpdater { };
|
||||
|
||||
meta = {
|
||||
|
@ -10,16 +10,16 @@ let
|
||||
in
|
||||
rustPlatform.buildRustPackage {
|
||||
pname = "lspce-module";
|
||||
version = "1.1.0-unstable-2024-07-14";
|
||||
version = "1.1.0-unstable-2024-07-29";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "zbelial";
|
||||
repo = "lspce";
|
||||
rev = "fd320476df89cfd5d10f1b70303c891d3b1e3c81";
|
||||
hash = "sha256-KnERYq/CvJhJIdQkpH/m82t9KFMapPl+CyZkYyujslU=";
|
||||
rev = "e954e4d77aeb45deb14182631f3d5aa9bcc9e587";
|
||||
hash = "sha256-9AUffkdgvVbHRIrHQPVl36plIfGxf3vsN9JCuFe0P6Q=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-I2OobRu1hc6xc4bRrIO1FImPYBbFy1jXPcTsivbbskk=";
|
||||
cargoHash = "sha256-wrrdXX/rEVxmHdyblm4I9iHD3bPoDd1KlBe3ODeGFeM=";
|
||||
|
||||
checkFlags = [
|
||||
# flaky test
|
||||
|
@ -1,77 +0,0 @@
|
||||
{ lib
|
||||
, python3
|
||||
, fetchFromGitHub
|
||||
, meson
|
||||
, ninja
|
||||
, gettext
|
||||
, appstream
|
||||
, appstream-glib
|
||||
, wrapGAppsHook4
|
||||
, desktop-file-utils
|
||||
, gobject-introspection
|
||||
, gtk4
|
||||
, gtksourceview5
|
||||
, libadwaita
|
||||
, libportal
|
||||
, librsvg
|
||||
, poppler_gi
|
||||
, webkitgtk_6_0
|
||||
}:
|
||||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "setzer";
|
||||
version = "65";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "cvfosammmm";
|
||||
repo = "Setzer";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-5Hpj/RkD11bNcr9/gQG0Y7BNMsh1BGZQiN4IMbI4osc=";
|
||||
};
|
||||
|
||||
format = "other";
|
||||
|
||||
nativeBuildInputs = [
|
||||
meson
|
||||
ninja
|
||||
gettext
|
||||
appstream # for appstreamcli
|
||||
appstream-glib
|
||||
wrapGAppsHook4
|
||||
desktop-file-utils
|
||||
gobject-introspection
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
gtk4
|
||||
gtksourceview5
|
||||
libadwaita
|
||||
libportal
|
||||
librsvg
|
||||
poppler_gi
|
||||
webkitgtk_6_0
|
||||
];
|
||||
|
||||
propagatedBuildInputs = with python3.pkgs; [
|
||||
bibtexparser
|
||||
numpy
|
||||
pdfminer-six
|
||||
pexpect
|
||||
pillow
|
||||
pycairo
|
||||
pygobject3
|
||||
pyxdg
|
||||
];
|
||||
|
||||
checkPhase = ''
|
||||
meson test --print-errorlogs
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "LaTeX editor written in Python with Gtk";
|
||||
mainProgram = "setzer";
|
||||
homepage = src.meta.homepage;
|
||||
license = licenses.gpl3Plus;
|
||||
maintainers = with maintainers; [ dotlambda ];
|
||||
};
|
||||
}
|
@ -4851,8 +4851,8 @@ let
|
||||
mktplcRef = {
|
||||
name = "uiua-vscode";
|
||||
publisher = "uiua-lang";
|
||||
version = "0.0.52";
|
||||
hash = "sha256-zFtu3AYnDxb/aMtkpiaItQtwLpynTVbSRGuqKv3SueM=";
|
||||
version = "0.0.53";
|
||||
hash = "sha256-5CHAX1jGyJ2VVEBTh5G1JM8+L9paryBa2zJoTkZ+G7Q=";
|
||||
};
|
||||
meta = {
|
||||
description = "VSCode language extension for Uiua";
|
||||
|
@ -23,6 +23,12 @@
|
||||
libslirp,
|
||||
wayland,
|
||||
wayland-scanner,
|
||||
libsndfile,
|
||||
flac,
|
||||
libogg,
|
||||
libvorbis,
|
||||
libopus,
|
||||
libmpg123,
|
||||
|
||||
enableDynarec ? with stdenv.hostPlatform; isx86 || isAarch,
|
||||
enableNewDynarec ? enableDynarec && stdenv.hostPlatform.isAarch,
|
||||
@ -34,13 +40,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "86Box";
|
||||
version = "4.1.1";
|
||||
version = "4.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "86Box";
|
||||
repo = "86Box";
|
||||
rev = "v${finalAttrs.version}";
|
||||
hash = "sha256-ioE0EVIXv/biXXvLqwhmtZ/RJM0nLqcE+i+CU+WXBY4=";
|
||||
hash = "sha256-hXupMQ+i27sw3XOweZGatdRCUlp7weGR/PqCLAw/8fo=";
|
||||
};
|
||||
|
||||
patches = [ ./darwin.patch ];
|
||||
@ -75,6 +81,12 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
libslirp
|
||||
qt5.qtbase
|
||||
qt5.qttools
|
||||
libsndfile
|
||||
flac.dev
|
||||
libogg.dev
|
||||
libvorbis.dev
|
||||
libopus.dev
|
||||
libmpg123.dev
|
||||
]
|
||||
++ lib.optional stdenv.isLinux alsa-lib
|
||||
++ lib.optional enableWayland wayland
|
||||
@ -107,7 +119,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
owner = "86Box";
|
||||
repo = "roms";
|
||||
rev = "v${finalAttrs.version}";
|
||||
hash = "sha256-58nNTOLund/KeDlNwzwwihjFVigs/P0K8SN07zExE2c=";
|
||||
hash = "sha256-WdQebSBuw2Wtz8ggMnGuxGoi2EKtNub3S8JKa6ZmdU8=";
|
||||
};
|
||||
updateScript = ./update.sh;
|
||||
};
|
||||
|
68
pkgs/applications/emulators/retroarch/README.md
Normal file
68
pkgs/applications/emulators/retroarch/README.md
Normal file
@ -0,0 +1,68 @@
|
||||
# RetroArch
|
||||
|
||||
This directory includes [RetroArch](https://www.retroarch.com/), [libretro
|
||||
cores](https://docs.libretro.com/guides/core-list/) and related packages.
|
||||
|
||||
## Adding new cores
|
||||
|
||||
The basic steps to add a new core are:
|
||||
|
||||
1. Add the core repository to [update_cores.py](./update_cores.py) inside the
|
||||
`CORES` map.
|
||||
- The minimum required parameter is `repo`
|
||||
- If the repository owner is not `libretro`, set `owner` parameter
|
||||
- If the core needs submodules, set `fetch_submodules` parameter to `True`
|
||||
- To pin the core to a specific release, set `rev` parameter
|
||||
2. Run `./pkgs/applications/emulators/retroarch/update_cores.py <emulator>` to
|
||||
generate [`hashes.json`](./hashes.json) file
|
||||
3. Add your new core to [`cores.nix`](./cores.nix) file, using
|
||||
[`mkLibretroCore`](./mkLibretroCore.nix) function
|
||||
- In general, the attribute name should be the same as the repo name, unless
|
||||
there is a good reason not to
|
||||
- Check the core repo and [Libretro
|
||||
documentation](https://docs.libretro.com/) for the core you're trying to add
|
||||
for instructions on how to build
|
||||
- Also check the examples inside [`cores.nix`](./cores.nix)
|
||||
- If your core is recently released, there is a good chance that you may
|
||||
need to update [`libretro-core-info`](./libretro-core-info.nix) for things
|
||||
to work inside RetroArch
|
||||
4. Try to build your core with `nix-build -A libretro.<core>`
|
||||
|
||||
## Updating cores
|
||||
|
||||
Just run:
|
||||
|
||||
```console
|
||||
# From the root of your nixpkgs directory
|
||||
./pkgs/applications/emulators/retroarch/update_cores.nix
|
||||
```
|
||||
|
||||
Keep in mind that because of the huge amount of cores that we package here, it
|
||||
is recommended to set `GITHUB_TOKEN` to your GitHub's [Personal Access
|
||||
Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)
|
||||
(PAT), otherwise the update will probably fail due to GitHub's API rate limit.
|
||||
|
||||
## Using RetroArch with cores
|
||||
|
||||
To create a custom RetroArch derivation with the cores you want (instead of
|
||||
using `retroarchFull` that includes all cores), you can use `.override` like
|
||||
this:
|
||||
|
||||
```nix
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
retroarchWithCores = (pkgs.retroarch.override {
|
||||
cores = with pkgs.libretro; [
|
||||
bsnes
|
||||
mgba
|
||||
quicknes
|
||||
];
|
||||
});
|
||||
in
|
||||
{
|
||||
environment.systemPackages = [
|
||||
retroarchWithCores
|
||||
];
|
||||
}
|
||||
```
|
@ -63,14 +63,14 @@ stdenv.mkDerivation rec {
|
||||
runHook preBuild
|
||||
|
||||
'' + lib.optionalString stdenv.isDarwin ''
|
||||
cp -R ${electron}/Applications/Electron.app Electron.app
|
||||
cp -R ${electron.dist}/Electron.app Electron.app
|
||||
chmod -R u+w Electron.app
|
||||
export CSC_IDENTITY_AUTO_DISCOVERY=false
|
||||
sed -i "/afterSign/d" electron-builder-linux-mac.json
|
||||
'' + ''
|
||||
yarn --offline run electron-builder --dir \
|
||||
${if stdenv.isDarwin then "--config electron-builder-linux-mac.json" else ""} \
|
||||
-c.electronDist=${if stdenv.isDarwin then "." else "${electron}/libexec/electron"} \
|
||||
${lib.optionalString stdenv.isDarwin "--config electron-builder-linux-mac.json"} \
|
||||
-c.electronDist=${if stdenv.isDarwin then "." else electron.dist} \
|
||||
-c.electronVersion=${electron.version}
|
||||
|
||||
runHook postBuild
|
||||
|
@ -6,7 +6,7 @@
|
||||
, kauth
|
||||
, libdrm
|
||||
, hwdata
|
||||
, glxinfo
|
||||
, mesa-demos
|
||||
, polkit
|
||||
, procps
|
||||
, pugixml
|
||||
@ -46,7 +46,7 @@ stdenv.mkDerivation rec{
|
||||
karchive
|
||||
kauth
|
||||
libdrm
|
||||
glxinfo
|
||||
mesa-demos
|
||||
polkit
|
||||
procps
|
||||
pugixml
|
||||
@ -68,7 +68,7 @@ stdenv.mkDerivation rec{
|
||||
"-DPOLKIT_POLICY_INSTALL_DIR=${placeholder "out"}/share/polkit-1/actions"
|
||||
];
|
||||
|
||||
runtimeDeps = [ hwdata glxinfo vulkan-tools util-linux procps ];
|
||||
runtimeDeps = [ hwdata mesa-demos vulkan-tools util-linux procps ];
|
||||
binPath = lib.makeBinPath runtimeDeps;
|
||||
|
||||
dontWrapQtApps = true;
|
||||
|
@ -12,7 +12,7 @@
|
||||
, wrapGAppsHook4
|
||||
, gdk-pixbuf
|
||||
, lsb-release
|
||||
, glxinfo
|
||||
, mesa-demos
|
||||
, vdpauinfo
|
||||
, clinfo
|
||||
}:
|
||||
@ -55,7 +55,7 @@ python3.pkgs.buildPythonApplication rec {
|
||||
|
||||
postFixup = ''
|
||||
makeWrapper ${python3.interpreter} $out/bin/gpu-viewer \
|
||||
--prefix PATH : "${lib.makeBinPath [ clinfo glxinfo lsb-release vdpauinfo vulkan-tools ]}" \
|
||||
--prefix PATH : "${lib.makeBinPath [ clinfo lsb-release mesa-demos vdpauinfo vulkan-tools ]}" \
|
||||
--add-flags "$out/share/gpu-viewer/Files/GPUViewer.py" \
|
||||
--prefix PYTHONPATH : "$PYTHONPATH" \
|
||||
--chdir "$out/share/gpu-viewer/Files" \
|
||||
|
@ -43,7 +43,7 @@ stdenv.mkDerivation rec {
|
||||
yarnBuildScript = "electron-builder";
|
||||
yarnBuildFlags = [
|
||||
"--dir"
|
||||
"-c.electronDist=${electron}/libexec/electron"
|
||||
"-c.electronDist=${electron.dist}"
|
||||
"-c.electronVersion=${electron.version}"
|
||||
];
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
, xrandr
|
||||
, pciutils
|
||||
, psmisc
|
||||
, glxinfo
|
||||
, mesa-demos
|
||||
, vulkan-tools
|
||||
, xboxdrv
|
||||
, pulseaudio
|
||||
@ -58,7 +58,7 @@ let
|
||||
xrandr
|
||||
pciutils
|
||||
psmisc
|
||||
glxinfo
|
||||
mesa-demos
|
||||
vulkan-tools
|
||||
xboxdrv
|
||||
pulseaudio
|
||||
|
@ -172,6 +172,46 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
firmwareupdater = buildPlugin rec {
|
||||
pname = "firmwareupdater";
|
||||
version = "1.14.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "OctoPrint";
|
||||
repo = "OctoPrint-FirmwareUpdater";
|
||||
rev = version;
|
||||
sha256 = "sha256-CUNjM/IJJS/lqccZ2B0mDOzv3k8AgmDreA/X9wNJ7iY=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with super; [ pyserial ];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Printer Firmware Updater";
|
||||
homepage = "https://github.com/OctoPrint/OctoPrint-FirmwareUpdater";
|
||||
license = licenses.agpl3Only;
|
||||
maintainers = with maintainers; [ tri-ler ];
|
||||
};
|
||||
};
|
||||
|
||||
fullscreen = buildPlugin rec {
|
||||
pname = "fullscreen";
|
||||
version = "0.0.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "BillyBlaze";
|
||||
repo = "OctoPrint-FullScreen";
|
||||
rev = version;
|
||||
sha256 = "sha256-Z8twpj+gqgbiWWxNd9I9qflEAln5Obpb3cn34KwSc5A=";
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
description = "Open webcam in fullscreen mode";
|
||||
homepage = "https://github.com/BillyBlaze/OctoPrint-FullScreen";
|
||||
license = licenses.agpl3Only;
|
||||
maintainers = with maintainers; [ tri-ler ];
|
||||
};
|
||||
};
|
||||
|
||||
gcodeeditor = buildPlugin rec {
|
||||
pname = "gcodeeditor";
|
||||
version = "0.2.12";
|
||||
@ -231,15 +271,102 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
mqttchambertemperature = buildPlugin rec {
|
||||
pname = "mqttchambertemperature";
|
||||
version = "0.0.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "synman";
|
||||
repo = "OctoPrint-MqttChamberTemperature";
|
||||
rev = version;
|
||||
sha256 = "sha256-CvNpi8HcBBUfCs3X8yflbhe0YCU0kW3u2ADSro/qnuI=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with super; [ jsonpath-ng ];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Enables Chamber temperature reporting via subscribing to an MQTT topic";
|
||||
homepage = "https://github.com/synman/OctoPrint-MqttChamberTemperature";
|
||||
license = licenses.wtfpl;
|
||||
maintainers = with maintainers; [ tri-ler ];
|
||||
};
|
||||
};
|
||||
|
||||
navbartemp = buildPlugin rec {
|
||||
pname = "navbartemp";
|
||||
version = "0.15";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "imrahil";
|
||||
repo = "OctoPrint-NavbarTemp";
|
||||
rev = version;
|
||||
sha256 = "sha256-ZPpTx+AadRffUb53sZbMUbCZa7xYGQW/5si7UB8mnVI=";
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
description = "Displays temperatures on navbar";
|
||||
homepage = "https://github.com/imrahil/OctoPrint-NavbarTemp";
|
||||
license = licenses.agpl3Only;
|
||||
maintainers = with maintainers; [ tri-ler ];
|
||||
};
|
||||
};
|
||||
|
||||
obico = buildPlugin rec {
|
||||
pname = "obico";
|
||||
version = "2.5.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "TheSpaghettiDetective";
|
||||
repo = "OctoPrint-Obico";
|
||||
rev = version;
|
||||
sha256 = "sha256-cAUXe/lRTqYuWnrRiNDuDjcayL5yV9/PtTd9oeSC8KA=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with super; [
|
||||
backoff
|
||||
sentry-sdk
|
||||
bson
|
||||
distro
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Monitor Octoprint-connected printers with Obico";
|
||||
homepage = "https://www.obico.io/";
|
||||
license = licenses.agpl3Only;
|
||||
maintainers = with maintainers; [ tri-ler ];
|
||||
};
|
||||
};
|
||||
|
||||
octopod = buildPlugin rec {
|
||||
pname = "octopod";
|
||||
version = "0.3.16";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "gdombiak";
|
||||
repo = "OctoPrint-OctoPod";
|
||||
rev = version;
|
||||
sha256 = "sha256-9QKC1MsYO3XihOTAijJUv5i20iMSQHOHPfLiYPV5y8s=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with super; [ pillow ];
|
||||
|
||||
meta = with lib; {
|
||||
description = "OctoPod extension for OctoPrint";
|
||||
homepage = "https://github.com/gdombiak/OctoPrint-OctoPod";
|
||||
license = licenses.asl20;
|
||||
maintainers = with maintainers; [ tri-ler ];
|
||||
};
|
||||
};
|
||||
|
||||
printtimegenius = buildPlugin rec {
|
||||
pname = "printtimegenius";
|
||||
version = "2.3.1";
|
||||
version = "2.3.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "eyal0";
|
||||
repo = "OctoPrint-PrintTimeGenius";
|
||||
rev = version;
|
||||
sha256 = "sha256-2lxaTcmPBSdfMmViIfLEbeYWfXZpNVAO4i5Z678gWy0=";
|
||||
sha256 = "sha256-hqm8RShCNpsVbrVXquat5VXqcVc7q5tn5+7Ipqmaw4U=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with super; [
|
||||
@ -261,6 +388,27 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
prusaslicerthumbnails = buildPlugin rec {
|
||||
pname = "prusaslicerthumbnails";
|
||||
version = "1.0.7";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "jneilliii";
|
||||
repo = "OctoPrint-PrusaSlicerThumbnails";
|
||||
rev = version;
|
||||
sha256 = "sha256-waNCTjAZwdBfhHyJCG2La7KTnJ8MDVuX1JLetFB5bS4=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with super; [ psutil ];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Plugin that extracts thumbnails from uploaded gcode files sliced by PrusaSlicer";
|
||||
homepage = "https://github.com/jneilliii/OctoPrint-PrusaSlicerThumbnails";
|
||||
license = licenses.agpl3Only;
|
||||
maintainers = with maintainers; [ tri-ler ];
|
||||
};
|
||||
};
|
||||
|
||||
psucontrol = buildPlugin rec {
|
||||
pname = "psucontrol";
|
||||
version = "1.0.6";
|
||||
@ -289,6 +437,27 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
resource-monitor = buildPlugin rec {
|
||||
pname = "resource-monitor";
|
||||
version = "0.3.16";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Renaud11232";
|
||||
repo = "OctoPrint-Resource-Monitor";
|
||||
rev = version;
|
||||
sha256 = "sha256-w1PBxO+Qf7cSSNocu7BiulZE7kesSa+LGV3uJlmd0ao=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with super; [ psutil ];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Plugin to view the current CPU and RAM usage on your system";
|
||||
homepage = "https://github.com/Renaud11232/OctoPrint-Resource-Monitor";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ tri-ler ];
|
||||
};
|
||||
};
|
||||
|
||||
simpleemergencystop = buildPlugin rec {
|
||||
pname = "simpleemergencystop";
|
||||
version = "1.0.5";
|
||||
@ -367,6 +536,25 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
timelapsepurger = buildPlugin rec {
|
||||
pname = "firmwareupdater";
|
||||
version = "0.1.4";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "jneilliii";
|
||||
repo = "OctoPrint-TimelapsePurger";
|
||||
rev = version;
|
||||
sha256 = "sha256-XS4m4KByScGTPfVE4kuRLw829gNE2CdM0RyhRqGGxyw=";
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
description = "Automatically deletes timelapses that are older than configured timeframe";
|
||||
homepage = "https://github.com/jneilliii/OctoPrint-TimelapsePurger";
|
||||
license = licenses.agpl3Only;
|
||||
maintainers = with maintainers; [ tri-ler ];
|
||||
};
|
||||
};
|
||||
|
||||
titlestatus = buildPlugin rec {
|
||||
pname = "titlestatus";
|
||||
version = "0.0.5";
|
||||
|
@ -13,13 +13,13 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "pgmodeler";
|
||||
version = "1.1.3";
|
||||
version = "1.1.4";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "pgmodeler";
|
||||
repo = "pgmodeler";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-LDgRv7Todyy2pnE21Z0O5JQ6mE4ZO3THv6rfEWU66Cc=";
|
||||
sha256 = "sha256-axw0/QFQfnEc2P8tFRtSY5vVUJTqv+kRn68GXdZ5SeQ=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ pkg-config qmake wrapQtAppsHook ];
|
||||
|
@ -3,10 +3,10 @@
|
||||
, fetchurl
|
||||
, cabextract
|
||||
, gettext
|
||||
, glxinfo
|
||||
, gnupg
|
||||
, icoutils
|
||||
, imagemagick
|
||||
, mesa-demos
|
||||
, netcat-gnu
|
||||
, p7zip
|
||||
, python3
|
||||
@ -37,10 +37,10 @@ let
|
||||
cabextract
|
||||
python
|
||||
gettext
|
||||
glxinfo
|
||||
gnupg
|
||||
icoutils
|
||||
imagemagick
|
||||
mesa-demos
|
||||
netcat-gnu
|
||||
p7zip
|
||||
unzip
|
||||
|
@ -73,7 +73,7 @@ stdenv.mkDerivation rec {
|
||||
yarn run nextron build --no-pack
|
||||
yarn run electron-builder --dir \
|
||||
--config electron-builder.yml \
|
||||
-c.electronDist="${electron}/libexec/electron" \
|
||||
-c.electronDist="${electron.dist}" \
|
||||
-c.electronVersion=${electron.version}
|
||||
|
||||
runHook postBuild
|
||||
|
@ -12,13 +12,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "xca";
|
||||
version = "2.6.0";
|
||||
version = "2.7.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "chris2511";
|
||||
repo = "xca";
|
||||
rev = "RELEASE.${finalAttrs.version}";
|
||||
hash = "sha256-E0Ap+JDK/oYTG+uaRHsdOxyLIywlYJ01T4ANQhNH220=";
|
||||
hash = "sha256-Ty6j0Fl2smMGxp+1nnD3Fu83bn19gqtRKSA1wDgNZes=";
|
||||
};
|
||||
|
||||
buildInputs = [ openssl qtbase ];
|
||||
|
@ -6,13 +6,13 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "arkade";
|
||||
version = "0.11.20";
|
||||
version = "0.11.21";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "alexellis";
|
||||
repo = "arkade";
|
||||
rev = version;
|
||||
hash = "sha256-xjJbO+42PUuRb4vMSKscTf2DEDekSwEF/v2QwKeBtvI=";
|
||||
hash = "sha256-vNJQLrpPJJG5FjQ73203V/Ky93HawRWgMiPYHU+eXPM=";
|
||||
};
|
||||
|
||||
CGO_ENABLED = 0;
|
||||
|
@ -1,16 +1,16 @@
|
||||
{ buildGoModule, lib, fetchFromGitHub }:
|
||||
buildGoModule rec {
|
||||
pname = "tfswitch";
|
||||
version = "1.0.2";
|
||||
version = "1.2.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "warrensbox";
|
||||
repo = "terraform-switcher";
|
||||
rev = version;
|
||||
sha256 = "sha256-Gp7+TEE7rmlabZhley/crpYZiqiKcc6uqSr6leZsmgU=";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-Ym0ypMfoceOvje1z1oCxjnFrl1oosMFSplM7bhI0KXU=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-DsC9djgt7Er2m2TacUldpJP43jC0IBklPnu41Saf4DY=";
|
||||
vendorHash = "sha256-44A9fF+HIOJrlxpps6GV3yjPBqfpwOhEZ8Ejnp2o/wk=";
|
||||
|
||||
# Disable tests since it requires network access and relies on the
|
||||
# presence of release.hashicorp.com
|
||||
|
@ -35,7 +35,7 @@ stdenv.mkDerivation rec {
|
||||
|
||||
npm exec electron-builder -- \
|
||||
--dir \
|
||||
-c.electronDist="${electron_30}/libexec/electron" \
|
||||
-c.electronDist="${electron_30.dist}" \
|
||||
-c.electronVersion="${electron_30.version}"
|
||||
|
||||
runHook postBuild
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"version" = "1.11.75";
|
||||
"version" = "1.11.76";
|
||||
"hashes" = {
|
||||
"desktopSrcHash" = "sha256-bO23E1xG3FfizBBAWh0kCN+5JYbiX5V/wxLlY6ljWVQ=";
|
||||
"desktopSrcHash" = "sha256-oG1nzOSXl2vjxvxdVg2o5ssKbAqrYHS4pnLCPJsIBCQ=";
|
||||
"desktopYarnHash" = "0bl78yd7apd5qbsqyhxnwj7lwrjx5820zh22rzgn9jqkcv25jwgw";
|
||||
"webSrcHash" = "sha256-cDayCoznbmALOiPg9FUYrfdFjzg0NV1NY9/b2KzTvMs=";
|
||||
"webYarnHash" = "04si1x663z70nxj6nfaq7m2wcd8r4l3vdpirnjhc13wrj1kb8r8x";
|
||||
"webSrcHash" = "sha256-1hmSdefNChRcUnwbxS00NYrEexMyg8FIL0BXdEbwm+s=";
|
||||
"webYarnHash" = "0bnxd7kig2a5scgdsd0yhhmanf7zqi2gd2si6kgnr0v2kc0akc0b";
|
||||
};
|
||||
}
|
||||
|
@ -68,14 +68,14 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "jami";
|
||||
version = "20240813.0";
|
||||
version = "20240823.0";
|
||||
|
||||
src = fetchFromGitLab {
|
||||
domain = "git.jami.net";
|
||||
owner = "savoirfairelinux";
|
||||
repo = "jami-client-qt";
|
||||
rev = "stable/${version}";
|
||||
hash = "sha256-XRWbV1s87niwNiWf2KRpV+wUH6ptw3vnVXCEwqh2r7M=";
|
||||
hash = "sha256-7jGH54sFiS6qrdEiKSS64lJyJXL1FOJVbesxo/FFmyA=";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
let
|
||||
inherit (darwin.apple_sdk.frameworks) Carbon CoreFoundation ApplicationServices OpenGL;
|
||||
|
||||
electronDist = electron + (if stdenv.isDarwin then "/Applications" else "/libexec/electron");
|
||||
in
|
||||
buildNpmPackage rec {
|
||||
pname = "jitsi-meet-electron";
|
||||
@ -70,7 +68,7 @@ buildNpmPackage rec {
|
||||
'';
|
||||
|
||||
postBuild = ''
|
||||
cp -r ${electronDist} electron-dist
|
||||
cp -r ${electron.dist} electron-dist
|
||||
chmod -R u+w electron-dist
|
||||
|
||||
# npmRebuild is needed because robotjs won't be built on darwin otherwise
|
||||
|
@ -50,7 +50,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
yarn --offline electron-builder \
|
||||
--dir ${if stdenv.isDarwin then "--macos" else "--linux"} ${if stdenv.hostPlatform.isAarch64 then "--arm64" else "--x64"} \
|
||||
-c.electronDist=${electron}/libexec/electron \
|
||||
-c.electronDist=${electron.dist} \
|
||||
-c.electronVersion=${electron.version}
|
||||
|
||||
runHook postBuild
|
||||
|
@ -8,6 +8,8 @@ buildGoModule rec {
|
||||
pname = "rclone";
|
||||
version = "1.67.0";
|
||||
|
||||
outputs = [ "out" "man" ];
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "rclone";
|
||||
repo = "rclone";
|
||||
@ -19,15 +21,19 @@ buildGoModule rec {
|
||||
|
||||
subPackages = [ "." ];
|
||||
|
||||
outputs = [ "out" "man" ];
|
||||
nativeBuildInputs = [ installShellFiles makeWrapper ];
|
||||
|
||||
buildInputs = lib.optional enableCmount (if stdenv.isDarwin then macfuse-stubs else fuse);
|
||||
nativeBuildInputs = [ installShellFiles makeWrapper ];
|
||||
|
||||
tags = lib.optionals enableCmount [ "cmount" ];
|
||||
|
||||
ldflags = [ "-s" "-w" "-X github.com/rclone/rclone/fs.Version=${version}" ];
|
||||
|
||||
postConfigure = lib.optionalString (!stdenv.isDarwin) ''
|
||||
substituteInPlace vendor/github.com/winfsp/cgofuse/fuse/host_cgo.go \
|
||||
--replace-fail '"libfuse.so.2"' '"${lib.getLib fuse}/lib/libfuse.so.2"'
|
||||
'';
|
||||
|
||||
postInstall =
|
||||
let
|
||||
rcloneBin =
|
||||
@ -50,8 +56,7 @@ buildGoModule rec {
|
||||
# as the setuid wrapper is required as non-root on NixOS.
|
||||
''
|
||||
wrapProgram $out/bin/rclone \
|
||||
--suffix PATH : "${lib.makeBinPath [ fuse3 ] }" \
|
||||
--prefix LD_LIBRARY_PATH : "${fuse3}/lib"
|
||||
--suffix PATH : "${lib.makeBinPath [ fuse3 ] }"
|
||||
'';
|
||||
|
||||
passthru.tests = {
|
||||
|
@ -33,14 +33,14 @@ let
|
||||
}.${system} or throwSystem;
|
||||
|
||||
hash = {
|
||||
x86_64-linux = "sha256-KLOI0lG0rZbLS2uiONNlgyCkohzQhytRovAfrjnGuDI=";
|
||||
x86_64-linux = "sha256-l67oq9Jj2mmxcLsEMI4t+85cKD65xxMNkTNJrrRrwJQ=";
|
||||
}.${system} or throwSystem;
|
||||
|
||||
displayname = "XPipe";
|
||||
|
||||
in stdenvNoCC.mkDerivation rec {
|
||||
pname = "xpipe";
|
||||
version = "10.2.2";
|
||||
version = "11.0";
|
||||
|
||||
src = fetchzip {
|
||||
url = "https://github.com/xpipe-io/xpipe/releases/download/${version}/xpipe-portable-linux-${arch}.tar.gz";
|
||||
|
@ -10,7 +10,7 @@
|
||||
}:
|
||||
|
||||
let
|
||||
version = "5.13.22";
|
||||
version = "5.13.28";
|
||||
in
|
||||
rustPlatform.buildRustPackage {
|
||||
pname = "git-mit";
|
||||
@ -20,10 +20,10 @@ rustPlatform.buildRustPackage {
|
||||
owner = "PurpleBooth";
|
||||
repo = "git-mit";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-nYKwf0+Ai6GU9CeRKI7NInmkA4yH41tMWoT9S03m0VI=";
|
||||
hash = "sha256-zw1yY/vCrxklmIXGHO5cMOQ9L3xfHD24f2JN7ibF/I8=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-dcTyombQBR0IGkK+2GWedFQf/1a74gVUIqM96xVxlj0=";
|
||||
cargoHash = "sha256-pnSp6XCVSxCY7b1LHeQM9/KsjG6sGQoMCPcL8Bby4A4=";
|
||||
|
||||
nativeBuildInputs = [ pkg-config ];
|
||||
|
||||
|
@ -34,7 +34,7 @@ let
|
||||
davinci = (
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "davinci-resolve${lib.optionalString studioVariant "-studio"}";
|
||||
version = "18.6.6";
|
||||
version = "19.0";
|
||||
|
||||
nativeBuildInputs = [
|
||||
(appimage-run.override { buildFHSEnv = buildFHSEnvChroot; } )
|
||||
@ -55,8 +55,8 @@ let
|
||||
outputHashAlgo = "sha256";
|
||||
outputHash =
|
||||
if studioVariant
|
||||
then "sha256-9iTdIjHH8uoXlVr6miyqmHuzbbpbqdJPEbPGycsccoI="
|
||||
else "sha256-WrIQ1FHm65MOGb5HfFl2WzXYJRlqktuZdrtzcjWp1gI=";
|
||||
then "sha256-KxoUXHMlgWoa00GSq/DLVgyOjuv7k8aUwl20XvDRZvc="
|
||||
else "sha256-XQP5RL/p/voQePLiBr1Hc+dBUZHW39XxDjyxKJyKXxw=";
|
||||
|
||||
impureEnvVars = lib.fetchers.proxyImpureEnvVars;
|
||||
|
||||
@ -94,7 +94,7 @@ let
|
||||
} ''
|
||||
DOWNLOADID=$(
|
||||
curl --silent --compressed "$DOWNLOADSURL" \
|
||||
| jq --raw-output '.downloads[] | select(.name | test("^'"$PRODUCT $VERSION"'( Update)?$")) | .urls.Linux[0].downloadId'
|
||||
| jq --raw-output '.downloads[] | .urls.Linux?[]? | select(.downloadTitle | test("^'"$PRODUCT $VERSION"'( Update)?$")) | .downloadId'
|
||||
)
|
||||
echo "downloadid is $DOWNLOADID"
|
||||
test -n "$DOWNLOADID"
|
||||
@ -271,13 +271,13 @@ buildFHSEnv {
|
||||
currentVersion=${lib.escapeShellArg davinci.version}
|
||||
downloadsJSON="$(curl --fail --silent https://www.blackmagicdesign.com/api/support/us/downloads.json)"
|
||||
|
||||
latestLinuxVersion="$(echo "$downloadsJSON" | jq '[.downloads[] | select(.urls.Linux) | .urls.Linux[] | select(.downloadTitle | test("DaVinci Resolve")) | .downloadTitle]' | grep -oP 'DaVinci Resolve \K\d+\.\d+\.\d+' | sort | tail -n 1)"
|
||||
latestLinuxVersion="$(echo "$downloadsJSON" | jq '[.downloads[] | select(.urls.Linux) | .urls.Linux[] | select(.downloadTitle | test("DaVinci Resolve")) | .downloadTitle]' | grep -oP 'DaVinci Resolve \K\d+\.\d+(\.\d+)?' | sort | tail -n 1)"
|
||||
update-source-version davinci-resolve "$latestLinuxVersion" --source-key=davinci.src
|
||||
|
||||
# Since the standard and studio both use the same version we need to reset it before updating studio
|
||||
sed -i -e "s/""$latestLinuxVersion""/""$currentVersion""/" "$drv"
|
||||
|
||||
latestStudioLinuxVersion="$(echo "$downloadsJSON" | jq '[.downloads[] | select(.urls.Linux) | .urls.Linux[] | select(.downloadTitle | test("DaVinci Resolve")) | .downloadTitle]' | grep -oP 'DaVinci Resolve Studio \K\d+\.\d+\.\d+' | sort | tail -n 1)"
|
||||
latestStudioLinuxVersion="$(echo "$downloadsJSON" | jq '[.downloads[] | select(.urls.Linux) | .urls.Linux[] | select(.downloadTitle | test("DaVinci Resolve")) | .downloadTitle]' | grep -oP 'DaVinci Resolve Studio \K\d+\.\d+(\.\d+)?' | sort | tail -n 1)"
|
||||
update-source-version davinci-resolve-studio "$latestStudioLinuxVersion" --source-key=davinci.src
|
||||
'';
|
||||
});
|
||||
|
@ -1,30 +0,0 @@
|
||||
{ lib
|
||||
, buildPythonApplication
|
||||
, fetchPypi
|
||||
, ffmpeg
|
||||
, ffmpeg-progress-yield
|
||||
}:
|
||||
|
||||
buildPythonApplication rec {
|
||||
pname = "ffmpeg-normalize";
|
||||
version = "1.26.1";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
hash = "sha256-OwREpfWaP0tdAjMGjGpVIAQn8rlTTjSfT+0t5g/2yjQ=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ ffmpeg ffmpeg-progress-yield ];
|
||||
|
||||
checkPhase = ''
|
||||
$out/bin/ffmpeg-normalize --help > /dev/null
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Normalize audio via ffmpeg";
|
||||
homepage = "https://github.com/slhck/ffmpeg-normalize";
|
||||
license = with licenses; [ mit ];
|
||||
maintainers = with maintainers; [ prusnak ];
|
||||
mainProgram = "ffmpeg-normalize";
|
||||
};
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
, libogg, libvorbis, flac, libxslt
|
||||
, lzo, libcdio, libmodplug, libass, libbluray, libudfread
|
||||
, sqlite, libmysqlclient, nasm, gnutls, libva, libdrm
|
||||
, curl, bzip2, zip, unzip, glxinfo
|
||||
, curl, bzip2, zip, unzip, mesa-demos
|
||||
, libcec, libcec_platform, dcadec, libuuid
|
||||
, libcrossguid, libmicrohttpd
|
||||
, bluez, doxygen, giflib, glib, harfbuzz, lcms2, libidn2, libpthreadstubs, libtasn1
|
||||
@ -119,7 +119,7 @@ in stdenv.mkDerivation (finalAttrs: {
|
||||
libogg libvorbis flac libxslt systemd
|
||||
lzo libcdio libmodplug libass libbluray libudfread
|
||||
sqlite libmysqlclient avahi lame
|
||||
curl bzip2 zip unzip glxinfo
|
||||
curl bzip2 zip unzip mesa-demos
|
||||
libcec libcec_platform dcadec libuuid
|
||||
libxcrypt libgcrypt libgpg-error libunistring
|
||||
libcrossguid libplist
|
||||
@ -229,7 +229,7 @@ in stdenv.mkDerivation (finalAttrs: {
|
||||
# TODO: figure out which binaries should be wrapped this way and which shouldn't
|
||||
for p in $(ls --ignore=kodi-send $out/bin/) ; do
|
||||
wrapProgram $out/bin/$p \
|
||||
--prefix PATH ":" "${lib.makeBinPath ([ python3Packages.python glxinfo ]
|
||||
--prefix PATH ":" "${lib.makeBinPath ([ python3Packages.python mesa-demos ]
|
||||
++ lib.optional x11Support xdpyinfo ++ lib.optional sambaSupport samba)}" \
|
||||
--prefix LD_LIBRARY_PATH ":" "${lib.makeLibraryPath
|
||||
([ curl systemd libmad libcec libcec_platform libass ]
|
||||
|
@ -3,13 +3,13 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "motion";
|
||||
version = "4.6.0";
|
||||
version = "4.7.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Motion-Project";
|
||||
repo = "motion";
|
||||
rev = "release-${version}";
|
||||
sha256 = "sha256-f23glk91HWSEW/Glq/DdEikTQeg1eELEg4XG9zTsU78=";
|
||||
sha256 = "sha256-bGjiO14a7xKRgoeo5JlexXlKggE+agRMmQViBXagmt8=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ autoreconfHook pkg-config ];
|
||||
|
@ -1,5 +1,5 @@
|
||||
{ stdenv, nixosTests, lib, edk2, util-linux, nasm, acpica-tools, llvmPackages
|
||||
, fetchurl, python3, pexpect, xorriso, qemu, dosfstools, mtools
|
||||
, fetchFromGitLab, python3, pexpect, xorriso, qemu, dosfstools, mtools
|
||||
, fdSize2MB ? false
|
||||
, fdSize4MB ? secureBoot
|
||||
, secureBoot ? false
|
||||
@ -12,7 +12,7 @@
|
||||
# to use as the PK and first KEK for the keystore.
|
||||
#
|
||||
# By default, we use Debian's cert. This default
|
||||
# should chnage to a NixOS cert once we have our
|
||||
# should change to a NixOS cert once we have our
|
||||
# own secure boot signing infrastructure.
|
||||
#
|
||||
# Ignored if msVarsTemplate is false.
|
||||
@ -66,9 +66,18 @@ let
|
||||
|
||||
OvmfPkKek1AppPrefix = "4e32566d-8e9e-4f52-81d3-5bb9715f9727";
|
||||
|
||||
debian-edk-src = fetchurl {
|
||||
url = "http://deb.debian.org/debian/pool/main/e/edk2/edk2_2023.11-5.debian.tar.xz";
|
||||
sha256 = "1yxlab4md30pxvjadr6b4xn6cyfw0c292q63pyfv4vylvhsb24g4";
|
||||
debian-edk-src = fetchFromGitLab {
|
||||
domain = "salsa.debian.org";
|
||||
owner = "qemu-team";
|
||||
repo = "edk2";
|
||||
nonConeMode = true;
|
||||
sparseCheckout = [
|
||||
"debian/edk2-vars-generator.py"
|
||||
"debian/python"
|
||||
"debian/PkKek-1-*.pem"
|
||||
];
|
||||
rev = "refs/tags/debian/2024.05-1";
|
||||
hash = "sha256-uAjXJaHOVh944ZxcA2IgCsrsncxuhc0JKlsXs0E03s0=";
|
||||
};
|
||||
|
||||
buildPrefix = "Build/*/*";
|
||||
@ -111,7 +120,7 @@ edk2.mkDerivation projectDscPath (finalAttrs: {
|
||||
env.PYTHON_COMMAND = "python3";
|
||||
|
||||
postUnpack = lib.optionalDrvAttr msVarsTemplate ''
|
||||
unpackFile ${debian-edk-src}
|
||||
ln -s ${debian-edk-src}/debian
|
||||
'';
|
||||
|
||||
postConfigure = lib.optionalDrvAttr msVarsTemplate ''
|
||||
@ -138,7 +147,8 @@ edk2.mkDerivation projectDscPath (finalAttrs: {
|
||||
'' + lib.optionalString msVarsTemplate ''
|
||||
(
|
||||
cd ${buildPrefix}
|
||||
python3 $NIX_BUILD_TOP/debian/edk2-vars-generator.py \
|
||||
# locale must be set on Darwin for invocations of mtools to work correctly
|
||||
LC_ALL=C python3 $NIX_BUILD_TOP/debian/edk2-vars-generator.py \
|
||||
--flavor ${msVarsArgs.flavor} \
|
||||
--enrolldefaultkeys ${msVarsArgs.archDir}/EnrollDefaultKeys.efi \
|
||||
--shell ${msVarsArgs.archDir}/Shell.efi \
|
||||
@ -165,7 +175,7 @@ edk2.mkDerivation projectDscPath (finalAttrs: {
|
||||
ln -sv $fd/FV/${fwPrefix}_CODE{,.ms}.fd
|
||||
'' + lib.optionalString stdenv.hostPlatform.isAarch ''
|
||||
mv -v $out/FV/QEMU_{EFI,VARS}.fd $fd/FV
|
||||
# Add symlinks for Fedora dir layout: https://src.fedoraproject.org/cgit/rpms/edk2.git/tree/edk2.spec
|
||||
# Add symlinks for Fedora dir layout: https://src.fedoraproject.org/rpms/edk2/blob/main/f/edk2.spec
|
||||
mkdir -vp $fd/AAVMF
|
||||
ln -s $fd/FV/AAVMF_CODE.fd $fd/AAVMF/QEMU_EFI-pflash.raw
|
||||
ln -s $fd/FV/AAVMF_VARS.fd $fd/AAVMF/vars-template-pflash.raw
|
||||
@ -179,6 +189,9 @@ edk2.mkDerivation projectDscPath (finalAttrs: {
|
||||
in {
|
||||
firmware = "${prefix}_CODE.fd";
|
||||
variables = "${prefix}_VARS.fd";
|
||||
variablesMs =
|
||||
assert msVarsTemplate;
|
||||
"${prefix}_VARS.ms.fd";
|
||||
# This will test the EFI firmware for the host platform as part of the NixOS Tests setup.
|
||||
tests.basic-systemd-boot = nixosTests.systemd-boot.basic;
|
||||
tests.secureBoot-systemd-boot = nixosTests.systemd-boot.secureBoot;
|
||||
@ -190,7 +203,7 @@ edk2.mkDerivation projectDscPath (finalAttrs: {
|
||||
homepage = "https://github.com/tianocore/tianocore.github.io/wiki/OVMF";
|
||||
license = lib.licenses.bsd2;
|
||||
platforms = metaPlatforms;
|
||||
maintainers = with lib.maintainers; [ adamcstephens raitobezarius ];
|
||||
broken = stdenv.isDarwin;
|
||||
maintainers = with lib.maintainers; [ adamcstephens raitobezarius mjoerg ];
|
||||
broken = stdenv.isDarwin && stdenv.isAarch64;
|
||||
};
|
||||
})
|
||||
|
@ -73,7 +73,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
yarn --offline run build
|
||||
yarn --offline run electron-builder --dir \
|
||||
--config .electron-builder.config.cjs \
|
||||
-c.electronDist=${electron}/libexec/electron \
|
||||
-c.electronDist=${electron.dist} \
|
||||
-c.electronVersion=${electron.version}
|
||||
|
||||
runHook postBuild
|
||||
|
@ -134,7 +134,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
# error: unknown type name 'NSUInteger'
|
||||
postPatch = ''
|
||||
substituteInPlace src/dialog_colorpicker.cpp \
|
||||
--replace "NSUInteger" "size_t"
|
||||
--replace-fail "NSUInteger" "size_t"
|
||||
'';
|
||||
|
||||
env = {
|
||||
|
@ -12,7 +12,7 @@ let
|
||||
self = python3;
|
||||
packageOverrides = _: super: { tree-sitter = super.tree-sitter_0_21; };
|
||||
};
|
||||
version = "0.51.0";
|
||||
version = "0.53.0";
|
||||
in
|
||||
python3.pkgs.buildPythonApplication {
|
||||
pname = "aider-chat";
|
||||
@ -23,7 +23,7 @@ python3.pkgs.buildPythonApplication {
|
||||
owner = "paul-gauthier";
|
||||
repo = "aider";
|
||||
rev = "refs/tags/v${version}";
|
||||
hash = "sha256-vomRXWL3++1R8jpjMKbsGrB+B1FWQxVbLKxuPttnspw=";
|
||||
hash = "sha256-KQp4qqQKm++oB9RVQZhAWQJs7Nbyssc9eKKRH1VZbRU=";
|
||||
};
|
||||
|
||||
build-system = with python3.pkgs; [ setuptools ];
|
||||
|
@ -7,13 +7,13 @@
|
||||
|
||||
stdenvNoCC.mkDerivation {
|
||||
pname = "ananicy-rules-cachyos";
|
||||
version = "0-unstable-2024-07-27";
|
||||
version = "0-unstable-2024-08-26";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "CachyOS";
|
||||
repo = "ananicy-rules";
|
||||
rev = "c6153c9e909475bbb08b4e56af152179ff7f171f";
|
||||
hash = "sha256-sAWHm3PK9mM+AtHdDhq3RIQBo58eEZtD1l7QfCTpl0s=";
|
||||
rev = "a78b76536246898045fd1844aced381d01b7f1c6";
|
||||
hash = "sha256-bDfvWg5r4LmWI8tPrx9qzgEnJuMSYBm6MDf6yOaPqkY=";
|
||||
};
|
||||
|
||||
dontConfigure = true;
|
||||
|
@ -7,16 +7,16 @@
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "ast-grep";
|
||||
version = "0.24.1";
|
||||
version = "0.26.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "ast-grep";
|
||||
repo = "ast-grep";
|
||||
rev = version;
|
||||
hash = "sha256-kNPmtaUb5rMbdTlNKD3PrInuxGQt/JamMDx8BwBxVd8=";
|
||||
hash = "sha256-i2M3QSwLj2px6tiYyW8jz/WZ2z+IETrSoxis+BgHGXg=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-iV2GXH7opNIyWsgi0EnRIXDhJd3s66qFhnZWawBPb6g=";
|
||||
cargoHash = "sha256-6CXttQ+r2Ye5tz1V7XgLLnKQg7LHUVUtqpThETrwtzQ=";
|
||||
|
||||
nativeBuildInputs = [ installShellFiles ];
|
||||
|
||||
|
@ -11,13 +11,13 @@
|
||||
|
||||
buildNpmPackage rec {
|
||||
pname = "bitwarden-cli";
|
||||
version = "2024.8.0";
|
||||
version = "2024.8.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "bitwarden";
|
||||
repo = "clients";
|
||||
rev = "cli-v${version}";
|
||||
hash = "sha256-vosEc8HCMHEaaQadzA+jDjQA1liEtD8sS1Zndz/Iv00=";
|
||||
hash = "sha256-l9fLh1YFivVcMs688vM0pHoN0Um2r/EDpo7dvwvZFwY=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
@ -27,10 +27,10 @@ buildNpmPackage rec {
|
||||
|
||||
nodejs = nodejs_20;
|
||||
|
||||
npmDepsHash = "sha256-5neEpU7ZhVO5OR181owsvAnFfl7lr0MymvqbRFCPs3M=";
|
||||
npmDepsHash = "sha256-/6yWdTy6/GvYy8u5eZB+x5KRG6vhPVE0DIn+RUAO5MI=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
python3
|
||||
(python3.withPackages (ps: with ps; [ setuptools ]))
|
||||
] ++ lib.optionals stdenv.isDarwin [
|
||||
cctools
|
||||
xcbuild.xcrun
|
||||
@ -38,7 +38,19 @@ buildNpmPackage rec {
|
||||
|
||||
makeCacheWritable = true;
|
||||
|
||||
env.ELECTRON_SKIP_BINARY_DOWNLOAD = "1";
|
||||
env = {
|
||||
ELECTRON_SKIP_BINARY_DOWNLOAD = "1";
|
||||
npm_config_build_from_source = "true";
|
||||
};
|
||||
|
||||
# node-argon2 builds with LTO, but that causes missing symbols. So disable it
|
||||
# and rebuild. See https://github.com/ranisalt/node-argon2/pull/415
|
||||
preConfigure = ''
|
||||
pushd node_modules/argon2
|
||||
substituteInPlace binding.gyp --replace-fail '"-flto", ' ""
|
||||
"$npm_config_node_gyp" rebuild
|
||||
popd
|
||||
'';
|
||||
|
||||
npmBuildScript = "build:oss:prod";
|
||||
|
||||
|
@ -120,7 +120,7 @@ in buildNpmPackage rec {
|
||||
|
||||
npm exec electron-builder -- \
|
||||
--dir \
|
||||
-c.electronDist=${electron}/libexec/electron \
|
||||
-c.electronDist=${electron.dist} \
|
||||
-c.electronVersion=${electron.version}
|
||||
|
||||
popd
|
||||
|
@ -10,9 +10,6 @@
|
||||
electron,
|
||||
}:
|
||||
|
||||
let
|
||||
electronDist = "${electron}/${if stdenv.isDarwin then "Applications" else "libexec/electron"}";
|
||||
in
|
||||
buildNpmPackage rec {
|
||||
pname = "blockbench";
|
||||
version = "4.10.4";
|
||||
@ -45,7 +42,7 @@ buildNpmPackage rec {
|
||||
|
||||
postBuild = ''
|
||||
# electronDist needs to be modifiable on Darwin
|
||||
cp -r ${electronDist} electron-dist
|
||||
cp -r ${electron.dist} electron-dist
|
||||
chmod -R u+w electron-dist
|
||||
|
||||
npm exec electron-builder -- \
|
||||
|
@ -103,7 +103,7 @@ buildNpmPackage' rec {
|
||||
${
|
||||
if stdenv.isDarwin then
|
||||
''
|
||||
cp -r ${electron}/Applications/Electron.app ./
|
||||
cp -r ${electron.dist}/Electron.app ./
|
||||
find ./Electron.app -name 'Info.plist' | xargs -d '\n' chmod +rw
|
||||
|
||||
substituteInPlace electron-builder-config.js \
|
||||
@ -121,7 +121,7 @@ buildNpmPackage' rec {
|
||||
''
|
||||
npm exec electron-builder -- \
|
||||
--dir \
|
||||
-c.electronDist=${electron}/libexec/electron \
|
||||
-c.electronDist=${electron.dist} \
|
||||
-c.electronVersion=${electron.version} \
|
||||
-c.npmRebuild=false
|
||||
''
|
||||
|
@ -8,9 +8,6 @@
|
||||
electron,
|
||||
}:
|
||||
|
||||
let
|
||||
electronDist = electron + (if stdenv.isDarwin then "/Applications" else "/libexec/electron");
|
||||
in
|
||||
buildNpmPackage rec {
|
||||
pname = "caprine";
|
||||
version = "2.60.1";
|
||||
@ -29,7 +26,7 @@ buildNpmPackage rec {
|
||||
nativeBuildInputs = [ copyDesktopItems ];
|
||||
|
||||
postBuild = ''
|
||||
cp -r ${electronDist} electron-dist
|
||||
cp -r ${electron.dist} electron-dist
|
||||
chmod -R u+w electron-dist
|
||||
|
||||
npm exec electron-builder -- \
|
||||
|
2749
pkgs/by-name/co/cosmic-notifications/Cargo.lock
generated
2749
pkgs/by-name/co/cosmic-notifications/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -15,27 +15,31 @@
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "cosmic-notifications";
|
||||
version = "unstable-2024-01-05";
|
||||
version = "1.0.0-alpha.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "pop-os";
|
||||
repo = pname;
|
||||
rev = "3b07cf550a54b757a5f136e4d8fde74d09afe3fd";
|
||||
hash = "sha256-+S8bPorarSJQwIQfTmo4qK+B1kKAlQvllUuZ2UBL0eY=";
|
||||
repo = "cosmic-notifications";
|
||||
rev = "epoch-${version}";
|
||||
hash = "sha256-tCizZePze94tbJbR91N9rfUhrLFTAMW2oL9ByKOeDAU=";
|
||||
};
|
||||
|
||||
cargoLock = {
|
||||
lockFile = ./Cargo.lock;
|
||||
outputHashes = {
|
||||
"accesskit-0.11.0" = "sha256-xVhe6adUb8VmwIKKjHxwCwOo5Y1p3Or3ylcJJdLDrrE=";
|
||||
"accesskit-0.12.2" = "sha256-1UwgRyUe0PQrZrpS7574oNLi13fg5HpgILtZGW6JNtQ=";
|
||||
"atomicwrites-0.4.2" = "sha256-QZSuGPrJXh+svMeFWqAXoqZQxLq/WfIiamqvjJNVhxA=";
|
||||
"cosmic-client-toolkit-0.1.0" = "sha256-AEgvF7i/OWPdEMi8WUaAg99igBwE/AexhAXHxyeJMdc=";
|
||||
"cosmic-config-0.1.0" = "sha256-DmuUvFjhoqI5lneiWFFYF3WM3mACx5ZfZqeKpsyL7Ss=";
|
||||
"cosmic-text-0.10.0" = "sha256-kIBhh6CakQaWGfBWu5qaV8LAbJENX7GW+BStJK/P4iA=";
|
||||
"cosmic-settings-daemon-0.1.0" = "sha256-z/dvRyc3Zc1fAQh2HKk6NI6QSDpNqarqslwszjU+0nc=";
|
||||
"glyphon-0.3.0" = "sha256-JGkNIfj1HjOF8kGxqJPNq/JO+NhZD6XrZ4KmkXEP6Xc=";
|
||||
"smithay-client-toolkit-0.18.0" = "sha256-2WbDKlSGiyVmi7blNBr2Aih9FfF2dq/bny57hoA4BrE=";
|
||||
"softbuffer-0.3.3" = "sha256-eKYFVr6C1+X6ulidHIu9SP591rJxStxwL9uMiqnXx4k=";
|
||||
"clipboard_macos-0.1.0" = "sha256-cG5vnkiyDlQnbEfV2sPbmBYKv1hd3pjJrymfZb8ziKk=";
|
||||
"cosmic-client-toolkit-0.1.0" = "sha256-1XtyEvednEMN4MApxTQid4eed19dEN5ZBDt/XRjuda0=";
|
||||
"cosmic-config-0.1.0" = "sha256-DgMh0gqWUmXjBhBySR0CMnv/8O3XbS2BwomU9eNt+4o=";
|
||||
"cosmic-panel-config-0.1.0" = "sha256-bBUSZ3CTLq/DCQ2dMvaIcGcIcjqM/5vny5kTE3Jclj8=";
|
||||
"cosmic-settings-daemon-0.1.0" = "sha256-+1XB7r45Uc71fLnNR4U0DUF2EB8uzKeE4HIrdvKhFXo=";
|
||||
"cosmic-text-0.12.1" = "sha256-x0XTxzbmtE2d4XCG/Nuq3DzBpz15BbnjRRlirfNJEiU=";
|
||||
"cosmic-time-0.4.0" = "sha256-w4yY1fc4r1+pSv93dy/Hu3AD+I1+sozIPbbCoaVQj7w=";
|
||||
"d3d12-0.19.0" = "sha256-usrxQXWLGJDjmIdw1LBXtBvX+CchZDvE8fHC0LjvhD4=";
|
||||
"glyphon-0.5.0" = "sha256-j1HrbEpUBqazWqNfJhpyjWuxYAxkvbXzRKeSouUoPWg=";
|
||||
"smithay-clipboard-0.8.0" = "sha256-4InFXm0ahrqFrtNLeqIuE3yeOpxKZJZx+Bc0yQDtv34=";
|
||||
"softbuffer-0.4.1" = "sha256-a0bUFz6O8CWRweNt/OxTvflnPYwO5nm6vsyc/WcXyNg=";
|
||||
"taffy-0.3.11" = "sha256-SCx9GEIJjWdoNVyq+RZAGn0N71qraKZxf9ZWhvyzLaI=";
|
||||
};
|
||||
};
|
||||
|
@ -6,13 +6,13 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "cosmic-protocols";
|
||||
version = "0-unstable-2024-01-11";
|
||||
version = "0-unstable-2024-07-31";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "pop-os";
|
||||
repo = pname;
|
||||
rev = "e65fa5e2bb47e51656221657049bd3f88ae9dae5";
|
||||
hash = "sha256-vj7Wm1uJ5ULvGNEwKznNhujCZQiuntsWMyKQbIVaO/Q=";
|
||||
rev = "de2fead49d6af3a221db153642e4d7c2235aafc4";
|
||||
hash = "sha256-qgo8FMKo/uCbhUjfykRRN8KSavbyhZpu82M8npLcIPI=";
|
||||
};
|
||||
|
||||
makeFlags = [ "PREFIX=${placeholder "out"}" ];
|
||||
@ -20,7 +20,7 @@ stdenv.mkDerivation rec {
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/pop-os/cosmic-protocols";
|
||||
description = "Addtional wayland-protocols used by the COSMIC desktop environment";
|
||||
description = "Additional wayland-protocols used by the COSMIC desktop environment";
|
||||
license = [ licenses.mit licenses.gpl3Only ];
|
||||
maintainers = with maintainers; [ nyanbinary ];
|
||||
platforms = platforms.linux;
|
||||
|
@ -8,16 +8,16 @@
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "cosmic-screenshot";
|
||||
version = "unstable-2023-11-08";
|
||||
version = "1.0.0-alpha.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "pop-os";
|
||||
repo = pname;
|
||||
rev = "b413a7128ddcdfb3c63e84bdade5c5b90b163a9a";
|
||||
hash = "sha256-SDxBBhmnqNDX95Rb7QiI46sAxrfodB5tSq8AbXAU480=";
|
||||
rev = "epoch-${version}";
|
||||
hash = "sha256-+yHpRbK+AWnpcGrC5U0wKbt0u8tm3CFGjKTCDQpb3G0=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-ZRsAhIWPm38Ys9jM/3yVJLW818lUGLCcSfFZb+UTbnU=";
|
||||
cargoHash = "sha256-d56y35npMPrQM0yF0ytNcOdMKBz9IQvEz37DNvKBBSk=";
|
||||
|
||||
nativeBuildInputs = [ just pkg-config ];
|
||||
|
||||
|
34
pkgs/by-name/de/departure-mono/package.nix
Normal file
34
pkgs/by-name/de/departure-mono/package.nix
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
lib,
|
||||
stdenvNoCC,
|
||||
fetchzip,
|
||||
}:
|
||||
|
||||
stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
pname = "departure-mono";
|
||||
version = "1.346";
|
||||
|
||||
src = fetchzip {
|
||||
url = "https://departuremono.com/assets/DepartureMono-${finalAttrs.version}.zip";
|
||||
stripRoot = false;
|
||||
hash = "sha256-xJVVtLnukcWQKVC3QiHvrfIA3W9EYt/iiphbLYT1iMg=";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
install -D -m 444 *.otf -t $out/share/fonts/otf
|
||||
install -D -m 444 *.woff -t $out/share/fonts/woff
|
||||
install -D -m 444 *.woff2 -t $out/share/fonts/woff2
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Departure Mono is a monospaced pixel font with a lo-fi technical vibe";
|
||||
homepage = "https://departuremono.com/";
|
||||
license = lib.licenses.ofl;
|
||||
platforms = lib.platforms.all;
|
||||
maintainers = with lib.maintainers; [ drupol ];
|
||||
};
|
||||
})
|
@ -1,12 +1,12 @@
|
||||
{ stdenv
|
||||
, fetchFromGitHub
|
||||
, fetchpatch
|
||||
, applyPatches
|
||||
, libuuid
|
||||
, bc
|
||||
, lib
|
||||
, buildPackages
|
||||
, nixosTests
|
||||
, runCommand
|
||||
, writeScript
|
||||
}:
|
||||
|
||||
@ -31,45 +31,68 @@ buildType = if stdenv.isDarwin then
|
||||
else
|
||||
"GCC5";
|
||||
|
||||
edk2 = stdenv.mkDerivation rec {
|
||||
edk2 = stdenv.mkDerivation {
|
||||
pname = "edk2";
|
||||
version = "202402";
|
||||
|
||||
patches = [
|
||||
# pass targetPrefix as an env var
|
||||
(fetchpatch {
|
||||
url = "https://src.fedoraproject.org/rpms/edk2/raw/08f2354cd280b4ce5a7888aa85cf520e042955c3/f/0021-Tweak-the-tools_def-to-support-cross-compiling.patch";
|
||||
hash = "sha256-E1/fiFNVx0aB1kOej2DJ2DlBIs9tAAcxoedym2Zhjxw=";
|
||||
})
|
||||
# https://github.com/tianocore/edk2/pull/5658
|
||||
(fetchpatch {
|
||||
url = "https://github.com/tianocore/edk2/commit/a34ff4a8f69a7b8a52b9b299153a8fac702c7df1.patch";
|
||||
hash = "sha256-u+niqwjuLV5tNPykW4xhb7PW2XvUmXhx5uvftG1UIbU=";
|
||||
})
|
||||
];
|
||||
version = "202408";
|
||||
|
||||
srcWithVendoring = fetchFromGitHub {
|
||||
owner = "tianocore";
|
||||
repo = "edk2";
|
||||
rev = "edk2-stable${edk2.version}";
|
||||
fetchSubmodules = true;
|
||||
hash = "sha256-Nurm6QNKCyV6wvbj0ELdYAL7mbZ0yg/tTwnEJ+N18ng=";
|
||||
hash = "sha256-2odaTqiAZD5xduT0dwIYWj3gY/aFPVsTFbblIsEhBiA=";
|
||||
};
|
||||
|
||||
# We don't want EDK2 to keep track of OpenSSL,
|
||||
# they're frankly bad at it.
|
||||
src = runCommand "edk2-unvendored-src" { } ''
|
||||
cp --no-preserve=mode -r ${srcWithVendoring} $out
|
||||
rm -rf $out/CryptoPkg/Library/OpensslLib/openssl
|
||||
mkdir -p $out/CryptoPkg/Library/OpensslLib/openssl
|
||||
tar --strip-components=1 -xf ${buildPackages.openssl.src} -C $out/CryptoPkg/Library/OpensslLib/openssl
|
||||
chmod -R +w $out/
|
||||
src = applyPatches {
|
||||
name = "edk2-${edk2.version}-unvendored-src";
|
||||
src = edk2.srcWithVendoring;
|
||||
|
||||
# Fix missing INT64_MAX include that edk2 explicitly does not provide
|
||||
# via it's own <stdint.h>. Let's pull in openssl's definition instead:
|
||||
sed -i $out/CryptoPkg/Library/OpensslLib/openssl/crypto/property/property_parse.c \
|
||||
-e '1i #include "internal/numbers.h"'
|
||||
'';
|
||||
patches = [
|
||||
# pass targetPrefix as an env var
|
||||
(fetchpatch {
|
||||
url = "https://src.fedoraproject.org/rpms/edk2/raw/08f2354cd280b4ce5a7888aa85cf520e042955c3/f/0021-Tweak-the-tools_def-to-support-cross-compiling.patch";
|
||||
hash = "sha256-E1/fiFNVx0aB1kOej2DJ2DlBIs9tAAcxoedym2Zhjxw=";
|
||||
})
|
||||
# https://github.com/tianocore/edk2/pull/5658
|
||||
(fetchpatch {
|
||||
name = "fix-cross-compilation-antlr-dlg.patch";
|
||||
url = "https://github.com/tianocore/edk2/commit/a34ff4a8f69a7b8a52b9b299153a8fac702c7df1.patch";
|
||||
hash = "sha256-u+niqwjuLV5tNPykW4xhb7PW2XvUmXhx5uvftG1UIbU=";
|
||||
})
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
# We don't want EDK2 to keep track of OpenSSL, they're frankly bad at it.
|
||||
rm -r CryptoPkg/Library/OpensslLib/openssl
|
||||
mkdir -p CryptoPkg/Library/OpensslLib/openssl
|
||||
(
|
||||
cd CryptoPkg/Library/OpensslLib/openssl
|
||||
tar --strip-components=1 -xf ${buildPackages.openssl.src}
|
||||
|
||||
# Apply OpenSSL patches.
|
||||
${lib.pipe buildPackages.openssl.patches [
|
||||
(builtins.filter (
|
||||
patch:
|
||||
!builtins.elem (baseNameOf patch) [
|
||||
# Exclude patches not required in this context.
|
||||
"nix-ssl-cert-file.patch"
|
||||
"openssl-disable-kernel-detection.patch"
|
||||
"use-etc-ssl-certs-darwin.patch"
|
||||
"use-etc-ssl-certs.patch"
|
||||
]
|
||||
))
|
||||
(map (patch: "patch -p1 < ${patch}\n"))
|
||||
lib.concatStrings
|
||||
]}
|
||||
)
|
||||
|
||||
# enable compilation using Clang
|
||||
# https://bugzilla.tianocore.org/show_bug.cgi?id=4620
|
||||
substituteInPlace BaseTools/Conf/tools_def.template --replace-fail \
|
||||
'DEFINE CLANGPDB_WARNING_OVERRIDES = ' \
|
||||
'DEFINE CLANGPDB_WARNING_OVERRIDES = -Wno-unneeded-internal-declaration '
|
||||
'';
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ pythonEnv ];
|
||||
depsBuildBuild = [ buildPackages.stdenv.cc buildPackages.bash ];
|
||||
@ -100,12 +123,13 @@ edk2 = stdenv.mkDerivation rec {
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
meta = with lib; {
|
||||
meta = {
|
||||
description = "Intel EFI development kit";
|
||||
homepage = "https://github.com/tianocore/tianocore.github.io/wiki/EDK-II/";
|
||||
changelog = "https://github.com/tianocore/edk2/releases/tag/edk2-stable${edk2.version}";
|
||||
license = licenses.bsd2;
|
||||
platforms = with platforms; aarch64 ++ arm ++ i686 ++ x86_64 ++ riscv64;
|
||||
license = lib.licenses.bsd2;
|
||||
platforms = with lib.platforms; aarch64 ++ arm ++ i686 ++ x86_64 ++ riscv64;
|
||||
maintainers = [ lib.maintainers.mjoerg ];
|
||||
};
|
||||
|
||||
passthru = {
|
||||
|
@ -17,16 +17,16 @@
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "eza";
|
||||
version = "0.19.0";
|
||||
version = "0.19.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "eza-community";
|
||||
repo = "eza";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-FhtgqfPQRUsnyi/qEe0PPtRfJIUa4UaNbvrkPvZpsQk=";
|
||||
hash = "sha256-VV8tqVJq+bsgfdNSxSzo1vqYtYT37D2pBX4HydY6cKs=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-z1jrCUstQk272EEeqcjGhm5b/YaxTFw21F+AbguMdmo=";
|
||||
cargoHash = "sha256-SUvQxW3STsP1VrPJKK2NYbApuoGfbmfUiywZILvcvj4=";
|
||||
|
||||
nativeBuildInputs = [ cmake pkg-config installShellFiles pandoc ];
|
||||
buildInputs = [ zlib ]
|
||||
|
@ -79,7 +79,7 @@ buildNpmPackage {
|
||||
postBuild =
|
||||
lib.optionalString stdenv.isDarwin ''
|
||||
# electron-builder appears to build directly on top of Electron.app, by overwriting the files in the bundle.
|
||||
cp -r ${electron}/Applications/Electron.app ./
|
||||
cp -r ${electron.dist}/Electron.app ./
|
||||
find ./Electron.app -name 'Info.plist' | xargs -d '\n' chmod +rw
|
||||
|
||||
# Disable code signing during build on macOS.
|
||||
@ -90,7 +90,7 @@ buildNpmPackage {
|
||||
+ ''
|
||||
npm exec electron-builder -- \
|
||||
--dir \
|
||||
-c.electronDist=${if stdenv.isDarwin then "./" else "${electron}/libexec/electron"} \
|
||||
-c.electronDist=${if stdenv.isDarwin then "./" else electron.dist} \
|
||||
-c.electronVersion=${electron.version} \
|
||||
-c.npmRebuild=false
|
||||
'';
|
||||
|
36
pkgs/by-name/ff/ffmpeg-normalize/package.nix
Normal file
36
pkgs/by-name/ff/ffmpeg-normalize/package.nix
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
lib,
|
||||
python3Packages,
|
||||
fetchPypi,
|
||||
ffmpeg,
|
||||
}:
|
||||
python3Packages.buildPythonApplication rec {
|
||||
pname = "ffmpeg-normalize";
|
||||
version = "1.28.3";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
hash = "sha256-8wNPuVRQRQpFK6opgwqdKYMYmAFRqq8p/T5V9kC8QaY=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
ffmpeg
|
||||
python3Packages.ffmpeg-progress-yield
|
||||
];
|
||||
dependencies = with python3Packages; [ colorlog ];
|
||||
|
||||
checkPhase = ''
|
||||
$out/bin/ffmpeg-normalize --help > /dev/null
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Normalize audio via ffmpeg";
|
||||
homepage = "https://github.com/slhck/ffmpeg-normalize";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [
|
||||
luftmensch-luftmensch
|
||||
prusnak
|
||||
];
|
||||
mainProgram = "ffmpeg-normalize";
|
||||
};
|
||||
}
|
91
pkgs/by-name/fi/firefly-iii-data-importer/package.nix
Normal file
91
pkgs/by-name/fi/firefly-iii-data-importer/package.nix
Normal file
@ -0,0 +1,91 @@
|
||||
{
|
||||
lib,
|
||||
fetchFromGitHub,
|
||||
stdenvNoCC,
|
||||
nodejs,
|
||||
fetchNpmDeps,
|
||||
buildPackages,
|
||||
php83,
|
||||
nixosTests,
|
||||
nix-update-script,
|
||||
dataDir ? "/var/lib/firefly-iii-data-importer",
|
||||
}:
|
||||
|
||||
let
|
||||
pname = "firefly-iii-data-importer";
|
||||
version = "1.5.4";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "firefly-iii";
|
||||
repo = "data-importer";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-XnPdoNtUoJpOpKVzQlFirh7u824H4xKAe2VRXfGIKeg=";
|
||||
};
|
||||
in
|
||||
|
||||
stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
inherit pname src version;
|
||||
|
||||
buildInputs = [ php83 ];
|
||||
|
||||
nativeBuildInputs = [
|
||||
nodejs
|
||||
nodejs.python
|
||||
buildPackages.npmHooks.npmConfigHook
|
||||
php83.composerHooks.composerInstallHook
|
||||
php83.packages.composer-local-repo-plugin
|
||||
];
|
||||
|
||||
composerNoDev = true;
|
||||
composerNoPlugins = true;
|
||||
composerNoScripts = true;
|
||||
composerStrictValidation = true;
|
||||
strictDeps = true;
|
||||
|
||||
vendorHash = "sha256-EjEco8zBR787eQuPhNsRScfuPQ6eS6TIJmMJOcmZA+Q=";
|
||||
|
||||
npmDeps = fetchNpmDeps {
|
||||
inherit src;
|
||||
name = "${pname}-npm-deps";
|
||||
hash = "sha256-VP1wM0+ca17aQU4FJ9gSbT2Np/sxb8wZ4pCJ6FV1V7w=";
|
||||
};
|
||||
|
||||
composerRepository = php83.mkComposerRepository {
|
||||
inherit (finalAttrs)
|
||||
pname
|
||||
src
|
||||
vendorHash
|
||||
version
|
||||
;
|
||||
composerNoDev = true;
|
||||
composerNoPlugins = true;
|
||||
composerNoScripts = true;
|
||||
composerStrictValidation = true;
|
||||
};
|
||||
|
||||
preInstall = ''
|
||||
npm run build --workspace=v2
|
||||
'';
|
||||
|
||||
passthru = {
|
||||
phpPackage = php83;
|
||||
tests = nixosTests.firefly-iii-data-importer;
|
||||
updateScript = nix-update-script { };
|
||||
};
|
||||
|
||||
postInstall = ''
|
||||
rm -R $out/share/php/firefly-iii-data-importer/{storage,bootstrap/cache,node_modules}
|
||||
mv $out/share/php/firefly-iii-data-importer/* $out/
|
||||
rm -R $out/share
|
||||
ln -s ${dataDir}/storage $out/storage
|
||||
ln -s ${dataDir}/cache $out/bootstrap/cache
|
||||
'';
|
||||
|
||||
meta = {
|
||||
changelog = "https://github.com/firefly-iii/data-importer/releases/tag/v${version}";
|
||||
description = "Firefly III Data Importer can import data into Firefly III.";
|
||||
homepage = "https://github.com/firefly-iii/data-importer";
|
||||
license = lib.licenses.agpl3Only;
|
||||
maintainers = [ lib.maintainers.savyajha ];
|
||||
};
|
||||
})
|
@ -5,16 +5,16 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "flarectl";
|
||||
version = "0.102.0";
|
||||
version = "0.103.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "cloudflare";
|
||||
repo = "cloudflare-go";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-i/JWbi8itjcFklknFGB23DtYh4+jd+2YMQysHtS3qf8=";
|
||||
hash = "sha256-mYdZgHJz2Ajrk/JRbaDeghm39PWidnAIZvjJTvl8lpM=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-4tJATAvWpWq1aTtV4ERTHF6S2D0azC3HlrwxkLIGT7s=";
|
||||
vendorHash = "sha256-R3By8/cR4pZQgUSyNGDnnvWwcpZqraqk5GRZ8Om9JOU=";
|
||||
|
||||
subPackages = [ "cmd/flarectl" ];
|
||||
|
||||
|
@ -1,33 +1,36 @@
|
||||
{ stdenv
|
||||
, lib
|
||||
, fetchFromGitHub
|
||||
, unstableGitUpdater
|
||||
, alsa-lib
|
||||
, libjack2
|
||||
, pkg-config
|
||||
, zlib
|
||||
{
|
||||
stdenv,
|
||||
lib,
|
||||
fetchFromGitHub,
|
||||
unstableGitUpdater,
|
||||
alsa-lib,
|
||||
cmake,
|
||||
libjack2,
|
||||
pkg-config,
|
||||
zlib,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "fmtoy";
|
||||
version = "0-unstable-2024-06-07";
|
||||
version = "0-unstable-2024-06-11";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "vampirefrog";
|
||||
repo = "fmtoy";
|
||||
rev = "1339600e2f5a4357f7a50f5c6ad49f3c7635adec";
|
||||
hash = "sha256-1kjUPEklZyue/DYn0jSfmXLjF22C+im6klY+S5KCvhc=";
|
||||
rev = "17d69350dcd7e2834e69f65420e5e3a8328b7e18";
|
||||
fetchSubmodules = true;
|
||||
hash = "sha256-to842vUWEWGSQkD09Q22whrdtZpbSlwaY5LSS208sP8=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
substituteInPlace Makefile \
|
||||
--replace 'pkg-config' "$PKG_CONFIG"
|
||||
--replace-fail 'pkg-config' "$PKG_CONFIG"
|
||||
'';
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
pkg-config
|
||||
];
|
||||
|
||||
@ -37,6 +40,8 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
zlib
|
||||
];
|
||||
|
||||
dontUseCmakeConfigure = true;
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
buildFlags = [
|
||||
@ -56,12 +61,12 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
updateScript = unstableGitUpdater { };
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
meta = {
|
||||
description = "FM synthesiser based on emulated Yamaha YM chips (OPL, OPM and OPN series)";
|
||||
homepage = "https://github.com/vampirefrog/fmtoy";
|
||||
license = licenses.gpl3Only;
|
||||
license = lib.licenses.gpl3Only;
|
||||
mainProgram = "fmtoy_jack";
|
||||
maintainers = with maintainers; [ OPNA2608 ];
|
||||
platforms = platforms.linux;
|
||||
maintainers = with lib.maintainers; [ OPNA2608 ];
|
||||
platforms = lib.platforms.linux;
|
||||
};
|
||||
})
|
||||
|
@ -28,13 +28,13 @@ let
|
||||
pieBuild = stdenv.hostPlatform.isMusl;
|
||||
in buildGoModule rec {
|
||||
pname = "frankenphp";
|
||||
version = "1.2.4";
|
||||
version = "1.2.5";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "dunglas";
|
||||
repo = "frankenphp";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-ZM8/1u4wIBHUgq2x8zyDJhf+qFQz4u5fhLNLaqAv/54=";
|
||||
hash = "sha256-X6lWbxgqj0wis/cljoNSh7AsH1zY30GTjSOAGXzUIek=";
|
||||
};
|
||||
|
||||
sourceRoot = "${src.name}/caddy";
|
||||
@ -42,7 +42,7 @@ in buildGoModule rec {
|
||||
# frankenphp requires C code that would be removed with `go mod tidy`
|
||||
# https://github.com/golang/go/issues/26366
|
||||
proxyVendor = true;
|
||||
vendorHash = "sha256-3Y5STb521iRois/KLQqdTxxTYdp39PTaiJEBjWrZsyw=";
|
||||
vendorHash = "sha256-U2B0ok6TgqUPMwlnkzpPkJLG22S3VpoU80bWwZAeaJo=";
|
||||
|
||||
buildInputs = [ phpUnwrapped brotli ] ++ phpUnwrapped.buildInputs;
|
||||
nativeBuildInputs = [ makeBinaryWrapper ] ++ lib.optionals stdenv.isDarwin [ pkg-config cctools darwin.autoSignDarwinBinariesHook ];
|
||||
|
@ -56,7 +56,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
npm exec electron-builder -- \
|
||||
--dir \
|
||||
-c.electronDist="${electron}/libexec/electron" \
|
||||
-c.electronDist="${electron.dist}" \
|
||||
-c.electronVersion="${electron.version}"
|
||||
|
||||
runHook postBuild
|
||||
|
@ -16,13 +16,13 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "grafana-alloy";
|
||||
version = "1.3.0";
|
||||
version = "1.3.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
rev = "v${version}";
|
||||
owner = "grafana";
|
||||
repo = "alloy";
|
||||
hash = "sha256-2OpBRSX/t6hwf1fHogrNTuDAmKArVXxwKHXuHyTXnYA=";
|
||||
hash = "sha256-6YjQUIHZmuguzqTeaLgkrM/WdBPZu/KUXUDOmEB7rNQ=";
|
||||
};
|
||||
|
||||
proxyVendor = true;
|
||||
|
43
pkgs/by-name/hx/hxtools/package.nix
Normal file
43
pkgs/by-name/hx/hxtools/package.nix
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchurl,
|
||||
pkg-config,
|
||||
zstd,
|
||||
libHX,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "hxtools";
|
||||
version = "20231224";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://inai.de/files/hxtools/hxtools-${finalAttrs.version}.tar.zst";
|
||||
hash = "sha256-TyT9bsp9qqGKQsSyWCfd2lH8ULjqJ5puMTw2TgWHV5c=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
zstd
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
libHX
|
||||
];
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
meta = {
|
||||
homepage = "https://inai.de/projects/hxtools/";
|
||||
description = "Collection of small tools over the years by j.eng";
|
||||
# Taken from https://codeberg.org/jengelh/hxtools/src/branch/master/LICENSES.txt
|
||||
license = with lib.licenses; [
|
||||
mit
|
||||
bsd2Patent
|
||||
lgpl21Plus
|
||||
gpl2Plus
|
||||
];
|
||||
maintainers = with lib.maintainers; [ meator ];
|
||||
platforms = lib.platforms.all;
|
||||
};
|
||||
})
|
@ -122,6 +122,9 @@ rustPlatform.buildRustPackage rec {
|
||||
withSecretProvisioning = kanidm.override { enableSecretProvisioning = true; };
|
||||
};
|
||||
|
||||
# can take over 4 hours on 2 cores and needs 16GB+ RAM
|
||||
requiredSystemFeatures = [ "big-parallel" ];
|
||||
|
||||
meta = with lib; {
|
||||
changelog = "https://github.com/kanidm/kanidm/releases/tag/v${version}";
|
||||
description = "Simple, secure and fast identity management platform";
|
||||
|
@ -13,9 +13,6 @@
|
||||
electron,
|
||||
}:
|
||||
|
||||
let
|
||||
electronDist = electron + (if stdenv.isDarwin then "/Applications" else "/libexec/electron");
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "koodo-reader";
|
||||
version = "1.6.7";
|
||||
@ -52,7 +49,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
env.CSC_IDENTITY_AUTO_DISCOVERY = "false";
|
||||
|
||||
postBuild = ''
|
||||
cp -r ${electronDist} electron-dist
|
||||
cp -r ${electron.dist} electron-dist
|
||||
chmod -R u+w electron-dist
|
||||
yarn --offline run electron-builder --dir \
|
||||
-c.electronDist=electron-dist \
|
||||
@ -117,7 +114,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
meta = {
|
||||
changelog = "https://github.com/troyeguo/koodo-reader/releases/tag/v${finalAttrs.version}";
|
||||
description = "A cross-platform ebook reader";
|
||||
description = "Cross-platform ebook reader";
|
||||
longDescription = ''
|
||||
A modern ebook manager and reader with sync and backup capacities
|
||||
for Windows, macOS, Linux and Web
|
||||
|
@ -7,11 +7,11 @@
|
||||
|
||||
stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
pname = "loopwm";
|
||||
version = "1.0.0";
|
||||
version = "1.1.1";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://github.com/MrKai77/Loop/releases/download/${finalAttrs.version}/Loop.zip";
|
||||
hash = "sha256-1DQ6O6QkD04/meS0XaS0+vpr+vd5cfwGSehV8QVgYtI=";
|
||||
hash = "sha256-eF8B4rmkyTtT0vWTcjdaNaWCHWSlPfS4uVV29L+wXiM=";
|
||||
};
|
||||
|
||||
sourceRoot = ".";
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user