Merge dc18c6f81c into haskell-updates
This commit is contained in:
@@ -108,6 +108,7 @@ A few markups for other kinds of literals are also available:
|
||||
These literal kinds are used mostly in NixOS option documentation.
|
||||
|
||||
This syntax is taken from [MyST](https://myst-parser.readthedocs.io/en/latest/syntax/syntax.html#roles-an-in-line-extension-point). Though, the feature originates from [reStructuredText](https://www.sphinx-doc.org/en/master/usage/restructuredtext/roles.html#role-manpage) with slightly different syntax.
|
||||
They are handled by `myst_role` defined per renderer. <!-- reverse references in code -->
|
||||
|
||||
#### Admonitions
|
||||
|
||||
|
||||
@@ -156,6 +156,7 @@ let
|
||||
makeScope makeScopeWithSplicing makeScopeWithSplicing'
|
||||
extendMkDerivation;
|
||||
inherit (self.derivations) lazyDerivation optionalDrvAttr warnOnInstantiate;
|
||||
inherit (self.generators) mkLuaInline;
|
||||
inherit (self.meta) addMetaAttrs dontDistribute setName updateName
|
||||
appendToName mapDerivationAttrset setPrio lowPrio lowPrioSet hiPrio
|
||||
hiPrioSet licensesSpdx getLicenseFromSpdxId getLicenseFromSpdxIdOr
|
||||
|
||||
+2
-2
@@ -743,6 +743,8 @@ in rec {
|
||||
"nil"
|
||||
else if isInt v || isFloat v || isString v || isBool v then
|
||||
toJSON v
|
||||
else if isPath v || isDerivation v then
|
||||
toJSON "${v}"
|
||||
else if isList v then
|
||||
(if v == [ ] then "{}" else
|
||||
"{${introSpace}${concatItems (map (value: "${toLua innerArgs value}") v)}${outroSpace}}")
|
||||
@@ -752,8 +754,6 @@ in rec {
|
||||
"(${v.expr})"
|
||||
else if v == { } then
|
||||
"{}"
|
||||
else if isDerivation v then
|
||||
''"${toString v}"''
|
||||
else
|
||||
"{${introSpace}${concatItems (
|
||||
mapAttrsToList (key: value: "[${toJSON key}] = ${toLua innerArgs value}") v
|
||||
|
||||
+5
-5
@@ -140,11 +140,6 @@ lib.mapAttrs mkLicense ({
|
||||
fullName = "Apache License 2.0";
|
||||
};
|
||||
|
||||
asl20-llvm = {
|
||||
spdxId = "Apache-2.0 WITH LLVM-exception";
|
||||
fullName = "Apache License 2.0 with LLVM Exceptions";
|
||||
};
|
||||
|
||||
bitstreamVera = {
|
||||
spdxId = "Bitstream-Vera";
|
||||
fullName = "Bitstream Vera Font License";
|
||||
@@ -859,6 +854,11 @@ lib.mapAttrs mkLicense ({
|
||||
url = "https://opensource.franz.com/preamble.html";
|
||||
};
|
||||
|
||||
llvm-exception = {
|
||||
spdxId = "LLVM-exception";
|
||||
fullName = "LLVM Exception"; # LLVM exceptions to the Apache 2.0 License
|
||||
};
|
||||
|
||||
lppl1 = {
|
||||
spdxId = "LPPL-1.0";
|
||||
fullName = "LaTeX Project Public License v1.0";
|
||||
|
||||
@@ -834,6 +834,15 @@ rec {
|
||||
};
|
||||
};
|
||||
|
||||
# A value produced by `lib.mkLuaInline`
|
||||
luaInline = mkOptionType {
|
||||
name = "luaInline";
|
||||
description = "inline lua";
|
||||
descriptionClass = "noun";
|
||||
check = x: x._type or null == "lua-inline";
|
||||
merge = mergeEqualOption;
|
||||
};
|
||||
|
||||
uniq = unique { message = ""; };
|
||||
|
||||
unique = { message }: type: mkOptionType rec {
|
||||
|
||||
@@ -579,6 +579,17 @@
|
||||
githubId = 50264672;
|
||||
name = "Adam Freeth";
|
||||
};
|
||||
adamperkowski = {
|
||||
name = "Adam Perkowski";
|
||||
email = "adas1per@protonmail.com";
|
||||
matrix = "@xx0a_q:matrix.org";
|
||||
github = "adamperkowski";
|
||||
githubId = 75480869;
|
||||
keys = [
|
||||
{ fingerprint = "00F6 1623 FB56 BC5B B709 4E63 4CE6 C117 2DF6 BE79"; }
|
||||
{ fingerprint = "5A53 0832 DA91 20B0 CA57 DDB6 7CBD B58E CF1D 3478"; }
|
||||
];
|
||||
};
|
||||
adamt = {
|
||||
email = "mail@adamtulinius.dk";
|
||||
github = "adamtulinius";
|
||||
@@ -1185,6 +1196,18 @@
|
||||
githubId = 30437811;
|
||||
name = "Alex Andrews";
|
||||
};
|
||||
alikindsys = {
|
||||
email = "alice@blocovermelho.org";
|
||||
github = "alikindsys";
|
||||
githubId = 36565196;
|
||||
name = "Alikind System";
|
||||
|
||||
keys = [
|
||||
{
|
||||
fingerprint = "7D31 15DC D912 C15A 2781 F7BB 511C B44B C752 2A89";
|
||||
}
|
||||
];
|
||||
};
|
||||
alirezameskin = {
|
||||
email = "alireza.meskin@gmail.com";
|
||||
github = "alirezameskin";
|
||||
@@ -9103,6 +9126,12 @@
|
||||
githubId = 39066502;
|
||||
name = "Guekka";
|
||||
};
|
||||
guelakais = {
|
||||
email = "koroyeldiores@gmail.com";
|
||||
github = "Guelakais";
|
||||
githubId = 76840985;
|
||||
name = "GueLaKais";
|
||||
};
|
||||
guibert = {
|
||||
email = "david.guibert@gmail.com";
|
||||
github = "dguibert";
|
||||
@@ -9176,6 +9205,11 @@
|
||||
github = "gytis-ivaskevicius";
|
||||
githubId = 23264966;
|
||||
};
|
||||
GZGavinZhao = {
|
||||
name = "Gavin Zhao";
|
||||
github = "GZGavinZhao";
|
||||
githubId = 74938940;
|
||||
};
|
||||
h3cth0r = {
|
||||
name = "Hector Miranda";
|
||||
email = "hector.miranda@tec.mx";
|
||||
@@ -10514,6 +10548,12 @@
|
||||
githubId = 94313;
|
||||
name = "Xianyi Lin";
|
||||
};
|
||||
izelnakri = {
|
||||
email = "contact@izelnakri.com";
|
||||
github = "izelnakri";
|
||||
githubId = 1190931;
|
||||
name = "Izel Nakri";
|
||||
};
|
||||
izorkin = {
|
||||
email = "Izorkin@gmail.com";
|
||||
github = "Izorkin";
|
||||
@@ -11415,6 +11455,13 @@
|
||||
githubId = 22916782;
|
||||
name = "Joan Massachs";
|
||||
};
|
||||
joaomoreira = {
|
||||
matrix = "@joaomoreira:matrix.org";
|
||||
github = "joaoymoreira";
|
||||
githubId = 151087767;
|
||||
name = "João Moreira";
|
||||
keys = [ { fingerprint = "F457 0A3A 5F89 22F8 F572 E075 EF8B F2C8 C5F4 097D"; } ];
|
||||
};
|
||||
joaquintrinanes = {
|
||||
email = "hi@joaquint.io";
|
||||
github = "JoaquinTrinanes";
|
||||
@@ -14202,6 +14249,17 @@
|
||||
githubId = 7910815;
|
||||
name = "Alex McGrath";
|
||||
};
|
||||
lykos153 = {
|
||||
email = "silvio.ankermann@cloudandheat.com";
|
||||
github = "Lykos153";
|
||||
githubId = 6453662;
|
||||
name = "Silvio Ankermann";
|
||||
keys = [
|
||||
{
|
||||
fingerprint = "8D47 6294 7205 541C 62A4 9C88 F422 6CA3 971C 4E97";
|
||||
}
|
||||
];
|
||||
};
|
||||
lyn = {
|
||||
name = "Lyn";
|
||||
matrix = "@lynatic:catgirl.cloud";
|
||||
@@ -21399,6 +21457,11 @@
|
||||
githubId = 19472270;
|
||||
name = "Sebastian";
|
||||
};
|
||||
sebaguardian = {
|
||||
name = "Sebaguardian";
|
||||
github = "Sebaguardian";
|
||||
githubId = 68247013;
|
||||
};
|
||||
sebastianblunt = {
|
||||
name = "Sebastian Blunt";
|
||||
email = "nix@sebastianblunt.com";
|
||||
@@ -21986,6 +22049,11 @@
|
||||
githubId = 91412114;
|
||||
keys = [ { fingerprint = "C1DA A551 B422 7A6F 3FD9 6B3A 467B 7D12 9EA7 3AC9"; } ];
|
||||
};
|
||||
silvanshade = {
|
||||
github = "silvanshade";
|
||||
githubId = 11022302;
|
||||
name = "silvanshade";
|
||||
};
|
||||
Silver-Golden = {
|
||||
name = "Brendan Golden";
|
||||
email = "github+nixpkgs@brendan.ie";
|
||||
@@ -22510,6 +22578,13 @@
|
||||
githubId = 47164123;
|
||||
name = "Spoonbaker";
|
||||
};
|
||||
sportshead = {
|
||||
email = "me@sportshead.dev";
|
||||
github = "sportshead";
|
||||
githubId = 32637656;
|
||||
name = "sportshead";
|
||||
keys = [ { fingerprint = "A6B6 D031 782E BDF7 631A 8E7E A874 DB2C BFD3 CFD0"; } ];
|
||||
};
|
||||
sprock = {
|
||||
email = "rmason@mun.ca";
|
||||
github = "sprock";
|
||||
|
||||
@@ -1018,8 +1018,9 @@ with lib.maintainers;
|
||||
|
||||
rocm = {
|
||||
members = [
|
||||
Madouura
|
||||
Flakebi
|
||||
GZGavinZhao
|
||||
LunNova
|
||||
mschwaig
|
||||
];
|
||||
githubTeams = [ "rocm-maintainers" ];
|
||||
|
||||
@@ -232,6 +232,13 @@ merging is handled.
|
||||
definitions cannot be merged. The regular expression is processed
|
||||
using `builtins.match`.
|
||||
|
||||
### Specialised types {#sec-option-types-specialised}
|
||||
|
||||
`types.luaInline`
|
||||
|
||||
: A string wrapped using `lib.mkLuaInline`. Allows embedding lua expressions
|
||||
inline within generated lua. Multiple definitions cannot be merged.
|
||||
|
||||
## Submodule types {#sec-option-types-submodule}
|
||||
|
||||
Submodules are detailed in [Submodule](#section-option-types-submodule).
|
||||
|
||||
@@ -402,6 +402,31 @@ have a predefined type and string generator already declared under
|
||||
: Outputs the given attribute set as an Elixir map, instead of the
|
||||
default Elixir keyword list
|
||||
|
||||
`pkgs.formats.lua { asBindings ? false, multiline ? true, columnWidth ? 100, indentWidth ? 2, indentUsingTabs ? false }`
|
||||
|
||||
: A function taking an attribute set with values
|
||||
|
||||
`asBindings` (default `false`)
|
||||
|
||||
: Whether to treat attributes as variable bindings
|
||||
|
||||
`multiline` (default `true`)
|
||||
|
||||
: Whether to procude a multiline output. The output may still wrap across
|
||||
multiple lines if it would otherwise exceed `columnWidth`.
|
||||
|
||||
`columnWidth` (default `100`)
|
||||
|
||||
: The column width to use to attempt to wrap lines.
|
||||
|
||||
`indentWidth` (default `2`)
|
||||
|
||||
: The width of a single indentation level.
|
||||
|
||||
`indentUsingTabs` (default `false`)
|
||||
|
||||
: Whether the indentation should use tabs instead of spaces.
|
||||
|
||||
`pkgs.formats.php { finalVariable }` []{#pkgs-formats-php}
|
||||
|
||||
: A function taking an attribute set with values
|
||||
|
||||
@@ -1592,6 +1592,9 @@
|
||||
"sec-option-types-string": [
|
||||
"index.html#sec-option-types-string"
|
||||
],
|
||||
"sec-option-types-specialised": [
|
||||
"index.html#sec-option-types-specialised"
|
||||
],
|
||||
"sec-option-types-submodule": [
|
||||
"index.html#sec-option-types-submodule"
|
||||
],
|
||||
|
||||
@@ -111,6 +111,8 @@
|
||||
|
||||
- [Schroot](https://codeberg.org/shelter/reschroot), a lightweight virtualisation tool. Securely enter a chroot and run a command or login shell. Available as [programs.schroot](#opt-programs.schroot.enable).
|
||||
|
||||
- [Firezone](https://firezone.dev), an enterprise-ready zero-trust access platform built on WireGuard. This includes the server stack as [services.firezone.server.enable](#opt-services.firezone.server.enable), a TURN/STUN relay service as [services.firezone.relay.enable](#opt-services.firezone.relay.enable), a gateway service as [services.firezone.gateway.enable](#opt-services.firezone.gateway.enable), a headless client as [services.firezone.headless-client.enable](#opt-services.firezone.headless-client.enable) and a GUI client as [services.firezone.gui-client.enable](#opt-services.firezone.gui-client.enable).
|
||||
|
||||
- [crab-hole](https://github.com/LuckyTurtleDev/crab-hole), a cross platform Pi-hole clone written in Rust using hickory-dns/trust-dns. Available as [services.crab-hole](#opt-services.crab-hole.enable).
|
||||
|
||||
- [zwave-js-ui](https://zwave-js.github.io/zwave-js-ui/), a full featured Z-Wave Control Panel and MQTT Gateway. Available as [services.zwave-js-ui](#opt-services.zwave-js-ui.enable).
|
||||
|
||||
@@ -376,4 +376,4 @@ foreach my $u (values %usersOut) {
|
||||
|
||||
updateFile("/etc/subuid", join("\n", @subUids) . "\n");
|
||||
updateFile("/etc/subgid", join("\n", @subGids) . "\n");
|
||||
updateFile($subUidMapFile, encode_json($subUidMap) . "\n");
|
||||
updateFile($subUidMapFile, to_json($subUidMap) . "\n");
|
||||
|
||||
@@ -951,6 +951,21 @@ in {
|
||||
}
|
||||
] ++ flatten (flip mapAttrsToList cfg.users (name: user:
|
||||
[
|
||||
(
|
||||
let
|
||||
# Things fail in various ways with especially non-ascii usernames.
|
||||
# This regex mirrors the one from shadow's is_valid_name:
|
||||
# https://github.com/shadow-maint/shadow/blob/bee77ffc291dfed2a133496db465eaa55e2b0fec/lib/chkname.c#L68
|
||||
# though without the trailing $, because Samba 3 got its last release
|
||||
# over 10 years ago and is not in Nixpkgs anymore,
|
||||
# while later versions don't appear to require anything like that.
|
||||
nameRegex = "[a-zA-Z0-9_.][a-zA-Z0-9_.-]*";
|
||||
in
|
||||
{
|
||||
assertion = builtins.match nameRegex user.name != null;
|
||||
message = "The username \"${user.name}\" is not valid, it does not match the regex \"${nameRegex}\".";
|
||||
}
|
||||
)
|
||||
{
|
||||
assertion = (user.hashedPassword != null)
|
||||
-> (match ".*:.*" user.hashedPassword == null);
|
||||
|
||||
@@ -47,7 +47,10 @@ let
|
||||
let
|
||||
module = ../. + "/installer/sd-card/sd-image-${pkgs.targetPlatform.qemuArch}.nix";
|
||||
in
|
||||
if builtins.pathExists module then [ module ] else throw "The module ${module} does not exist.";
|
||||
if builtins.pathExists module then
|
||||
[ module ]
|
||||
else
|
||||
throw "The module ${toString module} does not exist.";
|
||||
};
|
||||
kexec = ../installer/netboot/netboot-minimal.nix;
|
||||
};
|
||||
|
||||
@@ -1101,6 +1101,11 @@
|
||||
./services/networking/firewall.nix
|
||||
./services/networking/firewall-iptables.nix
|
||||
./services/networking/firewall-nftables.nix
|
||||
./services/networking/firezone/gateway.nix
|
||||
./services/networking/firezone/gui-client.nix
|
||||
./services/networking/firezone/headless-client.nix
|
||||
./services/networking/firezone/relay.nix
|
||||
./services/networking/firezone/server.nix
|
||||
./services/networking/flannel.nix
|
||||
./services/networking/freenet.nix
|
||||
./services/networking/freeradius.nix
|
||||
@@ -1364,6 +1369,7 @@
|
||||
./services/scheduling/atd.nix
|
||||
./services/scheduling/cron.nix
|
||||
./services/scheduling/fcron.nix
|
||||
./services/scheduling/prefect.nix
|
||||
./services/scheduling/scx.nix
|
||||
./services/search/elasticsearch-curator.nix
|
||||
./services/search/elasticsearch.nix
|
||||
|
||||
@@ -9,7 +9,8 @@ let
|
||||
registrationFile = "${dataDir}/telegram-registration.yaml";
|
||||
cfg = config.services.mautrix-telegram;
|
||||
settingsFormat = pkgs.formats.json { };
|
||||
settingsFile = settingsFormat.generate "mautrix-telegram-config.json" cfg.settings;
|
||||
settingsFileUnsubstituted = settingsFormat.generate "mautrix-telegram-config.json" cfg.settings;
|
||||
settingsFile = "${dataDir}/config.json";
|
||||
|
||||
in
|
||||
{
|
||||
@@ -132,10 +133,37 @@ in
|
||||
List of Systemd services to require and wait for when starting the application service.
|
||||
'';
|
||||
};
|
||||
|
||||
registerToSynapse = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = config.services.matrix-synapse.enable;
|
||||
defaultText = lib.literalExpression "config.services.matrix-synapse.enable";
|
||||
description = ''
|
||||
Whether to add the bridge's app service registration file to
|
||||
`services.matrix-synapse.settings.app_service_config_files`.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
users.users.mautrix-telegram = {
|
||||
isSystemUser = true;
|
||||
group = "mautrix-telegram";
|
||||
home = dataDir;
|
||||
description = "Mautrix-Telegram bridge user";
|
||||
};
|
||||
|
||||
users.groups.mautrix-telegram = { };
|
||||
|
||||
services.matrix-synapse = lib.mkIf cfg.registerToSynapse {
|
||||
settings.app_service_config_files = [ registrationFile ];
|
||||
};
|
||||
systemd.services.matrix-synapse = lib.mkIf cfg.registerToSynapse {
|
||||
serviceConfig.SupplementaryGroups = [ "mautrix-telegram" ];
|
||||
};
|
||||
|
||||
systemd.services.mautrix-telegram = {
|
||||
description = "Mautrix-Telegram, a Matrix-Telegram hybrid puppeting/relaybot bridge.";
|
||||
|
||||
@@ -161,6 +189,16 @@ in
|
||||
|
||||
preStart =
|
||||
''
|
||||
# substitute the settings file by environment variables
|
||||
# in this case read from EnvironmentFile
|
||||
test -f '${settingsFile}' && rm -f '${settingsFile}'
|
||||
old_umask=$(umask)
|
||||
umask 0177
|
||||
${pkgs.envsubst}/bin/envsubst \
|
||||
-o '${settingsFile}' \
|
||||
-i '${settingsFileUnsubstituted}'
|
||||
umask $old_umask
|
||||
|
||||
# generate the appservice's registration file if absent
|
||||
if [ ! -f '${registrationFile}' ]; then
|
||||
${pkgs.mautrix-telegram}/bin/mautrix-telegram \
|
||||
@@ -168,6 +206,19 @@ in
|
||||
--config='${settingsFile}' \
|
||||
--registration='${registrationFile}'
|
||||
fi
|
||||
|
||||
old_umask=$(umask)
|
||||
umask 0177
|
||||
# 1. Overwrite registration tokens in config
|
||||
# is set, set it as the login shared secret value for the configured
|
||||
# homeserver domain.
|
||||
${pkgs.yq}/bin/yq -s '.[0].appservice.as_token = .[1].as_token
|
||||
| .[0].appservice.hs_token = .[1].hs_token
|
||||
| .[0]' \
|
||||
'${settingsFile}' '${registrationFile}' > '${settingsFile}.tmp'
|
||||
mv '${settingsFile}.tmp' '${settingsFile}'
|
||||
|
||||
umask $old_umask
|
||||
''
|
||||
+ lib.optionalString (pkgs.mautrix-telegram ? alembic) ''
|
||||
# run automatic database init and migration scripts
|
||||
@@ -175,6 +226,8 @@ in
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
User = "mautrix-telegram";
|
||||
Group = "mautrix-telegram";
|
||||
Type = "simple";
|
||||
Restart = "always";
|
||||
|
||||
@@ -184,7 +237,6 @@ in
|
||||
ProtectKernelModules = true;
|
||||
ProtectControlGroups = true;
|
||||
|
||||
DynamicUser = true;
|
||||
PrivateTmp = true;
|
||||
WorkingDirectory = pkgs.mautrix-telegram; # necessary for the database migration scripts to be found
|
||||
StateDirectory = baseNameOf dataDir;
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
boolToString
|
||||
getExe
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.services.firezone.gateway;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.firezone.gateway = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
example = true;
|
||||
description = ''
|
||||
Whether to enable the firezone gateway.
|
||||
|
||||
You have to manually masquerade and forward traffic from the
|
||||
tun-firezone interface to your resource! Refer to the
|
||||
[upstream setup script](https://github.com/firezone/firezone/blob/8c7c0a9e8e33ae790aeb75fdb5a15432c2870b79/scripts/gateway-systemd-install.sh#L154-L168)
|
||||
for a list of iptable commands.
|
||||
|
||||
See the firezone nixos test in this repository for an nftables based example.
|
||||
'';
|
||||
type = lib.types.bool;
|
||||
};
|
||||
package = mkPackageOption pkgs "firezone-gateway" { };
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
description = "The name of this gateway as shown in firezone";
|
||||
};
|
||||
|
||||
apiUrl = mkOption {
|
||||
type = types.strMatching "^wss://.+/$";
|
||||
example = "wss://firezone.example.com/api/";
|
||||
description = ''
|
||||
The URL of your firezone server's API. This should be the same
|
||||
as your server's setting for {option}`services.firezone.server.settings.api.externalUrl`,
|
||||
but with `wss://` instead of `https://`.
|
||||
'';
|
||||
};
|
||||
|
||||
tokenFile = mkOption {
|
||||
type = types.path;
|
||||
example = "/run/secrets/firezone-gateway-token";
|
||||
description = ''
|
||||
A file containing the firezone gateway token. Do not use a nix-store path here
|
||||
as it will make the token publicly readable!
|
||||
|
||||
This file will be passed via systemd credentials, it should only be accessible
|
||||
by the root user.
|
||||
'';
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = types.str;
|
||||
default = "info";
|
||||
description = ''
|
||||
The log level for the firezone application. See
|
||||
[RUST_LOG](https://docs.rs/env_logger/latest/env_logger/#enabling-logging)
|
||||
for the format.
|
||||
'';
|
||||
};
|
||||
|
||||
enableTelemetry = mkEnableOption "telemetry";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.firezone-gateway = {
|
||||
description = "Gateway service for the Firezone zero-trust access platform";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
path = [ pkgs.util-linux ];
|
||||
script = ''
|
||||
# If FIREZONE_ID is not given by the user, use a persisted (or newly generated) uuid.
|
||||
if [[ -z "''${FIREZONE_ID:-}" ]]; then
|
||||
if [[ ! -e gateway_id ]]; then
|
||||
uuidgen -r > gateway_id
|
||||
fi
|
||||
export FIREZONE_ID=$(< gateway_id)
|
||||
fi
|
||||
|
||||
export FIREZONE_TOKEN=$(< "$CREDENTIALS_DIRECTORY/firezone-token")
|
||||
exec ${getExe cfg.package}
|
||||
'';
|
||||
|
||||
environment = {
|
||||
FIREZONE_API_URL = cfg.apiUrl;
|
||||
FIREZONE_NAME = cfg.name;
|
||||
FIREZONE_NO_TELEMETRY = boolToString (!cfg.enableTelemetry);
|
||||
RUST_LOG = cfg.logLevel;
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
DynamicUser = true;
|
||||
User = "firezone-gateway";
|
||||
LoadCredential = [ "firezone-token:${cfg.tokenFile}" ];
|
||||
|
||||
DeviceAllow = "/dev/net/tun";
|
||||
AmbientCapabilities = [ "CAP_NET_ADMIN" ];
|
||||
CapabilityBoundingSet = [ "CAP_NET_ADMIN" ];
|
||||
|
||||
StateDirectory = "firezone-gateway";
|
||||
WorkingDirectory = "/var/lib/firezone-gateway";
|
||||
|
||||
Restart = "on-failure";
|
||||
RestartSec = 10;
|
||||
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = false;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_NETLINK"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "@system-service";
|
||||
UMask = "077";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
oddlama
|
||||
patrickdag
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
boolToString
|
||||
getExe'
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.services.firezone.gui-client;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.firezone.gui-client = {
|
||||
enable = mkEnableOption "the firezone gui client";
|
||||
package = mkPackageOption pkgs "firezone-gui-client" { };
|
||||
|
||||
allowedUsers = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
All listed users will become part of the `firezone-client` group so
|
||||
they can control the IPC service. This is a convenience option.
|
||||
'';
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
description = "The name of this client as shown in firezone";
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = types.str;
|
||||
default = "info";
|
||||
description = ''
|
||||
The log level for the firezone application. See
|
||||
[RUST_LOG](https://docs.rs/env_logger/latest/env_logger/#enabling-logging)
|
||||
for the format.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
users.groups.firezone-client.members = cfg.allowedUsers;
|
||||
|
||||
# Required for deep-link mimetype registration
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
# Required for the token store in the gui application
|
||||
services.gnome.gnome-keyring.enable = true;
|
||||
|
||||
systemd.services.firezone-ipc-service = {
|
||||
description = "GUI IPC service for the Firezone zero-trust access platform";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
path = [ pkgs.util-linux ];
|
||||
script = ''
|
||||
# If FIREZONE_ID is not given by the user, use a persisted (or newly generated) uuid.
|
||||
if [[ -z "''${FIREZONE_ID:-}" ]]; then
|
||||
if [[ ! -e client_id ]]; then
|
||||
uuidgen -r > client_id
|
||||
fi
|
||||
export FIREZONE_ID=$(< client_id)
|
||||
fi
|
||||
|
||||
exec ${getExe' cfg.package "firezone-client-ipc"} run
|
||||
'';
|
||||
|
||||
environment = {
|
||||
FIREZONE_NAME = cfg.name;
|
||||
LOG_DIR = "%L/dev.firezone.client";
|
||||
RUST_LOG = cfg.logLevel;
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
Type = "notify";
|
||||
|
||||
DeviceAllow = "/dev/net/tun";
|
||||
AmbientCapabilities = [ "CAP_NET_ADMIN" ];
|
||||
CapabilityBoundingSet = [ "CAP_NET_ADMIN" ];
|
||||
|
||||
# This block contains hardcoded values in the client, we cannot change these :(
|
||||
Group = "firezone-client";
|
||||
RuntimeDirectory = "dev.firezone.client";
|
||||
StateDirectory = "dev.firezone.client";
|
||||
WorkingDirectory = "/var/lib/dev.firezone.client";
|
||||
LogsDirectory = "dev.firezone.client";
|
||||
|
||||
Restart = "on-failure";
|
||||
RestartSec = 10;
|
||||
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = false;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_NETLINK"
|
||||
"AF_UNIX"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "@system-service";
|
||||
UMask = "077";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
oddlama
|
||||
patrickdag
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
boolToString
|
||||
getExe
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.services.firezone.headless-client;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.firezone.headless-client = {
|
||||
enable = mkEnableOption "the firezone headless client";
|
||||
package = mkPackageOption pkgs "firezone-headless-client" { };
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
description = "The name of this client as shown in firezone";
|
||||
};
|
||||
|
||||
apiUrl = mkOption {
|
||||
type = types.strMatching "^wss://.+/$";
|
||||
example = "wss://firezone.example.com/api/";
|
||||
description = ''
|
||||
The URL of your firezone server's API. This should be the same
|
||||
as your server's setting for {option}`services.firezone.server.settings.api.externalUrl`,
|
||||
but with `wss://` instead of `https://`.
|
||||
'';
|
||||
};
|
||||
|
||||
tokenFile = mkOption {
|
||||
type = types.path;
|
||||
example = "/run/secrets/firezone-client-token";
|
||||
description = ''
|
||||
A file containing the firezone client token. Do not use a nix-store path here
|
||||
as it will make the token publicly readable!
|
||||
|
||||
This file will be passed via systemd credentials, it should only be accessible
|
||||
by the root user.
|
||||
'';
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = types.str;
|
||||
default = "info";
|
||||
description = ''
|
||||
The log level for the firezone application. See
|
||||
[RUST_LOG](https://docs.rs/env_logger/latest/env_logger/#enabling-logging)
|
||||
for the format.
|
||||
'';
|
||||
};
|
||||
|
||||
enableTelemetry = mkEnableOption "telemetry";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.firezone-headless-client = {
|
||||
description = "headless client service for the Firezone zero-trust access platform";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
path = [ pkgs.util-linux ];
|
||||
script = ''
|
||||
# If FIREZONE_ID is not given by the user, use a persisted (or newly generated) uuid.
|
||||
if [[ -z "''${FIREZONE_ID:-}" ]]; then
|
||||
if [[ ! -e client_id ]]; then
|
||||
uuidgen -r > client_id
|
||||
fi
|
||||
export FIREZONE_ID=$(< client_id)
|
||||
fi
|
||||
|
||||
exec ${getExe cfg.package}
|
||||
'';
|
||||
|
||||
environment = {
|
||||
FIREZONE_API_URL = cfg.apiUrl;
|
||||
FIREZONE_NAME = cfg.name;
|
||||
FIREZONE_NO_TELEMETRY = boolToString (!cfg.enableTelemetry);
|
||||
FIREZONE_TOKEN_PATH = "%d/firezone-token";
|
||||
LOG_DIR = "%L/dev.firezone.client";
|
||||
RUST_LOG = cfg.logLevel;
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
LoadCredential = [ "firezone-token:${cfg.tokenFile}" ];
|
||||
|
||||
DeviceAllow = "/dev/net/tun";
|
||||
AmbientCapabilities = [ "CAP_NET_ADMIN" ];
|
||||
CapabilityBoundingSet = [ "CAP_NET_ADMIN" ];
|
||||
|
||||
# Hardcoded values in the client :(
|
||||
RuntimeDirectory = "dev.firezone.client";
|
||||
StateDirectory = "dev.firezone.client";
|
||||
WorkingDirectory = "/var/lib/dev.firezone.client";
|
||||
LogsDirectory = "dev.firezone.client";
|
||||
|
||||
Restart = "on-failure";
|
||||
RestartSec = 10;
|
||||
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = false;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_NETLINK"
|
||||
"AF_UNIX"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "@system-service";
|
||||
UMask = "077";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
oddlama
|
||||
patrickdag
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,709 @@
|
||||
defmodule Provision do
|
||||
alias Domain.{Repo, Accounts, Auth, Actors, Resources, Tokens, Gateways, Relays, Policies}
|
||||
require Logger
|
||||
|
||||
# UUID Mapping handling
|
||||
defmodule UuidMapping do
|
||||
@mapping_file "provision-uuids.json"
|
||||
|
||||
# Loads the mapping from file
|
||||
def load do
|
||||
mappings = case File.read(@mapping_file) do
|
||||
{:ok, content} ->
|
||||
case Jason.decode(content) do
|
||||
{:ok, mapping} -> mapping
|
||||
_ -> %{"accounts" => %{}}
|
||||
end
|
||||
|
||||
_ -> %{"accounts" => %{}}
|
||||
end
|
||||
Process.put(:uuid_mappings, mappings)
|
||||
mappings
|
||||
end
|
||||
|
||||
# Saves the current mapping (defaulting to the one in the process dictionary)
|
||||
def save(mapping \\ Process.get(:uuid_mappings)) do
|
||||
File.write!(@mapping_file, Jason.encode!(mapping))
|
||||
end
|
||||
|
||||
# Retrieves the account-level mapping from a given mapping (or from Process)
|
||||
def get_account(mapping \\ Process.get(:uuid_mappings), account_slug) do
|
||||
get_in(mapping, ["accounts", account_slug]) || %{}
|
||||
end
|
||||
|
||||
# Retrieves the entity mapping for a specific account and type
|
||||
def get_entities(mapping \\ Process.get(:uuid_mappings), account_slug, type) do
|
||||
get_in(mapping, ["accounts", account_slug, type]) || %{}
|
||||
end
|
||||
|
||||
# Retrieves an entity mapping for a specific account, type and external_id
|
||||
def get_entity(mapping \\ Process.get(:uuid_mappings), account_slug, type, external_id) do
|
||||
get_in(mapping, ["accounts", account_slug, type, external_id])
|
||||
end
|
||||
|
||||
# Updates (or creates) the account UUID mapping and stores it in the process dictionary.
|
||||
def update_account(account_slug, uuid) do
|
||||
mapping = Process.get(:uuid_mappings) || load()
|
||||
mapping = ensure_account_exists(mapping, account_slug)
|
||||
mapping = put_in(mapping, ["accounts", account_slug, "id"], uuid)
|
||||
Process.put(:uuid_mappings, mapping)
|
||||
mapping
|
||||
end
|
||||
|
||||
# Ensures that the given account exists in the mapping.
|
||||
def ensure_account_exists(mapping, account_slug) do
|
||||
if not Map.has_key?(mapping["accounts"], account_slug) do
|
||||
put_in(mapping, ["accounts", account_slug], %{})
|
||||
else
|
||||
mapping
|
||||
end
|
||||
end
|
||||
|
||||
# Updates (or creates) the mapping for entities of a given type for the account.
|
||||
def update_entities(account_slug, type, new_entries) do
|
||||
mapping = Process.get(:uuid_mappings) || load()
|
||||
mapping = ensure_account_exists(mapping, account_slug)
|
||||
current = get_entities(mapping, account_slug, type)
|
||||
mapping = put_in(mapping, ["accounts", account_slug, type], Map.merge(current, new_entries))
|
||||
Process.put(:uuid_mappings, mapping)
|
||||
mapping
|
||||
end
|
||||
|
||||
# Removes an entire account from the mapping.
|
||||
def remove_account(account_slug) do
|
||||
mapping = Process.get(:uuid_mappings) || load()
|
||||
mapping = update_in(mapping, ["accounts"], fn accounts ->
|
||||
Map.delete(accounts, account_slug)
|
||||
end)
|
||||
Process.put(:uuid_mappings, mapping)
|
||||
mapping
|
||||
end
|
||||
|
||||
# Removes a specific entity mapping for the account.
|
||||
def remove_entity(account_slug, type, key) do
|
||||
mapping = Process.get(:uuid_mappings) || load()
|
||||
mapping = update_in(mapping, ["accounts", account_slug, type], fn entities ->
|
||||
Map.delete(entities || %{}, key)
|
||||
end)
|
||||
Process.put(:uuid_mappings, mapping)
|
||||
mapping
|
||||
end
|
||||
end
|
||||
|
||||
defp resolve_references(value) when is_map(value) do
|
||||
Enum.into(value, %{}, fn {k, v} -> {k, resolve_references(v)} end)
|
||||
end
|
||||
|
||||
defp resolve_references(value) when is_list(value) do
|
||||
Enum.map(value, &resolve_references/1)
|
||||
end
|
||||
|
||||
defp resolve_references(value) when is_binary(value) do
|
||||
Regex.replace(~r/\{env:([^}]+)\}/, value, fn _, var ->
|
||||
System.get_env(var) || raise "Environment variable #{var} not set"
|
||||
end)
|
||||
end
|
||||
|
||||
defp resolve_references(value), do: value
|
||||
|
||||
defp atomize_keys(map) when is_map(map) do
|
||||
Enum.into(map, %{}, fn {k, v} ->
|
||||
{
|
||||
if(is_binary(k), do: String.to_atom(k), else: k),
|
||||
if(is_map(v), do: atomize_keys(v), else: v)
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
defp cleanup_account(uuid) do
|
||||
case Accounts.fetch_account_by_id_or_slug(uuid) do
|
||||
{:ok, value} when value.deleted_at == nil ->
|
||||
Logger.info("Deleting removed account #{value.slug}")
|
||||
value |> Ecto.Changeset.change(%{ deleted_at: DateTime.utc_now() }) |> Repo.update!()
|
||||
_ -> :ok
|
||||
end
|
||||
end
|
||||
|
||||
defp cleanup_actor(uuid, subject) do
|
||||
case Actors.fetch_actor_by_id(uuid, subject) do
|
||||
{:ok, value} ->
|
||||
Logger.info("Deleting removed actor #{value.name}")
|
||||
{:ok, _} = Actors.delete_actor(value, subject)
|
||||
_ -> :ok
|
||||
end
|
||||
end
|
||||
|
||||
defp cleanup_provider(uuid, subject) do
|
||||
case Auth.fetch_provider_by_id(uuid, subject) do
|
||||
{:ok, value} ->
|
||||
Logger.info("Deleting removed provider #{value.name}")
|
||||
{:ok, _} = Auth.delete_provider(value, subject)
|
||||
_ -> :ok
|
||||
end
|
||||
end
|
||||
|
||||
defp cleanup_gateway_group(uuid, subject) do
|
||||
case Gateways.fetch_group_by_id(uuid, subject) do
|
||||
{:ok, value} ->
|
||||
Logger.info("Deleting removed gateway group #{value.name}")
|
||||
{:ok, _} = Gateways.delete_group(value, subject)
|
||||
_ -> :ok
|
||||
end
|
||||
end
|
||||
|
||||
defp cleanup_relay_group(uuid, subject) do
|
||||
case Relays.fetch_group_by_id(uuid, subject) do
|
||||
{:ok, value} ->
|
||||
Logger.info("Deleting removed relay group #{value.name}")
|
||||
{:ok, _} = Relays.delete_group(value, subject)
|
||||
_ -> :ok
|
||||
end
|
||||
end
|
||||
|
||||
defp cleanup_actor_group(uuid, subject) do
|
||||
case Actors.fetch_group_by_id(uuid, subject) do
|
||||
{:ok, value} ->
|
||||
Logger.info("Deleting removed actor group #{value.name}")
|
||||
{:ok, _} = Actors.delete_group(value, subject)
|
||||
_ -> :ok
|
||||
end
|
||||
end
|
||||
|
||||
# Fetch resource by uuid, but follow the chain of replacements if any
|
||||
defp fetch_resource(uuid, subject) do
|
||||
case Resources.fetch_resource_by_id(uuid, subject) do
|
||||
{:ok, resource} when resource.replaced_by_resource_id != nil -> fetch_resource(resource.replaced_by_resource_id, subject)
|
||||
v -> v
|
||||
end
|
||||
end
|
||||
|
||||
defp cleanup_resource(uuid, subject) do
|
||||
case fetch_resource(uuid, subject) do
|
||||
{:ok, value} when value.deleted_at == nil ->
|
||||
Logger.info("Deleting removed resource #{value.name}")
|
||||
{:ok, _} = Resources.delete_resource(value, subject)
|
||||
_ -> :ok
|
||||
end
|
||||
end
|
||||
|
||||
# Fetch policy by uuid, but follow the chain of replacements if any
|
||||
defp fetch_policy(uuid, subject) do
|
||||
case Policies.fetch_policy_by_id(uuid, subject) do
|
||||
{:ok, policy} when policy.replaced_by_policy_id != nil -> fetch_policy(policy.replaced_by_policy_id, subject)
|
||||
v -> v
|
||||
end
|
||||
end
|
||||
|
||||
defp cleanup_policy(uuid, subject) do
|
||||
case fetch_policy(uuid, subject) do
|
||||
{:ok, value} when value.deleted_at == nil ->
|
||||
Logger.info("Deleting removed policy #{value.description}")
|
||||
{:ok, _} = Policies.delete_policy(value, subject)
|
||||
_ -> :ok
|
||||
end
|
||||
end
|
||||
|
||||
defp cleanup_entity_type(account_slug, entity_type, cleanup_fn, temp_admin_subject) do
|
||||
# Get mapping for this entity type
|
||||
existing_entities = UuidMapping.get_entities(account_slug, entity_type)
|
||||
# Get current entities from account data
|
||||
current_entities = Process.get(:current_entities)
|
||||
# Determine which ones to remove
|
||||
removed_entity_ids = Map.keys(existing_entities) -- (current_entities[entity_type] || [])
|
||||
|
||||
# Process each entity to remove
|
||||
Enum.each(removed_entity_ids, fn entity_id ->
|
||||
case existing_entities[entity_id] do
|
||||
nil -> :ok
|
||||
uuid ->
|
||||
cleanup_fn.(uuid, temp_admin_subject)
|
||||
UuidMapping.remove_entity(account_slug, entity_type, entity_id)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
defp collect_current_entities(account_data) do
|
||||
%{
|
||||
"actors" => Map.keys(account_data["actors"] || %{}),
|
||||
"providers" => Map.keys(account_data["auth"] || %{}),
|
||||
"gateway_groups" => Map.keys(account_data["gatewayGroups"] || %{}),
|
||||
"relay_groups" => Map.keys(account_data["relayGroups"] || %{}),
|
||||
"actor_groups" => Map.keys(account_data["groups"] || %{}) ++ ["everyone"],
|
||||
"resources" => Map.keys(account_data["resources"] || %{}),
|
||||
"policies" => Map.keys(account_data["policies"] || %{})
|
||||
}
|
||||
end
|
||||
|
||||
defp nil_if_deleted_or_not_found(value) do
|
||||
case value do
|
||||
nil -> nil
|
||||
{:error, :not_found} -> nil
|
||||
{:ok, value} when value.deleted_at != nil -> nil
|
||||
v -> v
|
||||
end
|
||||
end
|
||||
|
||||
defp create_temp_admin(account, email_provider) do
|
||||
temp_admin_actor_email = "firezone-provision@localhost.local"
|
||||
temp_admin_actor_context = %Auth.Context{
|
||||
type: :browser,
|
||||
user_agent: "Unspecified/0.0",
|
||||
remote_ip: {127, 0, 0, 1},
|
||||
remote_ip_location_region: "N/A",
|
||||
remote_ip_location_city: "N/A",
|
||||
remote_ip_location_lat: 0.0,
|
||||
remote_ip_location_lon: 0.0
|
||||
}
|
||||
|
||||
{:ok, temp_admin_actor} =
|
||||
Actors.create_actor(account, %{
|
||||
type: :account_admin_user,
|
||||
name: "Provisioning"
|
||||
})
|
||||
|
||||
{:ok, temp_admin_actor_email_identity} =
|
||||
Auth.create_identity(temp_admin_actor, email_provider, %{
|
||||
provider_identifier: temp_admin_actor_email,
|
||||
provider_identifier_confirmation: temp_admin_actor_email
|
||||
})
|
||||
|
||||
{:ok, temp_admin_actor_token} =
|
||||
Auth.create_token(temp_admin_actor_email_identity, temp_admin_actor_context, "temporarynonce", DateTime.utc_now() |> DateTime.add(1, :hour))
|
||||
|
||||
{:ok, temp_admin_subject} =
|
||||
Auth.build_subject(temp_admin_actor_token, temp_admin_actor_context)
|
||||
|
||||
{temp_admin_subject, temp_admin_actor, temp_admin_actor_email_identity, temp_admin_actor_token}
|
||||
end
|
||||
|
||||
defp cleanup_temp_admin(temp_admin_actor, temp_admin_actor_email_identity, temp_admin_actor_token, subject) do
|
||||
Logger.info("Cleaning up temporary admin actor")
|
||||
{:ok, _} = Tokens.delete_token(temp_admin_actor_token, subject)
|
||||
{:ok, _} = Auth.delete_identity(temp_admin_actor_email_identity, subject)
|
||||
{:ok, _} = Actors.delete_actor(temp_admin_actor, subject)
|
||||
end
|
||||
|
||||
def provision() do
|
||||
Logger.info("Starting provisioning")
|
||||
|
||||
# Load desired state
|
||||
json_file = "provision-state.json"
|
||||
{:ok, raw_json} = File.read(json_file)
|
||||
{:ok, %{"accounts" => accounts}} = Jason.decode(raw_json)
|
||||
accounts = resolve_references(accounts)
|
||||
|
||||
# Load existing UUID mappings into the process dictionary.
|
||||
UuidMapping.load()
|
||||
|
||||
# Clean up removed accounts first
|
||||
current_account_slugs = Map.keys(accounts)
|
||||
existing_accounts = Map.keys(Process.get(:uuid_mappings)["accounts"])
|
||||
removed_accounts = existing_accounts -- current_account_slugs
|
||||
|
||||
Enum.each(removed_accounts, fn slug ->
|
||||
if uuid = get_in(Process.get(:uuid_mappings), ["accounts", slug, "id"]) do
|
||||
cleanup_account(uuid)
|
||||
# Remove the account from the UUID mapping.
|
||||
UuidMapping.remove_account(slug)
|
||||
end
|
||||
end)
|
||||
|
||||
multi = Enum.reduce(accounts, Ecto.Multi.new(), fn {slug, account_data}, multi ->
|
||||
account_attrs = atomize_keys(%{
|
||||
name: account_data["name"],
|
||||
slug: slug,
|
||||
features: Map.get(account_data, "features", %{}),
|
||||
metadata: Map.get(account_data, "metadata", %{}),
|
||||
limits: Map.get(account_data, "limits", %{})
|
||||
})
|
||||
|
||||
multi = multi
|
||||
|> Ecto.Multi.run({:account, slug}, fn repo, _changes ->
|
||||
case Accounts.fetch_account_by_id_or_slug(slug) do
|
||||
{:ok, acc} ->
|
||||
Logger.info("Updating existing account #{slug}")
|
||||
updated_acc = acc |> Ecto.Changeset.change(account_attrs) |> repo.update!()
|
||||
{:ok, {:existing, updated_acc}}
|
||||
_ ->
|
||||
Logger.info("Creating new account #{slug}")
|
||||
{:ok, account} = Accounts.create_account(account_attrs)
|
||||
|
||||
Logger.info("Creating internet gateway group")
|
||||
{:ok, internet_site} = Gateways.create_internet_group(account)
|
||||
|
||||
Logger.info("Creating internet resource")
|
||||
{:ok, _internet_resource} = Resources.create_internet_resource(account, internet_site)
|
||||
|
||||
# Store mapping of slug to UUID
|
||||
UuidMapping.update_account(slug, account.id)
|
||||
{:ok, {:new, account}}
|
||||
end
|
||||
end)
|
||||
|> Ecto.Multi.run({:everyone_group, slug}, fn _repo, changes ->
|
||||
case Map.get(changes, {:account, slug}) do
|
||||
{:new, account} ->
|
||||
Logger.info("Creating everyone group for new account")
|
||||
{:ok, actor_group} = Actors.create_managed_group(account, %{name: "Everyone", membership_rules: [%{operator: true}]})
|
||||
UuidMapping.update_entities(slug, "actor_groups", %{"everyone" => actor_group.id})
|
||||
{:ok, actor_group}
|
||||
{:existing, _account} ->
|
||||
{:ok, :skipped}
|
||||
end
|
||||
end)
|
||||
|> Ecto.Multi.run({:email_provider, slug}, fn _repo, changes ->
|
||||
case Map.get(changes, {:account, slug}) do
|
||||
{:new, account} ->
|
||||
Logger.info("Creating default email provider for new account")
|
||||
Auth.create_provider(account, %{name: "Email", adapter: :email, adapter_config: %{}})
|
||||
{:existing, account} ->
|
||||
Auth.Provider.Query.not_disabled()
|
||||
|> Auth.Provider.Query.by_adapter(:email)
|
||||
|> Auth.Provider.Query.by_account_id(account.id)
|
||||
|> Repo.fetch(Auth.Provider.Query, [])
|
||||
end
|
||||
end)
|
||||
|> Ecto.Multi.run({:temp_admin, slug}, fn _repo, changes ->
|
||||
{_, account} = changes[{:account, slug}]
|
||||
email_provider = changes[{:email_provider, slug}]
|
||||
{:ok, create_temp_admin(account, email_provider)}
|
||||
end)
|
||||
|
||||
# Clean up removed entities for this account after we have an admin subject
|
||||
multi = multi
|
||||
|> Ecto.Multi.run({:cleanup_entities, slug}, fn _repo, changes ->
|
||||
{temp_admin_subject, _, _, _} = changes[{:temp_admin, slug}]
|
||||
|
||||
# Store current entities in process dictionary for our helper function
|
||||
current_entities = collect_current_entities(account_data)
|
||||
Process.put(:current_entities, current_entities)
|
||||
|
||||
# Define entity types and their cleanup functions
|
||||
entity_types = [
|
||||
{"actors", &cleanup_actor/2},
|
||||
{"providers", &cleanup_provider/2},
|
||||
{"gateway_groups", &cleanup_gateway_group/2},
|
||||
{"relay_groups", &cleanup_relay_group/2},
|
||||
{"actor_groups", &cleanup_actor_group/2},
|
||||
{"resources", &cleanup_resource/2},
|
||||
{"policies", &cleanup_policy/2}
|
||||
]
|
||||
|
||||
# Clean up each entity type
|
||||
Enum.each(entity_types, fn {entity_type, cleanup_fn} ->
|
||||
cleanup_entity_type(slug, entity_type, cleanup_fn, temp_admin_subject)
|
||||
end)
|
||||
|
||||
{:ok, :cleaned}
|
||||
end)
|
||||
|
||||
# Create or update actors
|
||||
multi = Enum.reduce(account_data["actors"] || %{}, multi, fn {external_id, actor_data}, multi ->
|
||||
actor_attrs = atomize_keys(%{
|
||||
name: actor_data["name"],
|
||||
type: String.to_atom(actor_data["type"])
|
||||
})
|
||||
|
||||
Ecto.Multi.run(multi, {:actor, slug, external_id}, fn _repo, changes ->
|
||||
{_, account} = changes[{:account, slug}]
|
||||
{temp_admin_subject, _, _, _} = changes[{:temp_admin, slug}]
|
||||
uuid = UuidMapping.get_entity(slug, "actors", external_id)
|
||||
case uuid && Actors.fetch_actor_by_id(uuid, temp_admin_subject) |> nil_if_deleted_or_not_found() do
|
||||
nil ->
|
||||
Logger.info("Creating new actor #{actor_data["name"]}")
|
||||
{:ok, actor} = Actors.create_actor(account, actor_attrs)
|
||||
# Update the mapping without manually handling Process.get/put.
|
||||
UuidMapping.update_entities(slug, "actors", %{external_id => actor.id})
|
||||
{:ok, {:new, actor}}
|
||||
{:ok, existing_actor} ->
|
||||
Logger.info("Updating existing actor #{actor_data["name"]}")
|
||||
{:ok, updated_act} = Actors.update_actor(existing_actor, actor_attrs, temp_admin_subject)
|
||||
{:ok, {:existing, updated_act}}
|
||||
end
|
||||
end)
|
||||
|> Ecto.Multi.run({:actor_identity, slug, external_id}, fn repo, changes ->
|
||||
email_provider = changes[{:email_provider, slug}]
|
||||
case Map.get(changes, {:actor, slug, external_id}) do
|
||||
{:new, actor} ->
|
||||
Logger.info("Creating actor email identity")
|
||||
Auth.create_identity(actor, email_provider, %{
|
||||
provider_identifier: actor_data["email"],
|
||||
provider_identifier_confirmation: actor_data["email"]
|
||||
})
|
||||
{:existing, actor} ->
|
||||
Logger.info("Updating actor email identity")
|
||||
{:ok, identity} = Auth.Identity.Query.not_deleted()
|
||||
|> Auth.Identity.Query.by_actor_id(actor.id)
|
||||
|> Auth.Identity.Query.by_provider_id(email_provider.id)
|
||||
|> Repo.fetch(Auth.Identity.Query, [])
|
||||
|
||||
{:ok, identity |> Ecto.Changeset.change(%{
|
||||
provider_identifier: actor_data["email"]
|
||||
}) |> repo.update!()}
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
# Create or update providers
|
||||
multi = Enum.reduce(account_data["auth"] || %{}, multi, fn {external_id, provider_data}, multi ->
|
||||
Ecto.Multi.run(multi, {:provider, slug, external_id}, fn repo, changes ->
|
||||
provider_attrs = %{
|
||||
name: provider_data["name"],
|
||||
adapter: String.to_atom(provider_data["adapter"]),
|
||||
adapter_config: provider_data["adapter_config"]
|
||||
}
|
||||
|
||||
{_, account} = changes[{:account, slug}]
|
||||
{temp_admin_subject, _, _, _} = changes[{:temp_admin, slug}]
|
||||
uuid = UuidMapping.get_entity(slug, "providers", external_id)
|
||||
case uuid && Auth.fetch_provider_by_id(uuid, temp_admin_subject) |> nil_if_deleted_or_not_found() do
|
||||
nil ->
|
||||
Logger.info("Creating new provider #{provider_data["name"]}")
|
||||
{:ok, provider} = Auth.create_provider(account, provider_attrs)
|
||||
UuidMapping.update_entities(slug, "providers", %{external_id => provider.id})
|
||||
{:ok, provider}
|
||||
{:ok, existing} ->
|
||||
Logger.info("Updating existing provider #{provider_data["name"]}")
|
||||
{:ok, existing |> Ecto.Changeset.change(provider_attrs) |> repo.update!()}
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
# Create or update gateway_groups
|
||||
multi = Enum.reduce(account_data["gatewayGroups"] || %{}, multi, fn {external_id, gateway_group_data}, multi ->
|
||||
Ecto.Multi.run(multi, {:gateway_group, slug, external_id}, fn _repo, changes ->
|
||||
gateway_group_attrs = %{
|
||||
name: gateway_group_data["name"],
|
||||
tokens: [%{}]
|
||||
}
|
||||
|
||||
{_, account} = changes[{:account, slug}]
|
||||
{temp_admin_subject, _, _, _} = changes[{:temp_admin, slug}]
|
||||
uuid = UuidMapping.get_entity(slug, "gateway_groups", external_id)
|
||||
case uuid && Gateways.fetch_group_by_id(uuid, temp_admin_subject) |> nil_if_deleted_or_not_found() do
|
||||
nil ->
|
||||
Logger.info("Creating new gateway group #{gateway_group_data["name"]}")
|
||||
gateway_group = account
|
||||
|> Gateways.Group.Changeset.create(gateway_group_attrs, temp_admin_subject)
|
||||
|> Repo.insert!()
|
||||
UuidMapping.update_entities(slug, "gateway_groups", %{external_id => gateway_group.id})
|
||||
{:ok, gateway_group}
|
||||
{:ok, existing} ->
|
||||
# Nothing to update
|
||||
{:ok, existing}
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
# Create or update relay_groups
|
||||
multi = Enum.reduce(account_data["relayGroups"] || %{}, multi, fn {external_id, relay_group_data}, multi ->
|
||||
Ecto.Multi.run(multi, {:relay_group, slug, external_id}, fn _repo, changes ->
|
||||
relay_group_attrs = %{
|
||||
name: relay_group_data["name"]
|
||||
}
|
||||
|
||||
{temp_admin_subject, _, _, _} = changes[{:temp_admin, slug}]
|
||||
uuid = UuidMapping.get_entity(slug, "relay_groups", external_id)
|
||||
existing_relay_group = uuid && Relays.fetch_group_by_id(uuid, temp_admin_subject)
|
||||
case existing_relay_group do
|
||||
v when v in [nil, {:error, :not_found}] ->
|
||||
Logger.info("Creating new relay group #{relay_group_data["name"]}")
|
||||
{:ok, relay_group} = Relays.create_group(relay_group_attrs, temp_admin_subject)
|
||||
UuidMapping.update_entities(slug, "relay_groups", %{external_id => relay_group.id})
|
||||
{:ok, relay_group}
|
||||
{:ok, existing} ->
|
||||
# Nothing to update
|
||||
{:ok, existing}
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
# Create or update actor_groups
|
||||
multi = Enum.reduce(account_data["groups"] || %{}, multi, fn {external_id, actor_group_data}, multi ->
|
||||
Ecto.Multi.run(multi, {:actor_group, slug, external_id}, fn _repo, changes ->
|
||||
actor_group_attrs = %{
|
||||
name: actor_group_data["name"],
|
||||
type: :static
|
||||
}
|
||||
|
||||
{temp_admin_subject, _, _, _} = changes[{:temp_admin, slug}]
|
||||
uuid = UuidMapping.get_entity(slug, "actor_groups", external_id)
|
||||
case uuid && Actors.fetch_group_by_id(uuid, temp_admin_subject) |> nil_if_deleted_or_not_found() do
|
||||
nil ->
|
||||
Logger.info("Creating new actor group #{actor_group_data["name"]}")
|
||||
{:ok, actor_group} = Actors.create_group(actor_group_attrs, temp_admin_subject)
|
||||
UuidMapping.update_entities(slug, "actor_groups", %{external_id => actor_group.id})
|
||||
{:ok, actor_group}
|
||||
{:ok, existing} ->
|
||||
# Nothing to update
|
||||
{:ok, existing}
|
||||
end
|
||||
end)
|
||||
|> Ecto.Multi.run({:actor_group_members, slug, external_id}, fn repo, changes ->
|
||||
{_, account} = changes[{:account, slug}]
|
||||
group_uuid = UuidMapping.get_entity(slug, "actor_groups", external_id)
|
||||
|
||||
memberships =
|
||||
Actors.Membership.Query.all()
|
||||
|> Actors.Membership.Query.by_group_id(group_uuid)
|
||||
|> Actors.Membership.Query.returning_all()
|
||||
|> Repo.all()
|
||||
|
||||
existing_members = Enum.map(memberships, fn membership -> membership.actor_id end)
|
||||
desired_members = Enum.map(actor_group_data["members"] || [], fn member ->
|
||||
uuid = UuidMapping.get_entity(slug, "actors", member)
|
||||
if uuid == nil do
|
||||
raise "Cannot find provisioned actor #{member} to add to group"
|
||||
end
|
||||
uuid
|
||||
end)
|
||||
|
||||
missing_members = desired_members -- existing_members
|
||||
untracked_members = existing_members -- desired_members
|
||||
|
||||
Logger.info("Updating members for actor group #{external_id}")
|
||||
Enum.each(missing_members || [], fn actor_uuid ->
|
||||
Logger.info("Adding member #{external_id}")
|
||||
Actors.Membership.Changeset.upsert(account.id, %Actors.Membership{}, %{
|
||||
group_id: group_uuid,
|
||||
actor_id: actor_uuid
|
||||
})
|
||||
|> repo.insert!()
|
||||
end)
|
||||
|
||||
if actor_group_data["forceMembers"] == true do
|
||||
# Remove untracked members
|
||||
to_delete = Enum.map(untracked_members, fn actor_uuid -> {group_uuid, actor_uuid} end)
|
||||
if to_delete != [] do
|
||||
Actors.Membership.Query.by_group_id_and_actor_id({:in, to_delete})
|
||||
|> repo.delete_all()
|
||||
end
|
||||
end
|
||||
|
||||
{:ok, nil}
|
||||
end)
|
||||
end)
|
||||
|
||||
# Create or update resources
|
||||
multi = Enum.reduce(account_data["resources"] || %{}, multi, fn {external_id, resource_data}, multi ->
|
||||
Ecto.Multi.run(multi, {:resource, slug, external_id}, fn _repo, changes ->
|
||||
resource_attrs = %{
|
||||
type: String.to_atom(resource_data["type"]),
|
||||
name: resource_data["name"],
|
||||
address: resource_data["address"],
|
||||
address_description: resource_data["address_description"],
|
||||
connections: Enum.map(resource_data["gatewayGroups"] || [], fn group ->
|
||||
%{gateway_group_id: UuidMapping.get_entity(slug, "gateway_groups", group)}
|
||||
end),
|
||||
filters: Enum.map(resource_data["filters"] || [], fn filter ->
|
||||
%{
|
||||
ports: filter["ports"] || [],
|
||||
protocol: String.to_atom(filter["protocol"])
|
||||
}
|
||||
end)
|
||||
}
|
||||
|
||||
{temp_admin_subject, _, _, _} = changes[{:temp_admin, slug}]
|
||||
uuid = UuidMapping.get_entity(slug, "resources", external_id)
|
||||
case uuid && fetch_resource(uuid, temp_admin_subject) |> nil_if_deleted_or_not_found() do
|
||||
nil ->
|
||||
Logger.info("Creating new resource #{resource_data["name"]}")
|
||||
{:ok, resource} = Resources.create_resource(resource_attrs, temp_admin_subject)
|
||||
UuidMapping.update_entities(slug, "resources", %{external_id => resource.id})
|
||||
{:ok, resource}
|
||||
{:ok, existing} ->
|
||||
existing = Repo.preload(existing, :connections)
|
||||
Logger.info("Updating existing resource #{resource_data["name"]}")
|
||||
only_updated_attrs = resource_attrs
|
||||
|> Enum.reject(fn {key, value} ->
|
||||
case key do
|
||||
# Compare connections by gateway_group_id only
|
||||
:connections -> value == Enum.map(existing.connections || [], fn conn -> Map.take(conn, [:gateway_group_id]) end)
|
||||
# Compare filters by ports and protocol only
|
||||
:filters -> value == Enum.map(existing.filters || [], fn filter -> Map.take(filter, [:ports, :protocol]) end)
|
||||
_ -> Map.get(existing, key) == value
|
||||
end
|
||||
end)
|
||||
|> Enum.into(%{})
|
||||
|
||||
if only_updated_attrs == %{} do
|
||||
{:ok, existing}
|
||||
else
|
||||
resource = case existing |> Resources.update_resource(resource_attrs, temp_admin_subject) do
|
||||
{:replaced, _old, new} ->
|
||||
UuidMapping.update_entities(slug, "resources", %{external_id => new.id})
|
||||
new
|
||||
{:updated, value} -> value
|
||||
x -> x
|
||||
end
|
||||
|
||||
{:ok, resource}
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
# Create or update policies
|
||||
multi = Enum.reduce(account_data["policies"] || %{}, multi, fn {external_id, policy_data}, multi ->
|
||||
Ecto.Multi.run(multi, {:policy, slug, external_id}, fn _repo, changes ->
|
||||
policy_attrs = %{
|
||||
description: policy_data["description"],
|
||||
actor_group_id: UuidMapping.get_entity(slug, "actor_groups", policy_data["group"]),
|
||||
resource_id: UuidMapping.get_entity(slug, "resources", policy_data["resource"])
|
||||
}
|
||||
|
||||
{temp_admin_subject, _, _, _} = changes[{:temp_admin, slug}]
|
||||
uuid = UuidMapping.get_entity(slug, "policies", external_id)
|
||||
case uuid && fetch_policy(uuid, temp_admin_subject) |> nil_if_deleted_or_not_found() do
|
||||
nil ->
|
||||
Logger.info("Creating new policy #{policy_data["name"]}")
|
||||
{:ok, policy} = Policies.create_policy(policy_attrs, temp_admin_subject)
|
||||
UuidMapping.update_entities(slug, "policies", %{external_id => policy.id})
|
||||
{:ok, policy}
|
||||
{:ok, existing} ->
|
||||
Logger.info("Updating existing policy #{policy_data["name"]}")
|
||||
only_updated_attrs = policy_attrs
|
||||
|> Enum.reject(fn {key, value} -> Map.get(existing, key) == value end)
|
||||
|> Enum.into(%{})
|
||||
|
||||
if only_updated_attrs == %{} do
|
||||
{:ok, existing}
|
||||
else
|
||||
policy = case existing |> Policies.update_policy(policy_attrs, temp_admin_subject) do
|
||||
{:replaced, _old, new} ->
|
||||
UuidMapping.update_entities(slug, "policies", %{external_id => new.id})
|
||||
new
|
||||
{:updated, value} -> value
|
||||
x -> x
|
||||
end
|
||||
|
||||
{:ok, policy}
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
# Clean up temporary admin after all operations
|
||||
multi |> Ecto.Multi.run({:cleanup_temp_admin, slug}, fn _repo, changes ->
|
||||
{temp_admin_subject, temp_admin_actor, temp_admin_actor_email_identity, temp_admin_actor_token} =
|
||||
changes[{:temp_admin, slug}]
|
||||
|
||||
cleanup_temp_admin(temp_admin_actor, temp_admin_actor_email_identity, temp_admin_actor_token, temp_admin_subject)
|
||||
{:ok, :cleaned}
|
||||
end)
|
||||
end)
|
||||
|> Ecto.Multi.run({:save_state}, fn _repo, _changes ->
|
||||
# Save all UUID mappings to disk.
|
||||
UuidMapping.save()
|
||||
{:ok, :saved}
|
||||
end)
|
||||
|
||||
case Repo.transaction(multi) do
|
||||
{:ok, _result} ->
|
||||
Logger.info("Provisioning completed successfully")
|
||||
{:error, step, reason, _changes} ->
|
||||
Logger.error("Provisioning failed at step #{inspect(step)}, no changes were applied: #{inspect(reason)}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Provision.provision()
|
||||
@@ -0,0 +1,202 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
boolToString
|
||||
getExe
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
types
|
||||
;
|
||||
|
||||
cfg = config.services.firezone.relay;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.firezone.relay = {
|
||||
enable = mkEnableOption "the firezone relay server";
|
||||
package = mkPackageOption pkgs "firezone-relay" { };
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
example = "My relay";
|
||||
description = "The name of this gateway as shown in firezone";
|
||||
};
|
||||
|
||||
publicIpv4 = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "The public ipv4 address of this relay";
|
||||
};
|
||||
|
||||
publicIpv6 = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "The public ipv6 address of this relay";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Opens up the main STUN port and the TURN allocation range.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 3478;
|
||||
description = "The port to listen on for STUN messages";
|
||||
};
|
||||
|
||||
lowestPort = mkOption {
|
||||
type = types.port;
|
||||
default = 49152;
|
||||
description = "The lowest port to use in TURN allocation";
|
||||
};
|
||||
|
||||
highestPort = mkOption {
|
||||
type = types.port;
|
||||
default = 65535;
|
||||
description = "The highest port to use in TURN allocation";
|
||||
};
|
||||
|
||||
apiUrl = mkOption {
|
||||
type = types.strMatching "^wss://.+/$";
|
||||
example = "wss://firezone.example.com/api/";
|
||||
description = ''
|
||||
The URL of your firezone server's API. This should be the same
|
||||
as your server's setting for {option}`services.firezone.server.settings.api.externalUrl`,
|
||||
but with `wss://` instead of `https://`.
|
||||
'';
|
||||
};
|
||||
|
||||
tokenFile = mkOption {
|
||||
type = types.path;
|
||||
example = "/run/secrets/firezone-relay-token";
|
||||
description = ''
|
||||
A file containing the firezone relay token. Do not use a nix-store path here
|
||||
as it will make the token publicly readable!
|
||||
|
||||
This file will be passed via systemd credentials, it should only be accessible
|
||||
by the root user.
|
||||
'';
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = types.str;
|
||||
default = "info";
|
||||
description = ''
|
||||
The log level for the firezone application. See
|
||||
[RUST_LOG](https://docs.rs/env_logger/latest/env_logger/#enabling-logging)
|
||||
for the format.
|
||||
'';
|
||||
};
|
||||
|
||||
enableTelemetry = mkEnableOption "telemetry";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.publicIpv4 != null || cfg.publicIpv6 != null;
|
||||
message = "At least one of `services.firezone.relay.publicIpv4` and `services.firezone.relay.publicIpv6` must be set";
|
||||
}
|
||||
];
|
||||
|
||||
networking.firewall.allowedUDPPorts = mkIf cfg.openFirewall [ cfg.port ];
|
||||
networking.firewall.allowedUDPPortRanges = mkIf cfg.openFirewall [
|
||||
{
|
||||
from = cfg.lowestPort;
|
||||
to = cfg.highestPort;
|
||||
}
|
||||
];
|
||||
|
||||
systemd.services.firezone-relay = {
|
||||
description = "relay service for the Firezone zero-trust access platform";
|
||||
after = [ "network.target" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
path = [ pkgs.util-linux ];
|
||||
script = ''
|
||||
# If FIREZONE_ID is not given by the user, use a persisted (or newly generated) uuid.
|
||||
if [[ -z "''${FIREZONE_ID:-}" ]]; then
|
||||
if [[ ! -e relay_id ]]; then
|
||||
uuidgen -r > relay_id
|
||||
fi
|
||||
export FIREZONE_ID=$(< relay_id)
|
||||
fi
|
||||
|
||||
export FIREZONE_TOKEN=$(< "$CREDENTIALS_DIRECTORY/firezone-token")
|
||||
exec ${getExe cfg.package}
|
||||
'';
|
||||
|
||||
environment = {
|
||||
FIREZONE_API_URL = cfg.apiUrl;
|
||||
FIREZONE_NAME = cfg.name;
|
||||
FIREZONE_TELEMETRY = boolToString cfg.enableTelemetry;
|
||||
|
||||
PUBLIC_IP4_ADDR = cfg.publicIpv4;
|
||||
PUBLIC_IP6_ADDR = cfg.publicIpv6;
|
||||
|
||||
LISTEN_PORT = toString cfg.port;
|
||||
LOWEST_PORT = toString cfg.lowestPort;
|
||||
HIGHEST_PORT = toString cfg.highestPort;
|
||||
|
||||
RUST_LOG = cfg.logLevel;
|
||||
LOG_FORMAT = "human";
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
DynamicUser = true;
|
||||
User = "firezone-relay";
|
||||
LoadCredential = [ "firezone-token:${cfg.tokenFile}" ];
|
||||
|
||||
StateDirectory = "firezone-relay";
|
||||
WorkingDirectory = "/var/lib/firezone-relay";
|
||||
|
||||
Restart = "on-failure";
|
||||
RestartSec = 10;
|
||||
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = false;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_NETLINK"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = "@system-service";
|
||||
UMask = "077";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
oddlama
|
||||
patrickdag
|
||||
];
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,232 @@
|
||||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.services.prefect;
|
||||
inherit (lib.types)
|
||||
bool
|
||||
str
|
||||
enum
|
||||
path
|
||||
attrsOf
|
||||
nullOr
|
||||
submodule
|
||||
port
|
||||
;
|
||||
|
||||
in
|
||||
{
|
||||
options.services.prefect = {
|
||||
enable = lib.mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = "enable prefect server and worker services";
|
||||
};
|
||||
|
||||
package = lib.mkPackageOption pkgs "prefect" { };
|
||||
|
||||
host = lib.mkOption {
|
||||
type = str;
|
||||
default = "127.0.0.1";
|
||||
example = "0.0.0.0";
|
||||
description = "Prefect server host";
|
||||
};
|
||||
|
||||
port = lib.mkOption {
|
||||
type = port;
|
||||
default = 4200;
|
||||
description = "Prefect server port";
|
||||
};
|
||||
|
||||
dataDir = lib.mkOption {
|
||||
type = path;
|
||||
default = "/var/lib/prefect-server";
|
||||
description = ''
|
||||
Specify the directory for Prefect.
|
||||
'';
|
||||
};
|
||||
|
||||
database = lib.mkOption {
|
||||
type = enum [
|
||||
"sqlite"
|
||||
"postgres"
|
||||
];
|
||||
default = "sqlite";
|
||||
description = "which database to use for prefect server: sqlite or postgres";
|
||||
};
|
||||
|
||||
databaseHost = lib.mkOption {
|
||||
type = str;
|
||||
default = "localhost";
|
||||
description = "database host for postgres only";
|
||||
};
|
||||
|
||||
databasePort = lib.mkOption {
|
||||
type = str;
|
||||
default = "5432";
|
||||
description = "database port for postgres only";
|
||||
};
|
||||
|
||||
databaseName = lib.mkOption {
|
||||
type = str;
|
||||
default = "prefect";
|
||||
description = "database name for postgres only";
|
||||
};
|
||||
|
||||
databaseUser = lib.mkOption {
|
||||
type = str;
|
||||
default = "postgres";
|
||||
description = "database user for postgres only";
|
||||
};
|
||||
|
||||
databasePasswordFile = lib.mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
path to a file containing e.g.:
|
||||
DBPASSWORD=supersecret
|
||||
|
||||
stored outside the nix store, read by systemd as EnvironmentFile.
|
||||
'';
|
||||
};
|
||||
|
||||
# now define workerPools as an attribute set of submodules,
|
||||
# each key is the pool name, and the submodule has an installPolicy
|
||||
workerPools = lib.mkOption {
|
||||
type = attrsOf (submodule {
|
||||
options = {
|
||||
installPolicy = lib.mkOption {
|
||||
type = enum [
|
||||
"always"
|
||||
"if-not-present"
|
||||
"never"
|
||||
"prompt"
|
||||
];
|
||||
default = "always";
|
||||
description = "install policy for the worker (always, if-not-present, never, prompt)";
|
||||
};
|
||||
};
|
||||
});
|
||||
default = { };
|
||||
description = ''
|
||||
define a set of worker pools with submodule config. example:
|
||||
workerPools.my-pool = {
|
||||
installPolicy = "never";
|
||||
};
|
||||
'';
|
||||
};
|
||||
|
||||
baseUrl = lib.mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = "external url when served by a reverse proxy, e.g. https://example.com/prefect";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
# define systemd.services as the server plus any worker definitions
|
||||
systemd.services =
|
||||
{
|
||||
"prefect-server" = {
|
||||
description = "prefect server";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
StateDirectory = "prefect-server";
|
||||
# TODO all my efforts to setup the database url
|
||||
# have failed with some unable to open file
|
||||
Environment = [
|
||||
"PREFECT_HOME=%S/prefect-server"
|
||||
"PREFECT_UI_STATIC_DIRECTORY=%S/prefect-server"
|
||||
"PREFECT_SERVER_ANALYTICS_ENABLED=off"
|
||||
"PREFECT_UI_API_URL=${cfg.baseUrl}/api"
|
||||
"PREFECT_UI_URL=${cfg.baseUrl}"
|
||||
];
|
||||
EnvironmentFile =
|
||||
if cfg.database == "postgres" && cfg.databasePasswordFile != null then
|
||||
[ cfg.databasePasswordFile ]
|
||||
else
|
||||
[ ];
|
||||
|
||||
# ReadWritePaths = [ cfg.dataDir ];
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
NoNewPrivileges = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
LockPersonality = true;
|
||||
CapabilityBoundingSet = [ ];
|
||||
AmbientCapabilities = [ ];
|
||||
RestrictSUIDSGID = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_UNIX"
|
||||
];
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
MemoryAccounting = true;
|
||||
CPUAccounting = true;
|
||||
|
||||
ExecStart = "${pkgs.prefect}/bin/prefect server start --host ${cfg.host} --port ${toString cfg.port}";
|
||||
Restart = "always";
|
||||
WorkingDirectory = cfg.dataDir;
|
||||
};
|
||||
};
|
||||
}
|
||||
// lib.concatMapAttrs (poolName: poolCfg: {
|
||||
# return a partial attr set with one key: "prefect-worker-..."
|
||||
"prefect-worker-${poolName}" = {
|
||||
description = "prefect worker for pool '${poolName}'";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
environment.systemPackages = cfg.package;
|
||||
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
StateDirectory = "prefect-worker-${poolName}";
|
||||
Environment = [
|
||||
"PREFECT_HOME=%S/prefect-worker-${poolName}"
|
||||
"PREFECT_API_URL=${cfg.baseUrl}/api"
|
||||
];
|
||||
ProtectSystem = "strict";
|
||||
ProtectHome = true;
|
||||
PrivateTmp = true;
|
||||
NoNewPrivileges = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
LockPersonality = true;
|
||||
CapabilityBoundingSet = [ ];
|
||||
AmbientCapabilities = [ ];
|
||||
RestrictSUIDSGID = true;
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_UNIX"
|
||||
];
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
MemoryAccounting = true;
|
||||
CPUAccounting = true;
|
||||
ExecStart = ''
|
||||
${pkgs.prefect}/bin/prefect worker start \
|
||||
--pool ${poolName} \
|
||||
--type process \
|
||||
--install-policy ${poolCfg.installPolicy}
|
||||
'';
|
||||
Restart = "always";
|
||||
};
|
||||
};
|
||||
}) cfg.workerPools;
|
||||
};
|
||||
}
|
||||
@@ -75,9 +75,12 @@ in
|
||||
);
|
||||
|
||||
# Hardening
|
||||
AmbientCapabilities = "";
|
||||
CapabilityBoundingSet = [ "" ];
|
||||
DeviceAllow = [ "" ];
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
@@ -91,15 +94,19 @@ in
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_UNIX"
|
||||
];
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = [ "AF_INET AF_INET6 AF_UNIX" ];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
"~@resources"
|
||||
"setrlimit"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -107,9 +107,11 @@ in
|
||||
ExecStart = lib.getExe cfg.package;
|
||||
|
||||
# Hardening
|
||||
AmbientCapabilities = "";
|
||||
CapabilityBoundingSet = [ "" ];
|
||||
DeviceAllow = [ "" ];
|
||||
DevicePolicy = "closed";
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
@@ -123,15 +125,18 @@ in
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_UNIX"
|
||||
];
|
||||
RemoveIPC = true;
|
||||
RestrictAddressFamilies = [ "AF_INET AF_INET6 AF_UNIX AF_NETLINK" ];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~@privileged"
|
||||
"~@resources"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@ let
|
||||
kernel = config.system.modulesTree;
|
||||
firmware = config.hardware.firmware;
|
||||
allowMissing = false;
|
||||
inherit (config.boot.initrd) extraFirmwarePaths;
|
||||
};
|
||||
|
||||
|
||||
@@ -484,6 +485,14 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
boot.initrd.extraFirmwarePaths = mkOption {
|
||||
default = [ ];
|
||||
type = types.listOf types.str;
|
||||
description = ''
|
||||
Other firmware files (relative to `"''${config.hardware.firmware}/lib/firmware"`) to include in the final initrd we are building.
|
||||
'';
|
||||
};
|
||||
|
||||
boot.initrd.checkJournalingFS = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
|
||||
@@ -104,7 +104,7 @@ let
|
||||
"sleep.target"
|
||||
"hybrid-sleep.target"
|
||||
"systemd-hibernate.service"
|
||||
"systemd-hibernate-clear.service"
|
||||
] ++ (lib.optional cfg.package.withEfi "systemd-hibernate-clear.service") ++ [
|
||||
"systemd-hybrid-sleep.service"
|
||||
"systemd-suspend.service"
|
||||
"systemd-suspend-then-hibernate.service"
|
||||
@@ -130,11 +130,13 @@ let
|
||||
"systemd-ask-password-wall.service"
|
||||
|
||||
# Varlink APIs
|
||||
] ++ lib.optionals cfg.package.withBootloader [
|
||||
"systemd-bootctl@.service"
|
||||
"systemd-bootctl.socket"
|
||||
] ++ [
|
||||
"systemd-creds@.service"
|
||||
"systemd-creds.socket"
|
||||
] ++ lib.optional cfg.package.withTpm2Tss [
|
||||
] ++ lib.optional cfg.package.withTpm2Units [
|
||||
"systemd-pcrlock@.service"
|
||||
"systemd-pcrlock.socket"
|
||||
] ++ [
|
||||
|
||||
@@ -105,6 +105,7 @@ let
|
||||
kernel = config.system.modulesTree;
|
||||
firmware = config.hardware.firmware;
|
||||
allowMissing = false;
|
||||
inherit (config.boot.initrd) extraFirmwarePaths;
|
||||
};
|
||||
|
||||
initrdBinEnv = pkgs.buildEnv {
|
||||
@@ -703,10 +704,11 @@ in
|
||||
"|stage1panic"
|
||||
];
|
||||
};
|
||||
script = ''
|
||||
echo c > /proc/sysrq-trigger
|
||||
'';
|
||||
serviceConfig.Type = "oneshot";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.coreutils}/bin/echo c";
|
||||
StandardOutput = "file:/proc/sysrq-trigger";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
|
||||
options = {
|
||||
systemd.tpm2.enable = lib.mkEnableOption "systemd TPM2 support" // {
|
||||
default = config.systemd.package.withTpm2Tss;
|
||||
defaultText = "systemd.package.withTpm2Tss";
|
||||
default = config.systemd.package.withTpm2Units;
|
||||
defaultText = "systemd.package.withTpm2Units";
|
||||
};
|
||||
|
||||
boot.initrd.systemd.tpm2.enable = lib.mkEnableOption "systemd initrd TPM2 support" // {
|
||||
default = config.boot.initrd.systemd.package.withTpm2Tss;
|
||||
defaultText = "boot.initrd.systemd.package.withTpm2Tss";
|
||||
default = config.boot.initrd.systemd.package.withTpm2Units;
|
||||
defaultText = "boot.initrd.systemd.package.withTpm2Units";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Systemd services for docker.
|
||||
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, utils, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
@@ -271,11 +271,15 @@ in
|
||||
restartIfChanged = false;
|
||||
unitConfig.X-StopOnRemoval = false;
|
||||
|
||||
serviceConfig.Type = "oneshot";
|
||||
|
||||
script = ''
|
||||
${cfg.package}/bin/docker system prune -f ${toString cfg.autoPrune.flags}
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = utils.escapeSystemdExecArgs ([
|
||||
(lib.getExe cfg.package)
|
||||
"system"
|
||||
"prune"
|
||||
"-f"
|
||||
] ++ cfg.autoPrune.flags);
|
||||
};
|
||||
|
||||
startAt = optional cfg.autoPrune.enable cfg.autoPrune.dates;
|
||||
after = [ "docker.service" ];
|
||||
|
||||
@@ -178,7 +178,6 @@ let
|
||||
exec ${config.systemd.package}/bin/systemd-nspawn \
|
||||
--keep-unit \
|
||||
-M "$INSTANCE" -D "$root" "''${extraFlags[@]}" \
|
||||
$EXTRA_NSPAWN_FLAGS \
|
||||
--notify-ready=yes \
|
||||
--kill-signal=SIGRTMIN+3 \
|
||||
--bind-ro=/nix/store:/nix/store$NIX_BIND_OPT \
|
||||
@@ -203,6 +202,7 @@ let
|
||||
${optionalString (cfg.tmpfs != null && cfg.tmpfs != [])
|
||||
''--tmpfs=${concatStringsSep " --tmpfs=" cfg.tmpfs}''
|
||||
} \
|
||||
$EXTRA_NSPAWN_FLAGS \
|
||||
${containerInit cfg} "''${SYSTEM_PATH:-/nix/var/nix/profiles/system}/init"
|
||||
'';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
{ config, lib, utils, pkgs, ... }:
|
||||
let
|
||||
cfg = config.virtualisation.podman;
|
||||
json = pkgs.formats.json { };
|
||||
@@ -202,11 +202,15 @@ in
|
||||
restartIfChanged = false;
|
||||
unitConfig.X-StopOnRemoval = false;
|
||||
|
||||
serviceConfig.Type = "oneshot";
|
||||
|
||||
script = ''
|
||||
${cfg.package}/bin/podman system prune -f ${toString cfg.autoPrune.flags}
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = utils.escapeSystemdExecArgs ([
|
||||
(lib.getExe cfg.package)
|
||||
"system"
|
||||
"prune"
|
||||
"-f"
|
||||
] ++ cfg.autoPrune.flags);
|
||||
};
|
||||
|
||||
startAt = lib.optional cfg.autoPrune.enable cfg.autoPrune.dates;
|
||||
after = [ "podman.service" ];
|
||||
|
||||
@@ -353,7 +353,7 @@ in {
|
||||
early-mount-options = handleTest ./early-mount-options.nix {};
|
||||
ec2-config = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-config or {};
|
||||
ec2-nixops = (handleTestOn ["x86_64-linux"] ./ec2.nix {}).boot-ec2-nixops or {};
|
||||
echoip = handleTest ./echoip.nix {};
|
||||
echoip = runTest ./echoip.nix;
|
||||
ecryptfs = handleTest ./ecryptfs.nix {};
|
||||
fscrypt = handleTest ./fscrypt.nix {};
|
||||
fastnetmon-advanced = runTest ./fastnetmon-advanced.nix;
|
||||
@@ -425,6 +425,7 @@ in {
|
||||
firewall = handleTest ./firewall.nix { nftables = false; };
|
||||
firewall-nftables = handleTest ./firewall.nix { nftables = true; };
|
||||
fish = runTest ./fish.nix;
|
||||
firezone = handleTest ./firezone/firezone.nix {};
|
||||
flannel = handleTestOn ["x86_64-linux"] ./flannel.nix {};
|
||||
flaresolverr = handleTest ./flaresolverr.nix {};
|
||||
flood = handleTest ./flood.nix {};
|
||||
@@ -969,6 +970,7 @@ in {
|
||||
pppd = handleTest ./pppd.nix {};
|
||||
predictable-interface-names = handleTest ./predictable-interface-names.nix {};
|
||||
pretalx = runTest ./web-apps/pretalx.nix;
|
||||
prefect = runTest ./prefect.nix;
|
||||
pretix = runTest ./web-apps/pretix.nix;
|
||||
printing-socket = handleTest ./printing.nix { socket = true; listenTcp = true; };
|
||||
printing-service = handleTest ./printing.nix { socket = false; listenTcp = true; };
|
||||
|
||||
+23
-24
@@ -1,29 +1,28 @@
|
||||
import ./make-test-python.nix (
|
||||
{ lib, ... }:
|
||||
{
|
||||
name = "echoip";
|
||||
meta.maintainers = with lib.maintainers; [ defelo ];
|
||||
{ lib, ... }:
|
||||
|
||||
nodes.machine = {
|
||||
services.echoip = {
|
||||
enable = true;
|
||||
virtualHost = "echoip.local";
|
||||
};
|
||||
{
|
||||
name = "echoip";
|
||||
meta.maintainers = with lib.maintainers; [ defelo ];
|
||||
|
||||
networking.hosts = {
|
||||
"127.0.0.1" = [ "echoip.local" ];
|
||||
"::1" = [ "echoip.local" ];
|
||||
};
|
||||
nodes.machine = {
|
||||
services.echoip = {
|
||||
enable = true;
|
||||
virtualHost = "echoip.local";
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.wait_for_unit("echoip.service")
|
||||
machine.wait_for_open_port(8080)
|
||||
networking.hosts = {
|
||||
"127.0.0.1" = [ "echoip.local" ];
|
||||
"::1" = [ "echoip.local" ];
|
||||
};
|
||||
};
|
||||
|
||||
resp = machine.succeed("curl -4 http://echoip.local/ip")
|
||||
assert resp.strip() == "127.0.0.1"
|
||||
resp = machine.succeed("curl -6 http://echoip.local/ip")
|
||||
assert resp.strip() == "::1"
|
||||
'';
|
||||
}
|
||||
)
|
||||
testScript = ''
|
||||
machine.wait_for_unit("echoip.service")
|
||||
machine.wait_for_open_port(8080)
|
||||
|
||||
resp = machine.succeed("curl -4 http://echoip.local/ip")
|
||||
assert resp.strip() == "127.0.0.1"
|
||||
resp = machine.succeed("curl -6 http://echoip.local/ip")
|
||||
assert resp.strip() == "::1"
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
alias Domain.{Repo, Accounts, Auth, Actors, Tokens}
|
||||
|
||||
mappings = case File.read("provision-uuids.json") do
|
||||
{:ok, content} ->
|
||||
case Jason.decode(content) do
|
||||
{:ok, mapping} -> mapping
|
||||
_ -> %{"accounts" => %{}}
|
||||
end
|
||||
_ -> %{"accounts" => %{}}
|
||||
end
|
||||
|
||||
IO.puts("INFO: Fetching account")
|
||||
{:ok, account} = Accounts.fetch_account_by_id_or_slug("main")
|
||||
|
||||
IO.puts("INFO: Fetching email provider")
|
||||
{:ok, email_provider} = Auth.Provider.Query.not_disabled()
|
||||
|> Auth.Provider.Query.by_adapter(:email)
|
||||
|> Auth.Provider.Query.by_account_id(account.id)
|
||||
|> Repo.fetch(Auth.Provider.Query, [])
|
||||
|
||||
temp_admin_actor_email = "firezone-provision@localhost.local"
|
||||
temp_admin_actor_context = %Auth.Context{
|
||||
type: :browser,
|
||||
user_agent: "Unspecified/0.0",
|
||||
remote_ip: {127, 0, 0, 1},
|
||||
remote_ip_location_region: "N/A",
|
||||
remote_ip_location_city: "N/A",
|
||||
remote_ip_location_lat: 0.0,
|
||||
remote_ip_location_lon: 0.0
|
||||
}
|
||||
|
||||
{:ok, temp_admin_actor} =
|
||||
Actors.create_actor(account, %{
|
||||
type: :account_admin_user,
|
||||
name: "Token Provisioning"
|
||||
})
|
||||
|
||||
{:ok, temp_admin_actor_email_identity} =
|
||||
Auth.create_identity(temp_admin_actor, email_provider, %{
|
||||
provider_identifier: temp_admin_actor_email,
|
||||
provider_identifier_confirmation: temp_admin_actor_email
|
||||
})
|
||||
|
||||
{:ok, temp_admin_actor_token} =
|
||||
Auth.create_token(temp_admin_actor_email_identity, temp_admin_actor_context, "temporarynonce", DateTime.utc_now() |> DateTime.add(1, :hour))
|
||||
|
||||
{:ok, temp_admin_subject} =
|
||||
Auth.build_subject(temp_admin_actor_token, temp_admin_actor_context)
|
||||
|
||||
{:ok, relay_group_token} =
|
||||
Tokens.create_token(%{
|
||||
"type" => :relay_group,
|
||||
"expires_at" => DateTime.utc_now() |> DateTime.add(1, :hour),
|
||||
"secret_fragment" => Domain.Crypto.random_token(32, encoder: :hex32),
|
||||
"relay_group_id" => get_in(mappings, ["accounts", "main", "relay_groups", "my-relays"])
|
||||
})
|
||||
|
||||
relay_group_encoded_token = Tokens.encode_fragment!(relay_group_token)
|
||||
IO.puts("Created relay token: #{relay_group_encoded_token}")
|
||||
File.write("relay_token.txt", relay_group_encoded_token)
|
||||
|
||||
{:ok, gateway_group_token} =
|
||||
Tokens.create_token(%{
|
||||
"type" => :gateway_group,
|
||||
"expires_at" => DateTime.utc_now() |> DateTime.add(1, :hour),
|
||||
"secret_fragment" => Domain.Crypto.random_token(32, encoder: :hex32),
|
||||
"account_id" => get_in(mappings, ["accounts", "main", "id"]),
|
||||
"gateway_group_id" => get_in(mappings, ["accounts", "main", "gateway_groups", "site"])
|
||||
}, temp_admin_subject)
|
||||
|
||||
gateway_group_encoded_token = Tokens.encode_fragment!(gateway_group_token)
|
||||
IO.puts("Created gateway group token: #{gateway_group_encoded_token}")
|
||||
File.write("gateway_token.txt", gateway_group_encoded_token)
|
||||
|
||||
{:ok, service_account_actor_token} =
|
||||
Tokens.create_token(%{
|
||||
"type" => :client,
|
||||
"expires_at" => DateTime.utc_now() |> DateTime.add(1, :hour),
|
||||
"secret_fragment" => Domain.Crypto.random_token(32, encoder: :hex32),
|
||||
"account_id" => get_in(mappings, ["accounts", "main", "id"]),
|
||||
"actor_id" => get_in(mappings, ["accounts", "main", "actors", "client"])
|
||||
})
|
||||
|
||||
service_account_actor_encoded_token = Tokens.encode_fragment!(service_account_actor_token)
|
||||
IO.puts("Created service actor token: #{service_account_actor_encoded_token}")
|
||||
File.write("client_token.txt", service_account_actor_encoded_token)
|
||||
@@ -0,0 +1,349 @@
|
||||
import ../make-test-python.nix (
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
certs = import ../common/acme/server/snakeoil-certs.nix;
|
||||
domain = certs.domain;
|
||||
in
|
||||
{
|
||||
name = "firezone";
|
||||
meta.maintainers = with pkgs.lib.maintainers; [ oddlama ];
|
||||
|
||||
nodes = {
|
||||
server =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
security.pki.certificateFiles = [ certs.ca.cert ];
|
||||
|
||||
networking.extraHosts = ''
|
||||
${config.networking.primaryIPAddress} ${domain}
|
||||
${config.networking.primaryIPv6Address} ${domain}
|
||||
'';
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
80
|
||||
443
|
||||
];
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts.${domain} = {
|
||||
sslCertificate = certs.${domain}.cert;
|
||||
sslCertificateKey = certs.${domain}.key;
|
||||
};
|
||||
};
|
||||
|
||||
services.firezone.server = {
|
||||
enable = true;
|
||||
enableLocalDB = true;
|
||||
nginx.enable = true;
|
||||
|
||||
# Doesn't need to work for this test, but needs to be configured
|
||||
# otherwise the server will not start.
|
||||
smtp = {
|
||||
from = "firezone@example.com";
|
||||
host = "mail.localhost";
|
||||
port = 465;
|
||||
implicitTls = true;
|
||||
username = "firezone@example.com";
|
||||
passwordFile = pkgs.writeText "tmpmailpasswd" "supermailpassword";
|
||||
};
|
||||
|
||||
provision = {
|
||||
enable = true;
|
||||
accounts.main = {
|
||||
name = "My Account";
|
||||
relayGroups.my-relays.name = "Relays";
|
||||
gatewayGroups.site.name = "Site";
|
||||
actors = {
|
||||
admin = {
|
||||
type = "account_admin_user";
|
||||
name = "Admin";
|
||||
email = "admin@example.com";
|
||||
};
|
||||
client = {
|
||||
type = "service_account";
|
||||
name = "A client";
|
||||
email = "client@example.com";
|
||||
};
|
||||
};
|
||||
resources.res1 = {
|
||||
type = "dns";
|
||||
name = "Dns Resource";
|
||||
address = "resource.example.com";
|
||||
gatewayGroups = [ "site" ];
|
||||
filters = [
|
||||
{ protocol = "icmp"; }
|
||||
{
|
||||
protocol = "tcp";
|
||||
ports = [ 80 ];
|
||||
}
|
||||
];
|
||||
};
|
||||
resources.res2 = {
|
||||
type = "ip";
|
||||
name = "Ip Resource";
|
||||
address = "172.20.2.1";
|
||||
gatewayGroups = [ "site" ];
|
||||
};
|
||||
resources.res3 = {
|
||||
type = "cidr";
|
||||
name = "Cidr Resource";
|
||||
address = "172.20.1.0/24";
|
||||
gatewayGroups = [ "site" ];
|
||||
};
|
||||
policies.pol1 = {
|
||||
description = "Allow anyone res1 access";
|
||||
group = "everyone";
|
||||
resource = "res1";
|
||||
};
|
||||
policies.pol2 = {
|
||||
description = "Allow anyone res2 access";
|
||||
group = "everyone";
|
||||
resource = "res2";
|
||||
};
|
||||
policies.pol3 = {
|
||||
description = "Allow anyone res3 access";
|
||||
group = "everyone";
|
||||
resource = "res3";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
api.externalUrl = "https://${domain}/api/";
|
||||
web.externalUrl = "https://${domain}/";
|
||||
};
|
||||
|
||||
systemd.services.firezone-server-domain.postStart = lib.mkAfter ''
|
||||
${lib.getExe config.services.firezone.server.domain.package} rpc 'Code.eval_file("${./create-tokens.exs}")'
|
||||
'';
|
||||
};
|
||||
|
||||
relay =
|
||||
{
|
||||
nodes,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
security.pki.certificateFiles = [ certs.ca.cert ];
|
||||
networking.extraHosts = ''
|
||||
${nodes.server.networking.primaryIPAddress} ${domain}
|
||||
${nodes.server.networking.primaryIPv6Address} ${domain}
|
||||
'';
|
||||
|
||||
services.firezone.relay = {
|
||||
enable = true;
|
||||
logLevel = "debug";
|
||||
name = "test-relay";
|
||||
apiUrl = "wss://${domain}/api/";
|
||||
tokenFile = "/tmp/shared/relay_token.txt";
|
||||
publicIpv4 = config.networking.primaryIPAddress;
|
||||
publicIpv6 = config.networking.primaryIPv6Address;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
# Don't auto-start so we can wait until the token was provisioned
|
||||
systemd.services.firezone-relay.wantedBy = lib.mkForce [ ];
|
||||
};
|
||||
|
||||
# A resource that is only connected to the gateway,
|
||||
# allowing us to confirm the VPN works
|
||||
resource = {
|
||||
virtualisation.vlans = [
|
||||
1
|
||||
2
|
||||
];
|
||||
|
||||
networking.interfaces.eth1.ipv4.addresses = [
|
||||
{
|
||||
address = "172.20.1.1";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
networking.interfaces.eth2.ipv4.addresses = [
|
||||
{
|
||||
address = "172.20.2.1";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
80
|
||||
];
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts = {
|
||||
"localhost" = {
|
||||
default = true;
|
||||
locations."/".extraConfig = ''
|
||||
return 200 'greetings from the resource';
|
||||
add_header Content-Type text/plain;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
gateway =
|
||||
{
|
||||
nodes,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
virtualisation.vlans = [
|
||||
1
|
||||
2
|
||||
];
|
||||
|
||||
networking = {
|
||||
interfaces.eth1.ipv4.addresses = [
|
||||
{
|
||||
address = "172.20.1.2";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
interfaces.eth2.ipv4.addresses = [
|
||||
{
|
||||
address = "172.20.2.2";
|
||||
prefixLength = 24;
|
||||
}
|
||||
];
|
||||
|
||||
firewall.enable = false;
|
||||
nftables.enable = true;
|
||||
nftables.tables."filter".family = "inet";
|
||||
nftables.tables."filter".content = ''
|
||||
chain incoming {
|
||||
type filter hook input priority 0; policy accept;
|
||||
}
|
||||
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority srcnat; policy accept;
|
||||
meta protocol ip iifname "tun-firezone" oifname { "eth1", "eth2" } masquerade random
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority 0; policy drop;
|
||||
iifname "tun-firezone" accept
|
||||
oifname "tun-firezone" accept
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority 0; policy accept;
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
boot.kernel.sysctl."net.ipv4.ip_forward" = "1";
|
||||
# boot.kernel.sysctl."net.ipv4.conf.all.src_valid_mark" = "1";
|
||||
boot.kernel.sysctl."net.ipv6.conf.default.forwarding" = "1";
|
||||
boot.kernel.sysctl."net.ipv6.conf.all.forwarding" = "1";
|
||||
|
||||
security.pki.certificateFiles = [ certs.ca.cert ];
|
||||
networking.extraHosts = ''
|
||||
${nodes.server.networking.primaryIPAddress} ${domain}
|
||||
${nodes.server.networking.primaryIPv6Address} ${domain}
|
||||
172.20.1.1 resource.example.com
|
||||
'';
|
||||
|
||||
services.firezone.gateway = {
|
||||
enable = true;
|
||||
logLevel = "debug";
|
||||
name = "test-gateway";
|
||||
apiUrl = "wss://${domain}/api/";
|
||||
tokenFile = "/tmp/shared/gateway_token.txt";
|
||||
};
|
||||
|
||||
# Don't auto-start so we can wait until the token was provisioned
|
||||
systemd.services.firezone-gateway.wantedBy = lib.mkForce [ ];
|
||||
};
|
||||
|
||||
client =
|
||||
{
|
||||
nodes,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
security.pki.certificateFiles = [ certs.ca.cert ];
|
||||
networking.useNetworkd = true;
|
||||
networking.extraHosts = ''
|
||||
${nodes.server.networking.primaryIPAddress} ${domain}
|
||||
${nodes.server.networking.primaryIPv6Address} ${domain}
|
||||
'';
|
||||
|
||||
services.firezone.headless-client = {
|
||||
enable = true;
|
||||
logLevel = "debug";
|
||||
name = "test-client-somebody";
|
||||
apiUrl = "wss://${domain}/api/";
|
||||
tokenFile = "/tmp/shared/client_token.txt";
|
||||
};
|
||||
|
||||
# Don't auto-start so we can wait until the token was provisioned
|
||||
systemd.services.firezone-headless-client.wantedBy = lib.mkForce [ ];
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
{ ... }:
|
||||
''
|
||||
start_all()
|
||||
|
||||
with subtest("Start server"):
|
||||
server.wait_for_unit("firezone.target")
|
||||
server.wait_until_succeeds("curl -Lsf https://${domain} | grep 'Welcome to Firezone'")
|
||||
server.wait_until_succeeds("curl -Ls https://${domain}/api | grep 'Not Found'")
|
||||
|
||||
# Wait for tokens and copy them to shared folder
|
||||
server.wait_for_file("/var/lib/private/firezone/relay_token.txt")
|
||||
server.wait_for_file("/var/lib/private/firezone/gateway_token.txt")
|
||||
server.wait_for_file("/var/lib/private/firezone/client_token.txt")
|
||||
server.succeed("cp /var/lib/private/firezone/*_token.txt /tmp/shared")
|
||||
|
||||
with subtest("Connect relay"):
|
||||
relay.succeed("systemctl start firezone-relay")
|
||||
relay.wait_for_unit("firezone-relay.service")
|
||||
relay.wait_until_succeeds("journalctl --since -2m --unit firezone-relay.service --grep 'Connected to portal.*${domain}'", timeout=30)
|
||||
|
||||
with subtest("Connect gateway"):
|
||||
gateway.succeed("systemctl start firezone-gateway")
|
||||
gateway.wait_for_unit("firezone-gateway.service")
|
||||
gateway.wait_until_succeeds("journalctl --since -2m --unit firezone-gateway.service --grep 'Connected to portal.*${domain}'", timeout=30)
|
||||
relay.wait_until_succeeds("journalctl --since -2m --unit firezone-relay.service --grep 'Created allocation.*IPv4'", timeout=30)
|
||||
relay.wait_until_succeeds("journalctl --since -2m --unit firezone-relay.service --grep 'Created allocation.*IPv6'", timeout=30)
|
||||
|
||||
# Assert both relay ips are known
|
||||
gateway.wait_until_succeeds("journalctl --since -2m --unit firezone-gateway.service --grep 'Updated allocation.*relay_ip4.*Some.*relay_ip6.*Some'", timeout=30)
|
||||
|
||||
with subtest("Connect headless-client"):
|
||||
client.succeed("systemctl start firezone-headless-client")
|
||||
client.wait_for_unit("firezone-headless-client.service")
|
||||
client.wait_until_succeeds("journalctl --since -2m --unit firezone-headless-client.service --grep 'Connected to portal.*${domain}'", timeout=30)
|
||||
client.wait_until_succeeds("journalctl --since -2m --unit firezone-headless-client.service --grep 'Tunnel ready'", timeout=30)
|
||||
|
||||
with subtest("Check DNS based access"):
|
||||
# Check that we can access the resource through the VPN via DNS
|
||||
client.wait_until_succeeds("curl -4 -Lsf http://resource.example.com | grep 'greetings from the resource'")
|
||||
client.wait_until_succeeds("curl -6 -Lsf http://resource.example.com | grep 'greetings from the resource'")
|
||||
|
||||
with subtest("Check CIDR based access"):
|
||||
# Check that we can access the resource through the VPN via CIDR
|
||||
client.wait_until_succeeds("ping -c1 -W1 172.20.1.1")
|
||||
|
||||
with subtest("Check IP based access"):
|
||||
# Check that we can access the resource through the VPN via IP
|
||||
client.wait_until_succeeds("ping -c1 -W1 172.20.2.1")
|
||||
'';
|
||||
}
|
||||
)
|
||||
@@ -25,7 +25,10 @@ import ./make-test-python.nix (
|
||||
machine.wait_for_open_port(80)
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
# This establishes _something_
|
||||
machine.succeed("curl -sSf http://localhost")
|
||||
# The second request creates the database, unsure why both are required
|
||||
machine.succeed("curl -sSf http://localhost/")
|
||||
|
||||
machine.succeed(
|
||||
"curl -c cookies -sSf -X POST http://localhost/login -d 'username=admin&password=admin'"
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
services.paretosecurity.enable = true;
|
||||
};
|
||||
|
||||
# very basic test for now, need to add output asserts
|
||||
testScript = ''
|
||||
machine.wait_until_succeeds("paretosecurity check")
|
||||
(status, out) = machine.execute("paretosecurity check")
|
||||
assert status == 1, "paretosecurity did not return 1 on failing checks"
|
||||
'';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
mainPort = "4200";
|
||||
in
|
||||
{
|
||||
name = "prefect";
|
||||
|
||||
nodes = {
|
||||
machine =
|
||||
{ ... }:
|
||||
{
|
||||
services.prefect = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
machine.start()
|
||||
machine.wait_for_unit("prefect-server.service")
|
||||
machine.wait_for_open_port("${mainPort}")
|
||||
'';
|
||||
|
||||
meta = with lib.maintainers; {
|
||||
maintainers = [ happysalada ];
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
{ lib, ... }:
|
||||
|
||||
{
|
||||
name = "zipline";
|
||||
meta.maintainers = with lib.maintainers; [ defelo ];
|
||||
@@ -20,6 +21,18 @@
|
||||
networking.hosts."127.0.0.1" = [ "zipline.local" ];
|
||||
};
|
||||
|
||||
interactive.nodes.machine = {
|
||||
services.zipline.settings.CORE_HOSTNAME = lib.mkForce "0.0.0.0";
|
||||
networking.firewall.allowedTCPPorts = [ 8000 ];
|
||||
virtualisation.forwardPorts = [
|
||||
{
|
||||
from = "host";
|
||||
host.port = 8000;
|
||||
guest.port = 8000;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
import json
|
||||
import re
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ Before adding a new package, please consider the following questions:
|
||||
|
||||
If any of these questions' answer is no, then you should probably not add the package.
|
||||
|
||||
This is section describes a general framework of understanding and exceptions might apply.
|
||||
This section describes a general framework of understanding and exceptions might apply.
|
||||
|
||||
Luckily it's pretty easy to maintain your own package set with Nix, which can then be added to the [Nix User Repository](https://github.com/nix-community/nur) project.
|
||||
|
||||
|
||||
@@ -35,13 +35,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "musescore";
|
||||
version = "4.4.4";
|
||||
version = "4.5";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "musescore";
|
||||
repo = "MuseScore";
|
||||
rev = "v${finalAttrs.version}";
|
||||
sha256 = "sha256-/1kAgzmSbnuCqd6YxbaYW2+gE0Gvy373y5VfUK4OVzI=";
|
||||
sha256 = "sha256-7sD9AAuuDT0+VycKLL19DYdmuSLmt0Uy2NmoKQ1+c3A=";
|
||||
};
|
||||
|
||||
cmakeFlags = [
|
||||
@@ -127,17 +127,12 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
qtwayland
|
||||
];
|
||||
|
||||
postInstall =
|
||||
''
|
||||
# Remove unneeded bundled libraries and headers
|
||||
rm -r $out/{include,lib}
|
||||
''
|
||||
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||
mkdir -p "$out/Applications"
|
||||
mv "$out/mscore.app" "$out/Applications/mscore.app"
|
||||
mkdir -p $out/bin
|
||||
ln -s $out/Applications/mscore.app/Contents/MacOS/mscore $out/bin/mscore
|
||||
'';
|
||||
postInstall = lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||
mkdir -p "$out/Applications"
|
||||
mv "$out/mscore.app" "$out/Applications/mscore.app"
|
||||
mkdir -p $out/bin
|
||||
ln -s $out/Applications/mscore.app/Contents/MacOS/mscore $out/bin/mscore
|
||||
'';
|
||||
|
||||
# muse-sounds-manager installs Muse Sounds sampler libMuseSamplerCoreLib.so.
|
||||
# It requires that argv0 of the calling process ends with "/mscore" or "/MuseScore-4".
|
||||
|
||||
@@ -850,6 +850,19 @@ final: prev:
|
||||
meta.hydraPlatforms = [ ];
|
||||
};
|
||||
|
||||
arshlib-nvim = buildVimPlugin {
|
||||
pname = "arshlib.nvim";
|
||||
version = "2024-05-18";
|
||||
src = fetchFromGitHub {
|
||||
owner = "arsham";
|
||||
repo = "arshlib.nvim";
|
||||
rev = "111fd439268adda206a24b133096893869a50764";
|
||||
sha256 = "1jmac14w37lybanr8jg4jpi3rkbsjhmz65x5fr7mgd7kagsn3r1n";
|
||||
};
|
||||
meta.homepage = "https://github.com/arsham/arshlib.nvim/";
|
||||
meta.hydraPlatforms = [ ];
|
||||
};
|
||||
|
||||
astrocore = buildVimPlugin {
|
||||
pname = "astrocore";
|
||||
version = "2025-02-18";
|
||||
@@ -6125,6 +6138,19 @@ final: prev:
|
||||
meta.hydraPlatforms = [ ];
|
||||
};
|
||||
|
||||
indent-tools-nvim = buildVimPlugin {
|
||||
pname = "indent-tools.nvim";
|
||||
version = "2023-10-28";
|
||||
src = fetchFromGitHub {
|
||||
owner = "arsham";
|
||||
repo = "indent-tools.nvim";
|
||||
rev = "31b839d65aa04b568fabe5e100a63cc44ef3f5d5";
|
||||
sha256 = "0vw3j9plwi6ari5p5hmds257xw0szlj2ddf75mjfj6nfzd93ni0p";
|
||||
};
|
||||
meta.homepage = "https://github.com/arsham/indent-tools.nvim/";
|
||||
meta.hydraPlatforms = [ ];
|
||||
};
|
||||
|
||||
indentLine = buildVimPlugin {
|
||||
pname = "indentLine";
|
||||
version = "2023-07-14";
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
buildVimPlugin,
|
||||
callPackage,
|
||||
fetchFromGitHub,
|
||||
fetchFromSourcehut,
|
||||
fetchpatch,
|
||||
fetchurl,
|
||||
neovimUtils,
|
||||
@@ -158,14 +157,6 @@ in
|
||||
#######################
|
||||
# Regular overrides
|
||||
|
||||
aerial-nvim = super.aerial-nvim.overrideAttrs {
|
||||
# optional dependencies
|
||||
nvimSkipModule = [
|
||||
"lualine.components.aerial"
|
||||
"telescope._extensions.aerial"
|
||||
];
|
||||
};
|
||||
|
||||
advanced-git-search-nvim = super.advanced-git-search-nvim.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
telescope-nvim
|
||||
@@ -176,6 +167,14 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
aerial-nvim = super.aerial-nvim.overrideAttrs {
|
||||
# optional dependencies
|
||||
nvimSkipModule = [
|
||||
"lualine.components.aerial"
|
||||
"telescope._extensions.aerial"
|
||||
];
|
||||
};
|
||||
|
||||
agitator-nvim = super.agitator-nvim.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
telescope-nvim
|
||||
@@ -183,6 +182,23 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
aider-nvim = super.aider-nvim.overrideAttrs {
|
||||
patches = [
|
||||
(replaceVars ./patches/aider-nvim/bin.patch { aider = lib.getExe' aider-chat "aider"; })
|
||||
];
|
||||
};
|
||||
|
||||
animation-nvim = super.animation-nvim.overrideAttrs {
|
||||
dependencies = [ self.middleclass ];
|
||||
};
|
||||
|
||||
arshlib-nvim = super.arshlib-nvim.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
nui-nvim
|
||||
plenary-nvim
|
||||
];
|
||||
};
|
||||
|
||||
astrocore = super.astrocore.overrideAttrs {
|
||||
dependencies = [ self.lazy-nvim ];
|
||||
};
|
||||
@@ -200,10 +216,6 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
animation-nvim = super.animation-nvim.overrideAttrs {
|
||||
dependencies = [ self.middleclass ];
|
||||
};
|
||||
|
||||
autosave-nvim = super.autosave-nvim.overrideAttrs {
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
@@ -296,6 +308,10 @@ in
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
|
||||
blink-cmp-git = super.blink-cmp-git.overrideAttrs {
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
|
||||
blink-emoji-nvim = super.blink-emoji-nvim.overrideAttrs {
|
||||
dependencies = [ self.blink-cmp ];
|
||||
};
|
||||
@@ -304,10 +320,6 @@ in
|
||||
dependencies = [ self.blink-cmp ];
|
||||
};
|
||||
|
||||
blink-cmp-git = super.blink-cmp-git.overrideAttrs {
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
|
||||
blink-pairs = callPackage ./non-generated/blink-pairs { };
|
||||
|
||||
bluloco-nvim = super.bluloco-nvim.overrideAttrs {
|
||||
@@ -578,6 +590,10 @@ in
|
||||
dependencies = [ self.vim-lsp ];
|
||||
};
|
||||
|
||||
cmp-vimtex = super.cmp-vimtex.overrideAttrs {
|
||||
checkInputs = [ self.nvim-cmp ];
|
||||
};
|
||||
|
||||
cmp-vimwiki-tags = super.cmp-vimwiki-tags.overrideAttrs {
|
||||
checkInputs = [ self.nvim-cmp ];
|
||||
dependencies = [ self.vimwiki ];
|
||||
@@ -587,10 +603,6 @@ in
|
||||
checkInputs = [ self.nvim-cmp ];
|
||||
};
|
||||
|
||||
cmp-vimtex = super.cmp-vimtex.overrideAttrs {
|
||||
checkInputs = [ self.nvim-cmp ];
|
||||
};
|
||||
|
||||
cmp-zsh = super.cmp-zsh.overrideAttrs {
|
||||
checkInputs = [ self.nvim-cmp ];
|
||||
dependencies = [ zsh ];
|
||||
@@ -946,29 +958,14 @@ in
|
||||
dependencies = [ self.ddc-vim ];
|
||||
};
|
||||
|
||||
ddc-source-lsp = super.ddc-source-lsp.overrideAttrs {
|
||||
dependencies = [ self.ddc-vim ];
|
||||
};
|
||||
|
||||
ddc-vim = super.ddc-vim.overrideAttrs {
|
||||
dependencies = [ self.denops-vim ];
|
||||
};
|
||||
|
||||
ddc-filter-sorter_rank = super.ddc-filter-sorter_rank.overrideAttrs {
|
||||
dependencies = [ self.ddc-vim ];
|
||||
};
|
||||
|
||||
ddc-ui-native = super.ddc-ui-native.overrideAttrs {
|
||||
ddc-fuzzy = super.ddc-fuzzy.overrideAttrs {
|
||||
dependencies = [ self.ddc-vim ];
|
||||
};
|
||||
|
||||
ddc-ui-pum = super.ddc-ui-pum.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
ddc-vim
|
||||
pum-vim
|
||||
];
|
||||
};
|
||||
|
||||
ddc-source-around = super.ddc-source-around.overrideAttrs {
|
||||
dependencies = [ self.ddc-vim ];
|
||||
};
|
||||
@@ -977,10 +974,25 @@ in
|
||||
dependencies = [ self.ddc-vim ];
|
||||
};
|
||||
|
||||
ddc-fuzzy = super.ddc-fuzzy.overrideAttrs {
|
||||
ddc-source-lsp = super.ddc-source-lsp.overrideAttrs {
|
||||
dependencies = [ self.ddc-vim ];
|
||||
};
|
||||
|
||||
ddc-ui-pum = super.ddc-ui-pum.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
ddc-vim
|
||||
pum-vim
|
||||
];
|
||||
};
|
||||
|
||||
ddc-ui-native = super.ddc-ui-native.overrideAttrs {
|
||||
dependencies = [ self.ddc-vim ];
|
||||
};
|
||||
|
||||
ddc-vim = super.ddc-vim.overrideAttrs {
|
||||
dependencies = [ self.denops-vim ];
|
||||
};
|
||||
|
||||
defx-nvim = super.defx-nvim.overrideAttrs {
|
||||
dependencies = [ self.nvim-yarp ];
|
||||
};
|
||||
@@ -1196,18 +1208,6 @@ in
|
||||
'';
|
||||
});
|
||||
|
||||
fuzzy-nvim = super.fuzzy-nvim.overrideAttrs {
|
||||
checkInputs = with self; [
|
||||
# Optional sorters
|
||||
telescope-zf-native-nvim
|
||||
];
|
||||
dependencies = [ self.telescope-fzf-native-nvim ];
|
||||
nvimSkipModule = [
|
||||
# TODO: package fzy-lua-native
|
||||
"fuzzy_nvim.fzy_matcher"
|
||||
];
|
||||
};
|
||||
|
||||
fugit2-nvim = super.fugit2-nvim.overrideAttrs {
|
||||
# Requires web-devicons but mini.icons can mock them up
|
||||
checkInputs = [
|
||||
@@ -1226,6 +1226,18 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
fuzzy-nvim = super.fuzzy-nvim.overrideAttrs {
|
||||
checkInputs = with self; [
|
||||
# Optional sorters
|
||||
telescope-zf-native-nvim
|
||||
];
|
||||
dependencies = [ self.telescope-fzf-native-nvim ];
|
||||
nvimSkipModule = [
|
||||
# TODO: package fzy-lua-native
|
||||
"fuzzy_nvim.fzy_matcher"
|
||||
];
|
||||
};
|
||||
|
||||
fzf-checkout-vim = super.fzf-checkout-vim.overrideAttrs {
|
||||
# The plugin has a makefile which tries to run tests in a docker container.
|
||||
# This prevents it.
|
||||
@@ -1288,6 +1300,18 @@ in
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
|
||||
git-conflict-nvim = super.git-conflict-nvim.overrideAttrs {
|
||||
# TODO: Remove after next fixed version
|
||||
# https://github.com/akinsho/git-conflict.nvim/issues/103
|
||||
version = "2.1.0";
|
||||
src = fetchFromGitHub {
|
||||
owner = "akinsho";
|
||||
repo = "git-conflict.nvim";
|
||||
tag = "v2.1.0";
|
||||
hash = "sha256-1t0kKxTGLuOvuRkoLgkoqMZpF+oKo8+gMsTdgPsSb+8=";
|
||||
};
|
||||
};
|
||||
|
||||
git-worktree-nvim = super.git-worktree-nvim.overrideAttrs {
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
@@ -1363,14 +1387,14 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
haskell-snippets-nvim = super.haskell-snippets-nvim.overrideAttrs {
|
||||
dependencies = [ self.luasnip ];
|
||||
};
|
||||
|
||||
haskell-scope-highlighting-nvim = super.haskell-scope-highlighting-nvim.overrideAttrs {
|
||||
dependencies = [ self.nvim-treesitter ];
|
||||
};
|
||||
|
||||
haskell-snippets-nvim = super.haskell-snippets-nvim.overrideAttrs {
|
||||
dependencies = [ self.luasnip ];
|
||||
};
|
||||
|
||||
haskell-tools-nvim = neovimUtils.buildNeovimPlugin {
|
||||
luaAttr = luaPackages.haskell-tools-nvim;
|
||||
nvimSkipModule = [
|
||||
@@ -1447,6 +1471,14 @@ in
|
||||
nvimSkipModule = "ibl.config.types";
|
||||
};
|
||||
|
||||
indent-tools-nvim = super.indent-tools-nvim.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
arshlib-nvim
|
||||
nvim-treesitter
|
||||
nvim-treesitter-textobjects
|
||||
];
|
||||
};
|
||||
|
||||
instant-nvim = super.instant-nvim.overrideAttrs {
|
||||
nvimSkipModule = [
|
||||
# Requires global variable config
|
||||
@@ -1533,13 +1565,6 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
lean-nvim = super.lean-nvim.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
nvim-lspconfig
|
||||
plenary-nvim
|
||||
];
|
||||
};
|
||||
|
||||
LeaderF = super.LeaderF.overrideAttrs {
|
||||
nativeBuildInputs = [ python3.pkgs.setuptools ];
|
||||
buildInputs = [ python3 ];
|
||||
@@ -1553,6 +1578,13 @@ in
|
||||
stripDebugList = [ "autoload/leaderf/python" ];
|
||||
};
|
||||
|
||||
lean-nvim = super.lean-nvim.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
nvim-lspconfig
|
||||
plenary-nvim
|
||||
];
|
||||
};
|
||||
|
||||
leap-ast-nvim = super.leap-ast-nvim.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
leap-nvim
|
||||
@@ -1663,12 +1695,6 @@ in
|
||||
dependencies = [ self.nvim-lspconfig ];
|
||||
};
|
||||
|
||||
lsp_extensions-nvim = super.lsp_extensions-nvim.overrideAttrs {
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
|
||||
lsp_lines-nvim = callPackage ./non-generated/lsp_lines-nvim { };
|
||||
|
||||
lspecho-nvim = super.lspecho-nvim.overrideAttrs {
|
||||
meta.license = lib.licenses.mit;
|
||||
};
|
||||
@@ -1678,6 +1704,12 @@ in
|
||||
nvimRequireCheck = "lspsaga";
|
||||
};
|
||||
|
||||
lsp_extensions-nvim = super.lsp_extensions-nvim.overrideAttrs {
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
|
||||
lsp_lines-nvim = callPackage ./non-generated/lsp_lines-nvim { };
|
||||
|
||||
ltex_extra-nvim = super.ltex_extra-nvim.overrideAttrs {
|
||||
# Other modules require setup call first
|
||||
nvimRequireCheck = "ltex_extra";
|
||||
@@ -1806,18 +1838,6 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
git-conflict-nvim = super.git-conflict-nvim.overrideAttrs {
|
||||
# TODO: Remove after next fixed version
|
||||
# https://github.com/akinsho/git-conflict.nvim/issues/103
|
||||
version = "2.1.0";
|
||||
src = fetchFromGitHub {
|
||||
owner = "akinsho";
|
||||
repo = "git-conflict.nvim";
|
||||
tag = "v2.1.0";
|
||||
hash = "sha256-1t0kKxTGLuOvuRkoLgkoqMZpF+oKo8+gMsTdgPsSb+8=";
|
||||
};
|
||||
};
|
||||
|
||||
minimap-vim = super.minimap-vim.overrideAttrs {
|
||||
preFixup = ''
|
||||
substituteInPlace $out/plugin/minimap.vim \
|
||||
@@ -2229,11 +2249,11 @@ in
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
|
||||
notmuch-vim = notmuch.vim;
|
||||
|
||||
NotebookNavigator-nvim = super.NotebookNavigator-nvim.overrideAttrs {
|
||||
};
|
||||
|
||||
notmuch-vim = notmuch.vim;
|
||||
|
||||
nterm-nvim = super.nterm-nvim.overrideAttrs {
|
||||
dependencies = [ self.aniseed ];
|
||||
};
|
||||
@@ -2296,12 +2316,6 @@ in
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
|
||||
nvim-dap-cortex-debug = super.nvim-dap-cortex-debug.overrideAttrs {
|
||||
dependencies = [ self.nvim-dap ];
|
||||
};
|
||||
|
||||
nvim-dbee = callPackage ./non-generated/nvim-dbee { };
|
||||
|
||||
nvim-coverage = super.nvim-coverage.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
neotest
|
||||
@@ -2313,6 +2327,10 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
nvim-dap-cortex-debug = super.nvim-dap-cortex-debug.overrideAttrs {
|
||||
dependencies = [ self.nvim-dap ];
|
||||
};
|
||||
|
||||
nvim-dap-lldb = super.nvim-dap-lldb.overrideAttrs {
|
||||
dependencies = [ self.nvim-dap ];
|
||||
};
|
||||
@@ -2342,16 +2360,18 @@ in
|
||||
dependencies = [ self.nvim-dap ];
|
||||
};
|
||||
|
||||
nvim-dbee = callPackage ./non-generated/nvim-dbee { };
|
||||
|
||||
nvim-FeMaco-lua = super.nvim-FeMaco-lua.overrideAttrs {
|
||||
dependencies = [ self.nvim-treesitter ];
|
||||
};
|
||||
|
||||
nvim-fzf-commands = super.nvim-fzf-commands.overrideAttrs {
|
||||
dependencies = [ self.nvim-fzf ];
|
||||
# Requires global variable setup nvim_fzf_directory
|
||||
nvimSkipModule = "fzf-commands.rg";
|
||||
};
|
||||
|
||||
nvim-FeMaco-lua = super.nvim-FeMaco-lua.overrideAttrs {
|
||||
dependencies = [ self.nvim-treesitter ];
|
||||
};
|
||||
|
||||
nvim-genghis = super.nvim-genghis.overrideAttrs {
|
||||
dependencies = [ self.dressing-nvim ];
|
||||
|
||||
@@ -2428,6 +2448,9 @@ in
|
||||
nvim-navic
|
||||
];
|
||||
};
|
||||
nvim-navic = super.nvim-navic.overrideAttrs {
|
||||
dependencies = [ self.nvim-lspconfig ];
|
||||
};
|
||||
|
||||
nvim-neoclip-lua = super.nvim-neoclip-lua.overrideAttrs {
|
||||
nvimSkipModule = [
|
||||
@@ -2442,6 +2465,11 @@ in
|
||||
checkInputs = [ self.nvim-web-devicons ];
|
||||
};
|
||||
|
||||
nvim-notify = super.nvim-notify.overrideAttrs {
|
||||
# Optional fzf integration
|
||||
nvimSkipModule = "notify.integrations.fzf";
|
||||
};
|
||||
|
||||
nvim-nu = super.nvim-nu.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
nvim-treesitter
|
||||
@@ -2449,19 +2477,6 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
vim-mediawiki-editor = super.vim-mediawiki-editor.overrideAttrs {
|
||||
passthru.python3Dependencies = [ python3.pkgs.mwclient ];
|
||||
};
|
||||
|
||||
nvim-navic = super.nvim-navic.overrideAttrs {
|
||||
dependencies = [ self.nvim-lspconfig ];
|
||||
};
|
||||
|
||||
nvim-notify = super.nvim-notify.overrideAttrs {
|
||||
# Optional fzf integration
|
||||
nvimSkipModule = "notify.integrations.fzf";
|
||||
};
|
||||
|
||||
nvim-paredit = super.nvim-paredit.overrideAttrs {
|
||||
dependencies = with self; [ nvim-treesitter ];
|
||||
};
|
||||
@@ -2497,6 +2512,29 @@ in
|
||||
vimCommandCheck = "TealBuild";
|
||||
};
|
||||
|
||||
nvim-test = super.nvim-test.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
nvim-treesitter
|
||||
nvim-treesitter-parsers.c_sharp
|
||||
nvim-treesitter-parsers.go
|
||||
nvim-treesitter-parsers.haskell
|
||||
nvim-treesitter-parsers.javascript
|
||||
nvim-treesitter-parsers.python
|
||||
nvim-treesitter-parsers.ruby
|
||||
nvim-treesitter-parsers.rust
|
||||
nvim-treesitter-parsers.typescript
|
||||
nvim-treesitter-parsers.zig
|
||||
];
|
||||
nvimSkipModule = [
|
||||
# Optional toggleterm integration
|
||||
"nvim-test.terms.toggleterm"
|
||||
# Broken runners
|
||||
"nvim-test.runners.zig"
|
||||
"nvim-test.runners.hspec"
|
||||
"nvim-test.runners.stack"
|
||||
];
|
||||
};
|
||||
|
||||
nvim-tree-lua = super.nvim-tree-lua.overrideAttrs {
|
||||
nvimSkipModule = [
|
||||
# Meta can't be required
|
||||
@@ -2548,29 +2586,6 @@ in
|
||||
dependencies = [ self.nvim-treesitter ];
|
||||
};
|
||||
|
||||
nvim-test = super.nvim-test.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
nvim-treesitter
|
||||
nvim-treesitter-parsers.c_sharp
|
||||
nvim-treesitter-parsers.go
|
||||
nvim-treesitter-parsers.haskell
|
||||
nvim-treesitter-parsers.javascript
|
||||
nvim-treesitter-parsers.python
|
||||
nvim-treesitter-parsers.ruby
|
||||
nvim-treesitter-parsers.rust
|
||||
nvim-treesitter-parsers.typescript
|
||||
nvim-treesitter-parsers.zig
|
||||
];
|
||||
nvimSkipModule = [
|
||||
# Optional toggleterm integration
|
||||
"nvim-test.terms.toggleterm"
|
||||
# Broken runners
|
||||
"nvim-test.runners.zig"
|
||||
"nvim-test.runners.hspec"
|
||||
"nvim-test.runners.stack"
|
||||
];
|
||||
};
|
||||
|
||||
nvim-ufo = super.nvim-ufo.overrideAttrs {
|
||||
dependencies = [ self.promise-async ];
|
||||
};
|
||||
@@ -2590,6 +2605,10 @@ in
|
||||
dependencies = [ self.nvzone-volt ];
|
||||
};
|
||||
|
||||
nvzone-typr = super.nvzone-typr.overrideAttrs {
|
||||
dependencies = [ self.nvzone-volt ];
|
||||
};
|
||||
|
||||
obsidian-nvim = super.obsidian-nvim.overrideAttrs {
|
||||
checkInputs = with self; [
|
||||
# Optional pickers
|
||||
@@ -2615,10 +2634,6 @@ in
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
|
||||
onehalf = super.onehalf.overrideAttrs {
|
||||
configurePhase = "cd vim";
|
||||
};
|
||||
|
||||
omni-vim = super.omni-vim.overrideAttrs {
|
||||
# Optional lightline integration
|
||||
nvimSkipModule = "omni-lightline";
|
||||
@@ -2634,6 +2649,10 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
onehalf = super.onehalf.overrideAttrs {
|
||||
configurePhase = "cd vim";
|
||||
};
|
||||
|
||||
one-nvim = super.one-nvim.overrideAttrs {
|
||||
# E5108: /lua/one-nvim.lua:14: Unknown option 't_Co'
|
||||
# https://github.com/Th3Whit3Wolf/one-nvim/issues/23
|
||||
@@ -2785,6 +2804,17 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
quarto-nvim = super.quarto-nvim.overrideAttrs {
|
||||
checkInputs = [
|
||||
# Optional runner
|
||||
self.iron-nvim
|
||||
];
|
||||
dependencies = with self; [
|
||||
nvim-lspconfig
|
||||
otter-nvim
|
||||
];
|
||||
};
|
||||
|
||||
quicker-nvim = super.quicker-nvim.overrideAttrs {
|
||||
};
|
||||
|
||||
@@ -2802,12 +2832,6 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
aider-nvim = super.aider-nvim.overrideAttrs {
|
||||
patches = [
|
||||
(replaceVars ./patches/aider-nvim/bin.patch { aider = lib.getExe' aider-chat "aider"; })
|
||||
];
|
||||
};
|
||||
|
||||
refactoring-nvim = super.refactoring-nvim.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
nvim-treesitter
|
||||
@@ -2855,6 +2879,21 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
rocks-nvim =
|
||||
(neovimUtils.buildNeovimPlugin {
|
||||
luaAttr = luaPackages.rocks-nvim;
|
||||
}).overrideAttrs
|
||||
(oa: {
|
||||
passthru = oa.passthru // {
|
||||
initLua = ''
|
||||
vim.g.rocks_nvim = {
|
||||
luarocks_binary = "${neovim-unwrapped.lua.pkgs.luarocks_bootstrap}/bin/luarocks"
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
rustaceanvim = neovimUtils.buildNeovimPlugin {
|
||||
checkInputs = [
|
||||
# Optional integration
|
||||
@@ -3090,16 +3129,16 @@ in
|
||||
meta.maintainers = with lib.maintainers; [ callumio ];
|
||||
};
|
||||
|
||||
taskwarrior3 = buildVimPlugin {
|
||||
inherit (taskwarrior3) version pname;
|
||||
src = "${taskwarrior3.src}/scripts/vim";
|
||||
};
|
||||
|
||||
taskwarrior2 = buildVimPlugin {
|
||||
inherit (taskwarrior2) version pname;
|
||||
src = "${taskwarrior2.src}/scripts/vim";
|
||||
};
|
||||
|
||||
taskwarrior3 = buildVimPlugin {
|
||||
inherit (taskwarrior3) version pname;
|
||||
src = "${taskwarrior3.src}/scripts/vim";
|
||||
};
|
||||
|
||||
telekasten-nvim = super.telekasten-nvim.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
plenary-nvim
|
||||
@@ -3284,17 +3323,6 @@ in
|
||||
dependencies = with self; [ telescope-nvim ];
|
||||
};
|
||||
|
||||
quarto-nvim = super.quarto-nvim.overrideAttrs {
|
||||
checkInputs = [
|
||||
# Optional runner
|
||||
self.iron-nvim
|
||||
];
|
||||
dependencies = with self; [
|
||||
nvim-lspconfig
|
||||
otter-nvim
|
||||
];
|
||||
};
|
||||
|
||||
telescope-zoxide = super.telescope-zoxide.overrideAttrs {
|
||||
dependencies = with self; [ telescope-nvim ];
|
||||
|
||||
@@ -3344,6 +3372,11 @@ in
|
||||
dependencies = [ self.plenary-nvim ];
|
||||
};
|
||||
|
||||
trouble-nvim = super.trouble-nvim.overrideAttrs {
|
||||
# Meta file
|
||||
nvimSkipModule = "trouble.docs";
|
||||
};
|
||||
|
||||
tsc-nvim = super.tsc-nvim.overrideAttrs {
|
||||
patches = [ ./patches/tsc.nvim/fix-path.patch ];
|
||||
|
||||
@@ -3355,11 +3388,6 @@ in
|
||||
nvimSkipModule = "tsc.better-messages-test";
|
||||
};
|
||||
|
||||
trouble-nvim = super.trouble-nvim.overrideAttrs {
|
||||
# Meta file
|
||||
nvimSkipModule = "trouble.docs";
|
||||
};
|
||||
|
||||
tssorter-nvim = super.tssorter-nvim.overrideAttrs {
|
||||
dependencies = [ self.nvim-treesitter ];
|
||||
};
|
||||
@@ -3400,8 +3428,13 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
nvzone-typr = super.nvzone-typr.overrideAttrs {
|
||||
dependencies = [ self.nvzone-volt ];
|
||||
typst-preview-nvim = super.typst-preview-nvim.overrideAttrs {
|
||||
postPatch = ''
|
||||
substituteInPlace lua/typst-preview/config.lua \
|
||||
--replace-fail "['tinymist'] = nil," "tinymist = '${lib.getExe tinymist}'," \
|
||||
--replace-fail "['websocat'] = nil," "websocat = '${lib.getExe websocat}',"
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
unicode-vim =
|
||||
@@ -3439,6 +3472,22 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
vimacs = super.vimacs.overrideAttrs {
|
||||
buildPhase = ''
|
||||
substituteInPlace bin/vim \
|
||||
--replace-fail '/usr/bin/vim' 'vim' \
|
||||
--replace-fail '/usr/bin/gvim' 'gvim'
|
||||
# remove unnecessary duplicated bin wrapper script
|
||||
rm -r plugin/vimacs
|
||||
'';
|
||||
meta = with lib; {
|
||||
description = "Vim-Improved eMACS: Emacs emulation plugin for Vim";
|
||||
homepage = "http://algorithm.com.au/code/vimacs";
|
||||
license = licenses.gpl2Plus;
|
||||
maintainers = with lib.maintainers; [ millerjason ];
|
||||
};
|
||||
};
|
||||
|
||||
vimade = super.vimade.overrideAttrs {
|
||||
checkInputs = with self; [
|
||||
# Optional providers
|
||||
@@ -3448,6 +3497,51 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
# The GitHub repository returns 404, which breaks the update script
|
||||
VimCompletesMe = buildVimPlugin {
|
||||
pname = "VimCompletesMe";
|
||||
version = "2022-02-18";
|
||||
src = fetchFromGitHub {
|
||||
owner = "ackyshake";
|
||||
repo = "VimCompletesMe";
|
||||
rev = "9adf692d7ae6424038458a89d4a411f0a27d1388";
|
||||
sha256 = "1sndgb3291dyifaa8adri2mb8cgbinbar3nw1fnf67k9ahwycaz0";
|
||||
};
|
||||
meta.homepage = "https://github.com/ackyshake/VimCompletesMe/";
|
||||
};
|
||||
|
||||
vim2nix = buildVimPlugin {
|
||||
pname = "vim2nix";
|
||||
version = "1.0";
|
||||
src = ./vim2nix;
|
||||
dependencies = [ self.vim-addon-manager ];
|
||||
};
|
||||
|
||||
vimsence = super.vimsence.overrideAttrs {
|
||||
meta = with lib; {
|
||||
description = "Discord rich presence for Vim";
|
||||
homepage = "https://github.com/hugolgst/vimsence";
|
||||
maintainers = with lib.maintainers; [ hugolgst ];
|
||||
};
|
||||
};
|
||||
|
||||
vimproc-vim = super.vimproc-vim.overrideAttrs {
|
||||
buildInputs = [ which ];
|
||||
|
||||
# TODO: revisit
|
||||
buildPhase = ''
|
||||
substituteInPlace autoload/vimproc.vim \
|
||||
--replace-fail vimproc_mac.so vimproc_unix.so \
|
||||
--replace-fail vimproc_linux64.so vimproc_unix.so \
|
||||
--replace-fail vimproc_linux32.so vimproc_unix.so
|
||||
make -f make_unix.mak
|
||||
'';
|
||||
};
|
||||
|
||||
vimshell-vim = super.vimshell-vim.overrideAttrs {
|
||||
dependencies = [ self.vimproc-vim ];
|
||||
};
|
||||
|
||||
vim-addon-actions = super.vim-addon-actions.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
vim-addon-mw-utils
|
||||
@@ -3678,6 +3772,10 @@ in
|
||||
nvimSkipModule = "treesitter-matchup.third-party.query";
|
||||
};
|
||||
|
||||
vim-mediawiki-editor = super.vim-mediawiki-editor.overrideAttrs {
|
||||
passthru.python3Dependencies = [ python3.pkgs.mwclient ];
|
||||
};
|
||||
|
||||
vim-metamath = super.vim-metamath.overrideAttrs {
|
||||
preInstall = "cd vim";
|
||||
};
|
||||
@@ -3743,6 +3841,12 @@ in
|
||||
nvimSkipModule = "tpipeline.main";
|
||||
};
|
||||
|
||||
vim-ultest = super.vim-ultest.overrideAttrs {
|
||||
# NOTE: vim-ultest is no longer maintained.
|
||||
# If using Neovim, you can switch to using neotest (https://github.com/nvim-neotest/neotest) instead.
|
||||
nvimSkipModule = "ultest";
|
||||
};
|
||||
|
||||
vim-unimpaired = super.vim-unimpaired.overrideAttrs {
|
||||
dependencies = [ self.vim-repeat ];
|
||||
};
|
||||
@@ -3773,73 +3877,6 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
vim2nix = buildVimPlugin {
|
||||
pname = "vim2nix";
|
||||
version = "1.0";
|
||||
src = ./vim2nix;
|
||||
dependencies = [ self.vim-addon-manager ];
|
||||
};
|
||||
|
||||
vimacs = super.vimacs.overrideAttrs {
|
||||
buildPhase = ''
|
||||
substituteInPlace bin/vim \
|
||||
--replace-fail '/usr/bin/vim' 'vim' \
|
||||
--replace-fail '/usr/bin/gvim' 'gvim'
|
||||
# remove unnecessary duplicated bin wrapper script
|
||||
rm -r plugin/vimacs
|
||||
'';
|
||||
meta = with lib; {
|
||||
description = "Vim-Improved eMACS: Emacs emulation plugin for Vim";
|
||||
homepage = "http://algorithm.com.au/code/vimacs";
|
||||
license = licenses.gpl2Plus;
|
||||
maintainers = with lib.maintainers; [ millerjason ];
|
||||
};
|
||||
};
|
||||
|
||||
# The GitHub repository returns 404, which breaks the update script
|
||||
VimCompletesMe = buildVimPlugin {
|
||||
pname = "VimCompletesMe";
|
||||
version = "2022-02-18";
|
||||
src = fetchFromGitHub {
|
||||
owner = "ackyshake";
|
||||
repo = "VimCompletesMe";
|
||||
rev = "9adf692d7ae6424038458a89d4a411f0a27d1388";
|
||||
sha256 = "1sndgb3291dyifaa8adri2mb8cgbinbar3nw1fnf67k9ahwycaz0";
|
||||
};
|
||||
meta.homepage = "https://github.com/ackyshake/VimCompletesMe/";
|
||||
};
|
||||
|
||||
vimsence = super.vimsence.overrideAttrs {
|
||||
meta = with lib; {
|
||||
description = "Discord rich presence for Vim";
|
||||
homepage = "https://github.com/hugolgst/vimsence";
|
||||
maintainers = with lib.maintainers; [ hugolgst ];
|
||||
};
|
||||
};
|
||||
|
||||
vimproc-vim = super.vimproc-vim.overrideAttrs {
|
||||
buildInputs = [ which ];
|
||||
|
||||
# TODO: revisit
|
||||
buildPhase = ''
|
||||
substituteInPlace autoload/vimproc.vim \
|
||||
--replace-fail vimproc_mac.so vimproc_unix.so \
|
||||
--replace-fail vimproc_linux64.so vimproc_unix.so \
|
||||
--replace-fail vimproc_linux32.so vimproc_unix.so
|
||||
make -f make_unix.mak
|
||||
'';
|
||||
};
|
||||
|
||||
vimshell-vim = super.vimshell-vim.overrideAttrs {
|
||||
dependencies = [ self.vimproc-vim ];
|
||||
};
|
||||
|
||||
vim-ultest = super.vim-ultest.overrideAttrs {
|
||||
# NOTE: vim-ultest is no longer maintained.
|
||||
# If using Neovim, you can switch to using neotest (https://github.com/nvim-neotest/neotest) instead.
|
||||
nvimSkipModule = "ultest";
|
||||
};
|
||||
|
||||
vim-zettel = super.vim-zettel.overrideAttrs {
|
||||
dependencies = with self; [
|
||||
vimwiki
|
||||
@@ -3987,28 +4024,4 @@ in
|
||||
--replace-fail "'zoxide_executable', 'zoxide'" "'zoxide_executable', '${zoxide}/bin/zoxide'"
|
||||
'';
|
||||
};
|
||||
|
||||
typst-preview-nvim = super.typst-preview-nvim.overrideAttrs {
|
||||
postPatch = ''
|
||||
substituteInPlace lua/typst-preview/config.lua \
|
||||
--replace-fail "['tinymist'] = nil," "tinymist = '${lib.getExe tinymist}'," \
|
||||
--replace-fail "['websocat'] = nil," "websocat = '${lib.getExe websocat}',"
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
rocks-nvim =
|
||||
(neovimUtils.buildNeovimPlugin {
|
||||
luaAttr = luaPackages.rocks-nvim;
|
||||
}).overrideAttrs
|
||||
(oa: {
|
||||
passthru = oa.passthru // {
|
||||
initLua = ''
|
||||
vim.g.rocks_nvim = {
|
||||
luarocks_binary = "${neovim-unwrapped.lua.pkgs.luarocks_bootstrap}/bin/luarocks"
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ https://github.com/ckarnell/antonys-macro-repeater/,,
|
||||
https://github.com/solarnz/arcanist.vim/,,
|
||||
https://github.com/vim-scripts/argtextobj.vim/,,
|
||||
https://github.com/otavioschwanck/arrow.nvim/,,
|
||||
https://github.com/arsham/arshlib.nvim/,HEAD,
|
||||
https://github.com/AstroNvim/astrocore/,HEAD,
|
||||
https://github.com/AstroNvim/astrolsp/,HEAD,
|
||||
https://github.com/AstroNvim/astrotheme/,,
|
||||
@@ -469,6 +470,7 @@ https://github.com/haya14busa/incsearch-easymotion.vim/,,
|
||||
https://github.com/haya14busa/incsearch.vim/,,
|
||||
https://github.com/lukas-reineke/indent-blankline.nvim/,,
|
||||
https://github.com/Darazaki/indent-o-matic/,,
|
||||
https://github.com/arsham/indent-tools.nvim/,HEAD,
|
||||
https://github.com/Yggdroot/indentLine/,,
|
||||
https://github.com/ciaranm/inkpot/,,
|
||||
https://github.com/jbyuki/instant.nvim/,HEAD,
|
||||
|
||||
@@ -7,8 +7,8 @@ vscode-utils.buildVscodeMarketplaceExtension {
|
||||
mktplcRef = {
|
||||
publisher = "RooVeterinaryInc";
|
||||
name = "roo-cline";
|
||||
version = "3.8.6";
|
||||
hash = "sha256-t3QUqe0qYizrJQcsEmYYmNYS/cpYiHQXJHtzHk9MGS8=";
|
||||
version = "3.9.2";
|
||||
hash = "sha256-zRVppwnYpw03L+socmxAtLnkD72Ag7Wz9B4BbxpdFrk=";
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
python3Packages.buildPythonApplication rec {
|
||||
pname = "eddy";
|
||||
version = "3.6";
|
||||
version = "3.7";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "obdasystems";
|
||||
repo = pname;
|
||||
tag = "v${version}";
|
||||
sha256 = "sha256-vRmLUIqU0qfcnKzymBGb9gfM/uQiAcUHUnyz8iH/GrM=";
|
||||
sha256 = "sha256-ywAxlXuKoTXfJSzSsvVXxhycVEklIPQfUogs8QJ8DGQ=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
|
||||
@@ -12,7 +12,8 @@ let
|
||||
pname = "1password";
|
||||
|
||||
versions = builtins.fromJSON (builtins.readFile ./versions.json);
|
||||
inherit (versions.${channel} or (throw "unknown channel ${channel}")) version;
|
||||
hostOs = if stdenv.hostPlatform.isLinux then "linux" else "darwin";
|
||||
version = versions."${channel}-${hostOs}" or (throw "unknown channel-os ${channel}-${hostOs}");
|
||||
|
||||
sources = builtins.fromJSON (builtins.readFile ./sources.json);
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
{
|
||||
"stable": {
|
||||
"x86_64-linux": {
|
||||
"url": "https://downloads.1password.com/linux/tar/stable/x86_64/1password-8.10.60.x64.tar.gz",
|
||||
"hash": "sha256-QCoV66LvGo6vA5fjuE3fG+LwehKVMPmgaDghh9YEvmA="
|
||||
"url": "https://downloads.1password.com/linux/tar/stable/x86_64/1password-8.10.68.x64.tar.gz",
|
||||
"hash": "sha256-6MekdtKnjvrP0dai6VfBEFJ+oKf2WvPp+sU/kVIzCTw="
|
||||
},
|
||||
"aarch64-linux": {
|
||||
"url": "https://downloads.1password.com/linux/tar/stable/aarch64/1password-8.10.60.arm64.tar.gz",
|
||||
"hash": "sha256-E5TniXur9ATJ3ER/zTFc6EiBrH/kbNvIao0ADLyBZZE="
|
||||
"url": "https://downloads.1password.com/linux/tar/stable/aarch64/1password-8.10.68.arm64.tar.gz",
|
||||
"hash": "sha256-2SpfkLu/4K1t2ILwOBMVAXeW7rbEzsjofn8naM1Szfc="
|
||||
},
|
||||
"x86_64-darwin": {
|
||||
"url": "https://downloads.1password.com/mac/1Password-8.10.60-x86_64.zip",
|
||||
"hash": "sha256-2Nv4CHKLgCFbU1TeJQhIq8YdkJSQJXtUw2S17B8cS4s="
|
||||
"url": "https://downloads.1password.com/mac/1Password-8.10.68-x86_64.zip",
|
||||
"hash": "sha256-t/glPvEGJH+IcYyrnW0fMSEeLB8mKqGqmZ8wnVFCJpo="
|
||||
},
|
||||
"aarch64-darwin": {
|
||||
"url": "https://downloads.1password.com/mac/1Password-8.10.60-aarch64.zip",
|
||||
"hash": "sha256-drJiM8EiUM3M54+KPQdLvAmSfBH5YPqQk14yjHzoBtM="
|
||||
"url": "https://downloads.1password.com/mac/1Password-8.10.68-aarch64.zip",
|
||||
"hash": "sha256-bhmuy8gUVCv+hYSIpYXgm8a0f1+JtyKb4g5cUIJCb28="
|
||||
}
|
||||
},
|
||||
"beta": {
|
||||
|
||||
@@ -30,8 +30,8 @@ mk_url() {
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
if [[ -f ${GPG_KEYRING-} ]]; then
|
||||
rm "${GPG_KEYRING}"
|
||||
if [[ -d ${TMP_GNUPGHOME-} ]]; then
|
||||
rm -r "${TMP_GNUPGHOME}"
|
||||
fi
|
||||
|
||||
if [[ -f ${JSON_HEAP-} ]]; then
|
||||
@@ -42,14 +42,14 @@ cleanup() {
|
||||
trap cleanup EXIT
|
||||
|
||||
# Get channel versions from versions.json
|
||||
declare -A version=(
|
||||
["stable"]=$(jq -r '.stable.version' versions.json)
|
||||
["beta"]=$(jq -r '.beta.version' versions.json)
|
||||
)
|
||||
declare -A versions
|
||||
while IFS='=' read -r key value; do
|
||||
versions["${key}"]="${value}"
|
||||
done < <(jq -r 'to_entries[] | "\(.key)=\(.value)"' versions.json)
|
||||
|
||||
#
|
||||
GPG_KEYRING=$(mktemp -t 1password.kbx.XXXXXX)
|
||||
gpg --no-default-keyring --keyring "${GPG_KEYRING}" \
|
||||
TMP_GNUPGHOME=$(mktemp -dt 1password-gui.gnupghome.XXXXXX)
|
||||
export GNUPGHOME="${TMP_GNUPGHOME}"
|
||||
gpg --no-default-keyring --keyring trustedkeys.kbx \
|
||||
--keyserver keyserver.ubuntu.com \
|
||||
--receive-keys 3FEF9748469ADBE15DA7CA80AC2D62742012EA22
|
||||
|
||||
@@ -57,7 +57,8 @@ JSON_HEAP=$(mktemp -t 1password-gui.jsonheap.XXXXXX)
|
||||
for channel in stable beta; do
|
||||
for os in linux darwin; do
|
||||
for arch in x86_64 aarch64; do
|
||||
url=$(mk_url ${os} ${channel} ${arch} "${version[${channel}]}")
|
||||
version="${versions[${channel}-${os}]}"
|
||||
url=$(mk_url ${os} ${channel} ${arch} ${version})
|
||||
nix store prefetch-file --json "${url}" | jq "
|
||||
{
|
||||
\"${channel}\": {
|
||||
@@ -71,7 +72,7 @@ for channel in stable beta; do
|
||||
|
||||
# For some reason 1Password PGP signs only Linux binaries.
|
||||
if [[ ${os} == "linux" ]]; then
|
||||
gpgv --keyring "${GPG_KEYRING}" \
|
||||
gpgv \
|
||||
$(nix store prefetch-file --json "${url}.sig" | jq -r .storePath) \
|
||||
$(jq -r --slurp ".[-1].[].[].storePath" "${JSON_HEAP}")
|
||||
fi
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
{
|
||||
"stable": {
|
||||
"version": "8.10.60"
|
||||
},
|
||||
|
||||
"beta": {
|
||||
"version": "8.10.68-12.BETA"
|
||||
}
|
||||
"stable-linux": "8.10.68",
|
||||
"stable-darwin": "8.10.68",
|
||||
"beta-linux":"8.10.68-12.BETA",
|
||||
"beta-darwin": "8.10.68-12.BETA"
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
|
||||
mkDerivation rec {
|
||||
pname = "heimer";
|
||||
version = "4.4.0";
|
||||
version = "4.5.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "juzzlin";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
hash = "sha256-47bQmT2bHcbWpeosuF/vpSJcws4SqTmalY/XFEf7cxQ=";
|
||||
hash = "sha256-eKnGCYxC3b7qd/g2IMDyZveBg+jvFA9s3tWEGeTPSkU=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
}:
|
||||
buildGoModule rec {
|
||||
pname = "helm-dt";
|
||||
version = "0.4.4";
|
||||
version = "0.4.5";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "vmware-labs";
|
||||
repo = "distribution-tooling-for-helm";
|
||||
rev = "refs/tags/v${version}";
|
||||
hash = "sha256-jSX18FJCQORHFIUBROWZqAO5EBPXFvN/k0NRfkdkUFM=";
|
||||
hash = "sha256-/TRhi4YgEB5RwRZXuwGCCqHz3SoBfs1SdKLBWg1yed0=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-8HefE1a3pcbBgq/bC0mnhWzSa5xTi2dbqw0tyJ9EyTI=";
|
||||
vendorHash = "sha256-54QB8dZSqSpDb4z7di5K6d8/fFbXftKfQJAljV50/Jk=";
|
||||
|
||||
ldflags = [
|
||||
"-s"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
rke2Version = "1.31.5+rke2r1";
|
||||
rke2Commit = "08e198bbe3f0b8d4c9b0af4d92085c06bb94aa89";
|
||||
rke2TarballHash = "sha256-GG1GOs/kLWDCvc/+l0ymRpJzEthIyGpampCjvfnEPB8=";
|
||||
rke2VendorHash = "sha256-xWqMidOWiLgJXp6AEITkyOieLw4yi1JMmi80YS4RNy0=";
|
||||
k8sImageTag = "v1.31.5-rke2r1-build20250115";
|
||||
etcdVersion = "v3.5.16-k3s1-build20241106";
|
||||
rke2Version = "1.31.6+rke2r1";
|
||||
rke2Commit = "f75cdf813703af4bc224b91bfb3c48d10aeb9fd0";
|
||||
rke2TarballHash = "sha256-6HMF3EngR2S8LTpMq4b3B1ZUiBUJO8D3fhwaNMuAuPc=";
|
||||
rke2VendorHash = "sha256-ug1dO4t/QfPpg3mobCIJWb8/MERUoP9tEMlKRKZigXo=";
|
||||
k8sImageTag = "v1.31.6-rke2r1-build20250213";
|
||||
etcdVersion = "v3.5.18-k3s1-build20250210";
|
||||
pauseVersion = "3.6";
|
||||
ccmVersion = "v1.31.2-0.20241016053446-0955fa330f90-build20241016";
|
||||
dockerizedVersion = "v1.31.5-rke2r1";
|
||||
dockerizedVersion = "v1.31.6-rke2r1";
|
||||
}
|
||||
|
||||
@@ -866,6 +866,15 @@
|
||||
"spdx": "MPL-2.0",
|
||||
"vendorHash": "sha256-ZZtfVgxp7YXNRXpeUisLzweQhHzgYOuQDAp1MsxAVhg="
|
||||
},
|
||||
"nexus": {
|
||||
"hash": "sha256-6RPga80ZoqEEFL7I2OVXcrwaxbdhSzZDEV07xL07rZs=",
|
||||
"homepage": "https://registry.terraform.io/providers/datadrivers/nexus",
|
||||
"owner": "datadrivers",
|
||||
"repo": "terraform-provider-nexus",
|
||||
"rev": "v2.5.0",
|
||||
"spdx": "MPL-2.0",
|
||||
"vendorHash": "sha256-wOpR+AJYW7YiARSIACta8Tr4bmGLUONRTEBLxHyHZZk="
|
||||
},
|
||||
"nomad": {
|
||||
"hash": "sha256-k61iQ9FQG3nscBp5CE/fFCbHpeLawbUAtGPM+IZtfVc=",
|
||||
"homepage": "https://registry.terraform.io/providers/hashicorp/nomad",
|
||||
@@ -1066,11 +1075,11 @@
|
||||
"vendorHash": "sha256-j+3qtGlueKZgf0LuNps4Wc9G3EmpSgl8ZNSLqslyizI="
|
||||
},
|
||||
"rancher2": {
|
||||
"hash": "sha256-9I5awIsF/hQ4l4u518GoaUS+ik89mVPSkhHd9itE2eU=",
|
||||
"hash": "sha256-LJgYGgJ7PLRq3WlT2rAnnM8svn4EGghLy3rY7lpmJxI=",
|
||||
"homepage": "https://registry.terraform.io/providers/rancher/rancher2",
|
||||
"owner": "rancher",
|
||||
"repo": "terraform-provider-rancher2",
|
||||
"rev": "v6.0.0",
|
||||
"rev": "v6.1.4",
|
||||
"spdx": "MPL-2.0",
|
||||
"vendorHash": "sha256-uIyLOqabx8wQurxcG70LHm+jBga+bCNyf5XxGrt5OKA="
|
||||
},
|
||||
@@ -1300,11 +1309,11 @@
|
||||
"vendorHash": "sha256-0B2XRpvUk0mgDu3inz37LLJijwH3aQyoSb8IaHr6was="
|
||||
},
|
||||
"tencentcloud": {
|
||||
"hash": "sha256-UO3Gjz5+h4YIj62gCJccFWW8k7qNbmmBzFlT1WWdXl8=",
|
||||
"hash": "sha256-vWMEaA64/h1dhXJDw2kqoWgpp79ZuWP25rvfd6GiReg=",
|
||||
"homepage": "https://registry.terraform.io/providers/tencentcloudstack/tencentcloud",
|
||||
"owner": "tencentcloudstack",
|
||||
"repo": "terraform-provider-tencentcloud",
|
||||
"rev": "v1.81.171",
|
||||
"rev": "v1.81.174",
|
||||
"spdx": "MPL-2.0",
|
||||
"vendorHash": null
|
||||
},
|
||||
|
||||
@@ -153,6 +153,10 @@ let
|
||||
fixupPatches = dir: map (patch: replaceVars patch { inherit dir; });
|
||||
in
|
||||
{
|
||||
z3_4_14 = common {
|
||||
version = "4.14.1";
|
||||
sha256 = "sha256-pTsDzf6Frk4mYAgF81wlR5Kb1x56joFggO5Fa3G2s70=";
|
||||
};
|
||||
z3_4_13 = common {
|
||||
version = "4.13.4";
|
||||
sha256 = "sha256-8hWXCr6IuNVKkOegEmWooo5jkdmln9nU7wI8T882BSE=";
|
||||
|
||||
@@ -2,25 +2,27 @@
|
||||
lib,
|
||||
python3,
|
||||
fetchPypi,
|
||||
fetchFromGitHub,
|
||||
coreutils,
|
||||
gitMinimal,
|
||||
mercurial,
|
||||
}:
|
||||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
version = "0.6.1";
|
||||
version = "0.8.1";
|
||||
pname = "nbstripout";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
hash = "sha256-kGW83RSIs4bk88CB/8HUj0UTovjYv00NmiggjF2v6dM=";
|
||||
hash = "sha256-6qyLa05yno3+Hl3ywPi6RKvFoXplRI8EgBQfgL4jC7E=";
|
||||
};
|
||||
|
||||
# for some reason, darwin uses /bin/sh echo native instead of echo binary, so
|
||||
# force using the echo binary
|
||||
postPatch = ''
|
||||
substituteInPlace tests/test-git.t --replace "echo" "${coreutils}/bin/echo"
|
||||
'';
|
||||
testAssets = fetchFromGitHub {
|
||||
owner = "kynan";
|
||||
repo = "nbstripout";
|
||||
rev = "${version}";
|
||||
hash = "sha256-OSJLrWkYQIhcdyofS3Bo39ppsU6K3A4546UKB8Q1GGg=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with python3.pkgs; [
|
||||
nbformat
|
||||
@@ -33,14 +35,21 @@ python3.pkgs.buildPythonApplication rec {
|
||||
mercurial
|
||||
]
|
||||
++ (with python3.pkgs; [
|
||||
pytest-cram
|
||||
pytestCheckHook
|
||||
]);
|
||||
|
||||
checkInputs = [
|
||||
testAssets
|
||||
];
|
||||
|
||||
preCheck = ''
|
||||
export HOME=$(mktemp -d)
|
||||
export PATH=$out/bin:$PATH
|
||||
git config --global init.defaultBranch main
|
||||
|
||||
cp -r --no-preserve=mode,ownership ${testAssets}/tests/e2e_notebooks $TMPDIR/e2e_notebooks
|
||||
chmod -R +w $TMPDIR/e2e_notebooks
|
||||
substituteInPlace tests/test_end_to_end.py --replace "tests/e2e_notebooks" "$TMPDIR/e2e_notebooks"
|
||||
'';
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -21,19 +21,19 @@
|
||||
|
||||
rustPlatform.buildRustPackage {
|
||||
pname = "crosvm";
|
||||
version = "0-unstable-2025-02-18";
|
||||
version = "0-unstable-2025-03-14";
|
||||
|
||||
src = fetchgit {
|
||||
url = "https://chromium.googlesource.com/chromiumos/platform/crosvm";
|
||||
rev = "10d2f33440475cb1a96eba1dc27c59c8b57b68bd";
|
||||
hash = "sha256-FUTscDaqRgsabLcYq/fny3qXtBiwRRf8RVQBmDUyYrY=";
|
||||
rev = "af765802907dafe1ae1d1f39704c5020a882d362";
|
||||
hash = "sha256-p15gljpEaSloorT37J8Akn5DaqkjVD/QInik4FaF1HE=";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
separateDebugInfo = true;
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-hkDfqNoDn0TSvnQ2eVYEeB+f+JAnPI7BVcQBd9sjYzk=";
|
||||
cargoHash = "sha256-3+gV/4l+N4U2zZWU+UtA1gcmdwnXavbhBPQOB3hhGDk=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
|
||||
@@ -9,19 +9,19 @@ let
|
||||
callPackage
|
||||
(import ./generic.nix rec {
|
||||
pname = "apptainer";
|
||||
version = "1.3.6";
|
||||
version = "1.4.0";
|
||||
projectName = "apptainer";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "apptainer";
|
||||
repo = "apptainer";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-ZdSo9bKZ7Q1xwMe4SR840U3+fVpKwtiZQA5KDM5qF9M=";
|
||||
hash = "sha256-whitdwFOvQgRS9lwbsWhhm92+i1qGW+OFOreNSyvldk=";
|
||||
};
|
||||
|
||||
# Override vendorHash with overrideAttrs.
|
||||
# See https://nixos.org/manual/nixpkgs/unstable/#buildGoModule-vendorHash
|
||||
vendorHash = "sha256-W853++SSvkAYYUczbl8vnoBQZnimUdsAEXp4MCkLPBU=";
|
||||
vendorHash = "sha256-HP5XJ74ELaZT/bZgAPqe7vBPvJhHwyZVSNrUa+KToIE=";
|
||||
|
||||
extraDescription = " (previously known as Singularity)";
|
||||
extraMeta.homepage = "https://apptainer.org";
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
rootModules,
|
||||
kmod,
|
||||
allowMissing ? false,
|
||||
extraFirmwarePaths ? [ ],
|
||||
}:
|
||||
|
||||
stdenvNoCC.mkDerivation {
|
||||
@@ -25,6 +26,7 @@ stdenvNoCC.mkDerivation {
|
||||
firmware
|
||||
rootModules
|
||||
allowMissing
|
||||
extraFirmwarePaths
|
||||
;
|
||||
allowedReferences = [ "out" ];
|
||||
}
|
||||
|
||||
@@ -87,6 +87,15 @@ for module in $(< ~-/closure); do
|
||||
done || :
|
||||
done
|
||||
|
||||
for path in $extraFirmwarePaths; do
|
||||
mkdir -p $(dirname $out/lib/firmware/$path)
|
||||
for name in "$path" "$path.xz" "$path.zst" ""; do
|
||||
if cp -v --parents --no-preserve=mode lib/firmware/$name "$out" 2>/dev/null; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if test -e lib/firmware/edid ; then
|
||||
echo "lib/firmware/edid found, copying."
|
||||
mkdir -p "$out/lib/firmware"
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "ab-av1";
|
||||
version = "0.9.1";
|
||||
version = "0.9.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "alexheretic";
|
||||
repo = "ab-av1";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-I9XApll0/mvfhL/BLWoVwL0ffqa5r3dOBWYTHizJ0hc=";
|
||||
hash = "sha256-rj02Opkwi4M249Ya4uBl4u1l8Mx+FBcRcxDgD6ng9kg=";
|
||||
};
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-y+5rW3LruV1WeJXizbhHs01jkWrYsMXZkn1NG0Xz3bg=";
|
||||
cargoHash = "sha256-Vi38eNn+SnhQx7Gp1T2RPIBeu3bUAZ74dr0mMG5Mha0=";
|
||||
|
||||
nativeBuildInputs = [ installShellFiles ];
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "acpi";
|
||||
version = "1.7";
|
||||
version = "1.8";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://sourceforge/acpiclient/${version}/${pname}-${version}.tar.gz";
|
||||
sha256 = "01ahldvf0gc29dmbd5zi4rrnrw2i1ajnf30sx2vyaski3jv099fp";
|
||||
sha256 = "sha256-5kxuALU815dCfqMqFgUTQlsD7U8HdzP3Hx8J/zQPIws=";
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "alterx";
|
||||
version = "0.0.3";
|
||||
version = "0.0.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "projectdiscovery";
|
||||
repo = "alterx";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-A01XROFB2NkArfFtRMv/r9Nu5QoKMTOVzVIUnFoVe78=";
|
||||
hash = "sha256-IjCK0TVZOBegNdfpqOFoOTuj8KtmCuIqNPvcIa1vSo0=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-efwU41kFR8QYa2cevvj4pYAXgCisJ4OHaRIhWVnETvc=";
|
||||
vendorHash = "sha256-aTA5KGeYmJnbVRbEhT9LigQoJFLD17q9spzBV4BGhNw=";
|
||||
|
||||
meta = with lib; {
|
||||
description = "Fast and customizable subdomain wordlist generator using DSL";
|
||||
|
||||
@@ -2,32 +2,44 @@
|
||||
lib,
|
||||
python3,
|
||||
fetchFromGitLab,
|
||||
fetchPypi,
|
||||
}:
|
||||
|
||||
let
|
||||
tzdata = python3.pkgs.tzdata.overrideAttrs rec {
|
||||
version = "2023.4";
|
||||
|
||||
src = fetchPypi {
|
||||
pname = "tzdata";
|
||||
inherit version;
|
||||
hash = "sha256-3VTJTylHZVIsdzmWSbT+/ZVSJHmmZKDOyH9BvrxhSMk=";
|
||||
};
|
||||
};
|
||||
in
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "annextimelog";
|
||||
version = "0.13.1";
|
||||
version = "0.14.0";
|
||||
format = "pyproject";
|
||||
|
||||
src = fetchFromGitLab {
|
||||
owner = "nobodyinperson";
|
||||
repo = "annextimelog";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-VgeILw8WfqVrmsU/kBw+jHTOt2a6sVT7YgP2pKRp2AY=";
|
||||
hash = "sha256-+3PkG33qKckagSVvVdqkypulO7uu5AMOv8fQiP8IUbs=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = with python3.pkgs; [
|
||||
setuptools
|
||||
wheel
|
||||
poetry-core
|
||||
];
|
||||
] ++ [ tzdata ];
|
||||
|
||||
propagatedBuildInputs = with python3.pkgs; [
|
||||
rich
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
description = "️Git Annex-backed Time Tracking";
|
||||
description = "git-annex based cli time tracker";
|
||||
homepage = "https://gitlab.com/nobodyinperson/annextimelog";
|
||||
license = licenses.gpl3Plus;
|
||||
maintainers = with maintainers; [ matthiasbeyer ];
|
||||
|
||||
@@ -23,13 +23,13 @@
|
||||
}:
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "aquamarine";
|
||||
version = "0.7.2";
|
||||
version = "0.8.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "hyprwm";
|
||||
repo = "aquamarine";
|
||||
rev = "v${finalAttrs.version}";
|
||||
hash = "sha256-ldWD4ci3LcBIfUN41qlBO/oR5chcsRLejMbSW8eH628=";
|
||||
hash = "sha256-ybpV2+yNExdHnMhhhmtxqgBCgI+nRr8gi/D+VVb9lQY=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -32,13 +32,13 @@ let
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "ayatana-indicator-datetime";
|
||||
version = "24.5.0";
|
||||
version = "24.5.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "AyatanaIndicators";
|
||||
repo = "ayatana-indicator-datetime";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-lY49v2uZ7BawQoN/hmN6pbetHlSGjMHbS6S8Wl1bDmQ=";
|
||||
hash = "sha256-rbKAixFjXOMYzduABmoIXissQXAoehfbkNntdtRyAqA=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "badger";
|
||||
version = "4.5.2";
|
||||
version = "4.6.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "dgraph-io";
|
||||
repo = "badger";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-kjMLJAEZN+WANgXsQT7XYLEsc+IL9QwBmaNeD3kyjGw=";
|
||||
hash = "sha256-W3vPTLGI7YT7dFklJnOcpfYqQ9aBCsel9L6q4WNincY=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-m4Bv8RhaUzqyzQ78/Ktr+wLRwL4mlXEsisW4pOJw1DI=";
|
||||
vendorHash = "sha256-UVdOiaj1FN0etB9F0kt+THfO0Aa1kgdGYVeSVv4GpxY=";
|
||||
|
||||
subPackages = [ "badger" ];
|
||||
|
||||
|
||||
@@ -11,19 +11,24 @@
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "below";
|
||||
version = "0.8.1";
|
||||
version = "0.9.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "facebookincubator";
|
||||
repo = "below";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-87Fdx3Jqi3dNWM5DZl+UYs031qn2DoiiWd3IysT/glQ=";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-tPweJFqhZMOL+M08bDjW6HPmtuhr9IXJNP0c938O7Cg=";
|
||||
};
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-iRDe3zg7tfEYGLCRY6bJ6OdoT8ej0MB/vteCIf5xqNA=";
|
||||
# Upstream forgot to commit an up-to-date lockfile.
|
||||
cargoPatches = [ ./update-Cargo.lock.patch ];
|
||||
|
||||
prePatch = ''sed -i "s,ExecStart=.*/bin,ExecStart=$out/bin," etc/below.service'';
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-uNeWdsvJtkUz3E1NL10heDC7B55yKzDMMYzRhEE32EQ=";
|
||||
|
||||
prePatch = ''
|
||||
sed -i "s,ExecStart=.*/bin,ExecStart=$out/bin," etc/below.service
|
||||
'';
|
||||
postInstall = ''
|
||||
install -d $out/lib/systemd/system
|
||||
install -t $out/lib/systemd/system etc/below.service
|
||||
@@ -48,11 +53,11 @@ rustPlatform.buildRustPackage rec {
|
||||
# needs /sys/fs/cgroup
|
||||
doCheck = false;
|
||||
|
||||
meta = with lib; {
|
||||
platforms = platforms.linux;
|
||||
maintainers = with maintainers; [ globin ];
|
||||
meta = {
|
||||
platforms = lib.platforms.linux;
|
||||
maintainers = with lib.maintainers; [ globin ];
|
||||
description = "Time traveling resource monitor for modern Linux systems";
|
||||
license = licenses.asl20;
|
||||
license = lib.licenses.asl20;
|
||||
homepage = "https://github.com/facebookincubator/below";
|
||||
mainProgram = "below";
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
rustPlatform,
|
||||
pkg-config,
|
||||
libudev-zero,
|
||||
}:
|
||||
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "bitbox-bridge";
|
||||
version = "1.6.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "BitBoxSwiss";
|
||||
repo = "bitbox-bridge";
|
||||
tag = "v${finalAttrs.version}";
|
||||
fetchSubmodules = true;
|
||||
hash = "sha256-+pMXWXGHyyBx3N0kiro9NS0mPmSQzzBmp+pkoBLH7z0=";
|
||||
};
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-6vD0XjGH1PXjiRjgnHWSZSixXOc2Yecui8U5FAGefBU=";
|
||||
|
||||
postPatch = ''
|
||||
rm .cargo/config.toml
|
||||
'';
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
];
|
||||
|
||||
buildInputs = lib.optionals stdenv.hostPlatform.isLinux [
|
||||
libudev-zero
|
||||
];
|
||||
|
||||
meta = {
|
||||
description = "A bridge service that connects web wallets like Rabby to BitBox02";
|
||||
homepage = "https://github.com/BitBoxSwiss/bitbox-bridge";
|
||||
downloadPage = "https://bitbox.swiss/download/";
|
||||
changelog = "https://github.com/BitBoxSwiss/bitbox-bridge/blob/v${finalAttrs.version}/CHANGELOG.md";
|
||||
license = lib.licenses.asl20;
|
||||
maintainers = with lib.maintainers; [
|
||||
izelnakri
|
||||
tensor5
|
||||
];
|
||||
mainProgram = "bitbox-bridge";
|
||||
platforms = lib.platforms.unix;
|
||||
};
|
||||
})
|
||||
@@ -51,7 +51,7 @@ buildNpmPackage rec {
|
||||
npmFlags = [ "--legacy-peer-deps" ];
|
||||
|
||||
npmRebuildFlags = [
|
||||
# FIXME one of the esbuild versions fails to download @esbuild/linux-x64
|
||||
# we'll run npm rebuild manually later
|
||||
"--ignore-scripts"
|
||||
];
|
||||
|
||||
@@ -60,6 +60,11 @@ buildNpmPackage rec {
|
||||
shopt -s globstar
|
||||
rm -r node_modules/**/prebuilds
|
||||
shopt -u globstar
|
||||
|
||||
# FIXME one of the esbuild versions fails to download @esbuild/linux-x64
|
||||
rm -r node_modules/esbuild node_modules/vite/node_modules/esbuild
|
||||
|
||||
npm rebuild --verbose
|
||||
'';
|
||||
|
||||
postBuild = ''
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "bloop";
|
||||
version = "2.0.8";
|
||||
version = "2.0.9";
|
||||
|
||||
platform =
|
||||
if stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isx86_64 then
|
||||
@@ -42,11 +42,11 @@ stdenv.mkDerivation rec {
|
||||
url = "https://github.com/scalacenter/bloop/releases/download/v${version}/bloop-${platform}";
|
||||
sha256 =
|
||||
if stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isx86_64 then
|
||||
"sha256-ItPt5qjfRgtPNg6a/Zlc0ASfdvGXMMKV7SqNEOQ9u28="
|
||||
"sha256-mslCzvJ+z5VNQkVa9HXjw2bUBprMgs3bAy3RmEt8OlI="
|
||||
else if stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64 then
|
||||
"sha256-zUSDUwZY1id/WFuC87Wa4eB48X4rmXvVC1/b2v5bhw4="
|
||||
"sha256-XdMPo9O7ADhInmGFIOHihl1z4yPKAyDjCH7m3tCtKNo="
|
||||
else if stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64 then
|
||||
"sha256-1wsGL1G8/+xMvYNwe7EOyqEuEKDKiwA7yyyjfbGgxJQ="
|
||||
"sha256-sJM00f2KBI6fnVj3U/h/pYAFT7QjZkfJ7ubDfFlRJ0Q="
|
||||
else
|
||||
throw "unsupported platform";
|
||||
};
|
||||
|
||||
@@ -87,14 +87,14 @@ in
|
||||
let
|
||||
bolt = stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "bolt-launcher";
|
||||
version = "0.9.0";
|
||||
version = "0.14.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "AdamCake";
|
||||
repo = "bolt";
|
||||
rev = finalAttrs.version;
|
||||
tag = finalAttrs.version;
|
||||
fetchSubmodules = true;
|
||||
hash = "sha256-LIlRDcUWbQwIhFjtqYF+oVpTOPZ7IT0vMgysEVyJ1k8=";
|
||||
hash = "sha256-fNCi2Wu+oOL6p8IBm6bHZ/rcaFmqoKs2DnXQ+ZA9McE=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
@@ -154,8 +154,8 @@ let
|
||||
desktopName = "Bolt Launcher";
|
||||
genericName = finalAttrs.pname;
|
||||
comment = "An alternative launcher for RuneScape";
|
||||
exec = "${finalAttrs.pname}-${finalAttrs.version}";
|
||||
icon = finalAttrs.pname;
|
||||
exec = "bolt-launcher";
|
||||
icon = "bolt-launcher";
|
||||
categories = [ "Game" ];
|
||||
})
|
||||
];
|
||||
|
||||
@@ -15,17 +15,17 @@
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "broot";
|
||||
version = "1.44.7";
|
||||
version = "1.45.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Canop";
|
||||
repo = "broot";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-GaOPC1lIu48qFo99AQ99f49e8qH/TEQubpluptLc0jY=";
|
||||
hash = "sha256-Hif+ynwOxiZBAiNdbaU5SpI9s0yNxtH0qXXMfGO21H0=";
|
||||
};
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-J7zc1aTH62nL96cSb9CiIk8uJdR7nk9EnERiAfMvqNM=";
|
||||
cargoHash = "sha256-Cw0Bh8S04oUlbbn3O3+uBoHEgh82XIcGQSGqkZFOc78=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
installShellFiles
|
||||
|
||||
@@ -8,19 +8,19 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "carapace-bridge";
|
||||
version = "1.2.3";
|
||||
version = "1.2.4";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "carapace-sh";
|
||||
repo = "carapace-bridge";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-RMItv9HAPsxnb0NGlDjqY8Of4cxf8xU1c8ZE8Ajz0ao=";
|
||||
hash = "sha256-/HjoE6yaawo1hCemnvtfK3wj4SBSW91D4oyuZ5qxV4M=";
|
||||
};
|
||||
|
||||
# buildGoModule try to run `go mod vendor` instead of `go work vendor` on the
|
||||
# workspace if proxyVendor is off
|
||||
proxyVendor = true;
|
||||
vendorHash = "sha256-R2sk5yqhF+5pVWxCnEx+EKTvNPzg32/JguLMu6R3ETM=";
|
||||
vendorHash = "sha256-zfV5IcpwtK3n76jWs4ldMlpEqbyNmmXZWDj+fh66luw=";
|
||||
|
||||
postPatch = ''
|
||||
substituteInPlace cmd/carapace-bridge/main.go \
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "civo";
|
||||
version = "1.1.97";
|
||||
version = "1.1.98";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "civo";
|
||||
repo = "cli";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-0BIvKzG+ePN4VyXPj4VfCoZiq/pDZb9/7k/kTIa4Fqs=";
|
||||
hash = "sha256-gxqVWnhlLYizoij6L9/ThM9T7K7++nGZwgFP3OzBqOY=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-V1R5MQ3y8mcm8ffc2INKk6BTYUROEvr8lHBs6MvbpkQ=";
|
||||
vendorHash = "sha256-LN6rzZXw7YoHMyPCujPiyjs8tG+nN2fxwQnEenohw1c=";
|
||||
|
||||
nativeBuildInputs = [ installShellFiles ];
|
||||
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "cloud-nuke";
|
||||
version = "0.38.2";
|
||||
version = "0.39.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "gruntwork-io";
|
||||
repo = pname;
|
||||
tag = "v${version}";
|
||||
hash = "sha256-hQFuHEIxsvyCmP4DR9MsrWmPbo3BFU3k5nYNsQVNy/U=";
|
||||
hash = "sha256-r9/5A1f6GSDgF5/GM4UKxoCYUsc5xsZpTwDGDUySDfQ=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-ExZZHCGmU9r1DrJ3alN6Y39P6rfFymQSpK8b+ZD7h0s=";
|
||||
vendorHash = "sha256-AiPy/lmqrNeDWM7/pXmzHCbSWZdqdXnZNATlyi6oAGc=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
makeBinaryWrapper
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
fetchYarnDeps,
|
||||
yarnConfigHook,
|
||||
yarnInstallHook,
|
||||
nodejs,
|
||||
nix-update-script,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "cloudflare-cli";
|
||||
version = "4.2.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "danielpigott";
|
||||
repo = "cloudflare-cli";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-cT+cMekXhHKfFi+dH1dCA/YNBSyYePJIZBSkDMPZZ14=";
|
||||
};
|
||||
|
||||
yarnOfflineCache = fetchYarnDeps {
|
||||
yarnLock = finalAttrs.src + "/yarn.lock";
|
||||
hash = "sha256-0SFXgaLQE/MkqC9id7DAiP422tEyTt2gpgpIdXViFBI=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
yarnConfigHook
|
||||
yarnInstallHook
|
||||
nodejs
|
||||
];
|
||||
|
||||
doInstallCheck = true;
|
||||
installCheckPhase = ''
|
||||
runHook preInstallCheck
|
||||
|
||||
$out/bin/cfcli --help >/dev/null
|
||||
|
||||
runHook postInstallCheck
|
||||
'';
|
||||
|
||||
passthru.updateScript = nix-update-script { };
|
||||
|
||||
meta = {
|
||||
description = "CLI for interacting with Cloudflare";
|
||||
homepage = "https://github.com/danielpigott/cloudflare-cli";
|
||||
changelog = "https://github.com/danielpigott/cloudflare-cli/releases/tag/v${finalAttrs.version}";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [ defelo ];
|
||||
mainProgram = "cfcli";
|
||||
};
|
||||
})
|
||||
@@ -9,13 +9,13 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "clusterctl";
|
||||
version = "1.9.5";
|
||||
version = "1.9.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "kubernetes-sigs";
|
||||
repo = "cluster-api";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-4n+7/4ZMD0VzlD4PzEWVDut+rt8/4Vz3gAgCDAj+SVs=";
|
||||
hash = "sha256-XXtVGIpoR2JfkR7urfHuh6xKoIvsF42NV+4yjxb8nls=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-SdLeME6EFraGUXE1zUdEfxTETUKLDmecYpWEg5DE4PQ=";
|
||||
|
||||
@@ -113,7 +113,10 @@ python3Packages.buildPythonApplication rec {
|
||||
homepage = "https://github.com/Ericsson/codechecker";
|
||||
changelog = "https://github.com/Ericsson/codechecker/releases/tag/v${version}";
|
||||
description = "Analyzer tooling, defect database and viewer extension for the Clang Static Analyzer and Clang Tidy";
|
||||
license = licenses.asl20-llvm;
|
||||
license = with licenses; [
|
||||
asl20
|
||||
llvm-exception
|
||||
];
|
||||
maintainers = with maintainers; [
|
||||
zebreus
|
||||
felixsinger
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
# $ conda-shell
|
||||
# $ conda install spyder
|
||||
let
|
||||
version = "25.1.1";
|
||||
version = "25.1.1-2";
|
||||
|
||||
src =
|
||||
let
|
||||
@@ -57,10 +57,10 @@ let
|
||||
};
|
||||
in
|
||||
fetchurl {
|
||||
url = "https://repo.anaconda.com/miniconda/Miniconda3-py312_${version}-0-Linux-${arch}.sh";
|
||||
url = "https://repo.anaconda.com/miniconda/Miniconda3-py312_${version}-Linux-${arch}.sh";
|
||||
hash = selectSystem {
|
||||
x86_64-linux = "sha256-gy3ielo1t5Y/DYNGarraPrE45RmFJV8ZDg3DUEJ6ndE=";
|
||||
aarch64-linux = "sha256-rp0+qD35fnj9UcRS0Lx1AFoo1QTCLbbxAAgiKT+Ra1Q=";
|
||||
x86_64-linux = "sha256-R2bYW199I1ziUOmY67WoqCEMvU8rD+pNIXez7Z6oeIQ=";
|
||||
aarch64-linux = "sha256-bQW5+bfzJ7kHl6TPVtaMgVeLqy9jJXo+eotyyw8OS10=";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
# passthru
|
||||
conduit,
|
||||
python3Packages,
|
||||
nix-update-script,
|
||||
|
||||
mpiSupport ? false,
|
||||
@@ -50,6 +51,8 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
passthru = {
|
||||
tests = {
|
||||
withMpi = conduit.override { mpiSupport = true; };
|
||||
pythonModule = python3Packages.conduit;
|
||||
pythonModuleWithMpi = python3Packages.conduit-mpi;
|
||||
};
|
||||
updateScript = nix-update-script { };
|
||||
};
|
||||
|
||||
@@ -10,17 +10,17 @@
|
||||
}:
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "cook-cli";
|
||||
version = "0.7.1";
|
||||
version = "0.10.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "cooklang";
|
||||
repo = "cookcli";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-3gLVsk6GCxOG24Md7E9fk28Vnc4kVDdwyZUD/GtSwFE=";
|
||||
hash = "sha256-1m2+etJG+33fPTxBF8qT/U9WiZGcSn9r0WlK5PDL6/Q=";
|
||||
};
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-EoTCKpH8G3SsXkhQVsr9aX4Cupm+fzPtXHpoM1knqss=";
|
||||
cargoHash = "sha256-3tWVCP80a6odmi9C0klLbfO5UmdFczyUY8KQSaMIyw4=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
|
||||
@@ -8,17 +8,17 @@
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "ccat";
|
||||
version = "003";
|
||||
version = "004";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "DeeKahy";
|
||||
repo = "CopyCat";
|
||||
tag = version;
|
||||
hash = "sha256-BNXWubJ6eRnuK7+0kE9yHQzjJci5miTSG3dwWE2XDwc=";
|
||||
hash = "sha256-HLT88ghyT9AwvBTf7NrFkSPqMAh90GrBqZVXN5aaG3w=";
|
||||
};
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-2SI4h5RqzWKWnRmQ2t/eDAOK1ql7jlZKIgPlSiiB6Dg=";
|
||||
cargoHash = "sha256-gjFVvP2h+HJdDdNVtqTT1E1s4ZYXfWuhtMBRJkWRcDw=";
|
||||
|
||||
buildInputs = lib.optionals (stdenv.hostPlatform.isDarwin) [
|
||||
darwin.apple_sdk_11_0.frameworks.AppKit
|
||||
|
||||
@@ -9,18 +9,18 @@
|
||||
}:
|
||||
|
||||
let
|
||||
commitHash = "9d021bf61a094a5eac6ae3084ceed2dda4700a73"; # matches tag release
|
||||
commitHash = "d5bc935e4801a02fdbd953f8f0ae7989eaef50cf"; # matches tag release
|
||||
shortCommitHash = builtins.substring 0 7 commitHash;
|
||||
in
|
||||
buildGoModule rec {
|
||||
pname = "copywrite";
|
||||
version = "0.21.0";
|
||||
version = "0.22.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "hashicorp";
|
||||
repo = "copywrite";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-TGis7rreRen+vk3tUDehRkyas4xrBBxKlA70+VqoGWY=";
|
||||
hash = "sha256-gPVlHgFlLxoAj4pkg3OxD4CGQaLdAL312/Zn/pJ+7fg=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-Qxp6BwN/Y6Xb1BwFGT/T8WYsXGPgN27mzoTE0i6cS1Q=";
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
lib,
|
||||
rustPlatform,
|
||||
fetchFromGitHub,
|
||||
yq,
|
||||
pkg-config,
|
||||
openssl,
|
||||
versionCheckHook,
|
||||
nix-update-script,
|
||||
}:
|
||||
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "countryfetch";
|
||||
version = "0.1.9";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "nik-rev";
|
||||
repo = "countryfetch";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-KdFgY54vXLmq6IZfJzZ1IeZ2eQuNJoCRZUV3rVuPpcY=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
tomlq -ti '.dependencies.openssl.features[] |= select(.!="vendored")' countryfetch/Cargo.toml
|
||||
'';
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-XJI9k/5hdak8p0/J/x9u6lqJu/DIbX93Wwm3LALkAAw=";
|
||||
|
||||
env.RUSTC_BOOTSTRAP = 1;
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
yq # for `tomlq`
|
||||
];
|
||||
|
||||
buildInputs = [ openssl ];
|
||||
|
||||
cargoBuildFlags = [ "--package=countryfetch" ];
|
||||
|
||||
nativeInstallCheckInputs = [ versionCheckHook ];
|
||||
versionCheckProgramArg = "--version";
|
||||
doInstallCheck = true;
|
||||
|
||||
passthru.updateScript = nix-update-script { };
|
||||
|
||||
meta = {
|
||||
description = "Command-line tool similar to Neofetch for obtaining information about your country";
|
||||
homepage = "https://github.com/nik-rev/countryfetch";
|
||||
changelog = "https://github.com/nik-rev/countryfetch/blob/v${finalAttrs.version}/CHANGELOG.md";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [ defelo ];
|
||||
mainProgram = "countryfetch";
|
||||
};
|
||||
})
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "crocoddyl";
|
||||
version = "2.2.0";
|
||||
version = "3.0.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "loco-3d";
|
||||
repo = "crocoddyl";
|
||||
rev = "v${finalAttrs.version}";
|
||||
hash = "sha256-j3TL5TpIdTkTO32Fuu+LyiieiXoOMvShi/LbBL5YYzA=";
|
||||
hash = "sha256-oWcclzzuswiR1SaQJd6GnMltJ2vgt7AgJPT0FJzD1Gs=";
|
||||
};
|
||||
|
||||
outputs = [
|
||||
|
||||
@@ -27,17 +27,17 @@ let
|
||||
|
||||
self = buildRustPackage' {
|
||||
pname = "czkawka";
|
||||
version = "8.0.0";
|
||||
version = "9.0.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "qarmin";
|
||||
repo = "czkawka";
|
||||
tag = self.version;
|
||||
hash = "sha256-Uxko2TRIjqQvd7n9C+P7oMUrm3YY5j7TVzvijEjDwOM=";
|
||||
hash = "sha256-ePiHDfQ1QC3nff8uWE0ggiTuulBomuoZ3ta0redUYXY=";
|
||||
};
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-lYS/G3mHNqKcI6XRAtESzgBiUHnNfV0ct0W6E75a7J4=";
|
||||
cargoHash = "sha256-Djvb5Hen6XPm6aJuwa6cGPojz9+kXXidysr3URDwDFM=";
|
||||
|
||||
nativeBuildInputs = [
|
||||
gobject-introspection
|
||||
|
||||
@@ -13,7 +13,7 @@ let
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
inherit pname;
|
||||
version = "24.3.3";
|
||||
version = "25.1";
|
||||
|
||||
src =
|
||||
let
|
||||
@@ -21,7 +21,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
in
|
||||
fetchurl {
|
||||
url = "https://www.dbvis.com/product_download/dbvis-${finalAttrs.version}/media/dbvis_linux_${underscoreVersion}.tar.gz";
|
||||
hash = "sha256-RDmakZJ7mjTzx4QaKwT6H25dDvQANbLhd2+f8EYbmDA=";
|
||||
hash = "sha256-Se2d5S8nXKmNJ1UoYNGJyvHC20THShjzGh2T98NhFv4=";
|
||||
};
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "ddns-go";
|
||||
version = "6.9.0";
|
||||
version = "6.9.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "jeessy2";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
hash = "sha256-eHJVd7PHUrswF1j4MrsUmle0vB8/CtH43p5ILZGljrs=";
|
||||
hash = "sha256-QGvXUYeT01+P843gBX+IJWTyPg0cPI9jZWh3tAcmEqE=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-5XrwVIaQ2dMizx3Pj0dmLkpYwypUVnfxLNxmNsVhVzY=";
|
||||
|
||||
@@ -9,16 +9,16 @@
|
||||
|
||||
buildGoModule rec {
|
||||
pname = "diffoci";
|
||||
version = "0.1.5";
|
||||
version = "0.1.6";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "reproducible-containers";
|
||||
repo = "diffoci";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-ZVWnfg5uWYuqsNd4X6t1gWBGMfdcirSp7QZZDhqAfaI=";
|
||||
hash = "sha256-rCSLHlHUWS0wEnN8R2v1h+kQ7K62VQPfZmySHGSFZlQ=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-qb4HvK4UbJbtP/ypeptV/MMbhOu5UZDaGartq/RGpDM=";
|
||||
vendorHash = "sha256-udVigglpCgdYzJe9vdGZiQepZeOplQjqKB4Za8a+u6k=";
|
||||
|
||||
ldflags = [
|
||||
"-s"
|
||||
|
||||
@@ -20,11 +20,11 @@ let
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "apache-druid";
|
||||
version = "31.0.0";
|
||||
version = "32.0.0";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://apache/druid/${finalAttrs.version}/apache-druid-${finalAttrs.version}-bin.tar.gz";
|
||||
hash = "sha256-xppAoKNS/qB8WVMwBPxxHbOy5uDGl3IxrCWV1T+YQkE=";
|
||||
hash = "sha256-JeHmraWOQNjaVYyhYQesBrwLHAqnqsEG6it6quj3K3I=";
|
||||
};
|
||||
|
||||
dontBuild = true;
|
||||
@@ -57,7 +57,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
runHook preInstall
|
||||
mkdir $out
|
||||
mv * $out
|
||||
${optionalString mysqlSupport "ln -s ${mysql_jdbc}/share/java/mysql-connector-java.jar $out/extensions/mysql-metadata-storage"}
|
||||
${optionalString mysqlSupport "ln -s ${mysql_jdbc}/share/java/mysql-connector-j.jar $out/extensions/mysql-metadata-storage"}
|
||||
${finalAttrs.loadExtensions}
|
||||
${finalAttrs.loadJars}
|
||||
runHook postInstall
|
||||
|
||||
@@ -8,17 +8,17 @@
|
||||
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "dumbpipe";
|
||||
version = "0.25.0";
|
||||
version = "0.26.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "n0-computer";
|
||||
repo = "dumbpipe";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-nYM/QAG57491NqTAkqF1p3DeuVKDPvh6MUqYP/gAWyc=";
|
||||
hash = "sha256-xQHVEJ+EgsrboXbPg7pGXXMjyedSLooqkTt/yYZACSo=";
|
||||
};
|
||||
|
||||
useFetchCargoVendor = true;
|
||||
cargoHash = "sha256-lg/FmeCYL9WVvvEMnkQj1WaxFH+7rBBxgL9zfwSdaVE=";
|
||||
cargoHash = "sha256-uuY0nh4VHzyM7+cbgyycr5I3IjE0OeQ0eg12qVXe4BQ=";
|
||||
|
||||
buildInputs = lib.optionals stdenv.hostPlatform.isDarwin (
|
||||
with darwin.apple_sdk.frameworks;
|
||||
|
||||
@@ -33,14 +33,14 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "dwarfs";
|
||||
version = "0.10.2";
|
||||
version = "0.11.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "mhx";
|
||||
repo = "dwarfs";
|
||||
tag = "v${finalAttrs.version}";
|
||||
fetchSubmodules = true;
|
||||
hash = "sha256-wQ+6jSf/RWAI7cSRMb1zG09kOiyMM5xiy8yS6tl1ybI=";
|
||||
hash = "sha256-UOIHtyOGKG0WPwKS1z0agMTvI0RF5sapJ5GoJ7a8+Vs=";
|
||||
};
|
||||
|
||||
cmakeFlags = [
|
||||
|
||||
@@ -27,11 +27,11 @@ let
|
||||
in
|
||||
stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
pname = "dynamodb-local";
|
||||
version = "2.5.4";
|
||||
version = "2.6.0";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://d1ni2b6xgvw0s0.cloudfront.net/v2.x/dynamodb_local_2024-12-23.tar.gz";
|
||||
hash = "sha256-YLFWH6YUFkLb062at1pjFclId/b0LmBVESWxHqimLJc=";
|
||||
url = "https://d1ni2b6xgvw0s0.cloudfront.net/v2.x/dynamodb_local_2025-03-13.tar.gz";
|
||||
hash = "sha256-mAXZX+L17+z9f3/sMq+O+zLcg7YKGKL72BhhTtS2xuw=";
|
||||
};
|
||||
|
||||
sourceRoot = ".";
|
||||
|
||||
@@ -44,6 +44,9 @@ llvmPackages.stdenv.mkDerivation rec {
|
||||
description = "High-performance automatic differentiation of LLVM and MLIR";
|
||||
maintainers = with lib.maintainers; [ kiranshila ];
|
||||
platforms = lib.platforms.all;
|
||||
license = lib.licenses.asl20-llvm;
|
||||
license = with lib.licenses; [
|
||||
asl20
|
||||
llvm-exception
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
diff --git a/src/Etterna/Singletons/DownloadManager.cpp b/src/Etterna/Singletons/DownloadManager.cpp
|
||||
index b42ccd30..3606107d 100644
|
||||
--- a/src/Etterna/Singletons/DownloadManager.cpp
|
||||
+++ b/src/Etterna/Singletons/DownloadManager.cpp
|
||||
@@ -6265,7 +6265,10 @@ Download::Install()
|
||||
{
|
||||
Core::Platform::requestUserAttention();
|
||||
Message* msg;
|
||||
- if (!SongManager::InstallSmzip(m_TempFileName))
|
||||
+
|
||||
+ auto path = FILEMAN->ResolvePath(m_TempFileName);
|
||||
+
|
||||
+ if (!SongManager::InstallSmzip(path))
|
||||
msg = new Message("DownloadFailed");
|
||||
else
|
||||
msg = new Message("PackDownloaded");
|
||||
@@ -0,0 +1,109 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
makeDesktopItem,
|
||||
copyDesktopItems,
|
||||
# deps
|
||||
cmake,
|
||||
pkg-config,
|
||||
openssl,
|
||||
libGLU,
|
||||
xorg,
|
||||
alsa-lib,
|
||||
libjack2,
|
||||
libpulseaudio,
|
||||
libogg,
|
||||
sse2neon,
|
||||
}:
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "etterna";
|
||||
version = "0.74.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "etternagame";
|
||||
repo = "etterna";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-zzCk6axISswfTAk7rRha5HFzIHQ0AjpAZyAWzH+Cn1s=";
|
||||
};
|
||||
|
||||
patches = [ ./fix-download-manager.patch ];
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
pkg-config
|
||||
|
||||
copyDesktopItems
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
openssl
|
||||
alsa-lib
|
||||
libjack2
|
||||
libpulseaudio
|
||||
libGLU
|
||||
libogg
|
||||
sse2neon
|
||||
xorg.libXinerama
|
||||
xorg.libXrandr
|
||||
xorg.libX11
|
||||
xorg.libXext # Needed for DPMS
|
||||
xorg.libXvMC
|
||||
];
|
||||
|
||||
desktopItems = [
|
||||
(makeDesktopItem {
|
||||
name = "etterna";
|
||||
desktopName = "Etterna";
|
||||
genericName = "Rhythm and dance game";
|
||||
icon = "etterna";
|
||||
tryExec = "etterna";
|
||||
exec = "etterna";
|
||||
categories = [
|
||||
"Application"
|
||||
"Game"
|
||||
"ArcadeGame"
|
||||
];
|
||||
comment = "A cross-platform rhythm video game.";
|
||||
terminal = false;
|
||||
})
|
||||
];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out/{bin,share/etterna}
|
||||
mkdir -p $out/share/applications
|
||||
# copy select necessary game files into virtual fs
|
||||
cp -r /build/source/{Announcers,Assets,BGAnimations,BackgroundEffects,BackgroundTransitions,Data,GameTools,NoteSkins,Scripts,Themes} "$out/share/etterna"
|
||||
|
||||
# copy binary
|
||||
cp /build/source/Etterna $out/bin/.etterna-unwrapped
|
||||
|
||||
# Install the Icon
|
||||
install -Dm644 /build/source/Docs/images/etterna-logo-light.svg "$out/share/icons/hicolor/scalable/apps/etterna.svg"
|
||||
|
||||
# wacky insertion of wrapper directly into phase, so that $out is set
|
||||
cat > $out/bin/etterna << EOF
|
||||
#!${stdenv.shell}
|
||||
export ETTERNA_ROOT_DIR="\$HOME/.local/share/etterna"
|
||||
export ETTERNA_ADDITIONAL_ROOT_DIRS="$out/share/etterna"
|
||||
echo "HOME: \$HOME"
|
||||
echo "PWD: \$(pwd)"
|
||||
echo "ETTERNA_ADDITIONAL_ROOT_DIRS: \$ETTERNA_ADDITIONAL_ROOT_DIRS"
|
||||
exec $out/bin/.etterna-unwrapped "\$@"
|
||||
EOF
|
||||
chmod +x $out/bin/etterna
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
cmakeFlags = [ "-D WITH_CRASHPAD=OFF" ];
|
||||
|
||||
meta = {
|
||||
description = "Advanced cross-platform rhythm game focused on keyboard play";
|
||||
homepage = "https://etternaonline.com";
|
||||
changelog = "https://github.com/etternagame/etterna/release/tag/v${finalAttrs.version}";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [ alikindsys ];
|
||||
mainProgram = "etterna";
|
||||
};
|
||||
})
|
||||
@@ -8,14 +8,14 @@
|
||||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "exabgp";
|
||||
version = "4.2.22";
|
||||
version = "4.2.25";
|
||||
format = "pyproject";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Exa-Networks";
|
||||
repo = "exabgp";
|
||||
tag = version;
|
||||
hash = "sha256-PrdCAmefKCBmbBFp04KiQGSsZZ4KNFk/ZtMedh9oow4=";
|
||||
hash = "sha256-YBxRDcm4Qt44W3lBHDwdvZq2pXEujbqJDh24JbXthMg=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = with python3.pkgs; [
|
||||
@@ -39,7 +39,7 @@ python3.pkgs.buildPythonApplication rec {
|
||||
meta = with lib; {
|
||||
description = "BGP swiss army knife of networking";
|
||||
homepage = "https://github.com/Exa-Networks/exabgp";
|
||||
changelog = "https://github.com/Exa-Networks/exabgp/blob/${src.rev}/CHANGELOG.rst";
|
||||
changelog = "https://github.com/Exa-Networks/exabgp/blob/${src.tag}/CHANGELOG.rst";
|
||||
license = licenses.bsd3;
|
||||
maintainers = with maintainers; [
|
||||
hexa
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user