mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-22 15:03:28 +00:00
Merge branch 'master' into haskell-updates
This commit is contained in:
commit
81b5682da3
@ -513,3 +513,73 @@ If you do need to do create this sort of patch file, one way to do so is with gi
|
||||
```ShellSession
|
||||
$ git diff > nixpkgs/pkgs/the/package/0001-changes.patch
|
||||
```
|
||||
|
||||
## Package tests {#sec-package-tests}
|
||||
|
||||
Tests are important to ensure quality and make reviews and automatic updates easy.
|
||||
|
||||
Nix package tests are a lightweight alternative to [NixOS module tests](https://nixos.org/manual/nixos/stable/#sec-nixos-tests). They can be used to create simple integration tests for packages while the module tests are used to test services or programs with a graphical user interface on a NixOS VM. Unittests that are included in the source code of a package should be executed in the `checkPhase`.
|
||||
|
||||
### Writing package tests {#ssec-package-tests-writing}
|
||||
|
||||
This is an example using the `phoronix-test-suite` package with the current best practices.
|
||||
|
||||
Add the tests in `passthru.tests` to the package definition like this:
|
||||
|
||||
```nix
|
||||
{ stdenv, lib, fetchurl, callPackage }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
…
|
||||
|
||||
passthru.tests = {
|
||||
simple-execution = callPackage ./tests.nix { };
|
||||
};
|
||||
|
||||
meta = { … };
|
||||
}
|
||||
```
|
||||
|
||||
Create `tests.nix` in the package directory:
|
||||
|
||||
```nix
|
||||
{ runCommand, phoronix-test-suite }:
|
||||
|
||||
let
|
||||
inherit (phoronix-test-suite) pname version;
|
||||
in
|
||||
|
||||
runCommand "${pname}-tests" { meta.timeout = 3; }
|
||||
''
|
||||
# automatic initial setup to prevent interactive questions
|
||||
${phoronix-test-suite}/bin/phoronix-test-suite enterprise-setup >/dev/null
|
||||
# get version of installed program and compare with package version
|
||||
if [[ `${phoronix-test-suite}/bin/phoronix-test-suite version` != *"${version}"* ]]; then
|
||||
echo "Error: program version does not match package version"
|
||||
exit 1
|
||||
fi
|
||||
# run dummy command
|
||||
${phoronix-test-suite}/bin/phoronix-test-suite dummy_module.dummy-command >/dev/null
|
||||
# needed for Nix to register the command as successful
|
||||
touch $out
|
||||
''
|
||||
```
|
||||
|
||||
### Running package tests {#ssec-package-tests-running}
|
||||
|
||||
You can run these tests with:
|
||||
|
||||
```ShellSession
|
||||
$ cd path/to/nixpkgs
|
||||
$ nix-build -A phoronix-test-suite.tests
|
||||
```
|
||||
|
||||
### Examples of package tests {#ssec-package-tests-examples}
|
||||
|
||||
Here are examples of package tests:
|
||||
|
||||
- [Jasmin compile test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/compilers/jasmin/test-assemble-hello-world/default.nix)
|
||||
- [Lobster compile test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/compilers/lobster/test-can-run-hello-world.nix)
|
||||
- [Spacy annotation test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/python-modules/spacy/annotation-test/default.nix)
|
||||
- [Libtorch test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/science/math/libtorch/test/default.nix)
|
||||
- [Multiple tests for nanopb](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/nanopb/default.nix)
|
||||
|
@ -606,7 +606,7 @@ rec {
|
||||
This function will fail if the input string is longer than the
|
||||
requested length.
|
||||
|
||||
Type: fixedWidthString :: int -> string -> string
|
||||
Type: fixedWidthString :: int -> string -> string -> string
|
||||
|
||||
Example:
|
||||
fixedWidthString 5 "0" (toString 15)
|
||||
|
@ -337,7 +337,7 @@ rec {
|
||||
};
|
||||
|
||||
shellPackage = package // {
|
||||
check = x: (package.check x) && (hasAttr "shellPath" x);
|
||||
check = x: isDerivation x && hasAttr "shellPath" x;
|
||||
};
|
||||
|
||||
path = mkOptionType {
|
||||
|
@ -2177,6 +2177,12 @@
|
||||
githubId = 990767;
|
||||
name = "Daniel Olsen";
|
||||
};
|
||||
daneads = {
|
||||
email = "me@daneads.com";
|
||||
github = "daneads";
|
||||
githubId = 24708079;
|
||||
name = "Dan Eads";
|
||||
};
|
||||
danharaj = {
|
||||
email = "dan@obsidian.systems";
|
||||
github = "danharaj";
|
||||
@ -2439,6 +2445,12 @@
|
||||
githubId = 8404455;
|
||||
name = "Diego Lelis";
|
||||
};
|
||||
diogox = {
|
||||
name = "Diogo Xavier";
|
||||
email = "13244408+diogox@users.noreply.github.com";
|
||||
github = "diogox";
|
||||
githubId = 13244408;
|
||||
};
|
||||
dipinhora = {
|
||||
email = "dipinhora+github@gmail.com";
|
||||
github = "dipinhora";
|
||||
@ -3029,6 +3041,12 @@
|
||||
fingerprint = "F178 B4B4 6165 6D1B 7C15 B55D 4029 3358 C7B9 326B";
|
||||
}];
|
||||
};
|
||||
erikbackman = {
|
||||
email = "contact@ebackman.net";
|
||||
github = "erikbackman";
|
||||
githubId = 46724898;
|
||||
name = "Erik Backman";
|
||||
};
|
||||
erikryb = {
|
||||
email = "erik.rybakken@math.ntnu.no";
|
||||
github = "erikryb";
|
||||
@ -3107,6 +3125,16 @@
|
||||
githubId = 2147649;
|
||||
name = "Euan Kemp";
|
||||
};
|
||||
evalexpr = {
|
||||
name = "Jonathan Wilkins";
|
||||
email = "nixos@wilkins.tech";
|
||||
github = "evalexpr";
|
||||
githubId = 23485511;
|
||||
keys = [{
|
||||
longkeyid = "rsa4096/0x2D1D402E17763DD6";
|
||||
fingerprint = "8129 5B85 9C5A F703 C2F4 1E29 2D1D 402E 1776 3DD6";
|
||||
}];
|
||||
};
|
||||
evanjs = {
|
||||
email = "evanjsx@gmail.com";
|
||||
github = "evanjs";
|
||||
@ -4725,6 +4753,12 @@
|
||||
githubId = 1102396;
|
||||
name = "Jussi Maki";
|
||||
};
|
||||
joaquinito2051 = {
|
||||
email = "joaquinito2051@gmail.com";
|
||||
github = "heroku-miraheze";
|
||||
githubId = 61781343;
|
||||
name = "Joaquín Rufo Gutierrez";
|
||||
};
|
||||
jobojeha = {
|
||||
email = "jobojeha@jeppener.de";
|
||||
github = "jobojeha";
|
||||
@ -6144,11 +6178,11 @@
|
||||
fingerprint = "B573 5118 0375 A872 FBBF 7770 B629 036B E399 EEE9";
|
||||
}];
|
||||
};
|
||||
mausch = {
|
||||
email = "mauricioscheffer@gmail.com";
|
||||
github = "mausch";
|
||||
githubId = 95194;
|
||||
name = "Mauricio Scheffer";
|
||||
masipcat = {
|
||||
email = "jordi@masip.cat";
|
||||
github = "masipcat";
|
||||
githubId = 775189;
|
||||
name = "Jordi Masip";
|
||||
};
|
||||
matejc = {
|
||||
email = "cotman.matej@gmail.com";
|
||||
@ -6204,6 +6238,12 @@
|
||||
githubId = 136037;
|
||||
name = "Matthew Maurer";
|
||||
};
|
||||
mausch = {
|
||||
email = "mauricioscheffer@gmail.com";
|
||||
github = "mausch";
|
||||
githubId = 95194;
|
||||
name = "Mauricio Scheffer";
|
||||
};
|
||||
maxdamantus = {
|
||||
email = "maxdamantus@gmail.com";
|
||||
github = "Maxdamantus";
|
||||
@ -10537,7 +10577,12 @@
|
||||
githubId = 45292658;
|
||||
name = "Julius Schmitt";
|
||||
};
|
||||
|
||||
vojta001 = {
|
||||
email = "vojtech.kane@gmail.com";
|
||||
github = "vojta001";
|
||||
githubId = 7038383;
|
||||
name = "Vojta Káně";
|
||||
};
|
||||
volhovm = {
|
||||
email = "volhovm.cs@gmail.com";
|
||||
github = "volhovm";
|
||||
|
@ -144,6 +144,7 @@ with lib.maintainers; {
|
||||
mguentner
|
||||
ekleog
|
||||
ralith
|
||||
mjlbach
|
||||
];
|
||||
scope = "Maintain the ecosystem around Matrix, a decentralized messenger.";
|
||||
};
|
||||
|
@ -330,7 +330,18 @@
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>vim</literal> switched to Python 3, dropping all Python 2 support.
|
||||
<literal>vim</literal> and <literal>neovim</literal> switched to Python 3, dropping all Python 2 support.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link linkend="opt-networking.wireguard.interfaces">networking.wireguard.interfaces.<name>.generatePrivateKeyFile</link>,
|
||||
which is off by default, had a <literal>chmod</literal> race condition
|
||||
fixed. As an aside, the parent directory's permissions were widened,
|
||||
and the key files were made owner-writable.
|
||||
This only affects newly created keys.
|
||||
However, if the exact permissions are important for your setup, read
|
||||
<link xlink:href="https://github.com/NixOS/nixpkgs/pull/121294">#121294</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
@ -692,6 +703,17 @@ environment.systemPackages = [
|
||||
<literal>skip-kernel-setup true</literal> and takes care of setting forwarding and rp_filter sysctls by itself as well
|
||||
as for each interface in <varname>services.babeld.interfaces</varname>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <option>services.zigbee2mqtt.config</option> option has been renamed to <option>services.zigbee2mqtt.settings</option> and
|
||||
now follows <link xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC 0042</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The <package>yadm</package> dotfile manager has been updated from 2.x to 3.x, which has new (XDG) default locations for some data/state files. Most yadm commands will fail and print a legacy path warning (which describes how to upgrade/migrate your repository). If you have scripts, daemons, scheduled jobs, shell profiles, etc. that invoke yadm, expect them to fail or misbehave until you perform this migration and prepare accordingly.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
@ -807,6 +829,23 @@ environment.systemPackages = [
|
||||
default in the CLI tooling which in turn enables us to use
|
||||
<literal>unbound-control</literal> without passing a custom configuration location.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The module has also been reworked to be <link
|
||||
xlink:href="https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md">RFC
|
||||
0042</link> compliant. As such,
|
||||
<option>sevices.unbound.extraConfig</option> has been removed and replaced
|
||||
by <xref linkend="opt-services.unbound.settings"/>. <option>services.unbound.interfaces</option>
|
||||
has been renamed to <option>services.unbound.settings.server.interface</option>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<option>services.unbound.forwardAddresses</option> and
|
||||
<option>services.unbound.allowedAccess</option> have also been changed to
|
||||
use the new settings interface. You can follow the instructions when
|
||||
executing <literal>nixos-rebuild</literal> to upgrade your configuration to
|
||||
use the new interface.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
@ -978,6 +1017,24 @@ environment.systemPackages = [
|
||||
PostgreSQL 9.5 is scheduled EOL during the 21.05 life cycle and has been removed.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://www.xfce.org/">Xfce4</link> relies on
|
||||
GIO/GVfs for userspace virtual filesystem access in applications
|
||||
like <link xlink:href="https://docs.xfce.org/xfce/thunar/">thunar</link> and
|
||||
<link xlink:href="https://docs.xfce.org/apps/gigolo/">gigolo</link>.
|
||||
For that to work, the gvfs nixos service is enabled by default,
|
||||
and it can be configured with the specific package that provides
|
||||
GVfs. Until now Xfce4 was setting it to use a lighter version of
|
||||
GVfs (without support for samba). To avoid conflicts with other
|
||||
desktop environments this setting has been dropped. Users that
|
||||
still want it should add the following to their system
|
||||
configuration:
|
||||
<programlisting>
|
||||
<xref linkend="opt-services.gvfs.package" /> = pkgs.gvfs.override { samba = null; };
|
||||
</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
</section>
|
||||
|
@ -54,8 +54,13 @@ rec {
|
||||
};
|
||||
|
||||
# Run an automated test suite in the given virtual network.
|
||||
# `driver' is the script that runs the network.
|
||||
runTests = driver:
|
||||
runTests = {
|
||||
# the script that runs the network
|
||||
driver,
|
||||
# a source position in the format of builtins.unsafeGetAttrPos
|
||||
# for meta.position
|
||||
pos,
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
name = "vm-test-run-${driver.testName}";
|
||||
|
||||
@ -69,6 +74,8 @@ rec {
|
||||
'';
|
||||
|
||||
passthru = driver.passthru;
|
||||
|
||||
inherit pos;
|
||||
};
|
||||
|
||||
|
||||
@ -79,6 +86,11 @@ rec {
|
||||
# Skip linting (mainly intended for faster dev cycles)
|
||||
, skipLint ? false
|
||||
, passthru ? {}
|
||||
, # For meta.position
|
||||
pos ? # position used in error messages and for meta.position
|
||||
(if t.meta.description or null != null
|
||||
then builtins.unsafeGetAttrPos "description" t.meta
|
||||
else builtins.unsafeGetAttrPos "testScript" t)
|
||||
, ...
|
||||
} @ t:
|
||||
let
|
||||
@ -174,7 +186,7 @@ rec {
|
||||
driver = mkDriver null;
|
||||
driverInteractive = mkDriver pkgs.qemu;
|
||||
|
||||
test = passMeta (runTests driver);
|
||||
test = passMeta (runTests { inherit driver pos; });
|
||||
|
||||
nodeNames = builtins.attrNames driver.nodes;
|
||||
invalidNodeNames = lib.filter
|
||||
|
@ -41,7 +41,7 @@ in {
|
||||
|
||||
sizeMB = mkOption {
|
||||
type = with types; either (enum [ "auto" ]) int;
|
||||
default = "auto";
|
||||
default = if config.ec2.hvm then 2048 else 8192;
|
||||
example = 8192;
|
||||
description = "The size in MB of the image";
|
||||
};
|
||||
|
@ -126,6 +126,13 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
expandOnBoot = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to configure the sd image to expand it's partition on boot.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
@ -215,7 +222,7 @@ in
|
||||
'';
|
||||
}) {};
|
||||
|
||||
boot.postBootCommands = ''
|
||||
boot.postBootCommands = lib.mkIf config.sdImage.expandOnBoot ''
|
||||
# On the first boot do some maintenance tasks
|
||||
if [ -f /nix-path-registration ]; then
|
||||
set -euo pipefail
|
||||
|
@ -114,6 +114,9 @@
|
||||
./programs/autojump.nix
|
||||
./programs/bandwhich.nix
|
||||
./programs/bash/bash.nix
|
||||
./programs/bash/bash-completion.nix
|
||||
./programs/bash/ls-colors.nix
|
||||
./programs/bash/undistract-me.nix
|
||||
./programs/bash-my-aws.nix
|
||||
./programs/bcc.nix
|
||||
./programs/browserpass.nix
|
||||
@ -130,6 +133,7 @@
|
||||
./programs/droidcam.nix
|
||||
./programs/environment.nix
|
||||
./programs/evince.nix
|
||||
./programs/feedbackd.nix
|
||||
./programs/file-roller.nix
|
||||
./programs/firejail.nix
|
||||
./programs/fish.nix
|
||||
@ -163,6 +167,7 @@
|
||||
./programs/partition-manager.nix
|
||||
./programs/plotinus.nix
|
||||
./programs/proxychains.nix
|
||||
./programs/phosh.nix
|
||||
./programs/qt5ct.nix
|
||||
./programs/screen.nix
|
||||
./programs/sedutil.nix
|
||||
@ -509,6 +514,7 @@
|
||||
./services/misc/mame.nix
|
||||
./services/misc/matrix-appservice-discord.nix
|
||||
./services/misc/matrix-appservice-irc.nix
|
||||
./services/misc/matrix-dendrite.nix
|
||||
./services/misc/matrix-synapse.nix
|
||||
./services/misc/mautrix-telegram.nix
|
||||
./services/misc/mbpfan.nix
|
||||
@ -975,6 +981,7 @@
|
||||
./services/web-servers/shellinabox.nix
|
||||
./services/web-servers/tomcat.nix
|
||||
./services/web-servers/traefik.nix
|
||||
./services/web-servers/trafficserver.nix
|
||||
./services/web-servers/ttyd.nix
|
||||
./services/web-servers/uwsgi.nix
|
||||
./services/web-servers/varnish/default.nix
|
||||
|
37
nixos/modules/programs/bash/bash-completion.nix
Normal file
37
nixos/modules/programs/bash/bash-completion.nix
Normal file
@ -0,0 +1,37 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
enable = config.programs.bash.enableCompletion;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
programs.bash.enableCompletion = mkEnableOption "Bash completion for all interactive bash shells" // {
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf enable {
|
||||
programs.bash.promptPluginInit = ''
|
||||
# Check whether we're running a version of Bash that has support for
|
||||
# programmable completion. If we do, enable all modules installed in
|
||||
# the system and user profile in obsolete /etc/bash_completion.d/
|
||||
# directories. Bash loads completions in all
|
||||
# $XDG_DATA_DIRS/bash-completion/completions/
|
||||
# on demand, so they do not need to be sourced here.
|
||||
if shopt -q progcomp &>/dev/null; then
|
||||
. "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
|
||||
nullglobStatus=$(shopt -p nullglob)
|
||||
shopt -s nullglob
|
||||
for p in $NIX_PROFILES; do
|
||||
for m in "$p/etc/bash_completion.d/"*; do
|
||||
. $m
|
||||
done
|
||||
done
|
||||
eval "$nullglobStatus"
|
||||
unset nullglobStatus p m
|
||||
fi
|
||||
'';
|
||||
};
|
||||
}
|
@ -11,31 +11,6 @@ let
|
||||
|
||||
cfg = config.programs.bash;
|
||||
|
||||
bashCompletion = optionalString cfg.enableCompletion ''
|
||||
# Check whether we're running a version of Bash that has support for
|
||||
# programmable completion. If we do, enable all modules installed in
|
||||
# the system and user profile in obsolete /etc/bash_completion.d/
|
||||
# directories. Bash loads completions in all
|
||||
# $XDG_DATA_DIRS/bash-completion/completions/
|
||||
# on demand, so they do not need to be sourced here.
|
||||
if shopt -q progcomp &>/dev/null; then
|
||||
. "${pkgs.bash-completion}/etc/profile.d/bash_completion.sh"
|
||||
nullglobStatus=$(shopt -p nullglob)
|
||||
shopt -s nullglob
|
||||
for p in $NIX_PROFILES; do
|
||||
for m in "$p/etc/bash_completion.d/"*; do
|
||||
. $m
|
||||
done
|
||||
done
|
||||
eval "$nullglobStatus"
|
||||
unset nullglobStatus p m
|
||||
fi
|
||||
'';
|
||||
|
||||
lsColors = optionalString cfg.enableLsColors ''
|
||||
eval "$(${pkgs.coreutils}/bin/dircolors -b)"
|
||||
'';
|
||||
|
||||
bashAliases = concatStringsSep "\n" (
|
||||
mapAttrsFlatten (k: v: "alias ${k}=${escapeShellArg v}")
|
||||
(filterAttrs (k: v: v != null) cfg.shellAliases)
|
||||
@ -123,20 +98,13 @@ in
|
||||
type = types.lines;
|
||||
};
|
||||
|
||||
enableCompletion = mkOption {
|
||||
default = true;
|
||||
promptPluginInit = mkOption {
|
||||
default = "";
|
||||
description = ''
|
||||
Enable Bash completion for all interactive bash shells.
|
||||
Shell script code used to initialise bash prompt plugins.
|
||||
'';
|
||||
type = types.bool;
|
||||
};
|
||||
|
||||
enableLsColors = mkOption {
|
||||
default = true;
|
||||
description = ''
|
||||
Enable extra colors in directory listings.
|
||||
'';
|
||||
type = types.bool;
|
||||
type = types.lines;
|
||||
internal = true;
|
||||
};
|
||||
|
||||
};
|
||||
@ -167,8 +135,7 @@ in
|
||||
set +h
|
||||
|
||||
${cfg.promptInit}
|
||||
${bashCompletion}
|
||||
${lsColors}
|
||||
${cfg.promptPluginInit}
|
||||
${bashAliases}
|
||||
|
||||
${cfge.interactiveShellInit}
|
||||
|
20
nixos/modules/programs/bash/ls-colors.nix
Normal file
20
nixos/modules/programs/bash/ls-colors.nix
Normal file
@ -0,0 +1,20 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
enable = config.programs.bash.enableLsColors;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
programs.bash.enableLsColors = mkEnableOption "extra colors in directory listings" // {
|
||||
default = true;
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf enable {
|
||||
programs.bash.promptPluginInit = ''
|
||||
eval "$(${pkgs.coreutils}/bin/dircolors -b)"
|
||||
'';
|
||||
};
|
||||
}
|
36
nixos/modules/programs/bash/undistract-me.nix
Normal file
36
nixos/modules/programs/bash/undistract-me.nix
Normal file
@ -0,0 +1,36 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.bash.undistractMe;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
programs.bash.undistractMe = {
|
||||
enable = mkEnableOption "notifications when long-running terminal commands complete";
|
||||
|
||||
playSound = mkEnableOption "notification sounds when long-running terminal commands complete";
|
||||
|
||||
timeout = mkOption {
|
||||
default = 10;
|
||||
description = ''
|
||||
Number of seconds it would take for a command to be considered long-running.
|
||||
'';
|
||||
type = types.int;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
programs.bash.promptPluginInit = ''
|
||||
export LONG_RUNNING_COMMAND_TIMEOUT=${toString cfg.timeout}
|
||||
export UDM_PLAY_SOUND=${if cfg.playSound then "1" else "0"}
|
||||
. "${pkgs.undistract-me}/etc/profile.d/undistract-me.sh"
|
||||
'';
|
||||
};
|
||||
|
||||
meta = {
|
||||
maintainers = with maintainers; [ metadark ];
|
||||
};
|
||||
}
|
32
nixos/modules/programs/feedbackd.nix
Normal file
32
nixos/modules/programs/feedbackd.nix
Normal file
@ -0,0 +1,32 @@
|
||||
{ pkgs, lib, config, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.feedbackd;
|
||||
in {
|
||||
options = {
|
||||
programs.feedbackd = {
|
||||
enable = mkEnableOption ''
|
||||
Whether to enable the feedbackd D-BUS service and udev rules.
|
||||
|
||||
Your user needs to be in the `feedbackd` group to trigger effects.
|
||||
'';
|
||||
package = mkOption {
|
||||
description = ''
|
||||
Which feedbackd package to use.
|
||||
'';
|
||||
type = types.package;
|
||||
default = pkgs.feedbackd;
|
||||
};
|
||||
};
|
||||
};
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
services.dbus.packages = [ cfg.package ];
|
||||
services.udev.packages = [ cfg.package ];
|
||||
|
||||
users.groups.feedbackd = {};
|
||||
};
|
||||
}
|
167
nixos/modules/programs/phosh.nix
Normal file
167
nixos/modules/programs/phosh.nix
Normal file
@ -0,0 +1,167 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.phosh;
|
||||
|
||||
# Based on https://source.puri.sm/Librem5/librem5-base/-/blob/4596c1056dd75ac7f043aede07887990fd46f572/default/sm.puri.OSK0.desktop
|
||||
oskItem = pkgs.makeDesktopItem {
|
||||
name = "sm.puri.OSK0";
|
||||
type = "Application";
|
||||
desktopName = "On-screen keyboard";
|
||||
exec = "${pkgs.squeekboard}/bin/squeekboard";
|
||||
categories = "GNOME;Core;";
|
||||
extraEntries = ''
|
||||
OnlyShowIn=GNOME;
|
||||
NoDisplay=true
|
||||
X-GNOME-Autostart-Phase=Panel
|
||||
X-GNOME-Provides=inputmethod
|
||||
X-GNOME-Autostart-Notify=true
|
||||
X-GNOME-AutoRestart=true
|
||||
'';
|
||||
};
|
||||
|
||||
phocConfigType = types.submodule {
|
||||
options = {
|
||||
xwayland = mkOption {
|
||||
description = ''
|
||||
Whether to enable XWayland support.
|
||||
|
||||
To start XWayland immediately, use `immediate`.
|
||||
'';
|
||||
type = types.enum [ "true" "false" "immediate" ];
|
||||
default = "false";
|
||||
};
|
||||
cursorTheme = mkOption {
|
||||
description = ''
|
||||
Cursor theme to use in Phosh.
|
||||
'';
|
||||
type = types.str;
|
||||
default = "default";
|
||||
};
|
||||
outputs = mkOption {
|
||||
description = ''
|
||||
Output configurations.
|
||||
'';
|
||||
type = types.attrsOf phocOutputType;
|
||||
default = {
|
||||
DSI-1 = {
|
||||
scale = 2;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
phocOutputType = types.submodule {
|
||||
options = {
|
||||
modeline = mkOption {
|
||||
description = ''
|
||||
One or more modelines.
|
||||
'';
|
||||
type = types.either types.str (types.listOf types.str);
|
||||
default = [];
|
||||
example = [
|
||||
"87.25 720 776 848 976 1440 1443 1453 1493 -hsync +vsync"
|
||||
"65.13 768 816 896 1024 1024 1025 1028 1060 -HSync +VSync"
|
||||
];
|
||||
};
|
||||
mode = mkOption {
|
||||
description = ''
|
||||
Default video mode.
|
||||
'';
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "768x1024";
|
||||
};
|
||||
scale = mkOption {
|
||||
description = ''
|
||||
Display scaling factor.
|
||||
'';
|
||||
type = types.nullOr types.ints.unsigned;
|
||||
default = null;
|
||||
example = 2;
|
||||
};
|
||||
rotate = mkOption {
|
||||
description = ''
|
||||
Screen transformation.
|
||||
'';
|
||||
type = types.enum [
|
||||
"90" "180" "270" "flipped" "flipped-90" "flipped-180" "flipped-270" null
|
||||
];
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
optionalKV = k: v: if v == null then "" else "${k} = ${builtins.toString v}";
|
||||
|
||||
renderPhocOutput = name: output: let
|
||||
modelines = if builtins.isList output.modeline
|
||||
then output.modeline
|
||||
else [ output.modeline ];
|
||||
renderModeline = l: "modeline = ${l}";
|
||||
in ''
|
||||
[output:${name}]
|
||||
${concatStringsSep "\n" (map renderModeline modelines)}
|
||||
${optionalKV "mode" output.mode}
|
||||
${optionalKV "scale" output.scale}
|
||||
${optionalKV "rotate" output.rotate}
|
||||
'';
|
||||
|
||||
renderPhocConfig = phoc: let
|
||||
outputs = mapAttrsToList renderPhocOutput phoc.outputs;
|
||||
in ''
|
||||
[core]
|
||||
xwayland = ${phoc.xwayland}
|
||||
${concatStringsSep "\n" outputs}
|
||||
[cursor]
|
||||
theme = ${phoc.cursorTheme}
|
||||
'';
|
||||
in {
|
||||
options = {
|
||||
programs.phosh = {
|
||||
enable = mkEnableOption ''
|
||||
Whether to enable, Phosh, related packages and default configurations.
|
||||
'';
|
||||
phocConfig = mkOption {
|
||||
description = ''
|
||||
Configurations for the Phoc compositor.
|
||||
'';
|
||||
type = types.oneOf [ types.lines types.path phocConfigType ];
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [
|
||||
pkgs.phoc
|
||||
pkgs.phosh
|
||||
pkgs.squeekboard
|
||||
oskItem
|
||||
];
|
||||
|
||||
programs.feedbackd.enable = true;
|
||||
|
||||
# https://source.puri.sm/Librem5/phosh/-/issues/303
|
||||
security.pam.services.phosh = {
|
||||
text = ''
|
||||
auth requisite pam_nologin.so
|
||||
auth required pam_succeed_if.so user != root quiet_success
|
||||
auth required pam_securetty.so
|
||||
auth requisite pam_nologin.so
|
||||
'';
|
||||
};
|
||||
|
||||
services.gnome3.core-shell.enable = true;
|
||||
services.gnome3.core-os-services.enable = true;
|
||||
services.xserver.displayManager.sessionPackages = [ pkgs.phosh ];
|
||||
|
||||
environment.etc."phosh/phoc.ini".source =
|
||||
if builtins.isPath cfg.phocConfig then cfg.phocConfig
|
||||
else if builtins.isString cfg.phocConfig then pkgs.writeText "phoc.ini" cfg.phocConfig
|
||||
else pkgs.writeText "phoc.ini" (renderPhocConfig cfg.phocConfig);
|
||||
};
|
||||
}
|
@ -145,7 +145,7 @@ in
|
||||
extraOpts = mkOption {
|
||||
description = "Kubernetes apiserver extra command line options.";
|
||||
default = "";
|
||||
type = str;
|
||||
type = separatedString " ";
|
||||
};
|
||||
|
||||
extraSANs = mkOption {
|
||||
|
@ -38,7 +38,7 @@ in
|
||||
extraOpts = mkOption {
|
||||
description = "Kubernetes controller manager extra command line options.";
|
||||
default = "";
|
||||
type = str;
|
||||
type = separatedString " ";
|
||||
};
|
||||
|
||||
featureGates = mkOption {
|
||||
|
@ -142,7 +142,7 @@ in
|
||||
extraOpts = mkOption {
|
||||
description = "Kubernetes kubelet extra command line options.";
|
||||
default = "";
|
||||
type = str;
|
||||
type = separatedString " ";
|
||||
};
|
||||
|
||||
featureGates = mkOption {
|
||||
|
@ -25,7 +25,7 @@ in
|
||||
extraOpts = mkOption {
|
||||
description = "Kubernetes proxy extra command line options.";
|
||||
default = "";
|
||||
type = str;
|
||||
type = separatedString " ";
|
||||
};
|
||||
|
||||
featureGates = mkOption {
|
||||
|
@ -21,7 +21,7 @@ in
|
||||
extraOpts = mkOption {
|
||||
description = "Kubernetes scheduler extra command line options.";
|
||||
default = "";
|
||||
type = str;
|
||||
type = separatedString " ";
|
||||
};
|
||||
|
||||
featureGates = mkOption {
|
||||
|
@ -76,7 +76,7 @@ let
|
||||
};
|
||||
|
||||
tags = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
type = types.attrsOf (types.either types.str (types.listOf types.str));
|
||||
default = {};
|
||||
example = { queue = "default"; docker = "true"; ruby2 ="true"; };
|
||||
description = ''
|
||||
@ -230,7 +230,11 @@ in
|
||||
## don't end up in the Nix store.
|
||||
preStart = let
|
||||
sshDir = "${cfg.dataDir}/.ssh";
|
||||
tagStr = lib.concatStringsSep "," (lib.mapAttrsToList (name: value: "${name}=${value}") cfg.tags);
|
||||
tagStr = name: value:
|
||||
if lib.isList value
|
||||
then lib.concatStringsSep "," (builtins.map (v: "${name}=${v}") value)
|
||||
else "${name}=${value}";
|
||||
tagsStr = lib.concatStringsSep "," (lib.mapAttrsToList tagStr cfg.tags);
|
||||
in
|
||||
optionalString (cfg.privateSshKeyPath != null) ''
|
||||
mkdir -m 0700 -p "${sshDir}"
|
||||
@ -241,7 +245,7 @@ in
|
||||
token="$(cat ${toString cfg.tokenPath})"
|
||||
name="${cfg.name}"
|
||||
shell="${cfg.shell}"
|
||||
tags="${tagStr}"
|
||||
tags="${tagsStr}"
|
||||
build-path="${cfg.dataDir}/builds"
|
||||
hooks-path="${cfg.hooksPath}"
|
||||
${cfg.extraConfig}
|
||||
|
@ -1,79 +1,108 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
concatStringsSep
|
||||
flip
|
||||
literalExample
|
||||
optionalAttrs
|
||||
optionals
|
||||
recursiveUpdate
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
types
|
||||
versionAtLeast
|
||||
;
|
||||
|
||||
cfg = config.services.cassandra;
|
||||
|
||||
defaultUser = "cassandra";
|
||||
cassandraConfig = flip recursiveUpdate cfg.extraConfig
|
||||
({ commitlog_sync = "batch";
|
||||
commitlog_sync_batch_window_in_ms = 2;
|
||||
start_native_transport = cfg.allowClients;
|
||||
cluster_name = cfg.clusterName;
|
||||
partitioner = "org.apache.cassandra.dht.Murmur3Partitioner";
|
||||
endpoint_snitch = "SimpleSnitch";
|
||||
data_file_directories = [ "${cfg.homeDir}/data" ];
|
||||
commitlog_directory = "${cfg.homeDir}/commitlog";
|
||||
saved_caches_directory = "${cfg.homeDir}/saved_caches";
|
||||
} // (lib.optionalAttrs (cfg.seedAddresses != []) {
|
||||
seed_provider = [{
|
||||
class_name = "org.apache.cassandra.locator.SimpleSeedProvider";
|
||||
parameters = [ { seeds = concatStringsSep "," cfg.seedAddresses; } ];
|
||||
}];
|
||||
}) // (lib.optionalAttrs (lib.versionAtLeast cfg.package.version "3") {
|
||||
hints_directory = "${cfg.homeDir}/hints";
|
||||
})
|
||||
);
|
||||
cassandraConfigWithAddresses = cassandraConfig //
|
||||
( if cfg.listenAddress == null
|
||||
then { listen_interface = cfg.listenInterface; }
|
||||
else { listen_address = cfg.listenAddress; }
|
||||
) // (
|
||||
if cfg.rpcAddress == null
|
||||
then { rpc_interface = cfg.rpcInterface; }
|
||||
else { rpc_address = cfg.rpcAddress; }
|
||||
);
|
||||
cassandraEtc = pkgs.stdenv.mkDerivation
|
||||
{ name = "cassandra-etc";
|
||||
cassandraYaml = builtins.toJSON cassandraConfigWithAddresses;
|
||||
cassandraEnvPkg = "${cfg.package}/conf/cassandra-env.sh";
|
||||
cassandraLogbackConfig = pkgs.writeText "logback.xml" cfg.logbackConfig;
|
||||
passAsFile = [ "extraEnvSh" ];
|
||||
inherit (cfg) extraEnvSh;
|
||||
buildCommand = ''
|
||||
mkdir -p "$out"
|
||||
|
||||
echo "$cassandraYaml" > "$out/cassandra.yaml"
|
||||
ln -s "$cassandraLogbackConfig" "$out/logback.xml"
|
||||
cassandraConfig = flip recursiveUpdate cfg.extraConfig (
|
||||
{
|
||||
commitlog_sync = "batch";
|
||||
commitlog_sync_batch_window_in_ms = 2;
|
||||
start_native_transport = cfg.allowClients;
|
||||
cluster_name = cfg.clusterName;
|
||||
partitioner = "org.apache.cassandra.dht.Murmur3Partitioner";
|
||||
endpoint_snitch = "SimpleSnitch";
|
||||
data_file_directories = [ "${cfg.homeDir}/data" ];
|
||||
commitlog_directory = "${cfg.homeDir}/commitlog";
|
||||
saved_caches_directory = "${cfg.homeDir}/saved_caches";
|
||||
} // optionalAttrs (cfg.seedAddresses != [ ]) {
|
||||
seed_provider = [
|
||||
{
|
||||
class_name = "org.apache.cassandra.locator.SimpleSeedProvider";
|
||||
parameters = [{ seeds = concatStringsSep "," cfg.seedAddresses; }];
|
||||
}
|
||||
];
|
||||
} // optionalAttrs (versionAtLeast cfg.package.version "3") {
|
||||
hints_directory = "${cfg.homeDir}/hints";
|
||||
}
|
||||
);
|
||||
|
||||
( cat "$cassandraEnvPkg"
|
||||
echo "# lines from services.cassandra.extraEnvSh: "
|
||||
cat "$extraEnvShPath"
|
||||
) > "$out/cassandra-env.sh"
|
||||
cassandraConfigWithAddresses = cassandraConfig // (
|
||||
if cfg.listenAddress == null
|
||||
then { listen_interface = cfg.listenInterface; }
|
||||
else { listen_address = cfg.listenAddress; }
|
||||
) // (
|
||||
if cfg.rpcAddress == null
|
||||
then { rpc_interface = cfg.rpcInterface; }
|
||||
else { rpc_address = cfg.rpcAddress; }
|
||||
);
|
||||
|
||||
# Delete default JMX Port, otherwise we can't set it using env variable
|
||||
sed -i '/JMX_PORT="7199"/d' "$out/cassandra-env.sh"
|
||||
cassandraEtc = pkgs.stdenv.mkDerivation {
|
||||
name = "cassandra-etc";
|
||||
|
||||
# Delete default password file
|
||||
sed -i '/-Dcom.sun.management.jmxremote.password.file=\/etc\/cassandra\/jmxremote.password/d' "$out/cassandra-env.sh"
|
||||
'';
|
||||
};
|
||||
defaultJmxRolesFile = builtins.foldl'
|
||||
(left: right: left + right) ""
|
||||
(map (role: "${role.username} ${role.password}") cfg.jmxRoles);
|
||||
fullJvmOptions = cfg.jvmOpts
|
||||
++ lib.optionals (cfg.jmxRoles != []) [
|
||||
cassandraYaml = builtins.toJSON cassandraConfigWithAddresses;
|
||||
cassandraEnvPkg = "${cfg.package}/conf/cassandra-env.sh";
|
||||
cassandraLogbackConfig = pkgs.writeText "logback.xml" cfg.logbackConfig;
|
||||
|
||||
passAsFile = [ "extraEnvSh" ];
|
||||
inherit (cfg) extraEnvSh;
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p "$out"
|
||||
|
||||
echo "$cassandraYaml" > "$out/cassandra.yaml"
|
||||
ln -s "$cassandraLogbackConfig" "$out/logback.xml"
|
||||
|
||||
( cat "$cassandraEnvPkg"
|
||||
echo "# lines from services.cassandra.extraEnvSh: "
|
||||
cat "$extraEnvShPath"
|
||||
) > "$out/cassandra-env.sh"
|
||||
|
||||
# Delete default JMX Port, otherwise we can't set it using env variable
|
||||
sed -i '/JMX_PORT="7199"/d' "$out/cassandra-env.sh"
|
||||
|
||||
# Delete default password file
|
||||
sed -i '/-Dcom.sun.management.jmxremote.password.file=\/etc\/cassandra\/jmxremote.password/d' "$out/cassandra-env.sh"
|
||||
'';
|
||||
};
|
||||
|
||||
defaultJmxRolesFile =
|
||||
builtins.foldl'
|
||||
(left: right: left + right) ""
|
||||
(map (role: "${role.username} ${role.password}") cfg.jmxRoles);
|
||||
|
||||
fullJvmOptions =
|
||||
cfg.jvmOpts
|
||||
++ optionals (cfg.jmxRoles != [ ]) [
|
||||
"-Dcom.sun.management.jmxremote.authenticate=true"
|
||||
"-Dcom.sun.management.jmxremote.password.file=${cfg.jmxRolesFile}"
|
||||
]
|
||||
++ lib.optionals cfg.remoteJmx [
|
||||
] ++ optionals cfg.remoteJmx [
|
||||
"-Djava.rmi.server.hostname=${cfg.rpcAddress}"
|
||||
];
|
||||
in {
|
||||
|
||||
in
|
||||
{
|
||||
options.services.cassandra = {
|
||||
|
||||
enable = mkEnableOption ''
|
||||
Apache Cassandra – Scalable and highly available database.
|
||||
'';
|
||||
|
||||
clusterName = mkOption {
|
||||
type = types.str;
|
||||
default = "Test Cluster";
|
||||
@ -83,16 +112,19 @@ in {
|
||||
another. All nodes in a cluster must have the same value.
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = defaultUser;
|
||||
description = "Run Apache Cassandra under this user.";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = defaultUser;
|
||||
description = "Run Apache Cassandra under this group.";
|
||||
};
|
||||
|
||||
homeDir = mkOption {
|
||||
type = types.path;
|
||||
default = "/var/lib/cassandra";
|
||||
@ -100,6 +132,7 @@ in {
|
||||
Home directory for Apache Cassandra.
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.cassandra;
|
||||
@ -109,17 +142,19 @@ in {
|
||||
The Apache Cassandra package to use.
|
||||
'';
|
||||
};
|
||||
|
||||
jvmOpts = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
description = ''
|
||||
Populate the JVM_OPT environment variable.
|
||||
'';
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "127.0.0.1";
|
||||
example = literalExample "null";
|
||||
example = null;
|
||||
description = ''
|
||||
Address or interface to bind to and tell other Cassandra nodes
|
||||
to connect to. You _must_ change this if you want multiple
|
||||
@ -136,6 +171,7 @@ in {
|
||||
Setting listen_address to 0.0.0.0 is always wrong.
|
||||
'';
|
||||
};
|
||||
|
||||
listenInterface = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
@ -146,10 +182,11 @@ in {
|
||||
supported.
|
||||
'';
|
||||
};
|
||||
|
||||
rpcAddress = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "127.0.0.1";
|
||||
example = literalExample "null";
|
||||
example = null;
|
||||
description = ''
|
||||
The address or interface to bind the native transport server to.
|
||||
|
||||
@ -167,6 +204,7 @@ in {
|
||||
internet. Firewall it if needed.
|
||||
'';
|
||||
};
|
||||
|
||||
rpcInterface = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
@ -176,6 +214,7 @@ in {
|
||||
correspond to a single address, IP aliasing is not supported.
|
||||
'';
|
||||
};
|
||||
|
||||
logbackConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = ''
|
||||
@ -197,6 +236,7 @@ in {
|
||||
XML logback configuration for cassandra
|
||||
'';
|
||||
};
|
||||
|
||||
seedAddresses = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ "127.0.0.1" ];
|
||||
@ -207,6 +247,7 @@ in {
|
||||
Set to 127.0.0.1 for a single node cluster.
|
||||
'';
|
||||
};
|
||||
|
||||
allowClients = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
@ -219,16 +260,19 @@ in {
|
||||
<literal>extraConfig</literal>.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.attrs;
|
||||
default = {};
|
||||
default = { };
|
||||
example =
|
||||
{ commitlog_sync_batch_window_in_ms = 3;
|
||||
{
|
||||
commitlog_sync_batch_window_in_ms = 3;
|
||||
};
|
||||
description = ''
|
||||
Extra options to be merged into cassandra.yaml as nix attribute set.
|
||||
'';
|
||||
};
|
||||
|
||||
extraEnvSh = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
@ -237,48 +281,53 @@ in {
|
||||
Extra shell lines to be appended onto cassandra-env.sh.
|
||||
'';
|
||||
};
|
||||
|
||||
fullRepairInterval = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "3w";
|
||||
example = literalExample "null";
|
||||
example = null;
|
||||
description = ''
|
||||
Set the interval how often full repairs are run, i.e.
|
||||
<literal>nodetool repair --full</literal> is executed. See
|
||||
https://cassandra.apache.org/doc/latest/operating/repair.html
|
||||
for more information.
|
||||
Set the interval how often full repairs are run, i.e.
|
||||
<literal>nodetool repair --full</literal> is executed. See
|
||||
https://cassandra.apache.org/doc/latest/operating/repair.html
|
||||
for more information.
|
||||
|
||||
Set to <literal>null</literal> to disable full repairs.
|
||||
'';
|
||||
Set to <literal>null</literal> to disable full repairs.
|
||||
'';
|
||||
};
|
||||
|
||||
fullRepairOptions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
example = [ "--partitioner-range" ];
|
||||
description = ''
|
||||
Options passed through to the full repair command.
|
||||
'';
|
||||
Options passed through to the full repair command.
|
||||
'';
|
||||
};
|
||||
|
||||
incrementalRepairInterval = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "3d";
|
||||
example = literalExample "null";
|
||||
example = null;
|
||||
description = ''
|
||||
Set the interval how often incremental repairs are run, i.e.
|
||||
<literal>nodetool repair</literal> is executed. See
|
||||
https://cassandra.apache.org/doc/latest/operating/repair.html
|
||||
for more information.
|
||||
Set the interval how often incremental repairs are run, i.e.
|
||||
<literal>nodetool repair</literal> is executed. See
|
||||
https://cassandra.apache.org/doc/latest/operating/repair.html
|
||||
for more information.
|
||||
|
||||
Set to <literal>null</literal> to disable incremental repairs.
|
||||
'';
|
||||
Set to <literal>null</literal> to disable incremental repairs.
|
||||
'';
|
||||
};
|
||||
|
||||
incrementalRepairOptions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
default = [ ];
|
||||
example = [ "--partitioner-range" ];
|
||||
description = ''
|
||||
Options passed through to the incremental repair command.
|
||||
'';
|
||||
Options passed through to the incremental repair command.
|
||||
'';
|
||||
};
|
||||
|
||||
maxHeapSize = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
@ -299,6 +348,7 @@ in {
|
||||
expensive GC will be (usually).
|
||||
'';
|
||||
};
|
||||
|
||||
heapNewSize = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
@ -322,6 +372,7 @@ in {
|
||||
100 MB per physical CPU core.
|
||||
'';
|
||||
};
|
||||
|
||||
mallocArenaMax = mkOption {
|
||||
type = types.nullOr types.int;
|
||||
default = null;
|
||||
@ -330,6 +381,7 @@ in {
|
||||
Set this to control the amount of arenas per-thread in glibc.
|
||||
'';
|
||||
};
|
||||
|
||||
remoteJmx = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
@ -341,6 +393,7 @@ in {
|
||||
See: https://wiki.apache.org/cassandra/JmxSecurity
|
||||
'';
|
||||
};
|
||||
|
||||
jmxPort = mkOption {
|
||||
type = types.int;
|
||||
default = 7199;
|
||||
@ -351,8 +404,9 @@ in {
|
||||
Firewall it if needed.
|
||||
'';
|
||||
};
|
||||
|
||||
jmxRoles = mkOption {
|
||||
default = [];
|
||||
default = [ ];
|
||||
description = ''
|
||||
Roles that are allowed to access the JMX (e.g. nodetool)
|
||||
BEWARE: The passwords will be stored world readable in the nix-store.
|
||||
@ -375,11 +429,13 @@ in {
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
jmxRolesFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = if (lib.versionAtLeast cfg.package.version "3.11")
|
||||
then pkgs.writeText "jmx-roles-file" defaultJmxRolesFile
|
||||
else null;
|
||||
default =
|
||||
if versionAtLeast cfg.package.version "3.11"
|
||||
then pkgs.writeText "jmx-roles-file" defaultJmxRolesFile
|
||||
else null;
|
||||
example = "/var/lib/cassandra/jmx.password";
|
||||
description = ''
|
||||
Specify your own jmx roles file.
|
||||
@ -391,102 +447,115 @@ in {
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions =
|
||||
[ { assertion = (cfg.listenAddress == null) != (cfg.listenInterface == null);
|
||||
message = "You have to set either listenAddress or listenInterface";
|
||||
}
|
||||
{ assertion = (cfg.rpcAddress == null) != (cfg.rpcInterface == null);
|
||||
message = "You have to set either rpcAddress or rpcInterface";
|
||||
}
|
||||
{ assertion = (cfg.maxHeapSize == null) == (cfg.heapNewSize == null);
|
||||
message = "If you set either of maxHeapSize or heapNewSize you have to set both";
|
||||
}
|
||||
{ assertion = cfg.remoteJmx -> cfg.jmxRolesFile != null;
|
||||
message = ''
|
||||
If you want JMX available remotely you need to set a password using
|
||||
<literal>jmxRoles</literal> or <literal>jmxRolesFile</literal> if
|
||||
using Cassandra older than v3.11.
|
||||
'';
|
||||
}
|
||||
];
|
||||
assertions = [
|
||||
{
|
||||
assertion = (cfg.listenAddress == null) != (cfg.listenInterface == null);
|
||||
message = "You have to set either listenAddress or listenInterface";
|
||||
}
|
||||
{
|
||||
assertion = (cfg.rpcAddress == null) != (cfg.rpcInterface == null);
|
||||
message = "You have to set either rpcAddress or rpcInterface";
|
||||
}
|
||||
{
|
||||
assertion = (cfg.maxHeapSize == null) == (cfg.heapNewSize == null);
|
||||
message = "If you set either of maxHeapSize or heapNewSize you have to set both";
|
||||
}
|
||||
{
|
||||
assertion = cfg.remoteJmx -> cfg.jmxRolesFile != null;
|
||||
message = ''
|
||||
If you want JMX available remotely you need to set a password using
|
||||
<literal>jmxRoles</literal> or <literal>jmxRolesFile</literal> if
|
||||
using Cassandra older than v3.11.
|
||||
'';
|
||||
}
|
||||
];
|
||||
users = mkIf (cfg.user == defaultUser) {
|
||||
extraUsers.${defaultUser} =
|
||||
{ group = cfg.group;
|
||||
home = cfg.homeDir;
|
||||
createHome = true;
|
||||
uid = config.ids.uids.cassandra;
|
||||
description = "Cassandra service user";
|
||||
};
|
||||
extraGroups.${defaultUser}.gid = config.ids.gids.cassandra;
|
||||
users.${defaultUser} = {
|
||||
group = cfg.group;
|
||||
home = cfg.homeDir;
|
||||
createHome = true;
|
||||
uid = config.ids.uids.cassandra;
|
||||
description = "Cassandra service user";
|
||||
};
|
||||
groups.${defaultUser}.gid = config.ids.gids.cassandra;
|
||||
};
|
||||
|
||||
systemd.services.cassandra =
|
||||
{ description = "Apache Cassandra service";
|
||||
after = [ "network.target" ];
|
||||
environment =
|
||||
{ CASSANDRA_CONF = "${cassandraEtc}";
|
||||
JVM_OPTS = builtins.concatStringsSep " " fullJvmOptions;
|
||||
MAX_HEAP_SIZE = toString cfg.maxHeapSize;
|
||||
HEAP_NEWSIZE = toString cfg.heapNewSize;
|
||||
MALLOC_ARENA_MAX = toString cfg.mallocArenaMax;
|
||||
LOCAL_JMX = if cfg.remoteJmx then "no" else "yes";
|
||||
JMX_PORT = toString cfg.jmxPort;
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig =
|
||||
{ User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart = "${cfg.package}/bin/cassandra -f";
|
||||
SuccessExitStatus = 143;
|
||||
};
|
||||
systemd.services.cassandra = {
|
||||
description = "Apache Cassandra service";
|
||||
after = [ "network.target" ];
|
||||
environment = {
|
||||
CASSANDRA_CONF = "${cassandraEtc}";
|
||||
JVM_OPTS = builtins.concatStringsSep " " fullJvmOptions;
|
||||
MAX_HEAP_SIZE = toString cfg.maxHeapSize;
|
||||
HEAP_NEWSIZE = toString cfg.heapNewSize;
|
||||
MALLOC_ARENA_MAX = toString cfg.mallocArenaMax;
|
||||
LOCAL_JMX = if cfg.remoteJmx then "no" else "yes";
|
||||
JMX_PORT = toString cfg.jmxPort;
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart = "${cfg.package}/bin/cassandra -f";
|
||||
SuccessExitStatus = 143;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.cassandra-full-repair =
|
||||
{ description = "Perform a full repair on this Cassandra node";
|
||||
after = [ "cassandra.service" ];
|
||||
requires = [ "cassandra.service" ];
|
||||
serviceConfig =
|
||||
{ User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart =
|
||||
lib.concatStringsSep " "
|
||||
([ "${cfg.package}/bin/nodetool" "repair" "--full"
|
||||
] ++ cfg.fullRepairOptions);
|
||||
};
|
||||
systemd.services.cassandra-full-repair = {
|
||||
description = "Perform a full repair on this Cassandra node";
|
||||
after = [ "cassandra.service" ];
|
||||
requires = [ "cassandra.service" ];
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart =
|
||||
concatStringsSep " "
|
||||
([
|
||||
"${cfg.package}/bin/nodetool"
|
||||
"repair"
|
||||
"--full"
|
||||
] ++ cfg.fullRepairOptions);
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.cassandra-full-repair =
|
||||
mkIf (cfg.fullRepairInterval != null) {
|
||||
description = "Schedule full repairs on Cassandra";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig =
|
||||
{ OnBootSec = cfg.fullRepairInterval;
|
||||
OnUnitActiveSec = cfg.fullRepairInterval;
|
||||
Persistent = true;
|
||||
};
|
||||
timerConfig = {
|
||||
OnBootSec = cfg.fullRepairInterval;
|
||||
OnUnitActiveSec = cfg.fullRepairInterval;
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.cassandra-incremental-repair =
|
||||
{ description = "Perform an incremental repair on this cassandra node.";
|
||||
after = [ "cassandra.service" ];
|
||||
requires = [ "cassandra.service" ];
|
||||
serviceConfig =
|
||||
{ User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart =
|
||||
lib.concatStringsSep " "
|
||||
([ "${cfg.package}/bin/nodetool" "repair"
|
||||
] ++ cfg.incrementalRepairOptions);
|
||||
};
|
||||
systemd.services.cassandra-incremental-repair = {
|
||||
description = "Perform an incremental repair on this cassandra node.";
|
||||
after = [ "cassandra.service" ];
|
||||
requires = [ "cassandra.service" ];
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
ExecStart =
|
||||
concatStringsSep " "
|
||||
([
|
||||
"${cfg.package}/bin/nodetool"
|
||||
"repair"
|
||||
] ++ cfg.incrementalRepairOptions);
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.cassandra-incremental-repair =
|
||||
mkIf (cfg.incrementalRepairInterval != null) {
|
||||
description = "Schedule incremental repairs on Cassandra";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig =
|
||||
{ OnBootSec = cfg.incrementalRepairInterval;
|
||||
OnUnitActiveSec = cfg.incrementalRepairInterval;
|
||||
Persistent = true;
|
||||
};
|
||||
timerConfig = {
|
||||
OnBootSec = cfg.incrementalRepairInterval;
|
||||
OnUnitActiveSec = cfg.incrementalRepairInterval;
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ roberth ];
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ in
|
||||
|
||||
environment.etc."reader.conf".source = cfgFile;
|
||||
|
||||
environment.systemPackages = [ pkgs.pcsclite ];
|
||||
systemd.packages = [ (getBin pkgs.pcsclite) ];
|
||||
|
||||
systemd.sockets.pcscd.wantedBy = [ "sockets.target" ];
|
||||
|
@ -134,7 +134,7 @@ in {
|
||||
ReadWritePaths = [ cfg.keyPath ];
|
||||
|
||||
AmbientCapabilities = [];
|
||||
CapabilityBoundingSet = [];
|
||||
CapabilityBoundingSet = "";
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
|
@ -773,7 +773,7 @@ in
|
||||
};
|
||||
|
||||
services.postfix.config = (mapAttrs (_: v: mkDefault v) {
|
||||
compatibility_level = "9999";
|
||||
compatibility_level = pkgs.postfix.version;
|
||||
mail_owner = cfg.user;
|
||||
default_privs = "nobody";
|
||||
|
||||
|
@ -410,7 +410,7 @@ in
|
||||
StateDirectoryMode = "0700";
|
||||
|
||||
AmbientCapabilities = [];
|
||||
CapabilityBoundingSet = [];
|
||||
CapabilityBoundingSet = "";
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
|
@ -118,7 +118,7 @@ in {
|
||||
'';
|
||||
serviceConfig = {
|
||||
ExecStart = ''
|
||||
${pkgs.jre}/bin/java -Xmx${toString cfg.maxMemory}m \
|
||||
${pkgs.jre8}/bin/java -Xmx${toString cfg.maxMemory}m \
|
||||
-Dairsonic.home=${cfg.home} \
|
||||
-Dserver.address=${cfg.listenAddress} \
|
||||
-Dserver.port=${toString cfg.port} \
|
||||
|
@ -477,47 +477,49 @@ in
|
||||
in ''
|
||||
# copy custom configuration and generate a random secret key if needed
|
||||
${optionalString (cfg.useWizard == false) ''
|
||||
cp -f ${configFile} ${runConfig}
|
||||
function gitea_setup {
|
||||
cp -f ${configFile} ${runConfig}
|
||||
|
||||
if [ ! -e ${secretKey} ]; then
|
||||
${gitea}/bin/gitea generate secret SECRET_KEY > ${secretKey}
|
||||
fi
|
||||
if [ ! -e ${secretKey} ]; then
|
||||
${gitea}/bin/gitea generate secret SECRET_KEY > ${secretKey}
|
||||
fi
|
||||
|
||||
# Migrate LFS_JWT_SECRET filename
|
||||
if [[ -e ${oldLfsJwtSecret} && ! -e ${lfsJwtSecret} ]]; then
|
||||
mv ${oldLfsJwtSecret} ${lfsJwtSecret}
|
||||
fi
|
||||
# Migrate LFS_JWT_SECRET filename
|
||||
if [[ -e ${oldLfsJwtSecret} && ! -e ${lfsJwtSecret} ]]; then
|
||||
mv ${oldLfsJwtSecret} ${lfsJwtSecret}
|
||||
fi
|
||||
|
||||
if [ ! -e ${oauth2JwtSecret} ]; then
|
||||
${gitea}/bin/gitea generate secret JWT_SECRET > ${oauth2JwtSecret}
|
||||
fi
|
||||
if [ ! -e ${oauth2JwtSecret} ]; then
|
||||
${gitea}/bin/gitea generate secret JWT_SECRET > ${oauth2JwtSecret}
|
||||
fi
|
||||
|
||||
if [ ! -e ${lfsJwtSecret} ]; then
|
||||
${gitea}/bin/gitea generate secret LFS_JWT_SECRET > ${lfsJwtSecret}
|
||||
fi
|
||||
if [ ! -e ${lfsJwtSecret} ]; then
|
||||
${gitea}/bin/gitea generate secret LFS_JWT_SECRET > ${lfsJwtSecret}
|
||||
fi
|
||||
|
||||
if [ ! -e ${internalToken} ]; then
|
||||
${gitea}/bin/gitea generate secret INTERNAL_TOKEN > ${internalToken}
|
||||
fi
|
||||
if [ ! -e ${internalToken} ]; then
|
||||
${gitea}/bin/gitea generate secret INTERNAL_TOKEN > ${internalToken}
|
||||
fi
|
||||
|
||||
SECRETKEY="$(head -n1 ${secretKey})"
|
||||
DBPASS="$(head -n1 ${cfg.database.passwordFile})"
|
||||
OAUTH2JWTSECRET="$(head -n1 ${oauth2JwtSecret})"
|
||||
LFSJWTSECRET="$(head -n1 ${lfsJwtSecret})"
|
||||
INTERNALTOKEN="$(head -n1 ${internalToken})"
|
||||
${if (cfg.mailerPasswordFile == null) then ''
|
||||
MAILERPASSWORD="#mailerpass#"
|
||||
'' else ''
|
||||
MAILERPASSWORD="$(head -n1 ${cfg.mailerPasswordFile} || :)"
|
||||
''}
|
||||
sed -e "s,#secretkey#,$SECRETKEY,g" \
|
||||
-e "s,#dbpass#,$DBPASS,g" \
|
||||
-e "s,#oauth2jwtsecret#,$OAUTH2JWTSECRET,g" \
|
||||
-e "s,#lfsjwtsecret#,$LFSJWTSECRET,g" \
|
||||
-e "s,#internaltoken#,$INTERNALTOKEN,g" \
|
||||
-e "s,#mailerpass#,$MAILERPASSWORD,g" \
|
||||
-i ${runConfig}
|
||||
chmod 640 ${runConfig} ${secretKey} ${oauth2JwtSecret} ${lfsJwtSecret} ${internalToken}
|
||||
SECRETKEY="$(head -n1 ${secretKey})"
|
||||
DBPASS="$(head -n1 ${cfg.database.passwordFile})"
|
||||
OAUTH2JWTSECRET="$(head -n1 ${oauth2JwtSecret})"
|
||||
LFSJWTSECRET="$(head -n1 ${lfsJwtSecret})"
|
||||
INTERNALTOKEN="$(head -n1 ${internalToken})"
|
||||
${if (cfg.mailerPasswordFile == null) then ''
|
||||
MAILERPASSWORD="#mailerpass#"
|
||||
'' else ''
|
||||
MAILERPASSWORD="$(head -n1 ${cfg.mailerPasswordFile} || :)"
|
||||
''}
|
||||
sed -e "s,#secretkey#,$SECRETKEY,g" \
|
||||
-e "s,#dbpass#,$DBPASS,g" \
|
||||
-e "s,#oauth2jwtsecret#,$OAUTH2JWTSECRET,g" \
|
||||
-e "s,#lfsjwtsecret#,$LFSJWTSECRET,g" \
|
||||
-e "s,#internaltoken#,$INTERNALTOKEN,g" \
|
||||
-e "s,#mailerpass#,$MAILERPASSWORD,g" \
|
||||
-i ${runConfig}
|
||||
}
|
||||
(umask 027; gitea_setup)
|
||||
''}
|
||||
|
||||
# update all hooks' binary paths
|
||||
|
@ -245,22 +245,85 @@ in {
|
||||
rm -f "${cfg.configDir}/ui-lovelace.yaml"
|
||||
ln -s ${lovelaceConfigFile} "${cfg.configDir}/ui-lovelace.yaml"
|
||||
'');
|
||||
serviceConfig = {
|
||||
ExecStart = "${package}/bin/hass --config '${cfg.configDir}'";
|
||||
serviceConfig = let
|
||||
# List of capabilities to equip home-assistant with, depending on configured components
|
||||
capabilities = [
|
||||
# Empty string first, so we will never accidentally have an empty capability bounding set
|
||||
# https://github.com/NixOS/nixpkgs/issues/120617#issuecomment-830685115
|
||||
""
|
||||
] ++ (unique (optionals (useComponent "bluetooth_tracker" || useComponent "bluetooth_le_tracker") [
|
||||
# Required for interaction with hci devices and bluetooth sockets
|
||||
# https://www.home-assistant.io/integrations/bluetooth_le_tracker/#rootless-setup-on-core-installs
|
||||
"CAP_NET_ADMIN"
|
||||
"CAP_NET_RAW"
|
||||
] ++ lib.optionals (useComponent "emulated_hue") [
|
||||
# Alexa looks for the service on port 80
|
||||
# https://www.home-assistant.io/integrations/emulated_hue
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
] ++ lib.optionals (useComponent "nmap_tracker") [
|
||||
# https://www.home-assistant.io/integrations/nmap_tracker#linux-capabilities
|
||||
"CAP_NET_ADMIN"
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
"CAP_NET_RAW"
|
||||
]));
|
||||
in {
|
||||
ExecStart = "${package}/bin/hass --runner --config '${cfg.configDir}'";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
User = "hass";
|
||||
Group = "hass";
|
||||
Restart = "on-failure";
|
||||
RestartForceExitStatus = "100";
|
||||
SuccessExitStatus = "100";
|
||||
KillSignal = "SIGINT";
|
||||
|
||||
# Hardening
|
||||
AmbientCapabilities = capabilities;
|
||||
CapabilityBoundingSet = capabilities;
|
||||
DeviceAllow = [
|
||||
"char-ttyACM rw"
|
||||
"char-ttyAMA rw"
|
||||
"char-ttyUSB rw"
|
||||
];
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = false; # prevents gaining capabilities in the host namespace
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
ProtectSystem = "strict";
|
||||
RemoveIPC = true;
|
||||
ReadWritePaths = let
|
||||
# Allow rw access to explicitly configured paths
|
||||
cfgPath = [ "config" "homeassistant" "allowlist_external_dirs" ];
|
||||
value = attrByPath cfgPath [] cfg;
|
||||
allowPaths = if isList value then value else singleton value;
|
||||
in [ "${cfg.configDir}" ] ++ allowPaths;
|
||||
KillSignal = "SIGINT";
|
||||
PrivateTmp = true;
|
||||
RemoveIPC = true;
|
||||
AmbientCapabilities = "cap_net_raw,cap_net_admin+eip";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_UNIX"
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
] ++ optionals (useComponent "bluetooth_tracker" || useComponent "bluetooth_le_tracker") [
|
||||
"AF_BLUETOOTH"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SupplementaryGroups = [ "dialout" ];
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
path = [
|
||||
"/run/wrappers" # needed for ping
|
||||
@ -278,7 +341,6 @@ in {
|
||||
home = cfg.configDir;
|
||||
createHome = true;
|
||||
group = "hass";
|
||||
extraGroups = [ "dialout" ];
|
||||
uid = config.ids.uids.hass;
|
||||
};
|
||||
|
||||
|
181
nixos/modules/services/misc/matrix-dendrite.nix
Normal file
181
nixos/modules/services/misc/matrix-dendrite.nix
Normal file
@ -0,0 +1,181 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.matrix-dendrite;
|
||||
settingsFormat = pkgs.formats.yaml { };
|
||||
configurationYaml = settingsFormat.generate "dendrite.yaml" cfg.settings;
|
||||
workingDir = "/var/lib/matrix-dendrite";
|
||||
in
|
||||
{
|
||||
options.services.matrix-dendrite = {
|
||||
enable = lib.mkEnableOption "matrix.org dendrite";
|
||||
httpPort = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.port;
|
||||
default = 8008;
|
||||
description = ''
|
||||
The port to listen for HTTP requests on.
|
||||
'';
|
||||
};
|
||||
httpsPort = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.port;
|
||||
default = null;
|
||||
description = ''
|
||||
The port to listen for HTTPS requests on.
|
||||
'';
|
||||
};
|
||||
tlsCert = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
example = "/var/lib/matrix-dendrite/server.cert";
|
||||
default = null;
|
||||
description = ''
|
||||
The path to the TLS certificate.
|
||||
|
||||
<programlisting>
|
||||
nix-shell -p matrix-dendrite --command "generate-keys --tls-cert server.crt --tls-key server.key"
|
||||
</programlisting>
|
||||
'';
|
||||
};
|
||||
tlsKey = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
example = "/var/lib/matrix-dendrite/server.key";
|
||||
default = null;
|
||||
description = ''
|
||||
The path to the TLS key.
|
||||
|
||||
<programlisting>
|
||||
nix-shell -p matrix-dendrite --command "generate-keys --tls-cert server.crt --tls-key server.key"
|
||||
</programlisting>
|
||||
'';
|
||||
};
|
||||
environmentFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
example = "/var/lib/matrix-dendrite/registration_secret";
|
||||
default = null;
|
||||
description = ''
|
||||
Environment file as defined in <citerefentry>
|
||||
<refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum>
|
||||
</citerefentry>.
|
||||
Secrets may be passed to the service without adding them to the world-readable
|
||||
Nix store, by specifying placeholder variables as the option value in Nix and
|
||||
setting these variables accordingly in the environment file. Currently only used
|
||||
for the registration secret to allow secure registration when
|
||||
client_api.registration_disabled is true.
|
||||
|
||||
<programlisting>
|
||||
# snippet of dendrite-related config
|
||||
services.matrix-dendrite.settings.client_api.registration_shared_secret = "$REGISTRATION_SHARED_SECRET";
|
||||
</programlisting>
|
||||
|
||||
<programlisting>
|
||||
# content of the environment file
|
||||
REGISTRATION_SHARED_SECRET=verysecretpassword
|
||||
</programlisting>
|
||||
|
||||
Note that this file needs to be available on the host on which
|
||||
<literal>dendrite</literal> is running.
|
||||
'';
|
||||
};
|
||||
settings = lib.mkOption {
|
||||
type = lib.types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
options.global = {
|
||||
server_name = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
example = "example.com";
|
||||
description = ''
|
||||
The domain name of the server, with optional explicit port.
|
||||
This is used by remote servers to connect to this server.
|
||||
This is also the last part of your UserID.
|
||||
'';
|
||||
};
|
||||
private_key = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
example = "${workingDir}/matrix_key.pem";
|
||||
description = ''
|
||||
The path to the signing private key file, used to sign
|
||||
requests and events.
|
||||
|
||||
<programlisting>
|
||||
nix-shell -p matrix-dendrite --command "generate-keys --private-key matrix_key.pem"
|
||||
</programlisting>
|
||||
'';
|
||||
};
|
||||
trusted_third_party_id_servers = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
example = [ "matrix.org" ];
|
||||
default = [ "matrix.org" "vector.im" ];
|
||||
description = ''
|
||||
Lists of domains that the server will trust as identity
|
||||
servers to verify third party identifiers such as phone
|
||||
numbers and email addresses
|
||||
'';
|
||||
};
|
||||
};
|
||||
options.client_api = {
|
||||
registration_disabled = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to disable user registration to the server
|
||||
without the shared secret.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration for dendrite, see:
|
||||
<link xlink:href="https://github.com/matrix-org/dendrite/blob/master/dendrite-config.yaml"/>
|
||||
for available options with which to populate settings.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [{
|
||||
assertion = cfg.httpsPort != null -> (cfg.tlsCert != null && cfg.tlsKey != null);
|
||||
message = ''
|
||||
If Dendrite is configured to use https, tlsCert and tlsKey must be provided.
|
||||
|
||||
nix-shell -p matrix-dendrite --command "generate-keys --tls-cert server.crt --tls-key server.key"
|
||||
'';
|
||||
}];
|
||||
|
||||
systemd.services.matrix-dendrite = {
|
||||
description = "Dendrite Matrix homeserver";
|
||||
after = [
|
||||
"network.target"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "matrix-dendrite";
|
||||
WorkingDirectory = workingDir;
|
||||
RuntimeDirectory = "matrix-dendrite";
|
||||
RuntimeDirectoryMode = "0700";
|
||||
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
|
||||
ExecStartPre =
|
||||
if (cfg.environmentFile != null) then ''
|
||||
${pkgs.envsubst}/bin/envsubst \
|
||||
-i ${configurationYaml} \
|
||||
-o /run/matrix-dendrite/dendrite.yaml
|
||||
'' else ''
|
||||
${pkgs.coreutils}/bin/cp ${configurationYaml} /run/matrix-dendrite/dendrite.yaml
|
||||
'';
|
||||
ExecStart = lib.strings.concatStringsSep " " ([
|
||||
"${pkgs.matrix-dendrite}/bin/dendrite-monolith-server"
|
||||
"--config /run/matrix-dendrite/dendrite.yaml"
|
||||
] ++ lib.optionals (cfg.httpPort != null) [
|
||||
"--http-bind-address :${builtins.toString cfg.httpPort}"
|
||||
] ++ lib.optionals (cfg.httpsPort != null) [
|
||||
"--https-bind-address :${builtins.toString cfg.httpsPort}"
|
||||
"--tls-cert ${cfg.tlsCert}"
|
||||
"--tls-key ${cfg.tlsKey}"
|
||||
]);
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
};
|
||||
meta.maintainers = lib.teams.matrix.members;
|
||||
}
|
@ -24,55 +24,80 @@ in
|
||||
Your <filename>pinnwand.toml</filename> as a Nix attribute set. Look up
|
||||
possible options in the <link xlink:href="https://github.com/supakeen/pinnwand/blob/master/pinnwand.toml-example">pinnwand.toml-example</link>.
|
||||
'';
|
||||
default = {
|
||||
# https://github.com/supakeen/pinnwand/blob/master/pinnwand.toml-example
|
||||
database_uri = "sqlite:///var/lib/pinnwand/pinnwand.db";
|
||||
preferred_lexeres = [];
|
||||
paste_size = 262144;
|
||||
paste_help = ''
|
||||
<p>Welcome to pinnwand, this site is a pastebin. It allows you to share code with others. If you write code in the text area below and press the paste button you will be given a link you can share with others so they can view your code as well.</p><p>People with the link can view your pasted code, only you can remove your paste and it expires automatically. Note that anyone could guess the URI to your paste so don't rely on it being private.</p>
|
||||
'';
|
||||
footer = ''
|
||||
View <a href="//github.com/supakeen/pinnwand" target="_BLANK">source code</a>, the <a href="/removal">removal</a> or <a href="/expiry">expiry</a> stories, or read the <a href="/about">about</a> page.
|
||||
'';
|
||||
};
|
||||
default = {};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.pinnwand = {
|
||||
description = "Pinnwannd HTTP Server";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
services.pinnwand.settings = {
|
||||
database_uri = mkDefault "sqlite:////var/lib/pinnwand/pinnwand.db";
|
||||
paste_size = mkDefault 262144;
|
||||
paste_help = mkDefault ''
|
||||
<p>Welcome to pinnwand, this site is a pastebin. It allows you to share code with others. If you write code in the text area below and press the paste button you will be given a link you can share with others so they can view your code as well.</p><p>People with the link can view your pasted code, only you can remove your paste and it expires automatically. Note that anyone could guess the URI to your paste so don't rely on it being private.</p>
|
||||
'';
|
||||
footer = mkDefault ''
|
||||
View <a href="//github.com/supakeen/pinnwand" target="_BLANK">source code</a>, the <a href="/removal">removal</a> or <a href="/expiry">expiry</a> stories, or read the <a href="/about">about</a> page.
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services = let
|
||||
hardeningOptions = {
|
||||
User = "pinnwand";
|
||||
DynamicUser = true;
|
||||
|
||||
unitConfig.Documentation = "https://pinnwand.readthedocs.io/en/latest/";
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.pinnwand}/bin/pinnwand --configuration-path ${configFile} http --port ${toString(cfg.port)}";
|
||||
StateDirectory = "pinnwand";
|
||||
StateDirectoryMode = "0700";
|
||||
|
||||
AmbientCapabilities = [];
|
||||
CapabilityBoundingSet = "";
|
||||
DevicePolicy = "closed";
|
||||
DynamicUser = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
PrivateDevices = true;
|
||||
PrivateUsers = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
||||
ProtectProc = "invisible";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_UNIX"
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "@system-service";
|
||||
UMask = "0077";
|
||||
};
|
||||
|
||||
command = "${pkgs.pinnwand}/bin/pinnwand --configuration-path ${configFile}";
|
||||
in {
|
||||
pinnwand = {
|
||||
description = "Pinnwannd HTTP Server";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
unitConfig.Documentation = "https://pinnwand.readthedocs.io/en/latest/";
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${command} http --port ${toString(cfg.port)}";
|
||||
} // hardeningOptions;
|
||||
};
|
||||
|
||||
pinnwand-reaper = {
|
||||
description = "Pinnwand Reaper";
|
||||
startAt = "daily";
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${command} -vvvv reap"; # verbosity increased to show number of deleted pastes
|
||||
} // hardeningOptions;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -5,29 +5,17 @@ with lib;
|
||||
let
|
||||
cfg = config.services.zigbee2mqtt;
|
||||
|
||||
configJSON = pkgs.writeText "configuration.json"
|
||||
(builtins.toJSON (recursiveUpdate defaultConfig cfg.config));
|
||||
configFile = pkgs.runCommand "configuration.yaml" { preferLocalBuild = true; } ''
|
||||
${pkgs.remarshal}/bin/json2yaml -i ${configJSON} -o $out
|
||||
'';
|
||||
format = pkgs.formats.yaml { };
|
||||
configFile = format.generate "zigbee2mqtt.yaml" cfg.settings;
|
||||
|
||||
# the default config contains all required settings,
|
||||
# so the service starts up without crashing.
|
||||
defaultConfig = {
|
||||
homeassistant = false;
|
||||
permit_join = false;
|
||||
mqtt = {
|
||||
base_topic = "zigbee2mqtt";
|
||||
server = "mqtt://localhost:1883";
|
||||
};
|
||||
serial.port = "/dev/ttyACM0";
|
||||
# put device configuration into separate file because configuration.yaml
|
||||
# is copied from the store on startup
|
||||
devices = "devices.yaml";
|
||||
};
|
||||
in
|
||||
{
|
||||
meta.maintainers = with maintainers; [ sweber ];
|
||||
meta.maintainers = with maintainers; [ sweber hexa ];
|
||||
|
||||
imports = [
|
||||
# Remove warning before the 21.11 release
|
||||
(mkRenamedOptionModule [ "services" "zigbee2mqtt" "config" ] [ "services" "zigbee2mqtt" "settings" ])
|
||||
];
|
||||
|
||||
options.services.zigbee2mqtt = {
|
||||
enable = mkEnableOption "enable zigbee2mqtt service";
|
||||
@ -37,7 +25,11 @@ in
|
||||
default = pkgs.zigbee2mqtt.override {
|
||||
dataDir = cfg.dataDir;
|
||||
};
|
||||
defaultText = "pkgs.zigbee2mqtt";
|
||||
defaultText = literalExample ''
|
||||
pkgs.zigbee2mqtt {
|
||||
dataDir = services.zigbee2mqtt.dataDir
|
||||
}
|
||||
'';
|
||||
type = types.package;
|
||||
};
|
||||
|
||||
@ -47,9 +39,9 @@ in
|
||||
type = types.path;
|
||||
};
|
||||
|
||||
config = mkOption {
|
||||
settings = mkOption {
|
||||
type = format.type;
|
||||
default = {};
|
||||
type = with types; nullOr attrs;
|
||||
example = literalExample ''
|
||||
{
|
||||
homeassistant = config.services.home-assistant.enable;
|
||||
@ -61,11 +53,28 @@ in
|
||||
'';
|
||||
description = ''
|
||||
Your <filename>configuration.yaml</filename> as a Nix attribute set.
|
||||
Check the <link xlink:href="https://www.zigbee2mqtt.io/information/configuration.html">documentation</link>
|
||||
for possible options.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable) {
|
||||
|
||||
# preset config values
|
||||
services.zigbee2mqtt.settings = {
|
||||
homeassistant = mkDefault config.services.home-assistant.enable;
|
||||
permit_join = mkDefault false;
|
||||
mqtt = {
|
||||
base_topic = mkDefault "zigbee2mqtt";
|
||||
server = mkDefault "mqtt://localhost:1883";
|
||||
};
|
||||
serial.port = mkDefault "/dev/ttyACM0";
|
||||
# reference device configuration, that is kept in a separate file
|
||||
# to prevent it being overwritten in the units ExecStartPre script
|
||||
devices = mkDefault "devices.yaml";
|
||||
};
|
||||
|
||||
systemd.services.zigbee2mqtt = {
|
||||
description = "Zigbee2mqtt Service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
@ -76,10 +85,48 @@ in
|
||||
User = "zigbee2mqtt";
|
||||
WorkingDirectory = cfg.dataDir;
|
||||
Restart = "on-failure";
|
||||
|
||||
# Hardening
|
||||
CapabilityBoundingSet = "";
|
||||
DeviceAllow = [
|
||||
config.services.zigbee2mqtt.settings.serial.port
|
||||
];
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = false;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = false; # prevents access to /dev/serial, because it is set 0700 root:root
|
||||
PrivateUsers = true;
|
||||
PrivateTmp = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths = cfg.dataDir;
|
||||
PrivateTmp = true;
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SupplementaryGroups = [
|
||||
"dialout"
|
||||
];
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
"~@resources"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
preStart = ''
|
||||
cp --no-preserve=mode ${configFile} "${cfg.dataDir}/configuration.yaml"
|
||||
@ -90,7 +137,6 @@ in
|
||||
home = cfg.dataDir;
|
||||
createHome = true;
|
||||
group = "zigbee2mqtt";
|
||||
extraGroups = [ "dialout" ];
|
||||
uid = config.ids.uids.zigbee2mqtt;
|
||||
};
|
||||
|
||||
|
@ -32,6 +32,8 @@ in
|
||||
|
||||
{
|
||||
|
||||
meta.maintainers = with maintainers; [ hexa ];
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
@ -8,32 +8,37 @@ let
|
||||
|
||||
bindUser = "named";
|
||||
|
||||
bindZoneOptions = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
description = "Name of the zone.";
|
||||
};
|
||||
master = mkOption {
|
||||
description = "Master=false means slave server";
|
||||
type = types.bool;
|
||||
};
|
||||
file = mkOption {
|
||||
type = types.either types.str types.path;
|
||||
description = "Zone file resource records contain columns of data, separated by whitespace, that define the record.";
|
||||
};
|
||||
masters = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "List of servers for inclusion in stub and secondary zones.";
|
||||
};
|
||||
slaves = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "Addresses who may request zone transfers.";
|
||||
default = [];
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = types.str;
|
||||
description = "Extra zone config to be appended at the end of the zone section.";
|
||||
default = "";
|
||||
bindZoneCoerce = list: builtins.listToAttrs (lib.forEach list (zone: { name = zone.name; value = zone; }));
|
||||
|
||||
bindZoneOptions = { name, config, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = name;
|
||||
description = "Name of the zone.";
|
||||
};
|
||||
master = mkOption {
|
||||
description = "Master=false means slave server";
|
||||
type = types.bool;
|
||||
};
|
||||
file = mkOption {
|
||||
type = types.either types.str types.path;
|
||||
description = "Zone file resource records contain columns of data, separated by whitespace, that define the record.";
|
||||
};
|
||||
masters = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "List of servers for inclusion in stub and secondary zones.";
|
||||
};
|
||||
slaves = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "Addresses who may request zone transfers.";
|
||||
default = [];
|
||||
};
|
||||
extraConfig = mkOption {
|
||||
type = types.str;
|
||||
description = "Extra zone config to be appended at the end of the zone section.";
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@ -84,7 +89,7 @@ let
|
||||
${extraConfig}
|
||||
};
|
||||
'')
|
||||
cfg.zones }
|
||||
(attrValues cfg.zones) }
|
||||
'';
|
||||
|
||||
in
|
||||
@ -153,18 +158,19 @@ in
|
||||
|
||||
zones = mkOption {
|
||||
default = [];
|
||||
type = types.listOf (types.submodule [ { options = bindZoneOptions; } ]);
|
||||
type = with types; coercedTo (listOf attrs) bindZoneCoerce (attrsOf (types.submodule bindZoneOptions));
|
||||
description = "
|
||||
List of zones we claim authority over.
|
||||
";
|
||||
example = [{
|
||||
name = "example.com";
|
||||
master = false;
|
||||
file = "/var/dns/example.com";
|
||||
masters = ["192.168.0.1"];
|
||||
slaves = [];
|
||||
extraConfig = "";
|
||||
}];
|
||||
example = {
|
||||
"example.com" = {
|
||||
master = false;
|
||||
file = "/var/dns/example.com";
|
||||
masters = ["192.168.0.1"];
|
||||
slaves = [];
|
||||
extraConfig = "";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
|
@ -20,8 +20,7 @@ let
|
||||
acl_file ${aclFile}
|
||||
persistence true
|
||||
allow_anonymous ${boolToString cfg.allowAnonymous}
|
||||
bind_address ${cfg.host}
|
||||
port ${toString cfg.port}
|
||||
listener ${toString cfg.port} ${cfg.host}
|
||||
${passwordConf}
|
||||
${listenerConf}
|
||||
${cfg.extraConf}
|
||||
@ -233,15 +232,50 @@ in
|
||||
ExecStart = "${pkgs.mosquitto}/bin/mosquitto -c ${mosquittoConf}";
|
||||
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
# Hardening
|
||||
CapabilityBoundingSet = "";
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
ReadWritePaths = "${cfg.dataDir}";
|
||||
PrivateUsers = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
NoNewPrivileges = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
ProtectSystem = "strict";
|
||||
ReadWritePaths = [
|
||||
cfg.dataDir
|
||||
"/tmp" # mosquitto_passwd creates files in /tmp before moving them
|
||||
];
|
||||
ReadOnlyPaths = with cfg.ssl; lib.optionals (enable) [
|
||||
certfile
|
||||
keyfile
|
||||
cafile
|
||||
];
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_UNIX" # for sd_notify() call
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
"~@resources"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
preStart = ''
|
||||
rm -f ${cfg.dataDir}/passwd
|
||||
|
@ -4,51 +4,28 @@ with lib;
|
||||
let
|
||||
cfg = config.services.unbound;
|
||||
|
||||
stateDir = "/var/lib/unbound";
|
||||
yesOrNo = v: if v then "yes" else "no";
|
||||
|
||||
access = concatMapStringsSep "\n " (x: "access-control: ${x} allow") cfg.allowedAccess;
|
||||
toOption = indent: n: v: "${indent}${toString n}: ${v}";
|
||||
|
||||
interfaces = concatMapStringsSep "\n " (x: "interface: ${x}") cfg.interfaces;
|
||||
toConf = indent: n: v:
|
||||
if builtins.isFloat v then (toOption indent n (builtins.toJSON v))
|
||||
else if isInt v then (toOption indent n (toString v))
|
||||
else if isBool v then (toOption indent n (yesOrNo v))
|
||||
else if isString v then (toOption indent n v)
|
||||
else if isList v then (concatMapStringsSep "\n" (toConf indent n) v)
|
||||
else if isAttrs v then (concatStringsSep "\n" (
|
||||
["${indent}${n}:"] ++ (
|
||||
mapAttrsToList (toConf "${indent} ") v
|
||||
)
|
||||
))
|
||||
else throw (traceSeq v "services.unbound.settings: unexpected type");
|
||||
|
||||
isLocalAddress = x: substring 0 3 x == "::1" || substring 0 9 x == "127.0.0.1";
|
||||
confFile = pkgs.writeText "unbound.conf" (concatStringsSep "\n" ((mapAttrsToList (toConf "") cfg.settings) ++ [""]));
|
||||
|
||||
forward =
|
||||
optionalString (any isLocalAddress cfg.forwardAddresses) ''
|
||||
do-not-query-localhost: no
|
||||
''
|
||||
+ optionalString (cfg.forwardAddresses != []) ''
|
||||
forward-zone:
|
||||
name: .
|
||||
''
|
||||
+ concatMapStringsSep "\n" (x: " forward-addr: ${x}") cfg.forwardAddresses;
|
||||
rootTrustAnchorFile = "${cfg.stateDir}/root.key";
|
||||
|
||||
rootTrustAnchorFile = "${stateDir}/root.key";
|
||||
|
||||
trustAnchor = optionalString cfg.enableRootTrustAnchor
|
||||
"auto-trust-anchor-file: ${rootTrustAnchorFile}";
|
||||
|
||||
confFile = pkgs.writeText "unbound.conf" ''
|
||||
server:
|
||||
ip-freebind: yes
|
||||
directory: "${stateDir}"
|
||||
username: unbound
|
||||
chroot: ""
|
||||
pidfile: ""
|
||||
# when running under systemd there is no need to daemonize
|
||||
do-daemonize: no
|
||||
${interfaces}
|
||||
${access}
|
||||
${trustAnchor}
|
||||
${lib.optionalString (cfg.localControlSocketPath != null) ''
|
||||
remote-control:
|
||||
control-enable: yes
|
||||
control-interface: ${cfg.localControlSocketPath}
|
||||
''}
|
||||
${cfg.extraConfig}
|
||||
${forward}
|
||||
'';
|
||||
in
|
||||
{
|
||||
in {
|
||||
|
||||
###### interface
|
||||
|
||||
@ -64,27 +41,32 @@ in
|
||||
description = "The unbound package to use";
|
||||
};
|
||||
|
||||
allowedAccess = mkOption {
|
||||
default = [ "127.0.0.0/24" ];
|
||||
type = types.listOf types.str;
|
||||
description = "What networks are allowed to use unbound as a resolver.";
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "unbound";
|
||||
description = "User account under which unbound runs.";
|
||||
};
|
||||
|
||||
interfaces = mkOption {
|
||||
default = [ "127.0.0.1" ] ++ optional config.networking.enableIPv6 "::1";
|
||||
type = types.listOf types.str;
|
||||
description = ''
|
||||
What addresses the server should listen on. This supports the interface syntax documented in
|
||||
<citerefentry><refentrytitle>unbound.conf</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "unbound";
|
||||
description = "Group under which unbound runs.";
|
||||
};
|
||||
|
||||
stateDir = mkOption {
|
||||
default = "/var/lib/unbound";
|
||||
description = "Directory holding all state for unbound to run.";
|
||||
};
|
||||
|
||||
resolveLocalQueries = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Whether unbound should resolve local queries (i.e. add 127.0.0.1 to
|
||||
/etc/resolv.conf).
|
||||
'';
|
||||
};
|
||||
|
||||
forwardAddresses = mkOption {
|
||||
default = [];
|
||||
type = types.listOf types.str;
|
||||
description = "What servers to forward queries to.";
|
||||
};
|
||||
|
||||
enableRootTrustAnchor = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
@ -106,23 +88,66 @@ in
|
||||
and group will be <literal>nogroup</literal>.
|
||||
|
||||
Users that should be permitted to access the socket must be in the
|
||||
<literal>unbound</literal> group.
|
||||
<literal>config.services.unbound.group</literal> group.
|
||||
|
||||
If this option is <literal>null</literal> remote control will not be
|
||||
configured at all. Unbounds default values apply.
|
||||
enabled. Unbounds default values apply.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
settings = mkOption {
|
||||
default = {};
|
||||
type = with types; submodule {
|
||||
|
||||
freeformType = let
|
||||
validSettingsPrimitiveTypes = oneOf [ int str bool float ];
|
||||
validSettingsTypes = oneOf [ validSettingsPrimitiveTypes (listOf validSettingsPrimitiveTypes) ];
|
||||
settingsType = (attrsOf validSettingsTypes);
|
||||
in attrsOf (oneOf [ string settingsType (listOf settingsType) ])
|
||||
// { description = ''
|
||||
unbound.conf configuration type. The format consist of an attribute
|
||||
set of settings. Each settings can be either one value, a list of
|
||||
values or an attribute set. The allowed values are integers,
|
||||
strings, booleans or floats.
|
||||
'';
|
||||
};
|
||||
|
||||
options = {
|
||||
remote-control.control-enable = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
internal = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
example = literalExample ''
|
||||
{
|
||||
server = {
|
||||
interface = [ "127.0.0.1" ];
|
||||
};
|
||||
forward-zone = [
|
||||
{
|
||||
name = ".";
|
||||
forward-addr = "1.1.1.1@853#cloudflare-dns.com";
|
||||
}
|
||||
{
|
||||
name = "example.org.";
|
||||
forward-addr = [
|
||||
"1.1.1.1@853#cloudflare-dns.com"
|
||||
"1.0.0.1@853#cloudflare-dns.com"
|
||||
];
|
||||
}
|
||||
];
|
||||
remote-control.control-enable = true;
|
||||
};
|
||||
'';
|
||||
description = ''
|
||||
Extra unbound config. See
|
||||
<citerefentry><refentrytitle>unbound.conf</refentrytitle><manvolnum>8
|
||||
</manvolnum></citerefentry>.
|
||||
Declarative Unbound configuration
|
||||
See the <citerefentry><refentrytitle>unbound.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum></citerefentry> manpage for a list of
|
||||
available options.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@ -130,23 +155,56 @@ in
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
users.users.unbound = {
|
||||
description = "unbound daemon user";
|
||||
isSystemUser = true;
|
||||
group = lib.mkIf (cfg.localControlSocketPath != null) (lib.mkDefault "unbound");
|
||||
services.unbound.settings = {
|
||||
server = {
|
||||
directory = mkDefault cfg.stateDir;
|
||||
username = cfg.user;
|
||||
chroot = ''""'';
|
||||
pidfile = ''""'';
|
||||
# when running under systemd there is no need to daemonize
|
||||
do-daemonize = false;
|
||||
interface = mkDefault ([ "127.0.0.1" ] ++ (optional config.networking.enableIPv6 "::1"));
|
||||
access-control = mkDefault ([ "127.0.0.0/8 allow" ] ++ (optional config.networking.enableIPv6 "::1/128 allow"));
|
||||
auto-trust-anchor-file = mkIf cfg.enableRootTrustAnchor rootTrustAnchorFile;
|
||||
tls-cert-bundle = mkDefault "/etc/ssl/certs/ca-certificates.crt";
|
||||
# prevent race conditions on system startup when interfaces are not yet
|
||||
# configured
|
||||
ip-freebind = mkDefault true;
|
||||
};
|
||||
remote-control = {
|
||||
control-enable = mkDefault false;
|
||||
control-interface = mkDefault ([ "127.0.0.1" ] ++ (optional config.networking.enableIPv6 "::1"));
|
||||
server-key-file = mkDefault "${cfg.stateDir}/unbound_server.key";
|
||||
server-cert-file = mkDefault "${cfg.stateDir}/unbound_server.pem";
|
||||
control-key-file = mkDefault "${cfg.stateDir}/unbound_control.key";
|
||||
control-cert-file = mkDefault "${cfg.stateDir}/unbound_control.pem";
|
||||
} // optionalAttrs (cfg.localControlSocketPath != null) {
|
||||
control-enable = true;
|
||||
control-interface = cfg.localControlSocketPath;
|
||||
};
|
||||
};
|
||||
|
||||
# We need a group so that we can give users access to the configured
|
||||
# control socket. Unbound allows access to the socket only to the unbound
|
||||
# user and the primary group.
|
||||
users.groups = lib.mkIf (cfg.localControlSocketPath != null) {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
users.users = mkIf (cfg.user == "unbound") {
|
||||
unbound = {
|
||||
description = "unbound daemon user";
|
||||
isSystemUser = true;
|
||||
group = cfg.group;
|
||||
};
|
||||
};
|
||||
|
||||
users.groups = mkIf (cfg.group == "unbound") {
|
||||
unbound = {};
|
||||
};
|
||||
|
||||
networking.resolvconf.useLocalResolver = mkDefault true;
|
||||
networking = mkIf cfg.resolveLocalQueries {
|
||||
resolvconf = {
|
||||
useLocalResolver = mkDefault true;
|
||||
};
|
||||
|
||||
networkmanager.dns = "unbound";
|
||||
};
|
||||
|
||||
environment.etc."unbound/unbound.conf".source = confFile;
|
||||
|
||||
@ -156,8 +214,15 @@ in
|
||||
before = [ "nss-lookup.target" ];
|
||||
wantedBy = [ "multi-user.target" "nss-lookup.target" ];
|
||||
|
||||
preStart = lib.mkIf cfg.enableRootTrustAnchor ''
|
||||
${cfg.package}/bin/unbound-anchor -a ${rootTrustAnchorFile} || echo "Root anchor updated!"
|
||||
path = mkIf cfg.settings.remote-control.control-enable [ pkgs.openssl ];
|
||||
|
||||
preStart = ''
|
||||
${optionalString cfg.enableRootTrustAnchor ''
|
||||
${cfg.package}/bin/unbound-anchor -a ${rootTrustAnchorFile} || echo "Root anchor updated!"
|
||||
''}
|
||||
${optionalString cfg.settings.remote-control.control-enable ''
|
||||
${cfg.package}/bin/unbound-control-setup -d ${cfg.stateDir}
|
||||
''}
|
||||
'';
|
||||
|
||||
restartTriggers = [
|
||||
@ -181,8 +246,8 @@ in
|
||||
"CAP_SYS_RESOURCE"
|
||||
];
|
||||
|
||||
User = "unbound";
|
||||
Group = lib.mkIf (cfg.localControlSocketPath != null) (lib.mkDefault "unbound");
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
@ -211,9 +276,29 @@ in
|
||||
RestrictNamespaces = true;
|
||||
LockPersonality = true;
|
||||
RestrictSUIDSGID = true;
|
||||
|
||||
Restart = "on-failure";
|
||||
RestartSec = "5s";
|
||||
};
|
||||
};
|
||||
# If networkmanager is enabled, ask it to interface with unbound.
|
||||
networking.networkmanager.dns = "unbound";
|
||||
};
|
||||
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "services" "unbound" "interfaces" ] [ "services" "unbound" "settings" "server" "interface" ])
|
||||
(mkChangedOptionModule [ "services" "unbound" "allowedAccess" ] [ "services" "unbound" "settings" "server" "access-control" ] (
|
||||
config: map (value: "${value} allow") (getAttrFromPath [ "services" "unbound" "allowedAccess" ] config)
|
||||
))
|
||||
(mkRemovedOptionModule [ "services" "unbound" "forwardAddresses" ] ''
|
||||
Add a new setting:
|
||||
services.unbound.settings.forward-zone = [{
|
||||
name = ".";
|
||||
forward-addr = [ # Your current services.unbound.forwardAddresses ];
|
||||
}];
|
||||
If any of those addresses are local addresses (127.0.0.1 or ::1), you must
|
||||
also set services.unbound.settings.server.do-not-query-localhost to false.
|
||||
'')
|
||||
(mkRemovedOptionModule [ "services" "unbound" "extraConfig" ] ''
|
||||
You can use services.unbound.settings to add any configuration you want.
|
||||
'')
|
||||
];
|
||||
}
|
||||
|
@ -246,12 +246,15 @@ let
|
||||
};
|
||||
|
||||
script = ''
|
||||
mkdir --mode 0644 -p "${dirOf values.privateKeyFile}"
|
||||
set -e
|
||||
|
||||
# If the parent dir does not already exist, create it.
|
||||
# Otherwise, does nothing, keeping existing permisions intact.
|
||||
mkdir -p --mode 0755 "${dirOf values.privateKeyFile}"
|
||||
|
||||
if [ ! -f "${values.privateKeyFile}" ]; then
|
||||
touch "${values.privateKeyFile}"
|
||||
chmod 0600 "${values.privateKeyFile}"
|
||||
wg genkey > "${values.privateKeyFile}"
|
||||
chmod 0400 "${values.privateKeyFile}"
|
||||
# Write private key file with atomically-correct permissions.
|
||||
(set -e; umask 077; wg genkey > "${values.privateKeyFile}")
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
@ -62,6 +62,22 @@ in
|
||||
description = "The firewall package used by fail2ban service.";
|
||||
};
|
||||
|
||||
extraPackages = mkOption {
|
||||
default = [];
|
||||
type = types.listOf types.package;
|
||||
example = lib.literalExample "[ pkgs.ipset ]";
|
||||
description = ''
|
||||
Extra packages to be made available to the fail2ban service. The example contains
|
||||
the packages needed by the `iptables-ipset-proto6` action.
|
||||
'';
|
||||
};
|
||||
|
||||
maxretry = mkOption {
|
||||
default = 3;
|
||||
type = types.ints.unsigned;
|
||||
description = "Number of failures before a host gets banned.";
|
||||
};
|
||||
|
||||
banaction = mkOption {
|
||||
default = "iptables-multiport";
|
||||
type = types.str;
|
||||
@ -243,7 +259,7 @@ in
|
||||
restartTriggers = [ fail2banConf jailConf pathsConf ];
|
||||
reloadIfChanged = true;
|
||||
|
||||
path = [ cfg.package cfg.packageFirewall pkgs.iproute2 ];
|
||||
path = [ cfg.package cfg.packageFirewall pkgs.iproute2 ] ++ cfg.extraPackages;
|
||||
|
||||
unitConfig.Documentation = "man:fail2ban(1)";
|
||||
|
||||
@ -291,7 +307,7 @@ in
|
||||
''}
|
||||
# Miscellaneous options
|
||||
ignoreip = 127.0.0.1/8 ${optionalString config.networking.enableIPv6 "::1"} ${concatStringsSep " " cfg.ignoreIP}
|
||||
maxretry = 3
|
||||
maxretry = ${toString cfg.maxretry}
|
||||
backend = systemd
|
||||
# Actions
|
||||
banaction = ${cfg.banaction}
|
||||
|
@ -23,7 +23,8 @@ in
|
||||
config.services.oauth2_proxy = mkIf (cfg.virtualHosts != [] && (hasPrefix "127.0.0.1:" cfg.proxy)) {
|
||||
enable = true;
|
||||
};
|
||||
config.services.nginx = mkMerge ((optional (cfg.virtualHosts != []) {
|
||||
config.services.nginx = mkIf config.services.oauth2_proxy.enable (mkMerge
|
||||
((optional (cfg.virtualHosts != []) {
|
||||
recommendedProxySettings = true; # needed because duplicate headers
|
||||
}) ++ (map (vhost: {
|
||||
virtualHosts.${vhost} = {
|
||||
@ -60,5 +61,5 @@ in
|
||||
'';
|
||||
|
||||
};
|
||||
}) cfg.virtualHosts));
|
||||
}) cfg.virtualHosts)));
|
||||
}
|
||||
|
@ -819,28 +819,38 @@ in
|
||||
# Logs directory and mode
|
||||
LogsDirectory = "nginx";
|
||||
LogsDirectoryMode = "0750";
|
||||
# Proc filesystem
|
||||
ProcSubset = "pid";
|
||||
ProtectProc = "invisible";
|
||||
# New file permissions
|
||||
UMask = "0027"; # 0640 / 0750
|
||||
# Capabilities
|
||||
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" "CAP_SYS_RESOURCE" ];
|
||||
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" "CAP_SYS_RESOURCE" ];
|
||||
# Security
|
||||
NoNewPrivileges = true;
|
||||
# Sandboxing
|
||||
# Sandboxing (sorted by occurrence in https://www.freedesktop.org/software/systemd/man/systemd.exec.html)
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = mkDefault true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectHostname = true;
|
||||
ProtectClock = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
|
||||
RestrictNamespaces = true;
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = !(builtins.any (mod: (mod.allowMemoryWriteExecute or false)) cfg.package.modules);
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
RemoveIPC = true;
|
||||
PrivateMounts = true;
|
||||
# System Call Filtering
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "~@chown @cpu-emulation @debug @keyring @ipc @module @mount @obsolete @privileged @raw-io @reboot @setuid @swap";
|
||||
};
|
||||
};
|
||||
|
||||
|
318
nixos/modules/services/web-servers/trafficserver.nix
Normal file
318
nixos/modules/services/web-servers/trafficserver.nix
Normal file
@ -0,0 +1,318 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.services.trafficserver;
|
||||
user = config.users.users.trafficserver.name;
|
||||
group = config.users.groups.trafficserver.name;
|
||||
|
||||
getManualUrl = name: "https://docs.trafficserver.apache.org/en/latest/admin-guide/files/${name}.en.html";
|
||||
getConfPath = name: "${pkgs.trafficserver}/etc/trafficserver/${name}";
|
||||
|
||||
yaml = pkgs.formats.yaml { };
|
||||
|
||||
fromYAML = f:
|
||||
let
|
||||
jsonFile = pkgs.runCommand "in.json"
|
||||
{
|
||||
nativeBuildInputs = [ pkgs.remarshal ];
|
||||
} ''
|
||||
yaml2json < "${f}" > "$out"
|
||||
'';
|
||||
in
|
||||
builtins.fromJSON (builtins.readFile jsonFile);
|
||||
|
||||
mkYamlConf = name: cfg:
|
||||
if cfg != null then {
|
||||
"trafficserver/${name}.yaml".source = yaml.generate "${name}.yaml" cfg;
|
||||
} else {
|
||||
"trafficserver/${name}.yaml".text = "";
|
||||
};
|
||||
|
||||
mkRecordLines = path: value:
|
||||
if isAttrs value then
|
||||
lib.mapAttrsToList (n: v: mkRecordLines (path ++ [ n ]) v) value
|
||||
else if isInt value then
|
||||
"CONFIG ${concatStringsSep "." path} INT ${toString value}"
|
||||
else if isFloat value then
|
||||
"CONFIG ${concatStringsSep "." path} FLOAT ${toString value}"
|
||||
else
|
||||
"CONFIG ${concatStringsSep "." path} STRING ${toString value}";
|
||||
|
||||
mkRecordsConfig = cfg: concatStringsSep "\n" (flatten (mkRecordLines [ ] cfg));
|
||||
mkPluginConfig = cfg: concatStringsSep "\n" (map (p: "${p.path} ${p.arg}") cfg);
|
||||
in
|
||||
{
|
||||
options.services.trafficserver = {
|
||||
enable = mkEnableOption "Apache Traffic Server";
|
||||
|
||||
cache = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "dest_domain=example.com suffix=js action=never-cache";
|
||||
description = ''
|
||||
Caching rules that overrule the origin's caching policy.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "cache.config"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
hosting = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "domain=example.com volume=1";
|
||||
description = ''
|
||||
Partition the cache according to origin server or domain
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "hosting.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
ipAllow = mkOption {
|
||||
type = types.nullOr yaml.type;
|
||||
default = fromYAML (getConfPath "ip_allow.yaml");
|
||||
defaultText = "upstream defaults";
|
||||
example = literalExample {
|
||||
ip_allow = [{
|
||||
apply = "in";
|
||||
ip_addrs = "127.0.0.1";
|
||||
action = "allow";
|
||||
methods = "ALL";
|
||||
}];
|
||||
};
|
||||
description = ''
|
||||
Control client access to Traffic Server and Traffic Server connections
|
||||
to upstream servers.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "ip_allow.yaml"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
logging = mkOption {
|
||||
type = types.nullOr yaml.type;
|
||||
default = fromYAML (getConfPath "logging.yaml");
|
||||
defaultText = "upstream defaults";
|
||||
example = literalExample { };
|
||||
description = ''
|
||||
Configure logs.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "logging.yaml"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
parent = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = ''
|
||||
dest_domain=. method=get parent="p1.example:8080; p2.example:8080" round_robin=true
|
||||
'';
|
||||
description = ''
|
||||
Identify the parent proxies used in an cache hierarchy.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "parent.config"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
plugins = mkOption {
|
||||
default = [ ];
|
||||
|
||||
description = ''
|
||||
Controls run-time loadable plugins available to Traffic Server, as
|
||||
well as their configuration.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "plugin.config"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
|
||||
type = with types;
|
||||
listOf (submodule {
|
||||
options.path = mkOption {
|
||||
type = str;
|
||||
example = "xdebug.so";
|
||||
description = ''
|
||||
Path to plugin. The path can either be absolute, or relative to
|
||||
the plugin directory.
|
||||
'';
|
||||
};
|
||||
options.arg = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
example = "--header=ATS-My-Debug";
|
||||
description = "arguments to pass to the plugin";
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
records = mkOption {
|
||||
type = with types;
|
||||
let valueType = (attrsOf (oneOf [ int float str valueType ])) // {
|
||||
description = "Traffic Server records value";
|
||||
};
|
||||
in
|
||||
valueType;
|
||||
default = { };
|
||||
example = literalExample { proxy.config.proxy_name = "my_server"; };
|
||||
description = ''
|
||||
List of configurable variables used by Traffic Server.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "records.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
remap = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "map http://from.example http://origin.example";
|
||||
description = ''
|
||||
URL remapping rules used by Traffic Server.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "remap.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
splitDns = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = ''
|
||||
dest_domain=internal.corp.example named="255.255.255.255:212 255.255.255.254" def_domain=corp.example search_list="corp.example corp1.example"
|
||||
dest_domain=!internal.corp.example named=255.255.255.253
|
||||
'';
|
||||
description = ''
|
||||
Specify the DNS server that Traffic Server should use under specific
|
||||
conditions.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "splitdns.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
sslMulticert = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "dest_ip=* ssl_cert_name=default.pem";
|
||||
description = ''
|
||||
Configure SSL server certificates to terminate the SSL sessions.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "ssl_multicert.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
sni = mkOption {
|
||||
type = types.nullOr yaml.type;
|
||||
default = null;
|
||||
example = literalExample {
|
||||
sni = [{
|
||||
fqdn = "no-http2.example.com";
|
||||
https = "off";
|
||||
}];
|
||||
};
|
||||
description = ''
|
||||
Configure aspects of TLS connection handling for both inbound and
|
||||
outbound connections.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "sni.yaml"}">upstream
|
||||
documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
storage = mkOption {
|
||||
type = types.lines;
|
||||
default = "/var/cache/trafficserver 256M";
|
||||
example = "/dev/disk/by-id/XXXXX volume=1";
|
||||
description = ''
|
||||
List all the storage that make up the Traffic Server cache.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "storage.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
strategies = mkOption {
|
||||
type = types.nullOr yaml.type;
|
||||
default = null;
|
||||
description = ''
|
||||
Specify the next hop proxies used in an cache hierarchy and the
|
||||
algorithms used to select the next proxy.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "strategies.yaml"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
volume = mkOption {
|
||||
type = types.nullOr yaml.type;
|
||||
default = "";
|
||||
example = "volume=1 scheme=http size=20%";
|
||||
description = ''
|
||||
Manage cache space more efficiently and restrict disk usage by
|
||||
creating cache volumes of different sizes.
|
||||
|
||||
Consult the <link xlink:href="${getManualUrl "volume.config"}">
|
||||
upstream documentation</link> for more details.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.etc = {
|
||||
"trafficserver/cache.config".text = cfg.cache;
|
||||
"trafficserver/hosting.config".text = cfg.hosting;
|
||||
"trafficserver/parent.config".text = cfg.parent;
|
||||
"trafficserver/plugin.config".text = mkPluginConfig cfg.plugins;
|
||||
"trafficserver/records.config".text = mkRecordsConfig cfg.records;
|
||||
"trafficserver/remap.config".text = cfg.remap;
|
||||
"trafficserver/splitdns.config".text = cfg.splitDns;
|
||||
"trafficserver/ssl_multicert.config".text = cfg.sslMulticert;
|
||||
"trafficserver/storage.config".text = cfg.storage;
|
||||
"trafficserver/volume.config".text = cfg.volume;
|
||||
} // (mkYamlConf "ip_allow" cfg.ipAllow)
|
||||
// (mkYamlConf "logging" cfg.logging)
|
||||
// (mkYamlConf "sni" cfg.sni)
|
||||
// (mkYamlConf "strategies" cfg.strategies);
|
||||
|
||||
environment.systemPackages = [ pkgs.trafficserver ];
|
||||
systemd.packages = [ pkgs.trafficserver ];
|
||||
|
||||
# Traffic Server does privilege handling independently of systemd, and
|
||||
# therefore should be started as root
|
||||
systemd.services.trafficserver = {
|
||||
enable = true;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
# These directories can't be created by systemd because:
|
||||
#
|
||||
# 1. Traffic Servers starts as root and switches to an unprivileged user
|
||||
# afterwards. The runtime directories defined below are assumed to be
|
||||
# owned by that user.
|
||||
# 2. The bin/trafficserver script assumes these directories exist.
|
||||
systemd.tmpfiles.rules = [
|
||||
"d '/run/trafficserver' - ${user} ${group} - -"
|
||||
"d '/var/cache/trafficserver' - ${user} ${group} - -"
|
||||
"d '/var/lib/trafficserver' - ${user} ${group} - -"
|
||||
"d '/var/log/trafficserver' - ${user} ${group} - -"
|
||||
];
|
||||
|
||||
services.trafficserver = {
|
||||
records.proxy.config.admin.user_id = user;
|
||||
records.proxy.config.body_factory.template_sets_dir =
|
||||
"${pkgs.trafficserver}/etc/trafficserver/body_factory";
|
||||
};
|
||||
|
||||
users.users.trafficserver = {
|
||||
description = "Apache Traffic Server";
|
||||
isSystemUser = true;
|
||||
inherit group;
|
||||
};
|
||||
users.groups.trafficserver = { };
|
||||
};
|
||||
}
|
@ -151,7 +151,6 @@ in
|
||||
services.upower.enable = config.powerManagement.enable;
|
||||
services.gnome3.glib-networking.enable = true;
|
||||
services.gvfs.enable = true;
|
||||
services.gvfs.package = pkgs.xfce.gvfs;
|
||||
services.tumbler.enable = true;
|
||||
services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
|
||||
services.xserver.libinput.enable = mkDefault true; # used in xfce4-settings-manager
|
||||
|
@ -666,6 +666,7 @@ in
|
||||
# The default max inotify watches is 8192.
|
||||
# Nowadays most apps require a good number of inotify watches,
|
||||
# the value below is used by default on several other distros.
|
||||
boot.kernel.sysctl."fs.inotify.max_user_instances" = mkDefault 524288;
|
||||
boot.kernel.sysctl."fs.inotify.max_user_watches" = mkDefault 524288;
|
||||
|
||||
systemd.defaultUnit = mkIf cfg.autorun "graphical.target";
|
||||
|
@ -16,6 +16,16 @@ let
|
||||
|
||||
userData=/etc/ec2-metadata/user-data
|
||||
|
||||
# Check if user-data looks like a shell script and execute it with the
|
||||
# runtime shell if it does. Otherwise treat it as a nixos configuration
|
||||
# expression
|
||||
if IFS= LC_ALL=C read -rN2 shebang < $userData && [ "$shebang" = '#!' ]; then
|
||||
# NB: we cannot chmod the $userData file, this is why we execute it via
|
||||
# `pkgs.runtimeShell`. This means we have only limited support for shell
|
||||
# scripts compatible with the `pkgs.runtimeShell`.
|
||||
exec ${pkgs.runtimeShell} $userData
|
||||
fi
|
||||
|
||||
if [ -s "$userData" ]; then
|
||||
# If the user-data looks like it could be a nix expression,
|
||||
# copy it over. Also, look for a magic three-hash comment and set
|
||||
|
@ -224,6 +224,25 @@ in rec {
|
||||
);
|
||||
|
||||
|
||||
# Test job for https://github.com/NixOS/nixpkgs/issues/121354 to test
|
||||
# automatic sizing without blocking the channel.
|
||||
amazonImageAutomaticSize = forMatchingSystems [ "x86_64-linux" "aarch64-linux" ] (system:
|
||||
|
||||
with import ./.. { inherit system; };
|
||||
|
||||
hydraJob ((import lib/eval-config.nix {
|
||||
inherit system;
|
||||
modules =
|
||||
[ configuration
|
||||
versionModule
|
||||
./maintainers/scripts/ec2/amazon-image.nix
|
||||
({ ... }: { amazonImage.sizeMB = "auto"; })
|
||||
];
|
||||
}).config.system.build.amazonImage)
|
||||
|
||||
);
|
||||
|
||||
|
||||
# Ensure that all packages used by the minimal NixOS config end up in the channel.
|
||||
dummy = forAllSystems (system: pkgs.runCommand "dummy"
|
||||
{ toplevel = (import lib/eval-config.nix {
|
||||
|
32
nixos/tests/airsonic.nix
Normal file
32
nixos/tests/airsonic.nix
Normal file
@ -0,0 +1,32 @@
|
||||
import ./make-test-python.nix ({ pkgs, ... }: {
|
||||
name = "airsonic";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ sumnerevans ];
|
||||
};
|
||||
|
||||
machine =
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
services.airsonic = {
|
||||
enable = true;
|
||||
maxMemory = 800;
|
||||
};
|
||||
|
||||
# Airsonic is a Java application, and unfortunately requires a significant
|
||||
# amount of memory.
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
def airsonic_is_up(_) -> bool:
|
||||
return machine.succeed("curl --fail http://localhost:4040/login")
|
||||
|
||||
|
||||
machine.start()
|
||||
machine.wait_for_unit("airsonic.service")
|
||||
machine.wait_for_open_port(4040)
|
||||
|
||||
with machine.nested("Waiting for UI to work"):
|
||||
retry(airsonic_is_up)
|
||||
'';
|
||||
})
|
@ -24,6 +24,8 @@ in
|
||||
_3proxy = handleTest ./3proxy.nix {};
|
||||
acme = handleTest ./acme.nix {};
|
||||
agda = handleTest ./agda.nix {};
|
||||
airsonic = handleTest ./airsonic.nix {};
|
||||
amazon-init-shell = handleTest ./amazon-init-shell.nix {};
|
||||
ammonite = handleTest ./ammonite.nix {};
|
||||
atd = handleTest ./atd.nix {};
|
||||
avahi = handleTest ./avahi.nix {};
|
||||
@ -413,6 +415,7 @@ in
|
||||
# traefik test relies on docker-containers
|
||||
trac = handleTest ./trac.nix {};
|
||||
traefik = handleTestOn ["x86_64-linux"] ./traefik.nix {};
|
||||
trafficserver = handleTest ./trafficserver.nix {};
|
||||
transmission = handleTest ./transmission.nix {};
|
||||
trezord = handleTest ./trezord.nix {};
|
||||
trickster = handleTest ./trickster.nix {};
|
||||
|
40
nixos/tests/amazon-init-shell.nix
Normal file
40
nixos/tests/amazon-init-shell.nix
Normal file
@ -0,0 +1,40 @@
|
||||
# This test verifies that the amazon-init service can treat the `user-data` ec2
|
||||
# metadata file as a shell script. If amazon-init detects that `user-data` is a
|
||||
# script (based on the presence of the shebang #! line) it executes it and
|
||||
# exits.
|
||||
# Note that other tests verify that amazon-init can treat user-data as a nixos
|
||||
# configuration expression.
|
||||
|
||||
{ system ? builtins.currentSystem,
|
||||
config ? {},
|
||||
pkgs ? import ../.. { inherit system config; }
|
||||
}:
|
||||
|
||||
with import ../lib/testing-python.nix { inherit system pkgs; };
|
||||
with pkgs.lib;
|
||||
|
||||
makeTest {
|
||||
name = "amazon-init";
|
||||
meta = with maintainers; {
|
||||
maintainers = [ urbas ];
|
||||
};
|
||||
machine = { ... }:
|
||||
{
|
||||
imports = [ ../modules/profiles/headless.nix ../modules/virtualisation/amazon-init.nix ];
|
||||
services.openssh.enable = true;
|
||||
networking.hostName = "";
|
||||
environment.etc."ec2-metadata/user-data" = {
|
||||
text = ''
|
||||
#!/usr/bin/bash
|
||||
|
||||
echo successful > /tmp/evidence
|
||||
'';
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
# To wait until amazon-init terminates its run
|
||||
unnamed.wait_for_unit("amazon-init.service")
|
||||
|
||||
unnamed.succeed("grep -q successful /tmp/evidence")
|
||||
'';
|
||||
}
|
@ -18,6 +18,10 @@ import ./make-test-python.nix ({ pkgs, ...} :
|
||||
};
|
||||
|
||||
virtualisation.memorySize = 1024;
|
||||
# Need to switch to a different VGA card / GPU driver because Cage segfaults with the default one (std):
|
||||
# machine # [ 14.355893] .cage-wrapped[736]: segfault at 20 ip 00007f035fa0d8c7 sp 00007ffce9e4a2f0 error 4 in libwlroots.so.8[7f035fa07000+5a000]
|
||||
# machine # [ 14.358108] Code: 4f a8 ff ff eb aa 0f 1f 44 00 00 c3 0f 1f 80 00 00 00 00 41 54 49 89 f4 55 31 ed 53 48 89 fb 48 8d 7f 18 48 8d 83 b8 00 00 00 <80> 7f 08 00 75 0d 48 83 3f 00 0f 85 91 00 00 00 48 89 fd 48 83 c7
|
||||
virtualisation.qemu.options = [ "-vga virtio" ];
|
||||
};
|
||||
|
||||
enableOCR = true;
|
||||
@ -25,11 +29,6 @@ import ./make-test-python.nix ({ pkgs, ...} :
|
||||
testScript = { nodes, ... }: let
|
||||
user = nodes.machine.config.users.users.alice;
|
||||
in ''
|
||||
# Need to switch to a different VGA card / GPU driver because Cage segfaults with the default one (std):
|
||||
# machine # [ 14.355893] .cage-wrapped[736]: segfault at 20 ip 00007f035fa0d8c7 sp 00007ffce9e4a2f0 error 4 in libwlroots.so.8[7f035fa07000+5a000]
|
||||
# machine # [ 14.358108] Code: 4f a8 ff ff eb aa 0f 1f 44 00 00 c3 0f 1f 80 00 00 00 00 41 54 49 89 f4 55 31 ed 53 48 89 fb 48 8d 7f 18 48 8d 83 b8 00 00 00 <80> 7f 08 00 75 0d 48 83 3f 00 0f 85 91 00 00 00 48 89 fd 48 83 c7
|
||||
os.environ["QEMU_OPTS"] = "-vga virtio"
|
||||
|
||||
with subtest("Wait for cage to boot up"):
|
||||
start_all()
|
||||
machine.wait_for_file("/run/user/${toString user.uid}/wayland-0.lock")
|
||||
|
@ -92,13 +92,19 @@ in
|
||||
{ onlySSL = true;
|
||||
sslCertificate = "${example-good-cert}/server.crt";
|
||||
sslCertificateKey = "${example-good-cert}/server.key";
|
||||
locations."/".extraConfig = "return 200 'It works!';";
|
||||
locations."/".extraConfig = ''
|
||||
add_header Content-Type text/plain;
|
||||
return 200 'It works!';
|
||||
'';
|
||||
};
|
||||
services.nginx.virtualHosts."bad.example.com" =
|
||||
{ onlySSL = true;
|
||||
sslCertificate = "${example-bad-cert}/server.crt";
|
||||
sslCertificateKey = "${example-bad-cert}/server.key";
|
||||
locations."/".extraConfig = "return 200 'It does not work!';";
|
||||
locations."/".extraConfig = ''
|
||||
add_header Content-Type text/plain;
|
||||
return 200 'It does not work!';
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs;
|
||||
|
@ -18,6 +18,11 @@ in {
|
||||
|
||||
environment.systemPackages = [ pkgs.git ];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
# type path mode user group age arg
|
||||
" d /git 0755 root root - -"
|
||||
];
|
||||
|
||||
services.gitDaemon = {
|
||||
enable = true;
|
||||
basePath = "/git";
|
||||
@ -35,7 +40,6 @@ in {
|
||||
|
||||
with subtest("create project.git"):
|
||||
server.succeed(
|
||||
"mkdir /git",
|
||||
"git init --bare /git/project.git",
|
||||
"touch /git/project.git/git-daemon-export-ok",
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import ./make-test-python.nix ({ pkgs, ... }:
|
||||
import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
configDir = "/var/lib/foobar";
|
||||
@ -6,9 +6,7 @@ let
|
||||
mqttPassword = "secret";
|
||||
in {
|
||||
name = "home-assistant";
|
||||
meta = with pkgs.lib; {
|
||||
maintainers = with maintainers; [ dotlambda ];
|
||||
};
|
||||
meta.maintainers = lib.teams.home-assistant.members;
|
||||
|
||||
nodes.hass = { pkgs, ... }: {
|
||||
environment.systemPackages = with pkgs; [ mosquitto ];
|
||||
@ -47,6 +45,10 @@ in {
|
||||
payload_on = "let_there_be_light";
|
||||
payload_off = "off";
|
||||
}];
|
||||
emulated_hue = {
|
||||
host_ip = "127.0.0.1";
|
||||
listen_port = 80;
|
||||
};
|
||||
logger = {
|
||||
default = "info";
|
||||
logs."homeassistant.components.mqtt" = "debug";
|
||||
@ -82,6 +84,9 @@ in {
|
||||
hass.succeed(
|
||||
"mosquitto_pub -V mqttv5 -t home-assistant/test -u ${mqttUsername} -P '${mqttPassword}' -m let_there_be_light"
|
||||
)
|
||||
with subtest("Check that capabilities are passed for emulated_hue to bind to port 80"):
|
||||
hass.wait_for_open_port(80)
|
||||
hass.succeed("curl --fail http://localhost:80/description.xml")
|
||||
with subtest("Print log to ease debugging"):
|
||||
output_log = hass.succeed("cat ${configDir}/home-assistant.log")
|
||||
print("\n### home-assistant.log ###\n")
|
||||
@ -93,5 +98,8 @@ in {
|
||||
# example line: 2020-06-20 10:01:32 DEBUG (MainThread) [homeassistant.components.mqtt] Received message on home-assistant/test: b'let_there_be_light'
|
||||
with subtest("Check we received the mosquitto message"):
|
||||
assert "let_there_be_light" in output_log
|
||||
|
||||
with subtest("Check systemd unit hardening"):
|
||||
hass.log(hass.succeed("systemd-analyze security home-assistant.service"))
|
||||
'';
|
||||
})
|
||||
|
@ -75,7 +75,7 @@ let
|
||||
else ''
|
||||
def assemble_qemu_flags():
|
||||
flags = "-cpu max"
|
||||
${if system == "x86_64-linux"
|
||||
${if (system == "x86_64-linux" || system == "i686-linux")
|
||||
then ''flags += " -m 1024"''
|
||||
else ''flags += " -m 768 -enable-kvm -machine virt,gic-version=host"''
|
||||
}
|
||||
|
@ -1,16 +1,156 @@
|
||||
import ./make-test-python.nix ({ lib, ...}:
|
||||
import ./make-test-python.nix ({ lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
name = "jellyfin";
|
||||
meta.maintainers = with lib.maintainers; [ minijackson ];
|
||||
{
|
||||
name = "jellyfin";
|
||||
meta.maintainers = with lib.maintainers; [ minijackson ];
|
||||
|
||||
machine =
|
||||
{ ... }:
|
||||
{ services.jellyfin.enable = true; };
|
||||
machine =
|
||||
{ ... }:
|
||||
{
|
||||
services.jellyfin.enable = true;
|
||||
environment.systemPackages = with pkgs; [ ffmpeg ];
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("jellyfin.service")
|
||||
machine.wait_for_open_port(8096)
|
||||
machine.succeed("curl --fail http://localhost:8096/")
|
||||
'';
|
||||
})
|
||||
# Documentation of the Jellyfin API: https://api.jellyfin.org/
|
||||
# Beware, this link can be resource intensive
|
||||
testScript =
|
||||
let
|
||||
payloads = {
|
||||
auth = pkgs.writeText "auth.json" (builtins.toJSON {
|
||||
Username = "jellyfin";
|
||||
});
|
||||
empty = pkgs.writeText "empty.json" (builtins.toJSON { });
|
||||
};
|
||||
in
|
||||
''
|
||||
import json
|
||||
import time
|
||||
from urllib.parse import urlencode
|
||||
|
||||
machine.wait_for_unit("jellyfin.service")
|
||||
machine.wait_for_open_port(8096)
|
||||
machine.succeed("curl --fail http://localhost:8096/")
|
||||
|
||||
machine.wait_until_succeeds("curl --fail http://localhost:8096/health | grep Healthy")
|
||||
|
||||
auth_header = 'MediaBrowser Client="NixOS Integration Tests", DeviceId="1337", Device="Apple II", Version="20.09"'
|
||||
|
||||
|
||||
def api_get(path):
|
||||
return f"curl --fail 'http://localhost:8096{path}' -H 'X-Emby-Authorization:{auth_header}'"
|
||||
|
||||
|
||||
def api_post(path, json_file=None):
|
||||
if json_file:
|
||||
return f"curl --fail -X post 'http://localhost:8096{path}' -d '@{json_file}' -H Content-Type:application/json -H 'X-Emby-Authorization:{auth_header}'"
|
||||
else:
|
||||
return f"curl --fail -X post 'http://localhost:8096{path}' -H 'X-Emby-Authorization:{auth_header}'"
|
||||
|
||||
|
||||
with machine.nested("Wizard completes"):
|
||||
machine.wait_until_succeeds(api_get("/Startup/Configuration"))
|
||||
machine.succeed(api_get("/Startup/FirstUser"))
|
||||
machine.succeed(api_post("/Startup/Complete"))
|
||||
|
||||
with machine.nested("Can login"):
|
||||
auth_result = machine.succeed(
|
||||
api_post(
|
||||
"/Users/AuthenticateByName",
|
||||
"${payloads.auth}",
|
||||
)
|
||||
)
|
||||
auth_result = json.loads(auth_result)
|
||||
auth_token = auth_result["AccessToken"]
|
||||
auth_header += f", Token={auth_token}"
|
||||
|
||||
sessions_result = machine.succeed(api_get("/Sessions"))
|
||||
sessions_result = json.loads(sessions_result)
|
||||
|
||||
this_session = [
|
||||
session for session in sessions_result if session["DeviceId"] == "1337"
|
||||
]
|
||||
if len(this_session) != 1:
|
||||
raise Exception("Session not created")
|
||||
|
||||
me = machine.succeed(api_get("/Users/Me"))
|
||||
me = json.loads(me)["Id"]
|
||||
|
||||
with machine.nested("Can add library"):
|
||||
tempdir = machine.succeed("mktemp -d -p /var/lib/jellyfin").strip()
|
||||
machine.succeed(f"chmod 755 '{tempdir}'")
|
||||
|
||||
# Generate a dummy video that we can test later
|
||||
videofile = f"{tempdir}/Big Buck Bunny (2008) [1080p].mkv"
|
||||
machine.succeed(f"ffmpeg -f lavfi -i testsrc2=duration=5 '{videofile}'")
|
||||
|
||||
add_folder_query = urlencode(
|
||||
{
|
||||
"name": "My Library",
|
||||
"collectionType": "Movies",
|
||||
"paths": tempdir,
|
||||
"refreshLibrary": "true",
|
||||
}
|
||||
)
|
||||
|
||||
machine.succeed(
|
||||
api_post(
|
||||
f"/Library/VirtualFolders?{add_folder_query}",
|
||||
"${payloads.empty}",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def is_refreshed(_):
|
||||
folders = machine.succeed(api_get(f"/Library/VirtualFolders"))
|
||||
folders = json.loads(folders)
|
||||
print(folders)
|
||||
return all(folder["RefreshStatus"] == "Idle" for folder in folders)
|
||||
|
||||
|
||||
retry(is_refreshed)
|
||||
|
||||
with machine.nested("Can identify videos"):
|
||||
items = []
|
||||
|
||||
# For some reason, having the folder refreshed doesn't mean the
|
||||
# movie was scanned
|
||||
def has_movie(_):
|
||||
global items
|
||||
|
||||
items = machine.succeed(
|
||||
api_get(f"/Users/{me}/Items?IncludeItemTypes=Movie&Recursive=true")
|
||||
)
|
||||
items = json.loads(items)["Items"]
|
||||
|
||||
return len(items) == 1
|
||||
|
||||
retry(has_movie)
|
||||
|
||||
video = items[0]["Id"]
|
||||
|
||||
item_info = machine.succeed(api_get(f"/Users/{me}/Items/{video}"))
|
||||
item_info = json.loads(item_info)
|
||||
|
||||
if item_info["Name"] != "Big Buck Bunny":
|
||||
raise Exception("Jellyfin failed to properly identify file")
|
||||
|
||||
with machine.nested("Can read videos"):
|
||||
media_source_id = item_info["MediaSources"][0]["Id"]
|
||||
|
||||
machine.succeed(
|
||||
"ffmpeg"
|
||||
+ f" -headers 'X-Emby-Authorization:{auth_header}'"
|
||||
+ f" -i http://localhost:8096/Videos/{video}/master.m3u8?mediaSourceId={media_source_id}"
|
||||
+ f" /tmp/test.mkv"
|
||||
)
|
||||
|
||||
duration = machine.succeed(
|
||||
"ffprobe /tmp/test.mkv"
|
||||
+ " -show_entries format=duration"
|
||||
+ " -of compact=print_section=0:nokey=1"
|
||||
)
|
||||
|
||||
if duration.strip() != "5.000000":
|
||||
raise Exception("Downloaded video has wrong duration")
|
||||
'';
|
||||
})
|
||||
|
@ -1,4 +1,4 @@
|
||||
import ./make-test-python.nix ({ pkgs, ... }:
|
||||
import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
port = 1888;
|
||||
@ -30,6 +30,9 @@ in {
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# disable private /tmp for this test
|
||||
systemd.services.mosquitto.serviceConfig.PrivateTmp = lib.mkForce false;
|
||||
};
|
||||
|
||||
client1 = client;
|
||||
|
@ -69,6 +69,9 @@ in {
|
||||
imports = [ ../modules/profiles/installation-device.nix
|
||||
../modules/profiles/base.nix ];
|
||||
virtualisation.memorySize = 1300;
|
||||
# To add the secondary disk:
|
||||
virtualisation.qemu.options = [ "-drive index=2,file=${debianImage}/disk-image.qcow2,read-only,if=virtio" ];
|
||||
|
||||
# The test cannot access the network, so any packages
|
||||
# nixos-rebuild needs must be included in the VM.
|
||||
system.extraDependencies = with pkgs;
|
||||
@ -95,11 +98,6 @@ in {
|
||||
});
|
||||
|
||||
testScript = ''
|
||||
# hack to add the secondary disk
|
||||
os.environ[
|
||||
"QEMU_OPTS"
|
||||
] = "-drive index=2,file=${debianImage}/disk-image.qcow2,read-only,if=virtio"
|
||||
|
||||
machine.start()
|
||||
machine.succeed("udevadm settle")
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
@ -61,7 +61,7 @@ in
|
||||
client.wait_until_succeeds("ping -c1 server")
|
||||
|
||||
# make sure pinnwand is listening
|
||||
server.wait_until_succeeds("ss -lnp | grep ${toString port}")
|
||||
server.wait_for_open_port(${toString port})
|
||||
|
||||
# send the contents of /etc/machine-id
|
||||
response = client.succeed("steck paste /etc/machine-id")
|
||||
@ -75,6 +75,12 @@ in
|
||||
if line.startswith("Removal link:"):
|
||||
removal_link = line.split(":", 1)[1]
|
||||
|
||||
|
||||
# start the reaper, it shouldn't do anything meaningful here
|
||||
server.systemctl("start pinnwand-reaper.service")
|
||||
server.wait_until_fails("systemctl is-active -q pinnwand-reaper.service")
|
||||
server.log(server.execute("journalctl -u pinnwand-reaper -e --no-pager")[1])
|
||||
|
||||
# check whether paste matches what we sent
|
||||
client.succeed(f"curl {raw_url} > /tmp/machine-id")
|
||||
client.succeed("diff /tmp/machine-id /etc/machine-id")
|
||||
@ -82,5 +88,7 @@ in
|
||||
# remove paste and check that it's not available any more
|
||||
client.succeed(f"curl {removal_link}")
|
||||
client.fail(f"curl --fail {raw_url}")
|
||||
|
||||
server.log(server.succeed("systemd-analyze security pinnwand"))
|
||||
'';
|
||||
})
|
||||
|
@ -25,6 +25,7 @@ let
|
||||
machine = {
|
||||
services.rspamd.enable = true;
|
||||
networking.enableIPv6 = enableIPv6;
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
testScript = ''
|
||||
start_all()
|
||||
@ -68,6 +69,7 @@ in
|
||||
group = "rspamd";
|
||||
}];
|
||||
};
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
@ -116,6 +118,7 @@ in
|
||||
'';
|
||||
};
|
||||
};
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
@ -221,6 +224,7 @@ in
|
||||
rspamd_logger.infox(rspamd_config, 'Work dammit!!!')
|
||||
'';
|
||||
};
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
testScript = ''
|
||||
${initMachine}
|
||||
@ -287,6 +291,7 @@ in
|
||||
postfix.enable = true;
|
||||
workers.rspamd_proxy.type = "rspamd_proxy";
|
||||
};
|
||||
virtualisation.memorySize = 1024;
|
||||
};
|
||||
testScript = ''
|
||||
${initMachine}
|
||||
|
176
nixos/tests/trafficserver.nix
Normal file
176
nixos/tests/trafficserver.nix
Normal file
@ -0,0 +1,176 @@
|
||||
# verifies:
|
||||
# 1. Traffic Server is able to start
|
||||
# 2. Traffic Server spawns traffic_crashlog upon startup
|
||||
# 3. Traffic Server proxies HTTP requests according to URL remapping rules
|
||||
# in 'services.trafficserver.remap'
|
||||
# 4. Traffic Server applies per-map settings specified with the conf_remap
|
||||
# plugin
|
||||
# 5. Traffic Server caches HTTP responses
|
||||
# 6. Traffic Server processes HTTP PUSH requests
|
||||
# 7. Traffic Server can load the healthchecks plugin
|
||||
# 8. Traffic Server logs HTTP traffic as configured
|
||||
#
|
||||
# uses:
|
||||
# - bin/traffic_manager
|
||||
# - bin/traffic_server
|
||||
# - bin/traffic_crashlog
|
||||
# - bin/traffic_cache_tool
|
||||
# - bin/traffic_ctl
|
||||
# - bin/traffic_logcat
|
||||
# - bin/traffic_logstats
|
||||
# - bin/tspush
|
||||
import ./make-test-python.nix ({ pkgs, ... }: {
|
||||
name = "trafficserver";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ midchildan ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
ats = { pkgs, lib, config, ... }: let
|
||||
user = config.users.users.trafficserver.name;
|
||||
group = config.users.groups.trafficserver.name;
|
||||
healthchecks = pkgs.writeText "healthchecks.conf" ''
|
||||
/status /tmp/ats.status text/plain 200 500
|
||||
'';
|
||||
in {
|
||||
services.trafficserver.enable = true;
|
||||
|
||||
services.trafficserver.records = {
|
||||
proxy.config.http.server_ports = "80 80:ipv6";
|
||||
proxy.config.hostdb.host_file.path = "/etc/hosts";
|
||||
proxy.config.log.max_space_mb_headroom = 0;
|
||||
proxy.config.http.push_method_enabled = 1;
|
||||
|
||||
# check that cache storage is usable before accepting traffic
|
||||
proxy.config.http.wait_for_cache = 2;
|
||||
};
|
||||
|
||||
services.trafficserver.plugins = [
|
||||
{ path = "healthchecks.so"; arg = toString healthchecks; }
|
||||
{ path = "xdebug.so"; }
|
||||
];
|
||||
|
||||
services.trafficserver.remap = ''
|
||||
map http://httpbin.test http://httpbin
|
||||
map http://pristine-host-hdr.test http://httpbin \
|
||||
@plugin=conf_remap.so \
|
||||
@pparam=proxy.config.url_remap.pristine_host_hdr=1
|
||||
map http://ats/tspush http://httpbin/cache \
|
||||
@plugin=conf_remap.so \
|
||||
@pparam=proxy.config.http.cache.required_headers=0
|
||||
'';
|
||||
|
||||
services.trafficserver.storage = ''
|
||||
/dev/vdb volume=1
|
||||
'';
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
virtualisation.emptyDiskImages = [ 256 ];
|
||||
services.udev.extraRules = ''
|
||||
KERNEL=="vdb", OWNER="${user}", GROUP="${group}"
|
||||
'';
|
||||
};
|
||||
|
||||
httpbin = { pkgs, lib, ... }: let
|
||||
python = pkgs.python3.withPackages
|
||||
(ps: with ps; [ httpbin gunicorn gevent ]);
|
||||
in {
|
||||
systemd.services.httpbin = {
|
||||
enable = true;
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = "${python}/bin/gunicorn -b 0.0.0.0:80 httpbin:app -k gevent";
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
};
|
||||
|
||||
client = { pkgs, lib, ... }: {
|
||||
environment.systemPackages = with pkgs; [ curl ];
|
||||
};
|
||||
};
|
||||
|
||||
testScript = { nodes, ... }: let
|
||||
sampleFile = pkgs.writeText "sample.txt" ''
|
||||
It's the season of White Album.
|
||||
'';
|
||||
in ''
|
||||
import json
|
||||
import re
|
||||
|
||||
ats.wait_for_unit("trafficserver")
|
||||
ats.wait_for_open_port(80)
|
||||
httpbin.wait_for_unit("httpbin")
|
||||
httpbin.wait_for_open_port(80)
|
||||
|
||||
with subtest("Traffic Server is running"):
|
||||
out = ats.succeed("traffic_ctl server status")
|
||||
assert out.strip() == "Proxy -- on"
|
||||
|
||||
with subtest("traffic_crashlog is running"):
|
||||
ats.succeed("pgrep -f traffic_crashlog")
|
||||
|
||||
with subtest("basic remapping works"):
|
||||
out = client.succeed("curl -vv -H 'Host: httpbin.test' http://ats/headers")
|
||||
assert json.loads(out)["headers"]["Host"] == "httpbin"
|
||||
|
||||
with subtest("conf_remap plugin works"):
|
||||
out = client.succeed(
|
||||
"curl -vv -H 'Host: pristine-host-hdr.test' http://ats/headers"
|
||||
)
|
||||
assert json.loads(out)["headers"]["Host"] == "pristine-host-hdr.test"
|
||||
|
||||
with subtest("caching works"):
|
||||
out = client.succeed(
|
||||
"curl -vv -D - -H 'Host: httpbin.test' -H 'X-Debug: X-Cache' http://ats/cache/60 -o /dev/null"
|
||||
)
|
||||
assert "X-Cache: miss" in out
|
||||
|
||||
out = client.succeed(
|
||||
"curl -vv -D - -H 'Host: httpbin.test' -H 'X-Debug: X-Cache' http://ats/cache/60 -o /dev/null"
|
||||
)
|
||||
assert "X-Cache: hit-fresh" in out
|
||||
|
||||
with subtest("pushing to cache works"):
|
||||
url = "http://ats/tspush"
|
||||
|
||||
ats.succeed(f"echo {url} > /tmp/urls.txt")
|
||||
out = ats.succeed(
|
||||
f"tspush -f '${sampleFile}' -u {url}"
|
||||
)
|
||||
assert "HTTP/1.0 201 Created" in out, "cache push failed"
|
||||
|
||||
out = ats.succeed(
|
||||
"traffic_cache_tool --spans /etc/trafficserver/storage.config find --input /tmp/urls.txt"
|
||||
)
|
||||
assert "Span: /dev/vdb" in out, "cache not stored on disk"
|
||||
|
||||
out = client.succeed(f"curl {url}").strip()
|
||||
expected = (
|
||||
open("${sampleFile}").read().strip()
|
||||
)
|
||||
assert out == expected, "cache content mismatch"
|
||||
|
||||
with subtest("healthcheck plugin works"):
|
||||
out = client.succeed("curl -vv http://ats/status -o /dev/null -w '%{http_code}'")
|
||||
assert out.strip() == "500"
|
||||
|
||||
ats.succeed("touch /tmp/ats.status")
|
||||
|
||||
out = client.succeed("curl -vv http://ats/status -o /dev/null -w '%{http_code}'")
|
||||
assert out.strip() == "200"
|
||||
|
||||
with subtest("logging works"):
|
||||
access_log_path = "/var/log/trafficserver/squid.blog"
|
||||
ats.wait_for_file(access_log_path)
|
||||
|
||||
out = ats.succeed(f"traffic_logcat {access_log_path}").split("\n")[0]
|
||||
expected = "^\S+ \S+ \S+ TCP_MISS/200 \S+ GET http://httpbin/headers - DIRECT/httpbin application/json$"
|
||||
assert re.fullmatch(expected, out) is not None, "no matching logs"
|
||||
|
||||
out = json.loads(ats.succeed(f"traffic_logstats -jf {access_log_path}"))
|
||||
assert out["total"]["error.total"]["req"] == "0", "unexpected log stat"
|
||||
'';
|
||||
})
|
@ -61,13 +61,16 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
interfaces = [ "192.168.0.1" "fd21::1" "::1" "127.0.0.1" ];
|
||||
allowedAccess = [ "192.168.0.0/24" "fd21::/64" "::1" "127.0.0.0/8" ];
|
||||
extraConfig = ''
|
||||
server:
|
||||
local-data: "example.local. IN A 1.2.3.4"
|
||||
local-data: "example.local. IN AAAA abcd::eeff"
|
||||
'';
|
||||
settings = {
|
||||
server = {
|
||||
interface = [ "192.168.0.1" "fd21::1" "::1" "127.0.0.1" ];
|
||||
access-control = [ "192.168.0.0/24 allow" "fd21::/64 allow" "::1 allow" "127.0.0.0/8 allow" ];
|
||||
local-data = [
|
||||
''"example.local. IN A 1.2.3.4"''
|
||||
''"example.local. IN AAAA abcd::eeff"''
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@ -90,19 +93,25 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
allowedAccess = [ "192.168.0.0/24" "fd21::/64" "::1" "127.0.0.0/8" ];
|
||||
interfaces = [ "::1" "127.0.0.1" "192.168.0.2" "fd21::2"
|
||||
"192.168.0.2@853" "fd21::2@853" "::1@853" "127.0.0.1@853"
|
||||
"192.168.0.2@443" "fd21::2@443" "::1@443" "127.0.0.1@443" ];
|
||||
forwardAddresses = [
|
||||
(lib.head nodes.authoritative.config.networking.interfaces.eth1.ipv6.addresses).address
|
||||
(lib.head nodes.authoritative.config.networking.interfaces.eth1.ipv4.addresses).address
|
||||
];
|
||||
extraConfig = ''
|
||||
server:
|
||||
tls-service-pem: ${cert}/cert.pem
|
||||
tls-service-key: ${cert}/key.pem
|
||||
'';
|
||||
settings = {
|
||||
server = {
|
||||
interface = [ "::1" "127.0.0.1" "192.168.0.2" "fd21::2"
|
||||
"192.168.0.2@853" "fd21::2@853" "::1@853" "127.0.0.1@853"
|
||||
"192.168.0.2@443" "fd21::2@443" "::1@443" "127.0.0.1@443" ];
|
||||
access-control = [ "192.168.0.0/24 allow" "fd21::/64 allow" "::1 allow" "127.0.0.0/8 allow" ];
|
||||
tls-service-pem = "${cert}/cert.pem";
|
||||
tls-service-key = "${cert}/key.pem";
|
||||
};
|
||||
forward-zone = [
|
||||
{
|
||||
name = ".";
|
||||
forward-addr = [
|
||||
(lib.head nodes.authoritative.config.networking.interfaces.eth1.ipv6.addresses).address
|
||||
(lib.head nodes.authoritative.config.networking.interfaces.eth1.ipv4.addresses).address
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@ -122,12 +131,14 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
allowedAccess = [ "::1" "127.0.0.0/8" ];
|
||||
interfaces = [ "::1" "127.0.0.1" ];
|
||||
settings = {
|
||||
server = {
|
||||
interface = [ "::1" "127.0.0.1" ];
|
||||
access-control = [ "::1 allow" "127.0.0.0/8 allow" ];
|
||||
};
|
||||
include = "/etc/unbound/extra*.conf";
|
||||
};
|
||||
localControlSocketPath = "/run/unbound/unbound.ctl";
|
||||
extraConfig = ''
|
||||
include: "/etc/unbound/extra*.conf"
|
||||
'';
|
||||
};
|
||||
|
||||
users.users = {
|
||||
@ -143,12 +154,13 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||
unauthorizeduser = { isSystemUser = true; };
|
||||
};
|
||||
|
||||
# Used for testing configuration reloading
|
||||
environment.etc = {
|
||||
"unbound-extra1.conf".text = ''
|
||||
forward-zone:
|
||||
name: "example.local."
|
||||
forward-addr: ${(lib.head nodes.resolver.config.networking.interfaces.eth1.ipv6.addresses).address}
|
||||
forward-addr: ${(lib.head nodes.resolver.config.networking.interfaces.eth1.ipv4.addresses).address}
|
||||
name: "example.local."
|
||||
forward-addr: ${(lib.head nodes.resolver.config.networking.interfaces.eth1.ipv6.addresses).address}
|
||||
forward-addr: ${(lib.head nodes.resolver.config.networking.interfaces.eth1.ipv4.addresses).address}
|
||||
'';
|
||||
"unbound-extra2.conf".text = ''
|
||||
auth-zone:
|
||||
|
@ -1,4 +1,4 @@
|
||||
import ./make-test-python.nix ({ pkgs, ... }:
|
||||
import ./make-test-python.nix ({ pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
machine = { pkgs, ... }:
|
||||
@ -6,6 +6,8 @@ import ./make-test-python.nix ({ pkgs, ... }:
|
||||
services.zigbee2mqtt = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
systemd.services.zigbee2mqtt.serviceConfig.DevicePolicy = lib.mkForce "auto";
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
@ -14,6 +16,8 @@ import ./make-test-python.nix ({ pkgs, ... }:
|
||||
machine.succeed(
|
||||
"journalctl -eu zigbee2mqtt | grep \"Error: Error while opening serialport 'Error: Error: No such file or directory, cannot open /dev/ttyACM0'\""
|
||||
)
|
||||
|
||||
machine.log(machine.succeed("systemd-analyze security zigbee2mqtt.service"))
|
||||
'';
|
||||
}
|
||||
)
|
||||
|
63
pkgs/applications/audio/bucklespring/default.nix
Normal file
63
pkgs/applications/audio/bucklespring/default.nix
Normal file
@ -0,0 +1,63 @@
|
||||
{ lib
|
||||
, stdenv
|
||||
, fetchFromGitHub
|
||||
|
||||
, legacy ? false
|
||||
, libinput
|
||||
|
||||
, pkg-config
|
||||
, makeWrapper
|
||||
|
||||
, openal
|
||||
, alure
|
||||
, libXtst
|
||||
, libX11
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib) optionals;
|
||||
in
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "bucklespring";
|
||||
version = "1.5.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "zevv";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
sha256 = "114dib4npb7r1z2zd1fwsx71xbf9r6psxqd7n7590cwz1w3r51mz";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ pkg-config makeWrapper ];
|
||||
|
||||
buildInputs = [ openal alure ]
|
||||
++ optionals (legacy) [ libXtst libX11 ]
|
||||
++ optionals (!legacy) [ libinput ];
|
||||
|
||||
makeFlags = optionals (!legacy) [ "libinput=1" ];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/share/wav
|
||||
cp -r $src/wav $out/share/.
|
||||
install -D ./buckle.desktop $out/share/applications/buckle.desktop
|
||||
install -D ./buckle $out/bin/buckle
|
||||
wrapProgram $out/bin/buckle --add-flags "-p $out/share/wav"
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Nostalgia bucklespring keyboard sound";
|
||||
longDescription = ''
|
||||
When built with libinput (wayland or bare console),
|
||||
users need to be in the input group to use this:
|
||||
<code>users.users.alice.extraGroups = [ "input" ];</code>
|
||||
'';
|
||||
homepage = "https://github.com/zevv/bucklespring";
|
||||
license = licenses.gpl2Only;
|
||||
platforms = platforms.unix;
|
||||
maintainers = [ maintainers.evils ];
|
||||
};
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
, cmake
|
||||
, docbook_xml_dtd_45
|
||||
, docbook_xsl
|
||||
, ffmpeg_3
|
||||
, ffmpeg
|
||||
, flac
|
||||
, id3lib
|
||||
, libogg
|
||||
@ -31,21 +31,22 @@ stdenv.mkDerivation rec {
|
||||
version = "3.8.6";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://sourceforge/project/kid3/kid3/${version}/${pname}-${version}.tar.gz";
|
||||
sha256 = "sha256-ce+MWCJzAnN+u+07f0dvn0jnbqiUlS2RbcM9nAj5bgg=";
|
||||
url = "https://download.kde.org/stable/${pname}/${version}/${pname}-${version}.tar.xz";
|
||||
hash = "sha256-R4gAWlCw8RezhYbw1XDo+wdp797IbLoM3wqHwr+ul6k=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
docbook_xml_dtd_45
|
||||
docbook_xsl
|
||||
pkg-config
|
||||
python3
|
||||
wrapQtAppsHook
|
||||
];
|
||||
buildInputs = [
|
||||
automoc4
|
||||
chromaprint
|
||||
docbook_xml_dtd_45
|
||||
docbook_xsl
|
||||
ffmpeg_3
|
||||
ffmpeg
|
||||
flac
|
||||
id3lib
|
||||
libogg
|
||||
@ -53,7 +54,6 @@ stdenv.mkDerivation rec {
|
||||
libxslt
|
||||
mp4v2
|
||||
phonon
|
||||
python3
|
||||
qtbase
|
||||
qtmultimedia
|
||||
qtquickcontrols
|
||||
@ -71,6 +71,7 @@ stdenv.mkDerivation rec {
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://kid3.kde.org/";
|
||||
description = "A simple and powerful audio tag editor";
|
||||
longDescription = ''
|
||||
If you want to easily tag multiple MP3, Ogg/Vorbis, FLAC, MPC, MP4/AAC,
|
||||
@ -101,7 +102,6 @@ stdenv.mkDerivation rec {
|
||||
- Edit synchronized lyrics and event timing codes, import and export
|
||||
LRC files.
|
||||
'';
|
||||
homepage = "http://kid3.sourceforge.net/";
|
||||
license = licenses.lgpl2Plus;
|
||||
maintainers = [ maintainers.AndersonTorres ];
|
||||
platforms = platforms.linux;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,18 +4,17 @@
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "librespot";
|
||||
version = "0.1.3";
|
||||
version = "0.1.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "librespot-org";
|
||||
repo = "librespot";
|
||||
rev = "v${version}";
|
||||
sha256 = "1ixh47yvaamrpzagqsiimc3y6bi4nbym95843d23am55zkrgnmy5";
|
||||
sha256 = "153i9n3qwmmwc29f62cz8nbqrlry16iygvibm1sdnvpf0s6wk5f3";
|
||||
};
|
||||
|
||||
cargoSha256 = "1csls8kzzx28ng6w9vdwhnnav5sqp2m5fj430db5z306xh5acg3d";
|
||||
|
||||
cargoPatches = [ ./cargo-lock.patch ];
|
||||
cargoSha256 = "11d64rpq4b5rdxk5wx0hhzgc6mvs6h2br0w3kfncfklp67vn3v4v";
|
||||
|
||||
cargoBuildFlags = with lib; [
|
||||
"--no-default-features"
|
||||
|
@ -21,6 +21,8 @@ lib.makeScope newScope (self: with self; {
|
||||
|
||||
mopidy-musicbox-webclient = callPackage ./musicbox-webclient.nix { };
|
||||
|
||||
mopidy-podcast = callPackage ./podcast.nix { };
|
||||
|
||||
mopidy-scrobbler = callPackage ./scrobbler.nix { };
|
||||
|
||||
mopidy-somafm = callPackage ./somafm.nix { };
|
||||
|
31
pkgs/applications/audio/mopidy/podcast.nix
Normal file
31
pkgs/applications/audio/mopidy/podcast.nix
Normal file
@ -0,0 +1,31 @@
|
||||
{ lib, python3Packages, mopidy }:
|
||||
|
||||
python3Packages.buildPythonApplication rec {
|
||||
pname = "mopidy-podcast";
|
||||
version = "3.0.0";
|
||||
|
||||
src = python3Packages.fetchPypi {
|
||||
inherit version;
|
||||
pname = "Mopidy-Podcast";
|
||||
sha256 = "1z2b523yvdpcf8p7m7kczrvaw045lmxzhq4qj00dflxa2yw61qxr";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
mopidy
|
||||
python3Packages.cachetools
|
||||
python3Packages.uritools
|
||||
];
|
||||
|
||||
checkInputs = with python3Packages; [
|
||||
pytestCheckHook
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/tkem/mopidy-podcast";
|
||||
description = "Mopidy extension for browsing and playing podcasts";
|
||||
license = licenses.asl20;
|
||||
maintainers = [
|
||||
maintainers.daneads
|
||||
];
|
||||
};
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
, boost
|
||||
, curl
|
||||
, fetchFromGitHub
|
||||
, ffmpeg_3
|
||||
, ffmpeg
|
||||
, lame
|
||||
, libev
|
||||
, libmicrohttpd
|
||||
@ -17,13 +17,13 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "musikcube";
|
||||
version = "0.96.5";
|
||||
version = "0.96.7";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "clangen";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
sha256 = "sha256-GxMQPP8i/NWvduf10f+xVyuG666pChj9RsiF4jfygyY=";
|
||||
sha256 = "1y00vwn1h10cfflxrm5bk271ak9gilhjycgi44hlkkhmf5bdgn35";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
@ -34,7 +34,7 @@ stdenv.mkDerivation rec {
|
||||
alsaLib
|
||||
boost
|
||||
curl
|
||||
ffmpeg_3
|
||||
ffmpeg
|
||||
lame
|
||||
libev
|
||||
libmicrohttpd
|
||||
|
@ -11,17 +11,17 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "ocenaudio";
|
||||
version = "3.10.2";
|
||||
version = "3.10.6";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://www.ocenaudio.com/downloads/index.php/ocenaudio_debian9_64.deb?version=${version}";
|
||||
sha256 = "sha256-mmo6/zc/3R8ptXfY01RKUOLgmDhWTHiYBMlGqpdMTAo=";
|
||||
sha256 = "0fgvm1xw2kgrqj3w6slpfxbb3pw9k8i0dz16q9d5d8gyyvr2mh8g";
|
||||
};
|
||||
|
||||
|
||||
nativeBuildInputs = [
|
||||
autoPatchelfHook
|
||||
qt5.qtbase
|
||||
qt5.wrapQtAppsHook
|
||||
libjack2
|
||||
libpulseaudio
|
||||
bzip2
|
||||
@ -33,7 +33,6 @@ stdenv.mkDerivation rec {
|
||||
dontUnpack = true;
|
||||
dontBuild = true;
|
||||
dontStrip = true;
|
||||
dontWrapQtApps = true;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
|
@ -1,7 +1,7 @@
|
||||
{ lib, stdenv, fetchurl, python3, wrapGAppsHook, gettext, libsoup, gnome3, gtk3, gdk-pixbuf, librsvg,
|
||||
tag ? "", xvfb_run, dbus, glibcLocales, glib, glib-networking, gobject-introspection, hicolor-icon-theme,
|
||||
gst_all_1, withGstPlugins ? true,
|
||||
xineBackend ? false, xineLib,
|
||||
xineBackend ? false, xine-lib,
|
||||
withDbusPython ? false, withPyInotify ? false, withMusicBrainzNgs ? false, withPahoMqtt ? false,
|
||||
webkitgtk ? null,
|
||||
keybinder3 ? null, gtksourceview ? null, libmodplug ? null, kakasi ? null, libappindicator-gtk3 ? null }:
|
||||
@ -23,7 +23,7 @@ python3.pkgs.buildPythonApplication rec {
|
||||
checkInputs = [ gdk-pixbuf hicolor-icon-theme ] ++ (with python3.pkgs; [ pytest pytest_xdist polib xvfb_run dbus.daemon glibcLocales ]);
|
||||
|
||||
buildInputs = [ gnome3.adwaita-icon-theme libsoup glib glib-networking gtk3 webkitgtk gdk-pixbuf keybinder3 gtksourceview libmodplug libappindicator-gtk3 kakasi gobject-introspection ]
|
||||
++ (if xineBackend then [ xineLib ] else with gst_all_1;
|
||||
++ (if xineBackend then [ xine-lib ] else with gst_all_1;
|
||||
[ gstreamer gst-plugins-base ] ++ optionals withGstPlugins [ gst-plugins-good gst-plugins-ugly gst-plugins-bad ]);
|
||||
|
||||
propagatedBuildInputs = with python3.pkgs; [ pygobject3 pycairo mutagen gst-python feedparser ]
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
with lib;
|
||||
let
|
||||
version = "0.21.0";
|
||||
version = "0.21.1";
|
||||
majorMinorVersion = versions.majorMinor version;
|
||||
desktop = fetchurl {
|
||||
url = "https://raw.githubusercontent.com/bitcoin-core/packaging/${majorMinorVersion}/debian/bitcoin-qt.desktop";
|
||||
@ -38,7 +38,7 @@ stdenv.mkDerivation rec {
|
||||
"https://bitcoincore.org/bin/bitcoin-core-${version}/bitcoin-${version}.tar.gz"
|
||||
"https://bitcoin.org/bin/bitcoin-core-${version}/bitcoin-${version}.tar.gz"
|
||||
];
|
||||
sha256 = "1a91202c62ee49fb64d57a52b8d6d01cd392fffcbef257b573800f9289655f37";
|
||||
sha256 = "caff23449220cf45753f312cefede53a9eac64000bb300797916526236b6a1e0";
|
||||
};
|
||||
|
||||
nativeBuildInputs =
|
||||
|
29
pkgs/applications/blockchains/miniscript/default.nix
Normal file
29
pkgs/applications/blockchains/miniscript/default.nix
Normal file
@ -0,0 +1,29 @@
|
||||
{ stdenv, lib, fetchFromGitHub }:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "miniscript";
|
||||
version = "unstable-2020-12-01";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "sipa";
|
||||
repo = pname;
|
||||
rev = "02682a398a35b410571b10cde7f39837141ddad6";
|
||||
sha256 = "079jz4g88cfzfm9a6ykby9haxwcs033c1288mgr8cl2hw4qd2sjl";
|
||||
};
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out/bin
|
||||
cp miniscript $out/bin/miniscript
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "Compiler and inspector for the miniscript Bitcoin policy language";
|
||||
longDescription = "Miniscript is a language for writing (a subset of) Bitcoin Scripts in a structured way, enabling analysis, composition, generic signing and more.";
|
||||
homepage = "http://bitcoin.sipa.be/miniscript/";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.linux;
|
||||
maintainers = with maintainers; [ RaghavSood jb55 ];
|
||||
};
|
||||
}
|
@ -17,22 +17,15 @@
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
arch = if stdenv.isx86_64 then "x86-64"
|
||||
else if stdenv.isi686 then "i686"
|
||||
else if stdenv.isAarch64 then "armv8-a"
|
||||
else throw "unsupported architecture";
|
||||
in
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "monero-gui";
|
||||
version = "0.17.1.9";
|
||||
version = "0.17.2.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "monero-project";
|
||||
repo = "monero-gui";
|
||||
rev = "v${version}";
|
||||
sha256 = "0143mmxk0jfb5pmjlx6v0knvf8v49kmkpjxlp6rw8lwnlf71xadn";
|
||||
sha256 = "1apjvpvn6hg0k0ak6wpg4prcdcslnb6fqhzzg2p4iy846f0ai9ji";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
@ -58,7 +51,10 @@ stdenv.mkDerivation rec {
|
||||
chmod -R +w source/monero
|
||||
'';
|
||||
|
||||
patches = [ ./move-log-file.patch ];
|
||||
patches = [
|
||||
./move-log-file.patch
|
||||
./use-system-libquirc.patch
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
# set monero-gui version
|
||||
@ -69,17 +65,15 @@ stdenv.mkDerivation rec {
|
||||
substituteInPlace src/daemon/DaemonManager.cpp \
|
||||
--replace 'QApplication::applicationDirPath() + "' '"${monero}/bin'
|
||||
|
||||
# only build external deps, *not* the full monero
|
||||
# 1: only build external deps, *not* the full monero
|
||||
# 2: use nixpkgs libraries
|
||||
substituteInPlace CMakeLists.txt \
|
||||
--replace 'add_subdirectory(monero)' \
|
||||
'add_subdirectory(monero EXCLUDE_FROM_ALL)'
|
||||
|
||||
# use nixpkgs quirc
|
||||
substituteInPlace CMakeLists.txt \
|
||||
'add_subdirectory(monero EXCLUDE_FROM_ALL)' \
|
||||
--replace 'add_subdirectory(external)' ""
|
||||
'';
|
||||
|
||||
cmakeFlags = [ "-DARCH=${arch}" ];
|
||||
cmakeFlags = [ "-DARCH=default" ];
|
||||
|
||||
desktopItem = makeDesktopItem {
|
||||
name = "monero-wallet-gui";
|
||||
|
@ -0,0 +1,37 @@
|
||||
diff --git a/src/QR-Code-scanner/CMakeLists.txt b/src/QR-Code-scanner/CMakeLists.txt
|
||||
index 15e288df..2e9b3305 100644
|
||||
--- a/src/QR-Code-scanner/CMakeLists.txt
|
||||
+++ b/src/QR-Code-scanner/CMakeLists.txt
|
||||
@@ -1,11 +1,18 @@
|
||||
+find_library(QUIRC_LIBRARY quirc REQUIRED)
|
||||
+find_path(QUIRC_INCLUDE_DIR quirc.h REQUIRED)
|
||||
+
|
||||
add_library(qrdecoder STATIC
|
||||
Decoder.cpp
|
||||
)
|
||||
+target_include_directories(qrdecoder
|
||||
+ PUBLIC
|
||||
+ ${QUIRC_INCLUDE_DIR}
|
||||
+)
|
||||
target_link_libraries(qrdecoder
|
||||
PUBLIC
|
||||
Qt5::Gui
|
||||
PRIVATE
|
||||
- quirc
|
||||
+ ${QUIRC_LIBRARY}
|
||||
)
|
||||
|
||||
if(WITH_SCANNER)
|
||||
diff --git a/src/QR-Code-scanner/Decoder.cpp b/src/QR-Code-scanner/Decoder.cpp
|
||||
index 1bb99140..353ca189 100644
|
||||
--- a/src/QR-Code-scanner/Decoder.cpp
|
||||
+++ b/src/QR-Code-scanner/Decoder.cpp
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
-#include "quirc.h"
|
||||
+#include <quirc.h>
|
||||
|
||||
QrDecoder::QrDecoder()
|
||||
: m_qr(quirc_new())
|
@ -17,13 +17,13 @@ assert trezorSupport -> all (x: x!=null) [ libusb1 protobuf python3 ];
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "monero";
|
||||
version = "0.17.1.9";
|
||||
version = "0.17.2.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "monero-project";
|
||||
repo = "monero";
|
||||
rev = "v${version}";
|
||||
sha256 = "0jqss4csvkcrhrmaa3vrnyv6yiwqpbfw7037clx9xcfm4qrrfiwy";
|
||||
sha256 = "0jwlmrpzisvw1c06cvd5b3s3hd4w0pa1qmrypfwah67qj3x6hnb6";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "bluej";
|
||||
version = "5.0.0";
|
||||
version = "5.0.1";
|
||||
src = fetchurl {
|
||||
# We use the deb here. First instinct might be to go for the "generic" JAR
|
||||
# download, but that is actually a graphical installer that is much harder
|
||||
# to unpack than the deb.
|
||||
url = "https://www.bluej.org/download/files/BlueJ-linux-${builtins.replaceStrings ["."] [""] version}.deb";
|
||||
sha256 = "sha256-U81FIf67Qm/86+hA9iUCHt61dxiZsTkkequlVjft6/0=";
|
||||
sha256 = "sha256-KhNhJ2xsw1g2yemwP6NQmJvk4cxZAQQNPEUBuLso5qM=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
|
@ -4,8 +4,8 @@ let
|
||||
src = pkgs.fetchgit {
|
||||
url = "https://github.com/ttuegel/emacs2nix.git";
|
||||
fetchSubmodules = true;
|
||||
rev = "b815a9323c1f58f6c163a1f968939c57a8b6cfa0";
|
||||
sha256 = "183xlmhjmj4z2zssc0pw990h7bf3bam8zqswnf1zcsyp8z7yrl5g";
|
||||
rev = "860da04ca91cbb69c9b881a54248d16bdaaf9923";
|
||||
sha256 = "1r3xmyk9rfgx7ln69dk8mgbnh3awcalm3r1c5ia2shlsrymvv1df";
|
||||
};
|
||||
|
||||
in pkgs.mkShell {
|
||||
|
@ -362,6 +362,7 @@ let
|
||||
zmq = super.zmq.overrideAttrs (old: {
|
||||
stripDebugList = [ "share" ];
|
||||
preBuild = ''
|
||||
export EZMQ_LIBDIR=$(mktemp -d)
|
||||
make
|
||||
'';
|
||||
nativeBuildInputs = [
|
||||
@ -372,7 +373,7 @@ let
|
||||
(pkgs.zeromq.override { enableDrafts = true; })
|
||||
];
|
||||
postInstall = ''
|
||||
mv $out/share/emacs/site-lisp/elpa/zmq-*/src/.libs/emacs-zmq.so $out/share/emacs/site-lisp/elpa/zmq-*
|
||||
mv $EZMQ_LIBDIR/emacs-zmq.* $out/share/emacs/site-lisp/elpa/zmq-*
|
||||
rm -r $out/share/emacs/site-lisp/elpa/zmq-*/src
|
||||
rm $out/share/emacs/site-lisp/elpa/zmq-*/Makefile
|
||||
'';
|
||||
|
@ -99,7 +99,10 @@ return Promise to resolve in that process."
|
||||
("github" (list "nix-prefetch-url"
|
||||
"--unpack" (concat "https://github.com/" repo "/archive/" commit ".tar.gz")))
|
||||
("gitlab" (list "nix-prefetch-url"
|
||||
"--unpack" (concat "https://gitlab.com/" repo "/repository/archive.tar.gz?ref=" commit)))
|
||||
"--unpack" (concat "https://gitlab.com/api/v4/projects/"
|
||||
(url-hexify-string repo)
|
||||
"/repository/archive.tar.gz?ref="
|
||||
commit)))
|
||||
("bitbucket" (list "nix-prefetch-hg"
|
||||
(concat "https://bitbucket.com/" repo) commit))
|
||||
("hg" (list "nix-prefetch-hg"
|
||||
|
@ -242,12 +242,12 @@ in
|
||||
|
||||
clion = buildClion rec {
|
||||
name = "clion-${version}";
|
||||
version = "2021.1"; /* updated by script */
|
||||
version = "2021.1.1"; /* updated by script */
|
||||
description = "C/C++ IDE. New. Intelligent. Cross-platform";
|
||||
license = lib.licenses.unfree;
|
||||
src = fetchurl {
|
||||
url = "https://download.jetbrains.com/cpp/CLion-${version}.tar.gz";
|
||||
sha256 = "1qq2k14pf2qy93y1xchlv08vvx99zcml8bdcx3h6jnjz6d7gz0px"; /* updated by script */
|
||||
sha256 = "0xzlkf3gq6fcb0q9mcj8k39880l8h21pb1lz0xl2dqj8cfwpws9h"; /* updated by script */
|
||||
};
|
||||
wmClass = "jetbrains-clion";
|
||||
update-channel = "CLion RELEASE"; # channel's id as in http://www.jetbrains.com/updates/updates.xml
|
||||
@ -255,12 +255,12 @@ in
|
||||
|
||||
datagrip = buildDataGrip rec {
|
||||
name = "datagrip-${version}";
|
||||
version = "2021.1"; /* updated by script */
|
||||
version = "2021.1.1"; /* updated by script */
|
||||
description = "Your Swiss Army Knife for Databases and SQL";
|
||||
license = lib.licenses.unfree;
|
||||
src = fetchurl {
|
||||
url = "https://download.jetbrains.com/datagrip/${name}.tar.gz";
|
||||
sha256 = "11am11lkrhgfianr1apkkl4mn8gcsf6p1vz47y7lz4rfm05ac4gj"; /* updated by script */
|
||||
sha256 = "0smg0qbk3mnm2543w0nlvnyvbwmprf0p3z2spwrmcmfagv50crrx"; /* updated by script */
|
||||
};
|
||||
wmClass = "jetbrains-datagrip";
|
||||
update-channel = "DataGrip RELEASE";
|
||||
@ -268,12 +268,12 @@ in
|
||||
|
||||
goland = buildGoland rec {
|
||||
name = "goland-${version}";
|
||||
version = "2021.1"; /* updated by script */
|
||||
version = "2021.1.1"; /* updated by script */
|
||||
description = "Up and Coming Go IDE";
|
||||
license = lib.licenses.unfree;
|
||||
src = fetchurl {
|
||||
url = "https://download.jetbrains.com/go/${name}.tar.gz";
|
||||
sha256 = "1hxid7k5b26hiwwdxbvhi1fzhlrvm1xsd5gb0vj0g5zw658y2lzz"; /* updated by script */
|
||||
sha256 = "02fyrq4px9w34amincgjgm6maxpxn445j5h4nfbskx7z428ynx25"; /* updated by script */
|
||||
};
|
||||
wmClass = "jetbrains-goland";
|
||||
update-channel = "GoLand RELEASE";
|
||||
@ -281,12 +281,12 @@ in
|
||||
|
||||
idea-community = buildIdea rec {
|
||||
name = "idea-community-${version}";
|
||||
version = "2021.1"; /* updated by script */
|
||||
version = "2021.1.1"; /* updated by script */
|
||||
description = "Integrated Development Environment (IDE) by Jetbrains, community edition";
|
||||
license = lib.licenses.asl20;
|
||||
src = fetchurl {
|
||||
url = "https://download.jetbrains.com/idea/ideaIC-${version}.tar.gz";
|
||||
sha256 = "1d7m39rzdgh2fyx50rpifqfsdmvfpi04hjp52pl76m35gyb5hsvs"; /* updated by script */
|
||||
sha256 = "1say19p7kgx4b2ccs9bv61phllzhl8gmrd1fp1a5cnagya7vl1c5"; /* updated by script */
|
||||
};
|
||||
wmClass = "jetbrains-idea-ce";
|
||||
update-channel = "IntelliJ IDEA RELEASE";
|
||||
@ -294,12 +294,12 @@ in
|
||||
|
||||
idea-ultimate = buildIdea rec {
|
||||
name = "idea-ultimate-${version}";
|
||||
version = "2021.1"; /* updated by script */
|
||||
version = "2021.1.1"; /* updated by script */
|
||||
description = "Integrated Development Environment (IDE) by Jetbrains, requires paid license";
|
||||
license = lib.licenses.unfree;
|
||||
src = fetchurl {
|
||||
url = "https://download.jetbrains.com/idea/ideaIU-${version}-no-jbr.tar.gz";
|
||||
sha256 = "062kaph42xs5hc01sbmry4cm7nkyjks43qr5m7pbj5a2bgd7zzgx"; /* updated by script */
|
||||
sha256 = "19zi4njz79z8gi458kz1m0sia79y3rhbayix4rmh93mwfc0npkii"; /* updated by script */
|
||||
};
|
||||
wmClass = "jetbrains-idea";
|
||||
update-channel = "IntelliJ IDEA RELEASE";
|
||||
@ -320,12 +320,12 @@ in
|
||||
|
||||
phpstorm = buildPhpStorm rec {
|
||||
name = "phpstorm-${version}";
|
||||
version = "2021.1"; /* updated by script */
|
||||
version = "2021.1.2"; /* updated by script */
|
||||
description = "Professional IDE for Web and PHP developers";
|
||||
license = lib.licenses.unfree;
|
||||
src = fetchurl {
|
||||
url = "https://download.jetbrains.com/webide/PhpStorm-${version}.tar.gz";
|
||||
sha256 = "052m7mqa1s548my0gda9y2mysi2ijq27c9b3bskrwqsf1pm5ry63"; /* updated by script */
|
||||
sha256 = "02s75fqd9hfh302zha4jw6qynpgm9nkrlq7s78nk3fc3d3hw8v5y"; /* updated by script */
|
||||
};
|
||||
wmClass = "jetbrains-phpstorm";
|
||||
update-channel = "PhpStorm RELEASE";
|
||||
@ -333,12 +333,12 @@ in
|
||||
|
||||
pycharm-community = buildPycharm rec {
|
||||
name = "pycharm-community-${version}";
|
||||
version = "2021.1"; /* updated by script */
|
||||
version = "2021.1.1"; /* updated by script */
|
||||
description = "PyCharm Community Edition";
|
||||
license = lib.licenses.asl20;
|
||||
src = fetchurl {
|
||||
url = "https://download.jetbrains.com/python/${name}.tar.gz";
|
||||
sha256 = "1iiglh7s2zm37kj6hzlzxb1jnzh2p0j1f2zzhg3nqyrrakfbyq3h"; /* updated by script */
|
||||
sha256 = "04bs9sz872b0h1zzax23irvj6q5wxnzp6fl4f177j94kh4116cqh"; /* updated by script */
|
||||
};
|
||||
wmClass = "jetbrains-pycharm-ce";
|
||||
update-channel = "PyCharm RELEASE";
|
||||
@ -346,12 +346,12 @@ in
|
||||
|
||||
pycharm-professional = buildPycharm rec {
|
||||
name = "pycharm-professional-${version}";
|
||||
version = "2021.1"; /* updated by script */
|
||||
version = "2021.1.1"; /* updated by script */
|
||||
description = "PyCharm Professional Edition";
|
||||
license = lib.licenses.unfree;
|
||||
src = fetchurl {
|
||||
url = "https://download.jetbrains.com/python/${name}.tar.gz";
|
||||
sha256 = "1n3b4mdygzal7w88gwka5wh5jp09bh2zmm4n5rz9s7hr2srz71mz"; /* updated by script */
|
||||
sha256 = "0wc9j7nilakmm7scf7a71zb3k9vixgih05ni3n3pp4iznvwb3nxg"; /* updated by script */
|
||||
};
|
||||
wmClass = "jetbrains-pycharm";
|
||||
update-channel = "PyCharm RELEASE";
|
||||
@ -359,12 +359,12 @@ in
|
||||
|
||||
rider = buildRider rec {
|
||||
name = "rider-${version}";
|
||||
version = "2021.1.1"; /* updated by script */
|
||||
version = "2021.1.2"; /* updated by script */
|
||||
description = "A cross-platform .NET IDE based on the IntelliJ platform and ReSharper";
|
||||
license = lib.licenses.unfree;
|
||||
src = fetchurl {
|
||||
url = "https://download.jetbrains.com/rider/JetBrains.Rider-${version}.tar.gz";
|
||||
sha256 = "00kdbsjw9hmq7x94pjscslv0b412g8l0jbvyi7jiyay8xc6wiaaj"; /* updated by script */
|
||||
sha256 = "1a28pi18j0cb2wxhw1vnfg9gqsgf2kyfg0hl4xgqp50gzv7i3aam"; /* updated by script */
|
||||
};
|
||||
wmClass = "jetbrains-rider";
|
||||
update-channel = "Rider RELEASE";
|
||||
@ -372,12 +372,12 @@ in
|
||||
|
||||
ruby-mine = buildRubyMine rec {
|
||||
name = "ruby-mine-${version}";
|
||||
version = "2021.1"; /* updated by script */
|
||||
version = "2021.1.1"; /* updated by script */
|
||||
description = "The Most Intelligent Ruby and Rails IDE";
|
||||
license = lib.licenses.unfree;
|
||||
src = fetchurl {
|
||||
url = "https://download.jetbrains.com/ruby/RubyMine-${version}.tar.gz";
|
||||
sha256 = "12mkb51x1w5wbx436pfnfzcad10qd53y43n0p4l2zg9yx985gm7v"; /* updated by script */
|
||||
sha256 = "05sfjf5523idsl7byc7400r4xqv1d65gpmkh5x0lbgf1k3bx2wlm"; /* updated by script */
|
||||
};
|
||||
wmClass = "jetbrains-rubymine";
|
||||
update-channel = "RubyMine RELEASE";
|
||||
@ -385,12 +385,12 @@ in
|
||||
|
||||
webstorm = buildWebStorm rec {
|
||||
name = "webstorm-${version}";
|
||||
version = "2021.1"; /* updated by script */
|
||||
version = "2021.1.1"; /* updated by script */
|
||||
description = "Professional IDE for Web and JavaScript development";
|
||||
license = lib.licenses.unfree;
|
||||
src = fetchurl {
|
||||
url = "https://download.jetbrains.com/webstorm/WebStorm-${version}.tar.gz";
|
||||
sha256 = "15i521qj2b0y1viqr0xx815ckpq359j6nars4xxq8xvy7cg729yc"; /* updated by script */
|
||||
sha256 = "1hici40qsxj2fw29g68i6hr1vhr0h7xrlhkialy74ah53wi7myz1"; /* updated by script */
|
||||
};
|
||||
wmClass = "jetbrains-webstorm";
|
||||
update-channel = "WebStorm RELEASE";
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
# now defaults to false because some tests can be flaky (clipboard etc)
|
||||
, doCheck ? false
|
||||
, nodejs ? null, fish ? null, python ? null
|
||||
, nodejs ? null, fish ? null, python3 ? null
|
||||
}:
|
||||
|
||||
with lib;
|
||||
@ -19,7 +19,7 @@ let
|
||||
]
|
||||
));
|
||||
|
||||
pyEnv = python.withPackages(ps: [ ps.pynvim ps.msgpack ]);
|
||||
pyEnv = python3.withPackages(ps: with ps; [ pynvim msgpack ]);
|
||||
|
||||
# FIXME: this is verry messy and strange.
|
||||
# see https://github.com/NixOS/nixpkgs/pull/80528
|
||||
|
@ -1,5 +1,5 @@
|
||||
{ lib, mkDerivation, fetchFromGitHub, cmake, doxygen, makeWrapper
|
||||
, msgpack, neovim, pythonPackages, qtbase }:
|
||||
, msgpack, neovim, python3Packages, qtbase }:
|
||||
|
||||
mkDerivation rec {
|
||||
pname = "neovim-qt-unwrapped";
|
||||
@ -20,7 +20,7 @@ mkDerivation rec {
|
||||
buildInputs = [
|
||||
neovim.unwrapped # only used to generate help tags at build time
|
||||
qtbase
|
||||
] ++ (with pythonPackages; [
|
||||
] ++ (with python3Packages; [
|
||||
jinja2 python msgpack
|
||||
]);
|
||||
|
||||
|
@ -1,11 +1,14 @@
|
||||
{ lib, fetchFromGitHub, pythonPackages }:
|
||||
{ lib
|
||||
, fetchFromGitHub
|
||||
, python3
|
||||
, neovim
|
||||
}:
|
||||
|
||||
with lib;
|
||||
|
||||
pythonPackages.buildPythonApplication rec {
|
||||
with python3.pkgs; buildPythonApplication rec {
|
||||
pname = "neovim-remote";
|
||||
version = "2.4.0";
|
||||
disabled = !pythonPackages.isPy3k;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "mhinz";
|
||||
@ -14,12 +17,24 @@ pythonPackages.buildPythonApplication rec {
|
||||
sha256 = "0jlw0qksak4bdzddpsj74pm2f2bgpj3cwrlspdjjy0j9qzg0mpl9";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with pythonPackages; [
|
||||
propagatedBuildInputs = [
|
||||
pynvim
|
||||
psutil
|
||||
setuptools
|
||||
];
|
||||
|
||||
checkInputs = [
|
||||
neovim
|
||||
pytestCheckHook
|
||||
];
|
||||
|
||||
disabledTests = [
|
||||
# these tests get stuck and never return
|
||||
"test_escape_filenames_properly"
|
||||
"test_escape_single_quotes_in_filenames"
|
||||
"test_escape_double_quotes_in_filenames"
|
||||
];
|
||||
|
||||
meta = {
|
||||
description = "A tool that helps controlling nvim processes from a terminal";
|
||||
homepage = "https://github.com/mhinz/neovim-remote/";
|
||||
|
@ -1,5 +1,4 @@
|
||||
{ lib, stdenv, mkDerivation, fetchFromGitHub, cmake, doxygen, makeWrapper
|
||||
, msgpack, neovim, pythonPackages, qtbase, neovim-qt-unwrapped }:
|
||||
{ stdenv, makeWrapper, neovim, neovim-qt-unwrapped }:
|
||||
|
||||
let
|
||||
unwrapped = neovim-qt-unwrapped;
|
||||
|
@ -4,7 +4,6 @@
|
||||
, neovim-unwrapped
|
||||
, bundlerEnv
|
||||
, ruby
|
||||
, pythonPackages
|
||||
, python3Packages
|
||||
, writeText
|
||||
, wrapNeovimUnstable
|
||||
@ -48,12 +47,6 @@ let
|
||||
requiredPlugins = vimUtils.requiredPlugins configure;
|
||||
getDeps = attrname: map (plugin: plugin.${attrname} or (_: [ ]));
|
||||
|
||||
pluginPython2Packages = getDeps "pythonDependencies" requiredPlugins;
|
||||
python2Env = pythonPackages.python.withPackages (ps:
|
||||
[ ps.pynvim ]
|
||||
++ (extraPython2Packages ps)
|
||||
++ (lib.concatMap (f: f ps) pluginPython2Packages));
|
||||
|
||||
pluginPython3Packages = getDeps "python3Dependencies" requiredPlugins;
|
||||
python3Env = python3Packages.python.withPackages (ps:
|
||||
[ ps.pynvim ]
|
||||
@ -69,7 +62,6 @@ let
|
||||
# While the latter tells nvim that this provider is not available
|
||||
hostprog_check_table = {
|
||||
node = withNodeJs;
|
||||
python = withPython2;
|
||||
python3 = withPython3;
|
||||
ruby = withRuby;
|
||||
};
|
||||
@ -99,11 +91,12 @@ let
|
||||
manifestRc = vimUtils.vimrcContent (configure // { customRC = ""; });
|
||||
neovimRcContent = vimUtils.vimrcContent configure;
|
||||
in
|
||||
assert withPython2 -> throw "Python2 support has been removed from neovim, please remove withPython2 and extraPython2Packages.";
|
||||
|
||||
args // {
|
||||
wrapperArgs = makeWrapperArgs;
|
||||
inherit neovimRcContent;
|
||||
inherit manifestRc;
|
||||
inherit python2Env;
|
||||
inherit python3Env;
|
||||
inherit withNodeJs;
|
||||
} // lib.optionalAttrs withRuby {
|
||||
@ -120,7 +113,7 @@ let
|
||||
# to keep backwards compatibility
|
||||
legacyWrapper = neovim: {
|
||||
extraMakeWrapperArgs ? ""
|
||||
, withPython ? true
|
||||
, withPython ? false
|
||||
/* the function you would have passed to python.withPackages */
|
||||
, extraPythonPackages ? (_: [])
|
||||
/* the function you would have passed to python.withPackages */
|
||||
@ -138,14 +131,14 @@ let
|
||||
else funOrList);
|
||||
|
||||
res = makeNeovimConfig {
|
||||
withPython2 = withPython;
|
||||
extraPythonPackages = compatFun extraPythonPackages;
|
||||
inherit withPython3;
|
||||
extraPython3Packages = compatFun extraPython3Packages;
|
||||
inherit withNodeJs withRuby viAlias vimAlias;
|
||||
inherit configure;
|
||||
};
|
||||
in
|
||||
assert withPython -> throw "Python2 support has been removed from neovim, please remove withPython and extraPythonPackages.";
|
||||
|
||||
wrapNeovimUnstable neovim (res // {
|
||||
wrapperArgs = lib.escapeShellArgs (
|
||||
res.wrapperArgs ++ lib.optionals (configure != {}) [
|
||||
|
@ -3,7 +3,6 @@
|
||||
, bundlerEnv, ruby
|
||||
, nodejs
|
||||
, nodePackages
|
||||
, pythonPackages
|
||||
, python3Packages
|
||||
}:
|
||||
with lib;
|
||||
@ -15,7 +14,7 @@ let
|
||||
# should contain all args but the binary
|
||||
wrapperArgs ? ""
|
||||
, manifestRc ? null
|
||||
, withPython2 ? true, python2Env ? null
|
||||
, withPython2 ? false
|
||||
, withPython3 ? true, python3Env ? null
|
||||
, withNodeJs ? false
|
||||
, rubyEnv ? null
|
||||
@ -35,6 +34,8 @@ let
|
||||
[ "${neovim}/bin/nvim" "${placeholder "out"}/bin/nvim" ] ++
|
||||
[ "--set" "NVIM_SYSTEM_RPLUGIN_MANIFEST" "${placeholder "out"}/rplugin.vim" ];
|
||||
in
|
||||
assert withPython2 -> throw "Python2 support has been removed from the neovim wrapper, please remove withPython2 and python2Env.";
|
||||
|
||||
symlinkJoin {
|
||||
name = "neovim-${lib.getVersion neovim}";
|
||||
# Remove the symlinks created by symlinkJoin which we need to perform
|
||||
@ -44,9 +45,6 @@ let
|
||||
substitute ${neovim}/share/applications/nvim.desktop $out/share/applications/nvim.desktop \
|
||||
--replace 'Name=Neovim' 'Name=WrappedNeovim'
|
||||
''
|
||||
+ optionalString withPython2 ''
|
||||
makeWrapper ${python2Env}/bin/python $out/bin/nvim-python --unset PYTHONPATH
|
||||
''
|
||||
+ optionalString withPython3 ''
|
||||
makeWrapper ${python3Env}/bin/python3 $out/bin/nvim-python3 --unset PYTHONPATH
|
||||
''
|
||||
|
@ -4,13 +4,13 @@ with python3.pkgs;
|
||||
|
||||
buildPythonApplication rec {
|
||||
pname = "thonny";
|
||||
version = "3.3.2";
|
||||
version = "3.3.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = pname;
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "1pzy7v48x4ip8v6aqm8hl5ywx7xiqbsfypxxifih8gnlangp1n8y";
|
||||
sha256 = "0ga0pqvq3nglr4jgh8ajv0bv8c7q09h1jh6q6r5cwqa49fawkr02";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with python3.pkgs; [
|
||||
|
@ -1,7 +1,8 @@
|
||||
{ stdenv, lib, makeDesktopItem
|
||||
, unzip, libsecret, libXScrnSaver, libxshmfence, wrapGAppsHook
|
||||
, gtk2, atomEnv, at-spi2-atk, autoPatchelfHook
|
||||
, systemd, fontconfig, libdbusmenu
|
||||
, systemd, fontconfig, libdbusmenu, buildFHSUserEnvBubblewrap
|
||||
, writeShellScriptBin
|
||||
|
||||
# Populate passthru.tests
|
||||
, tests
|
||||
@ -13,13 +14,14 @@
|
||||
|
||||
let
|
||||
inherit (stdenv.hostPlatform) system;
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
unwrapped = stdenv.mkDerivation {
|
||||
|
||||
inherit pname version src sourceRoot;
|
||||
|
||||
passthru = {
|
||||
inherit executableName tests;
|
||||
fhs = fhs {};
|
||||
fhsWithPackages = f: fhs { additionalPkgs = f; };
|
||||
};
|
||||
|
||||
desktopItem = makeDesktopItem {
|
||||
@ -97,4 +99,64 @@ in
|
||||
'';
|
||||
|
||||
inherit meta;
|
||||
}
|
||||
};
|
||||
|
||||
# Vscode and variants allow for users to download and use extensions
|
||||
# which often include the usage of pre-built binaries.
|
||||
# This has been an on-going painpoint for many users, as
|
||||
# a full extension update cycle has to be done through nixpkgs
|
||||
# in order to create or update extensions.
|
||||
# See: #83288 #91179 #73810 #41189
|
||||
#
|
||||
# buildFHSUserEnv allows for users to use the existing vscode
|
||||
# extension tooling without significant pain.
|
||||
fhs = { additionalPkgs ? pkgs: [] }: buildFHSUserEnvBubblewrap {
|
||||
# also determines the name of the wrapped command
|
||||
name = executableName;
|
||||
|
||||
# additional libraries which are commonly needed for extensions
|
||||
targetPkgs = pkgs: (with pkgs; [
|
||||
# ld-linux-x86-64-linux.so.2 and others
|
||||
glibc
|
||||
|
||||
# dotnet
|
||||
curl
|
||||
icu
|
||||
libunwind
|
||||
libuuid
|
||||
openssl
|
||||
zlib
|
||||
|
||||
# mono
|
||||
krb5
|
||||
]) ++ additionalPkgs pkgs;
|
||||
|
||||
# restore desktop item icons
|
||||
extraInstallCommands = ''
|
||||
mkdir -p $out/share/applications
|
||||
for item in ${unwrapped}/share/applications/*.desktop; do
|
||||
ln -s $item $out/share/applications/
|
||||
done
|
||||
'';
|
||||
|
||||
runScript = "${unwrapped}/bin/${executableName}";
|
||||
|
||||
# vscode likes to kill the parent so that the
|
||||
# gui application isn't attached to the terminal session
|
||||
dieWithParent = false;
|
||||
|
||||
passthru = {
|
||||
inherit executableName;
|
||||
inherit (unwrapped) pname version; # for home-manager module
|
||||
};
|
||||
|
||||
meta = meta // {
|
||||
description = ''
|
||||
Wrapped variant of ${pname} which launches in a FHS compatible envrionment.
|
||||
Should allow for easy usage of extensions without nix-specific modifications.
|
||||
'';
|
||||
};
|
||||
};
|
||||
in
|
||||
unwrapped
|
||||
|
||||
|
@ -18,13 +18,13 @@ mkDerivation rec {
|
||||
|
||||
cmakeFlags = [
|
||||
"-DROUTINO_XML_PATH=${routino}/share/routino"
|
||||
"-DQUAZIP_INCLUDE_DIR=${quazip}/include/quazip5"
|
||||
"-DLIBQUAZIP_LIBRARY=${quazip}/lib/libquazip.so"
|
||||
];
|
||||
|
||||
patches = [
|
||||
"${src}/FindPROJ4.patch"
|
||||
"${src}/FindQuaZip5.patch"
|
||||
|
||||
# Support QuaZip 1.x.
|
||||
./pr350-support-quazip-1x.patch
|
||||
];
|
||||
|
||||
qtWrapperArgs = [
|
||||
|
141
pkgs/applications/gis/qmapshack/pr350-support-quazip-1x.patch
Normal file
141
pkgs/applications/gis/qmapshack/pr350-support-quazip-1x.patch
Normal file
@ -0,0 +1,141 @@
|
||||
From 8fb751c656a14020ba37fb91b7f7cba3c49d8504 Mon Sep 17 00:00:00 2001
|
||||
From: kiozen <oliver.eichler@gmx.de>
|
||||
Date: Sat, 20 Mar 2021 12:14:29 +0100
|
||||
Subject: [PATCH] [QMS-349] Upgrade to Quazip Qt5 V1.x
|
||||
|
||||
Simply adjusted the cmake scripts
|
||||
---
|
||||
CMakeLists.txt | 2 +-
|
||||
src/qmapshack/CMakeLists.txt | 27 +++++++++++++--------------
|
||||
3 files changed, 15 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 8d2cf127..7420d9b2 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -152,7 +152,7 @@ find_package(GDAL REQUIRED)
|
||||
find_package(PROJ REQUIRED)
|
||||
find_package(JPEG REQUIRED)
|
||||
find_package(ROUTINO REQUIRED)
|
||||
-find_package(QuaZip5 REQUIRED)
|
||||
+find_package(QuaZip-Qt5 REQUIRED)
|
||||
find_package(ALGLIB ) # optional as we can use our local version
|
||||
|
||||
|
||||
diff --git a/src/qmapshack/CMakeLists.txt b/src/qmapshack/CMakeLists.txt
|
||||
index 08eeb183..9b3836d6 100644
|
||||
--- a/src/qmapshack/CMakeLists.txt
|
||||
+++ b/src/qmapshack/CMakeLists.txt
|
||||
@@ -22,8 +22,8 @@ add_definitions(-DROUTINO_XML_PATH=${ROUTINO_XML_PATH})
|
||||
# All source files needed to compile
|
||||
###############################################################################################
|
||||
|
||||
-set( SRCS
|
||||
- CAbout.cpp
|
||||
+set( SRCS
|
||||
+ CAbout.cpp
|
||||
CMainWindow.cpp
|
||||
CSingleInstanceProxy.cpp
|
||||
canvas/CCanvas.cpp
|
||||
@@ -160,7 +160,7 @@ set( SRCS
|
||||
gis/trk/CInvalidTrk.cpp
|
||||
gis/trk/CKnownExtension.cpp
|
||||
gis/trk/CListTrkPts.cpp
|
||||
- gis/trk/CPropertyTrk.cpp
|
||||
+ gis/trk/CPropertyTrk.cpp
|
||||
gis/trk/CScrOptTrk.cpp
|
||||
gis/trk/CSelectActivityColor.cpp
|
||||
gis/trk/CTableTrk.cpp
|
||||
@@ -272,7 +272,7 @@ set( SRCS
|
||||
mouse/line/CLineOpMovePoint.cpp
|
||||
mouse/line/CLineOpSelectRange.cpp
|
||||
mouse/line/CScrOptEditLine.cpp
|
||||
- mouse/line/CScrOptRangeLine.cpp
|
||||
+ mouse/line/CScrOptRangeLine.cpp
|
||||
mouse/line/ILineOp.cpp
|
||||
mouse/line/IMouseEditLine.cpp
|
||||
plot/CPlot.cpp
|
||||
@@ -401,7 +401,7 @@ set( HDRS
|
||||
gis/CGisListDB.h
|
||||
gis/CGisListWks.h
|
||||
gis/CGisWorkspace.h
|
||||
- gis/CSelDevices.h
|
||||
+ gis/CSelDevices.h
|
||||
gis/IGisItem.h
|
||||
gis/IGisLine.h
|
||||
gis/Poi.h
|
||||
@@ -512,7 +512,7 @@ set( HDRS
|
||||
gis/trk/CInvalidTrk.h
|
||||
gis/trk/CKnownExtension.h
|
||||
gis/trk/CListTrkPts.h
|
||||
- gis/trk/CPropertyTrk.h
|
||||
+ gis/trk/CPropertyTrk.h
|
||||
gis/trk/CScrOptTrk.h
|
||||
gis/trk/CSelectActivityColor.h
|
||||
gis/trk/CTableTrk.h
|
||||
@@ -579,7 +579,7 @@ set( HDRS
|
||||
map/CMapList.h
|
||||
map/CMapMAP.h
|
||||
map/CMapPathSetup.h
|
||||
- map/CMapPropSetup.h
|
||||
+ map/CMapPropSetup.h
|
||||
map/CMapRMAP.h
|
||||
map/CMapTMS.h
|
||||
map/CMapVRT.h
|
||||
@@ -655,7 +655,7 @@ set( HDRS
|
||||
realtime/CRtSelectSource.h
|
||||
realtime/CRtWorkspace.h
|
||||
realtime/IRtInfo.h
|
||||
- realtime/IRtRecord.h
|
||||
+ realtime/IRtRecord.h
|
||||
realtime/IRtSource.h
|
||||
realtime/gpstether/CRtGpsTether.h
|
||||
realtime/gpstether/CRtGpsTetherInfo.h
|
||||
@@ -764,7 +764,7 @@ set( UIS
|
||||
gis/search/IGeoSearchWebConfigDialog.ui
|
||||
gis/search/ISearchExplanationDialog.ui
|
||||
gis/summary/IGisSummary.ui
|
||||
- gis/summary/IGisSummarySetup.ui
|
||||
+ gis/summary/IGisSummarySetup.ui
|
||||
gis/trk/ICombineTrk.ui
|
||||
gis/trk/ICutTrk.ui
|
||||
gis/trk/IDetailsTrk.ui
|
||||
@@ -818,7 +818,7 @@ set( UIS
|
||||
mouse/range/IActionSelect.ui
|
||||
mouse/range/IRangeToolSetup.ui
|
||||
mouse/range/IScrOptRangeTool.ui
|
||||
- mouse/range/IScrOptRangeTrk.ui
|
||||
+ mouse/range/IScrOptRangeTrk.ui
|
||||
mouse/IScrOptRuler.ui
|
||||
mouse/IScrOptSelect.ui
|
||||
mouse/line/IScrOptEditLine.ui
|
||||
@@ -899,7 +899,6 @@ include_directories(
|
||||
${PROJ_INCLUDE_DIRS}
|
||||
${ROUTINO_INCLUDE_DIRS}
|
||||
${ALGLIB_INCLUDE_DIRS}
|
||||
- ${QUAZIP_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
@@ -934,10 +933,10 @@ endif(Qt5DBus_FOUND)
|
||||
|
||||
target_link_libraries(${APPLICATION_NAME}
|
||||
Qt5::Widgets
|
||||
- Qt5::Xml
|
||||
+ Qt5::Xml
|
||||
Qt5::Sql
|
||||
Qt5::PrintSupport
|
||||
- Qt5::UiTools
|
||||
+ Qt5::UiTools
|
||||
Qt5::Network
|
||||
Qt5::WebEngineWidgets
|
||||
Qt5::Qml
|
||||
@@ -947,7 +946,7 @@ target_link_libraries(${APPLICATION_NAME}
|
||||
${PROJ_LIBRARIES}
|
||||
${ROUTINO_LIBRARIES}
|
||||
${ALGLIB_LIBRARIES}
|
||||
- ${QUAZIP_LIBRARIES}
|
||||
+ QuaZip::QuaZip
|
||||
)
|
||||
|
||||
if(APPLE)
|
@ -25,14 +25,14 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "foxotron";
|
||||
version = "2021-03-12";
|
||||
version = "2021-04-19";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Gargaj";
|
||||
repo = "Foxotron";
|
||||
rev = version;
|
||||
fetchSubmodules = true;
|
||||
sha256 = "1finvbs3pbfyvm525blwgwl5jci2zjxb1923i0cm8rmf7wasaapb";
|
||||
sha256 = "sha256-YTCnWHXBNqvJmhRqRQRFCVvBcqbjKzcc3AKVXS0jvno=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ cmake pkg-config makeWrapper ];
|
||||
@ -67,7 +67,7 @@ stdenv.mkDerivation rec {
|
||||
Revision 2021 3D Graphics Competition.
|
||||
'';
|
||||
homepage = "https://github.com/Gargaj/Foxotron";
|
||||
license = licenses.publicDomain;
|
||||
license = licenses.unlicense;
|
||||
maintainers = with maintainers; [ OPNA2608 ];
|
||||
platforms = platforms.all;
|
||||
};
|
||||
|
@ -27,6 +27,15 @@ mkDerivation rec {
|
||||
sha256 = "1bq7bv4p7w67172y893lvpk90d6fgdpnylynbj2kn8m2hs6khya4";
|
||||
};
|
||||
|
||||
patches = [
|
||||
# Add support for Quazip 1.x.
|
||||
(fetchpatch {
|
||||
url = "https://github.com/nomacs/nomacs/pull/576.patch";
|
||||
sha256 = "11ryjvd9jbb0cqagai4a6980jfq8lrcbyw2d7z9yld1f42w9kbxm";
|
||||
stripLen = 1;
|
||||
})
|
||||
];
|
||||
|
||||
setSourceRoot = ''
|
||||
sourceRoot=$(echo */ImageLounge)
|
||||
'';
|
||||
|
@ -34,7 +34,8 @@ in mkDerivation rec {
|
||||
|
||||
postPatch = ''
|
||||
substituteInPlace OpenBoard.pro \
|
||||
--replace '/usr/include/quazip' '${quazip}/include/quazip5' \
|
||||
--replace '/usr/include/quazip' '${quazip}/include/QuaZip-Qt5-${quazip.version}/quazip' \
|
||||
--replace '-lquazip5' '-lquazip1-qt5' \
|
||||
--replace '/usr/include/poppler' '${poppler.dev}/include/poppler'
|
||||
'';
|
||||
|
||||
|
99
pkgs/applications/misc/authenticator/default.nix
Normal file
99
pkgs/applications/misc/authenticator/default.nix
Normal file
@ -0,0 +1,99 @@
|
||||
{ lib
|
||||
, stdenv
|
||||
, fetchFromGitLab
|
||||
, fetchpatch
|
||||
, appstream-glib
|
||||
, desktop-file-utils
|
||||
, meson
|
||||
, ninja
|
||||
, pkg-config
|
||||
, python3
|
||||
, rustPlatform
|
||||
, wrapGAppsHook
|
||||
, gdk-pixbuf
|
||||
, glib
|
||||
, gst_all_1
|
||||
, gtk4
|
||||
, libadwaita
|
||||
, openssl
|
||||
, sqlite
|
||||
, wayland
|
||||
, zbar
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "authenticator";
|
||||
version = "4.0.3";
|
||||
|
||||
src = fetchFromGitLab {
|
||||
domain = "gitlab.gnome.org";
|
||||
owner = "World";
|
||||
repo = "Authenticator";
|
||||
rev = version;
|
||||
sha256 = "0fvs76f3fm5pxn7wg6sjbqpgip5w2j7xrh4siasdcl2bx6vsld8b";
|
||||
};
|
||||
|
||||
cargoDeps = rustPlatform.fetchCargoTarball {
|
||||
inherit src;
|
||||
name = "${pname}-${version}";
|
||||
sha256 = "1s97jyszxf24rs3ni11phiyvmp1wm8sicb0rh1jgwz4bn1cnakx4";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
patchShebangs build-aux
|
||||
'';
|
||||
|
||||
nativeBuildInputs = [
|
||||
appstream-glib
|
||||
desktop-file-utils
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
python3
|
||||
wrapGAppsHook
|
||||
] ++ (with rustPlatform; [
|
||||
cargoSetupHook
|
||||
rust.cargo
|
||||
rust.rustc
|
||||
]);
|
||||
|
||||
buildInputs = [
|
||||
gdk-pixbuf
|
||||
glib
|
||||
gst_all_1.gstreamer
|
||||
gst_all_1.gst-plugins-base
|
||||
|
||||
# gst-plugins-good needs gtk4 support:
|
||||
# https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/767
|
||||
# We copy the way it is built from the Flatpak:
|
||||
# https://gitlab.gnome.org/World/Authenticator/-/blob/master/build-aux/com.belmoussaoui.Authenticator.Devel.json
|
||||
(gst_all_1.gst-plugins-good.overrideAttrs (old: {
|
||||
patches = old.patches or [ ] ++ [
|
||||
"${src}/build-aux/767.patch"
|
||||
];
|
||||
mesonFlags = old.mesonFlags ++ [
|
||||
"-Dgtk3=disabled"
|
||||
"-Dgtk4=enabled"
|
||||
"-Dgtk4-experiments=true"
|
||||
];
|
||||
buildInputs = old.buildInputs ++ [
|
||||
gtk4
|
||||
];
|
||||
}))
|
||||
|
||||
(gst_all_1.gst-plugins-bad.override { enableZbar = true; })
|
||||
gtk4
|
||||
libadwaita
|
||||
openssl
|
||||
sqlite
|
||||
wayland
|
||||
zbar
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Two-factor authentication code generator for GNOME";
|
||||
homepage = "https://gitlab.gnome.org/World/Authenticator";
|
||||
license = licenses.gpl3Plus;
|
||||
maintainers = with maintainers; [ dotlambda ];
|
||||
};
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
, stdenv
|
||||
, copyDesktopItems
|
||||
, fetchFromGitHub
|
||||
, fetchpatch
|
||||
, makeDesktopItem
|
||||
, makeWrapper
|
||||
, fontconfig
|
||||
@ -19,18 +18,18 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "dbeaver-ce";
|
||||
version = "21.0.3"; # When updating also update fetchedMavenDeps.sha256
|
||||
version = "21.0.4"; # When updating also update fetchedMavenDeps.sha256
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "dbeaver";
|
||||
repo = "dbeaver";
|
||||
rev = version;
|
||||
sha256 = "sha256-ItM8t+gqE0ccuuimfEMUddykl+xt2eZIBd3MbpreRwA=";
|
||||
sha256 = "sha256-jV7Pe4MsLQnIrkDnlI2SrPzSjiDHM59GbMy4G7oeQK8=";
|
||||
};
|
||||
|
||||
fetchedMavenDeps = stdenv.mkDerivation {
|
||||
name = "dbeaver-${version}-maven-deps";
|
||||
inherit src patches;
|
||||
inherit src;
|
||||
|
||||
buildInputs = [
|
||||
maven
|
||||
@ -51,18 +50,9 @@ stdenv.mkDerivation rec {
|
||||
dontFixup = true;
|
||||
outputHashAlgo = "sha256";
|
||||
outputHashMode = "recursive";
|
||||
outputHash = "sha256-rsK/B39ogNu5nC41OfyAsLiwBz4gWyH+8Fj7E6+rOng=";
|
||||
outputHash = "sha256-RspJTWVM0ZpAz4yDeKsG7wSHZ//bi3SSV5c0gbsqZKY=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
# Fix eclipse-color-theme URL (https://github.com/dbeaver/dbeaver/pull/12133)
|
||||
# After April 15, 2021 eclipse-color-theme.github.com no longer redirects to eclipse-color-theme.github.io
|
||||
(fetchpatch {
|
||||
url = "https://github.com/dbeaver/dbeaver/commit/65d65e2c2c711cc87fddcec425a6915aa80f4ced.patch";
|
||||
sha256 = "sha256-pxOcRYkV/5o+tHcRhHDZ1TmZSHMnKBmkNTVAlIf9nUE=";
|
||||
})
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
copyDesktopItems
|
||||
makeWrapper
|
||||
|
@ -1,5 +1,5 @@
|
||||
{ lib, stdenv, fetchurl, perl, libX11, libXinerama, libjpeg, libpng, libtiff, pkg-config,
|
||||
librsvg, glib, gtk2, libXext, libXxf86vm, poppler, xineLib, ghostscript, makeWrapper }:
|
||||
librsvg, glib, gtk2, libXext, libXxf86vm, poppler, xine-lib, ghostscript, makeWrapper }:
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "eaglemode";
|
||||
@ -12,11 +12,11 @@ stdenv.mkDerivation rec {
|
||||
|
||||
nativeBuildInputs = [ pkg-config ];
|
||||
buildInputs = [ perl libX11 libXinerama libjpeg libpng libtiff
|
||||
librsvg glib gtk2 libXxf86vm libXext poppler xineLib ghostscript makeWrapper ];
|
||||
librsvg glib gtk2 libXxf86vm libXext poppler xine-lib ghostscript makeWrapper ];
|
||||
|
||||
# The program tries to dlopen Xxf86vm, Xext and Xinerama, so we use the
|
||||
# trick on NIX_LDFLAGS and dontPatchELF to make it find them.
|
||||
# I use 'yes y' to skip a build error linking with xineLib,
|
||||
# I use 'yes y' to skip a build error linking with xine-lib,
|
||||
# because xine stopped exporting "_x_vo_new_port"
|
||||
# https://sourceforge.net/projects/eaglemode/forums/forum/808824/topic/5115261
|
||||
buildPhase = ''
|
||||
|
@ -41,6 +41,11 @@ stdenv.mkDerivation rec {
|
||||
json-glib
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p $out/lib/udev/rules.d
|
||||
sed "s|/usr/libexec/|$out/libexec/|" < $src/debian/feedbackd.udev > $out/lib/udev/rules.d/90-feedbackd.rules
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "A daemon to provide haptic (and later more) feedback on events";
|
||||
homepage = "https://source.puri.sm/Librem5/feedbackd";
|
||||
|
@ -2,16 +2,16 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "geoipupdate";
|
||||
version = "4.6.0";
|
||||
version = "4.7.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "maxmind";
|
||||
repo = "geoipupdate";
|
||||
rev = "v${version}";
|
||||
sha256 = "1rzc8kidm8nr9pbcbq96kax3cbf39afrk5vzpl04lzpw3jbbakjq";
|
||||
sha256 = "sha256-nshQxr6y3TxKsAVSA9mzL7LJfCtpv0QuuTTqk3/lENc=";
|
||||
};
|
||||
|
||||
vendorSha256 = "1f858k8cl0dgiw124jv0p9jhi9aqxnc3nmc7hksw70fla2nzjrv0";
|
||||
vendorSha256 = "sha256-fqQWFhFeyW4GntRBxEeN6WSOo0G+1hH9vSEZmBKglz8=";
|
||||
|
||||
doCheck = false;
|
||||
|
||||
|
@ -1,41 +1,54 @@
|
||||
{ lib, stdenv, fetchurl, glibc, libGLU, libGL, freetype, glib, libSM, libICE, libXi, libXv
|
||||
, libXrender, libXrandr, libXfixes, libXcursor, libXinerama, libXext, libX11, libXcomposite
|
||||
, libxcb, sqlite, zlib, fontconfig, dpkg, libproxy, libxml2, gst_all_1, dbus, makeWrapper }:
|
||||
{ lib
|
||||
, stdenv
|
||||
, mkDerivation
|
||||
, fetchurl
|
||||
, ffmpeg_3
|
||||
, freetype
|
||||
, gdal_2
|
||||
, glib
|
||||
, libGL
|
||||
, libGLU
|
||||
, libICE
|
||||
, libSM
|
||||
, libXi
|
||||
, libXv
|
||||
, libav_12
|
||||
|
||||
, libXrender
|
||||
, libXrandr
|
||||
, libXfixes
|
||||
, libXcursor
|
||||
, libXinerama
|
||||
, libXext
|
||||
, libX11
|
||||
, libXcomposite
|
||||
|
||||
, libxcb
|
||||
, sqlite
|
||||
, zlib
|
||||
, fontconfig
|
||||
, dpkg
|
||||
, libproxy
|
||||
, libxml2
|
||||
, gst_all_1
|
||||
, dbus
|
||||
, makeWrapper
|
||||
|
||||
, qtlocation
|
||||
, qtwebkit
|
||||
, qtx11extras
|
||||
, qtsensors
|
||||
, qtscript
|
||||
|
||||
, xkeyboardconfig
|
||||
, autoPatchelfHook
|
||||
}:
|
||||
let
|
||||
arch =
|
||||
if stdenv.hostPlatform.system == "x86_64-linux" then "amd64"
|
||||
else throw "Unsupported system ${stdenv.hostPlatform.system} ";
|
||||
fullPath = lib.makeLibraryPath [
|
||||
glibc
|
||||
glib
|
||||
stdenv.cc.cc
|
||||
libSM
|
||||
libICE
|
||||
libXi
|
||||
libXv
|
||||
libGLU libGL
|
||||
libXrender
|
||||
libXrandr
|
||||
libXfixes
|
||||
libXcursor
|
||||
libXinerama
|
||||
libXcomposite
|
||||
freetype
|
||||
libXext
|
||||
libX11
|
||||
libxcb
|
||||
sqlite
|
||||
zlib
|
||||
fontconfig
|
||||
libproxy
|
||||
libxml2
|
||||
dbus
|
||||
gst_all_1.gstreamer
|
||||
gst_all_1.gst-plugins-base
|
||||
];
|
||||
in
|
||||
stdenv.mkDerivation rec {
|
||||
mkDerivation rec {
|
||||
pname = "googleearth-pro";
|
||||
version = "7.3.3.7786";
|
||||
|
||||
@ -44,20 +57,56 @@ stdenv.mkDerivation rec {
|
||||
sha256 = "1s3cakwrgf702g33rh8qs657d8bl68wgg8k89rksgvswwpd2zbb3";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ dpkg makeWrapper ];
|
||||
nativeBuildInputs = [ dpkg makeWrapper autoPatchelfHook ];
|
||||
propagatedBuildInputs = [ xkeyboardconfig ];
|
||||
buildInputs = [
|
||||
dbus
|
||||
ffmpeg_3
|
||||
fontconfig
|
||||
freetype
|
||||
gdal_2
|
||||
glib
|
||||
gst_all_1.gst-plugins-base
|
||||
gst_all_1.gstreamer
|
||||
libGL
|
||||
libGLU
|
||||
libICE
|
||||
libSM
|
||||
libX11
|
||||
libXcomposite
|
||||
libXcursor
|
||||
libXext
|
||||
libXfixes
|
||||
libXi
|
||||
libXinerama
|
||||
libXrandr
|
||||
libXrender
|
||||
libXv
|
||||
libav_12
|
||||
libproxy
|
||||
libxcb
|
||||
libxml2
|
||||
qtlocation
|
||||
qtscript
|
||||
qtsensors
|
||||
qtwebkit
|
||||
qtx11extras
|
||||
sqlite
|
||||
zlib
|
||||
];
|
||||
|
||||
doInstallCheck = true;
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
dontPatchELF = true;
|
||||
|
||||
unpackPhase = ''
|
||||
# deb file contains a setuid binary, so 'dpkg -x' doesn't work here
|
||||
dpkg --fsys-tarfile ${src} | tar --extract
|
||||
'';
|
||||
|
||||
installPhase =''
|
||||
runHook preInstall
|
||||
|
||||
mkdir $out
|
||||
mv usr/* $out/
|
||||
rmdir usr
|
||||
@ -66,20 +115,9 @@ stdenv.mkDerivation rec {
|
||||
|
||||
# patch and link googleearth binary
|
||||
ln -s $out/opt/google/earth/pro/googleearth-bin $out/bin/googleearth-pro
|
||||
patchelf --interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
|
||||
--set-rpath "${fullPath}:\$ORIGIN" \
|
||||
$out/opt/google/earth/pro/googleearth-bin
|
||||
|
||||
# patch and link gpsbabel binary
|
||||
ln -s $out/opt/google/earth/pro/gpsbabel $out/bin/gpsbabel
|
||||
patchelf --interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
|
||||
--set-rpath "${fullPath}:\$ORIGIN" \
|
||||
$out/opt/google/earth/pro/gpsbabel
|
||||
|
||||
# patch libraries
|
||||
for a in $out/opt/google/earth/pro/*.so* ; do
|
||||
patchelf --set-rpath "${fullPath}:\$ORIGIN" $a
|
||||
done
|
||||
|
||||
# Add desktop config file and icons
|
||||
mkdir -p $out/share/{applications,icons/hicolor/{16x16,22x22,24x24,32x32,48x48,64x64,128x128,256x256}/apps,pixmaps}
|
||||
@ -89,23 +127,37 @@ stdenv.mkDerivation rec {
|
||||
ln -s $out/opt/google/earth/pro/product_logo_"$size".png $out/share/icons/hicolor/"$size"x"$size"/apps/google-earth-pro.png
|
||||
done
|
||||
ln -s $out/opt/google/earth/pro/product_logo_256.png $out/share/pixmaps/google-earth-pro.png
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
postInstall = ''
|
||||
find "$out/opt/google/earth/pro" -name "*.so.*" | \
|
||||
egrep -v 'libssl*|libcrypto*|libicu*' | \
|
||||
xargs rm
|
||||
find "$out/opt/google/earth/pro" -name "*.so" | \
|
||||
egrep -v 'libgoogle*|libauth*|libbase*|libcommon*|libcommon_gui*|libcommon_platform*|libcommon_webbrowser*|libcomponentframework*|libgeobase*|libgeobaseutils*|libge_net*|libgdata*|libgoogleapi*|libmath*|libmoduleframework*|libmaps*|libport*|libprintmodule*|libprofile*|librender*|libreporting*|libsgutil*|libspatial*|libxsltransform*|libbase*|libport*|libport*|libbase*|libcomponentframework*|libIGCore*|libIGUtils*|libaction*|libapiloader*|libapiloader*|libIGCore*|libIGUtils*|libIGMath*|libfusioncommon*|libge_exif*|libaction*|libfusioncommon*|libapiloader*|liblayer*|libapiloader*|libIGAttrs*|libIGCore*|libIGGfx*|libIGMath*|libIGSg*|libIGUtils*|libwmsbase*|libwebbrowser*|libevllpro*|libalchemyext*|libge_cache*|libflightsim*|libnpgeinprocessplugin*|libmeasure*|libviewsync*|libcapture*|libtheme*|libgps*|libgisingest*|libsearchmodule*|libinput_plugin*|libnavigate*|libspnav*|libsearch*|libLeap*' | \
|
||||
xargs rm
|
||||
'';
|
||||
|
||||
autoPatchelfIgnoreMissingDeps=true;
|
||||
|
||||
installCheckPhase = ''
|
||||
$out/bin/gpsbabel -V > /dev/null
|
||||
'';
|
||||
|
||||
# wayland is not supported by Qt included in binary package, so make sure it uses xcb
|
||||
fixupPhase = ''
|
||||
wrapProgram $out/bin/googleearth-pro --set QT_QPA_PLATFORM xcb
|
||||
postFixup = ''
|
||||
wrapProgram $out/bin/googleearth-pro \
|
||||
--set QT_QPA_PLATFORM xcb \
|
||||
--set QT_XKB_CONFIG_ROOT "${xkeyboardconfig}/share/X11/xkb"
|
||||
'';
|
||||
|
||||
|
||||
meta = with lib; {
|
||||
description = "A world sphere viewer";
|
||||
homepage = "https://earth.google.com";
|
||||
homepage = "https://www.google.com/earth/";
|
||||
license = licenses.unfree;
|
||||
maintainers = with maintainers; [ friedelino ];
|
||||
maintainers = with maintainers; [ friedelino shamilton ];
|
||||
platforms = platforms.linux;
|
||||
};
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user