Merge master into haskell-updates
This commit is contained in:
@@ -14,7 +14,17 @@
|
||||
</itemizedlist>
|
||||
<section xml:id="sec-release-22.05-highlights">
|
||||
<title>Highlights</title>
|
||||
<itemizedlist spacing="compact">
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>security.acme.defaults</literal> has been added to
|
||||
simplify configuring settings for many certificates at once.
|
||||
This also opens up the the option to use DNS-01 validation
|
||||
when using <literal>enableACME</literal> on web server virtual
|
||||
hosts (e.g.
|
||||
<literal>services.nginx.virtualHosts.*.enableACME</literal>).
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
PHP 8.1 is now available
|
||||
@@ -33,6 +43,14 @@
|
||||
<link linkend="opt-services.aesmd.enable">services.aesmd</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://docs.docker.com/engine/security/rootless/">rootless
|
||||
Docker</link>, a <literal>systemd --user</literal> Docker
|
||||
service which runs without root permissions. Available as
|
||||
<link xlink:href="options.html#opt-virtualisation.docker.rootless.enable">virtualisation.docker.rootless.enable</link>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<link xlink:href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html">filebeat</link>,
|
||||
@@ -189,6 +207,20 @@
|
||||
using this default will print a warning when rebuilt.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>security.acme</literal> certificates will now
|
||||
correctly check for CA revokation before reaching their
|
||||
minimum age.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Removing domains from
|
||||
<literal>security.acme.certs._name_.extraDomainNames</literal>
|
||||
will now correctly remove those domains during rebuild/renew.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The option
|
||||
|
||||
@@ -6,11 +6,17 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
|
||||
## Highlights {#sec-release-22.05-highlights}
|
||||
|
||||
- `security.acme.defaults` has been added to simplify configuring
|
||||
settings for many certificates at once. This also opens up the
|
||||
the option to use DNS-01 validation when using `enableACME` on
|
||||
web server virtual hosts (e.g. `services.nginx.virtualHosts.*.enableACME`).
|
||||
|
||||
- PHP 8.1 is now available
|
||||
|
||||
## New Services {#sec-release-22.05-new-services}
|
||||
|
||||
- [aesmd](https://github.com/intel/linux-sgx#install-the-intelr-sgx-psw), the Intel SGX Architectural Enclave Service Manager. Available as [services.aesmd](#opt-services.aesmd.enable).
|
||||
- [rootless Docker](https://docs.docker.com/engine/security/rootless/), a `systemd --user` Docker service which runs without root permissions. Available as [virtualisation.docker.rootless.enable](options.html#opt-virtualisation.docker.rootless.enable).
|
||||
|
||||
- [filebeat](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-overview.html), a lightweight shipper for forwarding and centralizing log data. Available as [services.filebeat](#opt-services.filebeat.enable).
|
||||
|
||||
@@ -75,6 +81,12 @@ In addition to numerous new and upgraded packages, this release has the followin
|
||||
- The `services.unifi.openPorts` option default value of `true` is now deprecated and will be changed to `false` in 22.11.
|
||||
Configurations using this default will print a warning when rebuilt.
|
||||
|
||||
- `security.acme` certificates will now correctly check for CA
|
||||
revokation before reaching their minimum age.
|
||||
|
||||
- Removing domains from `security.acme.certs._name_.extraDomainNames`
|
||||
will now correctly remove those domains during rebuild/renew.
|
||||
|
||||
- The option
|
||||
[services.ssh.enableAskPassword](#opt-services.ssh.enableAskPassword) was
|
||||
added, decoupling the setting of `SSH_ASKPASS` from
|
||||
|
||||
@@ -1187,6 +1187,7 @@
|
||||
./virtualisation/oci-containers.nix
|
||||
./virtualisation/cri-o.nix
|
||||
./virtualisation/docker.nix
|
||||
./virtualisation/docker-rootless.nix
|
||||
./virtualisation/ecs-agent.nix
|
||||
./virtualisation/libvirtd.nix
|
||||
./virtualisation/lxc.nix
|
||||
|
||||
+267
-221
@@ -3,6 +3,7 @@ with lib;
|
||||
let
|
||||
cfg = config.security.acme;
|
||||
opt = options.security.acme;
|
||||
user = if cfg.useRoot then "root" else "acme";
|
||||
|
||||
# Used to calculate timer accuracy for coalescing
|
||||
numCerts = length (builtins.attrNames cfg.certs);
|
||||
@@ -23,7 +24,7 @@ let
|
||||
# security.acme.certs.<cert>.group on some of the services.
|
||||
commonServiceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "acme";
|
||||
User = user;
|
||||
Group = mkDefault "acme";
|
||||
UMask = 0022;
|
||||
StateDirectoryMode = 750;
|
||||
@@ -101,12 +102,12 @@ let
|
||||
# is configurable on a per-cert basis.
|
||||
userMigrationService = let
|
||||
script = with builtins; ''
|
||||
chown -R acme .lego/accounts
|
||||
chown -R ${user} .lego/accounts
|
||||
'' + (concatStringsSep "\n" (mapAttrsToList (cert: data: ''
|
||||
for fixpath in ${escapeShellArg cert} .lego/${escapeShellArg cert}; do
|
||||
if [ -d "$fixpath" ]; then
|
||||
chmod -R u=rwX,g=rX,o= "$fixpath"
|
||||
chown -R acme:${data.group} "$fixpath"
|
||||
chown -R ${user}:${data.group} "$fixpath"
|
||||
fi
|
||||
done
|
||||
'') certConfigs));
|
||||
@@ -128,7 +129,7 @@ let
|
||||
};
|
||||
|
||||
certToConfig = cert: data: let
|
||||
acmeServer = if data.server != null then data.server else cfg.server;
|
||||
acmeServer = data.server;
|
||||
useDns = data.dnsProvider != null;
|
||||
destPath = "/var/lib/acme/${cert}";
|
||||
selfsignedDeps = optionals (cfg.preliminarySelfsigned) [ "acme-selfsigned-${cert}.service" ];
|
||||
@@ -156,6 +157,7 @@ let
|
||||
${toString data.ocspMustStaple} ${data.keyType}
|
||||
'';
|
||||
certDir = mkHash hashData;
|
||||
# TODO remove domainHash usage entirely. Waiting on go-acme/lego#1532
|
||||
domainHash = mkHash "${concatStringsSep " " extraDomains} ${data.domain}";
|
||||
accountHash = (mkAccountHash acmeServer data);
|
||||
accountDir = accountDirRoot + accountHash;
|
||||
@@ -210,7 +212,7 @@ let
|
||||
description = "Renew ACME Certificate for ${cert}";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = cfg.renewInterval;
|
||||
OnCalendar = data.renewInterval;
|
||||
Unit = "acme-${cert}.service";
|
||||
Persistent = "yes";
|
||||
|
||||
@@ -267,7 +269,7 @@ let
|
||||
cat key.pem fullchain.pem > full.pem
|
||||
|
||||
# Group might change between runs, re-apply it
|
||||
chown 'acme:${data.group}' *
|
||||
chown '${user}:${data.group}' *
|
||||
|
||||
# Default permissions make the files unreadable by group + anon
|
||||
# Need to be readable by group
|
||||
@@ -322,7 +324,7 @@ let
|
||||
fi
|
||||
'');
|
||||
} // optionalAttrs (data.listenHTTP != null && toInt (elemAt (splitString ":" data.listenHTTP) 1) < 1024) {
|
||||
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
|
||||
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
|
||||
};
|
||||
|
||||
# Working directory will be /tmp
|
||||
@@ -355,7 +357,7 @@ let
|
||||
expiration_s=$[expiration_date - now]
|
||||
expiration_days=$[expiration_s / (3600 * 24)] # rounds down
|
||||
|
||||
[[ $expiration_days -gt ${toString cfg.validMinDays} ]]
|
||||
[[ $expiration_days -gt ${toString data.validMinDays} ]]
|
||||
}
|
||||
|
||||
${optionalString (data.webroot != null) ''
|
||||
@@ -372,37 +374,40 @@ let
|
||||
|
||||
echo '${domainHash}' > domainhash.txt
|
||||
|
||||
# Check if we can renew
|
||||
if [ -e 'certificates/${keyName}.key' -a -e 'certificates/${keyName}.crt' -a -n "$(ls -1 accounts)" ]; then
|
||||
# Check if we can renew.
|
||||
# We can only renew if the list of domains has not changed.
|
||||
if cmp -s domainhash.txt certificates/domainhash.txt && [ -e 'certificates/${keyName}.key' -a -e 'certificates/${keyName}.crt' -a -n "$(ls -1 accounts)" ]; then
|
||||
|
||||
# When domains are updated, there's no need to do a full
|
||||
# Lego run, but it's likely renew won't work if days is too low.
|
||||
if [ -e certificates/domainhash.txt ] && cmp -s domainhash.txt certificates/domainhash.txt; then
|
||||
# Even if a cert is not expired, it may be revoked by the CA.
|
||||
# Try to renew, and silently fail if the cert is not expired.
|
||||
# Avoids #85794 and resolves #129838
|
||||
if ! lego ${renewOpts} --days ${toString data.validMinDays}; then
|
||||
if is_expiration_skippable out/full.pem; then
|
||||
echo 1>&2 "nixos-acme: skipping renewal because expiration isn't within the coming ${toString cfg.validMinDays} days"
|
||||
echo 1>&2 "nixos-acme: Ignoring failed renewal because expiration isn't within the coming ${toString data.validMinDays} days"
|
||||
else
|
||||
echo 1>&2 "nixos-acme: renewing now, because certificate expires within the configured ${toString cfg.validMinDays} days"
|
||||
lego ${renewOpts} --days ${toString cfg.validMinDays}
|
||||
# High number to avoid Systemd reserved codes.
|
||||
exit 11
|
||||
fi
|
||||
else
|
||||
echo 1>&2 "certificate domain(s) have changed; will renew now"
|
||||
# Any number > 90 works, but this one is over 9000 ;-)
|
||||
lego ${renewOpts} --days 9001
|
||||
fi
|
||||
|
||||
# Otherwise do a full run
|
||||
else
|
||||
lego ${runOpts}
|
||||
elif ! lego ${runOpts}; then
|
||||
# Produce a nice error for those doing their first nixos-rebuild with these certs
|
||||
echo Failed to fetch certificates. \
|
||||
This may mean your DNS records are set up incorrectly. \
|
||||
${optionalString (cfg.preliminarySelfsigned) "Selfsigned certs are in place and dependant services will still start."}
|
||||
# Exit 10 so that users can potentially amend SuccessExitStatus to ignore this error.
|
||||
# High number to avoid Systemd reserved codes.
|
||||
exit 10
|
||||
fi
|
||||
|
||||
mv domainhash.txt certificates/
|
||||
|
||||
# Group might change between runs, re-apply it
|
||||
chown 'acme:${data.group}' certificates/*
|
||||
chown '${user}:${data.group}' certificates/*
|
||||
|
||||
# Copy all certs to the "real" certs directory
|
||||
CERT='certificates/${keyName}.crt'
|
||||
if [ -e "$CERT" ] && ! cmp -s "$CERT" out/fullchain.pem; then
|
||||
if ! cmp -s 'certificates/${keyName}.crt' out/fullchain.pem; then
|
||||
touch out/renewed
|
||||
echo Installing new certificate
|
||||
cp -vp 'certificates/${keyName}.crt' out/fullchain.pem
|
||||
@@ -421,7 +426,194 @@ let
|
||||
|
||||
certConfigs = mapAttrs certToConfig cfg.certs;
|
||||
|
||||
certOpts = { name, ... }: {
|
||||
# These options can be specified within
|
||||
# security.acme.defaults or security.acme.certs.<name>
|
||||
inheritableModule = isDefaults: { config, ... }: let
|
||||
defaultAndText = name: default: {
|
||||
# When ! isDefaults then this is the option declaration for the
|
||||
# security.acme.certs.<name> path, which has the extra inheritDefaults
|
||||
# option, which if disabled means that we can't inherit it
|
||||
default = if isDefaults || ! config.inheritDefaults then default else cfg.defaults.${name};
|
||||
# The docs however don't need to depend on inheritDefaults, they should
|
||||
# stay constant. Though notably it wouldn't matter much, because to get
|
||||
# the option information, a submodule with name `<name>` is evaluated
|
||||
# without any definitions.
|
||||
defaultText = if isDefaults then default else literalExpression "config.security.acme.defaults.${name}";
|
||||
};
|
||||
in {
|
||||
options = {
|
||||
validMinDays = mkOption {
|
||||
type = types.int;
|
||||
inherit (defaultAndText "validMinDays" 30) default defaultText;
|
||||
description = "Minimum remaining validity before renewal in days.";
|
||||
};
|
||||
|
||||
renewInterval = mkOption {
|
||||
type = types.str;
|
||||
inherit (defaultAndText "renewInterval" "daily") default defaultText;
|
||||
description = ''
|
||||
Systemd calendar expression when to check for renewal. See
|
||||
<citerefentry><refentrytitle>systemd.time</refentrytitle>
|
||||
<manvolnum>7</manvolnum></citerefentry>.
|
||||
'';
|
||||
};
|
||||
|
||||
enableDebugLogs = mkEnableOption "debug logging for this certificate" // {
|
||||
inherit (defaultAndText "enableDebugLogs" true) default defaultText;
|
||||
};
|
||||
|
||||
webroot = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
inherit (defaultAndText "webroot" null) default defaultText;
|
||||
example = "/var/lib/acme/acme-challenge";
|
||||
description = ''
|
||||
Where the webroot of the HTTP vhost is located.
|
||||
<filename>.well-known/acme-challenge/</filename> directory
|
||||
will be created below the webroot if it doesn't exist.
|
||||
<literal>http://example.org/.well-known/acme-challenge/</literal> must also
|
||||
be available (notice unencrypted HTTP).
|
||||
'';
|
||||
};
|
||||
|
||||
server = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
inherit (defaultAndText "server" null) default defaultText;
|
||||
description = ''
|
||||
ACME Directory Resource URI. Defaults to Let's Encrypt's
|
||||
production endpoint,
|
||||
<link xlink:href="https://acme-v02.api.letsencrypt.org/directory"/>, if unset.
|
||||
'';
|
||||
};
|
||||
|
||||
email = mkOption {
|
||||
type = types.str;
|
||||
inherit (defaultAndText "email" null) default defaultText;
|
||||
description = ''
|
||||
Email address for account creation and correspondence from the CA.
|
||||
It is recommended to use the same email for all certs to avoid account
|
||||
creation limits.
|
||||
'';
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
inherit (defaultAndText "group" "acme") default defaultText;
|
||||
description = "Group running the ACME client.";
|
||||
};
|
||||
|
||||
reloadServices = mkOption {
|
||||
type = types.listOf types.str;
|
||||
inherit (defaultAndText "reloadServices" []) default defaultText;
|
||||
description = ''
|
||||
The list of systemd services to call <code>systemctl try-reload-or-restart</code>
|
||||
on.
|
||||
'';
|
||||
};
|
||||
|
||||
postRun = mkOption {
|
||||
type = types.lines;
|
||||
inherit (defaultAndText "postRun" "") default defaultText;
|
||||
example = "cp full.pem backup.pem";
|
||||
description = ''
|
||||
Commands to run after new certificates go live. Note that
|
||||
these commands run as the root user.
|
||||
|
||||
Executed in the same directory with the new certificate.
|
||||
'';
|
||||
};
|
||||
|
||||
keyType = mkOption {
|
||||
type = types.str;
|
||||
inherit (defaultAndText "keyType" "ec256") default defaultText;
|
||||
description = ''
|
||||
Key type to use for private keys.
|
||||
For an up to date list of supported values check the --key-type option
|
||||
at <link xlink:href="https://go-acme.github.io/lego/usage/cli/#usage"/>.
|
||||
'';
|
||||
};
|
||||
|
||||
dnsProvider = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
inherit (defaultAndText "dnsProvider" null) default defaultText;
|
||||
example = "route53";
|
||||
description = ''
|
||||
DNS Challenge provider. For a list of supported providers, see the "code"
|
||||
field of the DNS providers listed at <link xlink:href="https://go-acme.github.io/lego/dns/"/>.
|
||||
'';
|
||||
};
|
||||
|
||||
dnsResolver = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
inherit (defaultAndText "dnsResolver" null) default defaultText;
|
||||
example = "1.1.1.1:53";
|
||||
description = ''
|
||||
Set the resolver to use for performing recursive DNS queries. Supported:
|
||||
host:port. The default is to use the system resolvers, or Google's DNS
|
||||
resolvers if the system's cannot be determined.
|
||||
'';
|
||||
};
|
||||
|
||||
credentialsFile = mkOption {
|
||||
type = types.path;
|
||||
inherit (defaultAndText "credentialsFile" null) default defaultText;
|
||||
description = ''
|
||||
Path to an EnvironmentFile for the cert's service containing any required and
|
||||
optional environment variables for your selected dnsProvider.
|
||||
To find out what values you need to set, consult the documentation at
|
||||
<link xlink:href="https://go-acme.github.io/lego/dns/"/> for the corresponding dnsProvider.
|
||||
'';
|
||||
example = "/var/src/secrets/example.org-route53-api-token";
|
||||
};
|
||||
|
||||
dnsPropagationCheck = mkOption {
|
||||
type = types.bool;
|
||||
inherit (defaultAndText "dnsPropagationCheck" true) default defaultText;
|
||||
description = ''
|
||||
Toggles lego DNS propagation check, which is used alongside DNS-01
|
||||
challenge to ensure the DNS entries required are available.
|
||||
'';
|
||||
};
|
||||
|
||||
ocspMustStaple = mkOption {
|
||||
type = types.bool;
|
||||
inherit (defaultAndText "ocspMustStaple" false) default defaultText;
|
||||
description = ''
|
||||
Turns on the OCSP Must-Staple TLS extension.
|
||||
Make sure you know what you're doing! See:
|
||||
<itemizedlist>
|
||||
<listitem><para><link xlink:href="https://blog.apnic.net/2019/01/15/is-the-web-ready-for-ocsp-must-staple/" /></para></listitem>
|
||||
<listitem><para><link xlink:href="https://blog.hboeck.de/archives/886-The-Problem-with-OCSP-Stapling-and-Must-Staple-and-why-Certificate-Revocation-is-still-broken.html" /></para></listitem>
|
||||
</itemizedlist>
|
||||
'';
|
||||
};
|
||||
|
||||
extraLegoFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
inherit (defaultAndText "extraLegoFlags" []) default defaultText;
|
||||
description = ''
|
||||
Additional global flags to pass to all lego commands.
|
||||
'';
|
||||
};
|
||||
|
||||
extraLegoRenewFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
inherit (defaultAndText "extraLegoRenewFlags" []) default defaultText;
|
||||
description = ''
|
||||
Additional flags to pass to lego renew.
|
||||
'';
|
||||
};
|
||||
|
||||
extraLegoRunFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
inherit (defaultAndText "extraLegoRunFlags" []) default defaultText;
|
||||
description = ''
|
||||
Additional flags to pass to lego run.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
certOpts = { name, config, ... }: {
|
||||
options = {
|
||||
# user option has been removed
|
||||
user = mkOption {
|
||||
@@ -441,40 +633,11 @@ let
|
||||
default = "_mkMergedOptionModule";
|
||||
};
|
||||
|
||||
enableDebugLogs = mkEnableOption "debug logging for this certificate" // { default = cfg.enableDebugLogs; };
|
||||
|
||||
webroot = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "/var/lib/acme/acme-challenge";
|
||||
description = ''
|
||||
Where the webroot of the HTTP vhost is located.
|
||||
<filename>.well-known/acme-challenge/</filename> directory
|
||||
will be created below the webroot if it doesn't exist.
|
||||
<literal>http://example.org/.well-known/acme-challenge/</literal> must also
|
||||
be available (notice unencrypted HTTP).
|
||||
'';
|
||||
};
|
||||
|
||||
listenHTTP = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = ":1360";
|
||||
description = ''
|
||||
Interface and port to listen on to solve HTTP challenges
|
||||
in the form [INTERFACE]:PORT.
|
||||
If you use a port other than 80, you must proxy port 80 to this port.
|
||||
'';
|
||||
};
|
||||
|
||||
server = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
ACME Directory Resource URI. Defaults to Let's Encrypt's
|
||||
production endpoint,
|
||||
<link xlink:href="https://acme-v02.api.letsencrypt.org/directory"/>, if unset.
|
||||
'';
|
||||
directory = mkOption {
|
||||
type = types.str;
|
||||
readOnly = true;
|
||||
default = "/var/lib/acme/${name}";
|
||||
description = "Directory where certificate and other state is stored.";
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
@@ -483,47 +646,6 @@ let
|
||||
description = "Domain to fetch certificate for (defaults to the entry name).";
|
||||
};
|
||||
|
||||
email = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = cfg.email;
|
||||
defaultText = literalExpression "config.${opt.email}";
|
||||
description = "Contact email address for the CA to be able to reach you.";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "acme";
|
||||
description = "Group running the ACME client.";
|
||||
};
|
||||
|
||||
reloadServices = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
The list of systemd services to call <code>systemctl try-reload-or-restart</code>
|
||||
on.
|
||||
'';
|
||||
};
|
||||
|
||||
postRun = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
example = "cp full.pem backup.pem";
|
||||
description = ''
|
||||
Commands to run after new certificates go live. Note that
|
||||
these commands run as the root user.
|
||||
|
||||
Executed in the same directory with the new certificate.
|
||||
'';
|
||||
};
|
||||
|
||||
directory = mkOption {
|
||||
type = types.str;
|
||||
readOnly = true;
|
||||
default = "/var/lib/acme/${name}";
|
||||
description = "Directory where certificate and other state is stored.";
|
||||
};
|
||||
|
||||
extraDomainNames = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
@@ -538,92 +660,25 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
keyType = mkOption {
|
||||
type = types.str;
|
||||
default = "ec256";
|
||||
description = ''
|
||||
Key type to use for private keys.
|
||||
For an up to date list of supported values check the --key-type option
|
||||
at <link xlink:href="https://go-acme.github.io/lego/usage/cli/#usage"/>.
|
||||
'';
|
||||
};
|
||||
|
||||
dnsProvider = mkOption {
|
||||
# This setting must be different for each configured certificate, otherwise
|
||||
# two or more renewals may fail to bind to the address. Hence, it is not in
|
||||
# the inheritableOpts.
|
||||
listenHTTP = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "route53";
|
||||
example = ":1360";
|
||||
description = ''
|
||||
DNS Challenge provider. For a list of supported providers, see the "code"
|
||||
field of the DNS providers listed at <link xlink:href="https://go-acme.github.io/lego/dns/"/>.
|
||||
Interface and port to listen on to solve HTTP challenges
|
||||
in the form [INTERFACE]:PORT.
|
||||
If you use a port other than 80, you must proxy port 80 to this port.
|
||||
'';
|
||||
};
|
||||
|
||||
dnsResolver = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "1.1.1.1:53";
|
||||
description = ''
|
||||
Set the resolver to use for performing recursive DNS queries. Supported:
|
||||
host:port. The default is to use the system resolvers, or Google's DNS
|
||||
resolvers if the system's cannot be determined.
|
||||
'';
|
||||
};
|
||||
|
||||
credentialsFile = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
Path to an EnvironmentFile for the cert's service containing any required and
|
||||
optional environment variables for your selected dnsProvider.
|
||||
To find out what values you need to set, consult the documentation at
|
||||
<link xlink:href="https://go-acme.github.io/lego/dns/"/> for the corresponding dnsProvider.
|
||||
'';
|
||||
example = "/var/src/secrets/example.org-route53-api-token";
|
||||
};
|
||||
|
||||
dnsPropagationCheck = mkOption {
|
||||
type = types.bool;
|
||||
inheritDefaults = mkOption {
|
||||
default = true;
|
||||
description = ''
|
||||
Toggles lego DNS propagation check, which is used alongside DNS-01
|
||||
challenge to ensure the DNS entries required are available.
|
||||
'';
|
||||
};
|
||||
|
||||
ocspMustStaple = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Turns on the OCSP Must-Staple TLS extension.
|
||||
Make sure you know what you're doing! See:
|
||||
<itemizedlist>
|
||||
<listitem><para><link xlink:href="https://blog.apnic.net/2019/01/15/is-the-web-ready-for-ocsp-must-staple/" /></para></listitem>
|
||||
<listitem><para><link xlink:href="https://blog.hboeck.de/archives/886-The-Problem-with-OCSP-Stapling-and-Must-Staple-and-why-Certificate-Revocation-is-still-broken.html" /></para></listitem>
|
||||
</itemizedlist>
|
||||
'';
|
||||
};
|
||||
|
||||
extraLegoFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Additional global flags to pass to all lego commands.
|
||||
'';
|
||||
};
|
||||
|
||||
extraLegoRenewFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Additional flags to pass to lego renew.
|
||||
'';
|
||||
};
|
||||
|
||||
extraLegoRunFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
Additional flags to pass to lego run.
|
||||
'';
|
||||
example = true;
|
||||
description = "Whether to inherit values set in `security.acme.defaults` or not.";
|
||||
type = lib.types.bool;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -632,41 +687,6 @@ in {
|
||||
|
||||
options = {
|
||||
security.acme = {
|
||||
|
||||
enableDebugLogs = mkEnableOption "debug logging for all certificates by default" // { default = true; };
|
||||
|
||||
validMinDays = mkOption {
|
||||
type = types.int;
|
||||
default = 30;
|
||||
description = "Minimum remaining validity before renewal in days.";
|
||||
};
|
||||
|
||||
email = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Contact email address for the CA to be able to reach you.";
|
||||
};
|
||||
|
||||
renewInterval = mkOption {
|
||||
type = types.str;
|
||||
default = "daily";
|
||||
description = ''
|
||||
Systemd calendar expression when to check for renewal. See
|
||||
<citerefentry><refentrytitle>systemd.time</refentrytitle>
|
||||
<manvolnum>7</manvolnum></citerefentry>.
|
||||
'';
|
||||
};
|
||||
|
||||
server = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
ACME Directory Resource URI. Defaults to Let's Encrypt's
|
||||
production endpoint,
|
||||
<link xlink:href="https://acme-v02.api.letsencrypt.org/directory"/>, if unset.
|
||||
'';
|
||||
};
|
||||
|
||||
preliminarySelfsigned = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
@@ -689,9 +709,31 @@ in {
|
||||
'';
|
||||
};
|
||||
|
||||
useRoot = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to use the root user when generating certs. This is not recommended
|
||||
for security + compatiblity reasons. If a service requires root owned certificates
|
||||
consider following the guide on "Using ACME with services demanding root
|
||||
owned certificates" in the NixOS manual, and only using this as a fallback
|
||||
or for testing.
|
||||
'';
|
||||
};
|
||||
|
||||
defaults = mkOption {
|
||||
type = types.submodule (inheritableModule true);
|
||||
description = ''
|
||||
Default values inheritable by all configured certs. You can
|
||||
use this to define options shared by all your certs. These defaults
|
||||
can also be ignored on a per-cert basis using the
|
||||
`security.acme.certs.''${cert}.inheritDefaults' option.
|
||||
'';
|
||||
};
|
||||
|
||||
certs = mkOption {
|
||||
default = { };
|
||||
type = with types; attrsOf (submodule certOpts);
|
||||
type = with types; attrsOf (submodule [ (inheritableModule false) certOpts ]);
|
||||
description = ''
|
||||
Attribute set of certificates to get signed and renewed. Creates
|
||||
<literal>acme-''${cert}.{service,timer}</literal> systemd units for
|
||||
@@ -722,12 +764,16 @@ in {
|
||||
|
||||
To use the let's encrypt staging server, use security.acme.server =
|
||||
"https://acme-staging-v02.api.letsencrypt.org/directory".
|
||||
''
|
||||
)
|
||||
'')
|
||||
(mkRemovedOptionModule [ "security" "acme" "directory" ] "ACME Directory is now hardcoded to /var/lib/acme and its permisisons are managed by systemd. See https://github.com/NixOS/nixpkgs/issues/53852 for more info.")
|
||||
(mkRemovedOptionModule [ "security" "acme" "preDelay" ] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
|
||||
(mkRemovedOptionModule [ "security" "acme" "activationDelay" ] "This option has been removed. If you want to make sure that something executes before certificates are provisioned, add a RequiredBy=acme-\${cert}.service to the service you want to execute before the cert renewal")
|
||||
(mkChangedOptionModule [ "security" "acme" "validMin" ] [ "security" "acme" "validMinDays" ] (config: config.security.acme.validMin / (24 * 3600)))
|
||||
(mkChangedOptionModule [ "security" "acme" "validMin" ] [ "security" "acme" "defaults" "validMinDays" ] (config: config.security.acme.validMin / (24 * 3600)))
|
||||
(mkChangedOptionModule [ "security" "acme" "validMinDays" ] [ "security" "acme" "defaults" "validMinDays" ] (config: config.security.acme.validMinDays))
|
||||
(mkChangedOptionModule [ "security" "acme" "renewInterval" ] [ "security" "acme" "defaults" "renewInterval" ] (config: config.security.acme.renewInterval))
|
||||
(mkChangedOptionModule [ "security" "acme" "email" ] [ "security" "acme" "defaults" "email" ] (config: config.security.acme.email))
|
||||
(mkChangedOptionModule [ "security" "acme" "server" ] [ "security" "acme" "defaults" "server" ] (config: config.security.acme.server))
|
||||
(mkChangedOptionModule [ "security" "acme" "enableDebugLogs" ] [ "security" "acme" "defaults" "enableDebugLogs" ] (config: config.security.acme.enableDebugLogs))
|
||||
];
|
||||
|
||||
config = mkMerge [
|
||||
@@ -842,8 +888,8 @@ in {
|
||||
# Create some targets which can be depended on to be "active" after cert renewals
|
||||
finishedTargets = mapAttrs' (cert: conf: nameValuePair "acme-finished-${cert}" {
|
||||
wantedBy = [ "default.target" ];
|
||||
requires = [ "acme-${cert}.service" ] ++ conf.selfsignedDeps;
|
||||
after = [ "acme-${cert}.service" ] ++ conf.selfsignedDeps;
|
||||
requires = [ "acme-${cert}.service" ];
|
||||
after = [ "acme-${cert}.service" ];
|
||||
}) certConfigs;
|
||||
|
||||
# Create targets to limit the number of simultaneous account creations
|
||||
|
||||
+137
-22
@@ -7,8 +7,9 @@
|
||||
<para>
|
||||
NixOS supports automatic domain validation & certificate retrieval and
|
||||
renewal using the ACME protocol. Any provider can be used, but by default
|
||||
NixOS uses Let's Encrypt. The alternative ACME client <literal>lego</literal>
|
||||
is used under the hood.
|
||||
NixOS uses Let's Encrypt. The alternative ACME client
|
||||
<link xlink:href="https://go-acme.github.io/lego/">lego</link> is used under
|
||||
the hood.
|
||||
</para>
|
||||
<para>
|
||||
Automatic cert validation and configuration for Apache and Nginx virtual
|
||||
@@ -29,7 +30,7 @@
|
||||
<para>
|
||||
You must also set an email address to be used when creating accounts with
|
||||
Let's Encrypt. You can set this for all certs with
|
||||
<literal><xref linkend="opt-security.acme.email" /></literal>
|
||||
<literal><xref linkend="opt-security.acme.defaults.email" /></literal>
|
||||
and/or on a per-cert basis with
|
||||
<literal><xref linkend="opt-security.acme.certs._name_.email" /></literal>.
|
||||
This address is only used for registration and renewal reminders,
|
||||
@@ -38,7 +39,7 @@
|
||||
|
||||
<para>
|
||||
Alternatively, you can use a different ACME server by changing the
|
||||
<literal><xref linkend="opt-security.acme.server" /></literal> option
|
||||
<literal><xref linkend="opt-security.acme.defaults.server" /></literal> option
|
||||
to a provider of your choosing, or just change the server for one cert with
|
||||
<literal><xref linkend="opt-security.acme.certs._name_.server" /></literal>.
|
||||
</para>
|
||||
@@ -60,12 +61,12 @@
|
||||
= true;</literal> in a virtualHost config. We first create self-signed
|
||||
placeholder certificates in place of the real ACME certs. The placeholder
|
||||
certs are overwritten when the ACME certs arrive. For
|
||||
<literal>foo.example.com</literal> the config would look like.
|
||||
<literal>foo.example.com</literal> the config would look like this:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
<xref linkend="opt-security.acme.acceptTerms" /> = true;
|
||||
<xref linkend="opt-security.acme.email" /> = "admin+acme@example.com";
|
||||
<xref linkend="opt-security.acme.defaults.email" /> = "admin+acme@example.com";
|
||||
services.nginx = {
|
||||
<link linkend="opt-services.nginx.enable">enable</link> = true;
|
||||
<link linkend="opt-services.nginx.virtualHosts">virtualHosts</link> = {
|
||||
@@ -114,7 +115,7 @@ services.nginx = {
|
||||
|
||||
<programlisting>
|
||||
<xref linkend="opt-security.acme.acceptTerms" /> = true;
|
||||
<xref linkend="opt-security.acme.email" /> = "admin+acme@example.com";
|
||||
<xref linkend="opt-security.acme.defaults.email" /> = "admin+acme@example.com";
|
||||
|
||||
# /var/lib/acme/.challenges must be writable by the ACME user
|
||||
# and readable by the Nginx user. The easiest way to achieve
|
||||
@@ -218,7 +219,7 @@ services.bind = {
|
||||
|
||||
# Now we can configure ACME
|
||||
<xref linkend="opt-security.acme.acceptTerms" /> = true;
|
||||
<xref linkend="opt-security.acme.email" /> = "admin+acme@example.com";
|
||||
<xref linkend="opt-security.acme.defaults.email" /> = "admin+acme@example.com";
|
||||
<xref linkend="opt-security.acme.certs" />."example.com" = {
|
||||
<link linkend="opt-security.acme.certs._name_.domain">domain</link> = "*.example.com";
|
||||
<link linkend="opt-security.acme.certs._name_.dnsProvider">dnsProvider</link> = "rfc2136";
|
||||
@@ -231,25 +232,39 @@ services.bind = {
|
||||
<para>
|
||||
The <filename>dnskeys.conf</filename> and <filename>certs.secret</filename>
|
||||
must be kept secure and thus you should not keep their contents in your
|
||||
Nix config. Instead, generate them one time with these commands:
|
||||
Nix config. Instead, generate them one time with a systemd service:
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
mkdir -p /var/lib/secrets
|
||||
tsig-keygen rfc2136key.example.com > /var/lib/secrets/dnskeys.conf
|
||||
chown named:root /var/lib/secrets/dnskeys.conf
|
||||
chmod 400 /var/lib/secrets/dnskeys.conf
|
||||
systemd.services.dns-rfc2136-conf = {
|
||||
requiredBy = ["acme-example.com.service", "bind.service"];
|
||||
before = ["acme-example.com.service", "bind.service"];
|
||||
unitConfig = {
|
||||
ConditionPathExists = "!/var/lib/secrets/dnskeys.conf";
|
||||
};
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
UMask = 0077;
|
||||
};
|
||||
path = [ pkgs.bind ];
|
||||
script = ''
|
||||
mkdir -p /var/lib/secrets
|
||||
tsig-keygen rfc2136key.example.com > /var/lib/secrets/dnskeys.conf
|
||||
chown named:root /var/lib/secrets/dnskeys.conf
|
||||
chmod 400 /var/lib/secrets/dnskeys.conf
|
||||
|
||||
# Copy the secret value from the dnskeys.conf, and put it in
|
||||
# RFC2136_TSIG_SECRET below
|
||||
# Copy the secret value from the dnskeys.conf, and put it in
|
||||
# RFC2136_TSIG_SECRET below
|
||||
|
||||
cat > /var/lib/secrets/certs.secret << EOF
|
||||
RFC2136_NAMESERVER='127.0.0.1:53'
|
||||
RFC2136_TSIG_ALGORITHM='hmac-sha256.'
|
||||
RFC2136_TSIG_KEY='rfc2136key.example.com'
|
||||
RFC2136_TSIG_SECRET='your secret key'
|
||||
EOF
|
||||
chmod 400 /var/lib/secrets/certs.secret
|
||||
cat > /var/lib/secrets/certs.secret << EOF
|
||||
RFC2136_NAMESERVER='127.0.0.1:53'
|
||||
RFC2136_TSIG_ALGORITHM='hmac-sha256.'
|
||||
RFC2136_TSIG_KEY='rfc2136key.example.com'
|
||||
RFC2136_TSIG_SECRET='your secret key'
|
||||
EOF
|
||||
chmod 400 /var/lib/secrets/certs.secret
|
||||
'';
|
||||
};
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
@@ -258,6 +273,106 @@ chmod 400 /var/lib/secrets/certs.secret
|
||||
journalctl -fu acme-example.com.service</literal> and watching its log output.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="module-security-acme-config-dns-with-vhosts">
|
||||
<title>Using DNS validation with web server virtual hosts</title>
|
||||
|
||||
<para>
|
||||
It is possible to use DNS-01 validation with all certificates,
|
||||
including those automatically configured via the Nginx/Apache
|
||||
<literal><link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link></literal>
|
||||
option. This configuration pattern is fully
|
||||
supported and part of the module's test suite for Nginx + Apache.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You must follow the guide above on configuring DNS-01 validation
|
||||
first, however instead of setting the options for one certificate
|
||||
(e.g. <xref linkend="opt-security.acme.certs._name_.dnsProvider" />)
|
||||
you will set them as defaults
|
||||
(e.g. <xref linkend="opt-security.acme.defaults.dnsProvider" />).
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
# Configure ACME appropriately
|
||||
<xref linkend="opt-security.acme.acceptTerms" /> = true;
|
||||
<xref linkend="opt-security.acme.defaults.email" /> = "admin+acme@example.com";
|
||||
<xref linkend="opt-security.acme.defaults" /> = {
|
||||
<link linkend="opt-security.acme.defaults.dnsProvider">dnsProvider</link> = "rfc2136";
|
||||
<link linkend="opt-security.acme.defaults.credentialsFile">credentialsFile</link> = "/var/lib/secrets/certs.secret";
|
||||
# We don't need to wait for propagation since this is a local DNS server
|
||||
<link linkend="opt-security.acme.defaults.dnsPropagationCheck">dnsPropagationCheck</link> = false;
|
||||
};
|
||||
|
||||
# For each virtual host you would like to use DNS-01 validation with,
|
||||
# set acmeRoot = null
|
||||
services.nginx = {
|
||||
<link linkend="opt-services.nginx.enable">enable</link> = true;
|
||||
<link linkend="opt-services.nginx.virtualHosts">virtualHosts</link> = {
|
||||
"foo.example.com" = {
|
||||
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
|
||||
<link linkend="opt-services.nginx.virtualHosts._name_.acmeRoot">acmeRoot</link> = null;
|
||||
};
|
||||
};
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
And that's it! Next time your configuration is rebuilt, or when
|
||||
you add a new virtualHost, it will be DNS-01 validated.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section xml:id="module-security-acme-root-owned">
|
||||
<title>Using ACME with services demanding root owned certificates</title>
|
||||
|
||||
<para>
|
||||
Some services refuse to start if the configured certificate files
|
||||
are not owned by root. PostgreSQL and OpenSMTPD are examples of these.
|
||||
There is no way to change the user the ACME module uses (it will always be
|
||||
<literal>acme</literal>), however you can use systemd's
|
||||
<literal>LoadCredential</literal> feature to resolve this elegantly.
|
||||
Below is an example configuration for OpenSMTPD, but this pattern
|
||||
can be applied to any service.
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
# Configure ACME however you like (DNS or HTTP validation), adding
|
||||
# the following configuration for the relevant certificate.
|
||||
# Note: You cannot use `systemctl reload` here as that would mean
|
||||
# the LoadCredential configuration below would be skipped and
|
||||
# the service would continue to use old certificates.
|
||||
security.acme.certs."mail.example.com".postRun = ''
|
||||
systemctl restart opensmtpd
|
||||
'';
|
||||
|
||||
# Now you must augment OpenSMTPD's systemd service to load
|
||||
# the certificate files.
|
||||
<link linkend="opt-systemd.services._name_.requires">systemd.services.opensmtpd.requires</link> = ["acme-finished-mail.example.com.target"];
|
||||
<link linkend="opt-systemd.services._name_.serviceConfig">systemd.services.opensmtpd.serviceConfig.LoadCredential</link> = let
|
||||
certDir = config.security.acme.certs."mail.example.com".directory;
|
||||
in [
|
||||
"cert.pem:${certDir}/cert.pem"
|
||||
"key.pem:${certDir}/key.pem"
|
||||
];
|
||||
|
||||
# Finally, configure OpenSMTPD to use these certs.
|
||||
services.opensmtpd = let
|
||||
credsDir = "/run/credentials/opensmtpd.service";
|
||||
in {
|
||||
enable = true;
|
||||
setSendmail = false;
|
||||
serverConfiguration = ''
|
||||
pki mail.example.com cert "${credsDir}/cert.pem"
|
||||
pki mail.example.com key "${credsDir}/key.pem"
|
||||
listen on localhost tls pki mail.example.com
|
||||
action act1 relay host smtp://127.0.0.1:10027
|
||||
match for local action act1
|
||||
'';
|
||||
};
|
||||
</programlisting>
|
||||
</section>
|
||||
|
||||
<section xml:id="module-security-acme-regenerate">
|
||||
<title>Regenerating certificates</title>
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
format = pkgs.formats.json { };
|
||||
cfg = config.services.influxdb2;
|
||||
@@ -9,12 +11,14 @@ in
|
||||
options = {
|
||||
services.influxdb2 = {
|
||||
enable = mkEnableOption "the influxdb2 server";
|
||||
|
||||
package = mkOption {
|
||||
default = pkgs.influxdb2-server;
|
||||
defaultText = literalExpression "pkgs.influxdb2";
|
||||
description = "influxdb2 derivation to use.";
|
||||
type = types.package;
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
default = { };
|
||||
description = ''configuration options for influxdb2, see <link xlink:href="https://docs.influxdata.com/influxdb/v2.0/reference/config-options"/> for details.'';
|
||||
@@ -28,18 +32,20 @@ in
|
||||
assertion = !(builtins.hasAttr "bolt-path" cfg.settings) && !(builtins.hasAttr "engine-path" cfg.settings);
|
||||
message = "services.influxdb2.config: bolt-path and engine-path should not be set as they are managed by systemd";
|
||||
}];
|
||||
|
||||
systemd.services.influxdb2 = {
|
||||
description = "InfluxDB is an open-source, distributed, time series database";
|
||||
documentation = [ "https://docs.influxdata.com/influxdb/" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
environment = {
|
||||
INFLUXD_CONFIG_PATH = "${configFile}";
|
||||
INFLUXD_CONFIG_PATH = configFile;
|
||||
};
|
||||
serviceConfig = {
|
||||
ExecStart = "${cfg.package}/bin/influxd --bolt-path \${STATE_DIRECTORY}/influxd.bolt --engine-path \${STATE_DIRECTORY}/engine";
|
||||
StateDirectory = "influxdb2";
|
||||
DynamicUser = true;
|
||||
User = "influxdb2";
|
||||
Group = "influxdb2";
|
||||
CapabilityBoundingSet = "";
|
||||
SystemCallFilter = "@system-service";
|
||||
LimitNOFILE = 65536;
|
||||
@@ -47,6 +53,13 @@ in
|
||||
Restart = "on-failure";
|
||||
};
|
||||
};
|
||||
|
||||
users.extraUsers.influxdb2 = {
|
||||
isSystemUser = true;
|
||||
group = "influxdb2";
|
||||
};
|
||||
|
||||
users.extraGroups.influxdb2 = {};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ nickcao ];
|
||||
|
||||
@@ -28,38 +28,45 @@ let
|
||||
}
|
||||
'';
|
||||
|
||||
dhcpdService = postfix: cfg: optionalAttrs cfg.enable {
|
||||
"dhcpd${postfix}" = {
|
||||
description = "DHCPv${postfix} server";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
dhcpdService = postfix: cfg:
|
||||
let
|
||||
configFile =
|
||||
if cfg.configFile != null
|
||||
then cfg.configFile
|
||||
else writeConfig cfg;
|
||||
leaseFile = "/var/lib/dhcpd${postfix}/dhcpd.leases";
|
||||
args = [
|
||||
"@${pkgs.dhcp}/sbin/dhcpd" "dhcpd${postfix}" "-${postfix}"
|
||||
"-pf" "/run/dhcpd${postfix}/dhcpd.pid"
|
||||
"-cf" configFile
|
||||
"-lf" leaseFile
|
||||
] ++ cfg.extraFlags
|
||||
++ cfg.interfaces;
|
||||
in
|
||||
optionalAttrs cfg.enable {
|
||||
"dhcpd${postfix}" = {
|
||||
description = "DHCPv${postfix} server";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
preStart = ''
|
||||
mkdir -m 755 -p ${cfg.stateDir}
|
||||
chown dhcpd:nogroup ${cfg.stateDir}
|
||||
touch ${cfg.stateDir}/dhcpd.leases
|
||||
'';
|
||||
|
||||
serviceConfig =
|
||||
let
|
||||
configFile = if cfg.configFile != null then cfg.configFile else writeConfig cfg;
|
||||
args = [ "@${pkgs.dhcp}/sbin/dhcpd" "dhcpd${postfix}" "-${postfix}"
|
||||
"-pf" "/run/dhcpd${postfix}/dhcpd.pid"
|
||||
"-cf" "${configFile}"
|
||||
"-lf" "${cfg.stateDir}/dhcpd.leases"
|
||||
"-user" "dhcpd" "-group" "nogroup"
|
||||
] ++ cfg.extraFlags
|
||||
++ cfg.interfaces;
|
||||
|
||||
in {
|
||||
ExecStart = concatMapStringsSep " " escapeShellArg args;
|
||||
Type = "forking";
|
||||
Restart = "always";
|
||||
RuntimeDirectory = [ "dhcpd${postfix}" ];
|
||||
PIDFile = "/run/dhcpd${postfix}/dhcpd.pid";
|
||||
preStart = "touch ${leaseFile}";
|
||||
serviceConfig = {
|
||||
ExecStart = concatMapStringsSep " " escapeShellArg args;
|
||||
Type = "forking";
|
||||
Restart = "always";
|
||||
DynamicUser = true;
|
||||
User = "dhcpd";
|
||||
Group = "dhcpd";
|
||||
AmbientCapabilities = [
|
||||
"CAP_NET_RAW" # to send ICMP messages
|
||||
"CAP_NET_BIND_SERVICE" # to bind on DHCP port (67)
|
||||
];
|
||||
StateDirectory = "dhcpd${postfix}";
|
||||
RuntimeDirectory = "dhcpd${postfix}";
|
||||
PIDFile = "/run/dhcpd${postfix}/dhcpd.pid";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
machineOpts = { ... }: {
|
||||
|
||||
@@ -102,15 +109,6 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
stateDir = mkOption {
|
||||
type = types.path;
|
||||
# We use /var/lib/dhcp for DHCPv4 to save backwards compatibility.
|
||||
default = "/var/lib/dhcp${if postfix == "4" then "" else postfix}";
|
||||
description = ''
|
||||
State directory for the DHCP server.
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = mkOption {
|
||||
type = types.lines;
|
||||
default = "";
|
||||
@@ -194,7 +192,13 @@ in
|
||||
|
||||
imports = [
|
||||
(mkRenamedOptionModule [ "services" "dhcpd" ] [ "services" "dhcpd4" ])
|
||||
];
|
||||
] ++ flip map [ "4" "6" ] (postfix:
|
||||
mkRemovedOptionModule [ "services" "dhcpd${postfix}" "stateDir" ] ''
|
||||
The DHCP server state directory is now managed with the systemd's DynamicUser mechanism.
|
||||
This means the directory is named after the service (dhcpd${postfix}), created under
|
||||
/var/lib/private/ and symlinked to /var/lib/.
|
||||
''
|
||||
);
|
||||
|
||||
###### interface
|
||||
|
||||
@@ -210,15 +214,6 @@ in
|
||||
|
||||
config = mkIf (cfg4.enable || cfg6.enable) {
|
||||
|
||||
users = {
|
||||
users.dhcpd = {
|
||||
isSystemUser = true;
|
||||
group = "dhcpd";
|
||||
description = "DHCP daemon user";
|
||||
};
|
||||
groups.dhcpd = {};
|
||||
};
|
||||
|
||||
systemd.services = dhcpdService "4" cfg4 // dhcpdService "6" cfg6;
|
||||
|
||||
};
|
||||
|
||||
@@ -236,6 +236,7 @@ in
|
||||
|
||||
environment = {
|
||||
KEA_PIDFILE_DIR = "/run/kea";
|
||||
KEA_LOCKFILE_DIR = "/run/kea";
|
||||
};
|
||||
|
||||
restartTriggers = [
|
||||
@@ -271,6 +272,7 @@ in
|
||||
|
||||
environment = {
|
||||
KEA_PIDFILE_DIR = "/run/kea";
|
||||
KEA_LOCKFILE_DIR = "/run/kea";
|
||||
};
|
||||
|
||||
restartTriggers = [
|
||||
@@ -313,6 +315,7 @@ in
|
||||
|
||||
environment = {
|
||||
KEA_PIDFILE_DIR = "/run/kea";
|
||||
KEA_LOCKFILE_DIR = "/run/kea";
|
||||
};
|
||||
|
||||
restartTriggers = [
|
||||
@@ -353,6 +356,7 @@ in
|
||||
|
||||
environment = {
|
||||
KEA_PIDFILE_DIR = "/run/kea";
|
||||
KEA_LOCKFILE_DIR = "/run/kea";
|
||||
};
|
||||
|
||||
restartTriggers = [
|
||||
@@ -361,7 +365,7 @@ in
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = "${package}/bin/kea-dhcp-ddns -c /etc/kea/dhcp-ddns.conf ${lib.escapeShellArgs cfg.dhcp-ddns.extraArgs}";
|
||||
AmbientCapabilites = [
|
||||
AmbientCapabilities = [
|
||||
"CAP_NET_BIND_SERVICE"
|
||||
];
|
||||
CapabilityBoundingSet = [
|
||||
|
||||
@@ -72,7 +72,7 @@ services.prosody = {
|
||||
a TLS certificate for the three endponits:
|
||||
<programlisting>
|
||||
security.acme = {
|
||||
<link linkend="opt-security.acme.email">email</link> = "root@example.org";
|
||||
<link linkend="opt-security.acme.defaults.email">email</link> = "root@example.org";
|
||||
<link linkend="opt-security.acme.acceptTerms">acceptTerms</link> = true;
|
||||
<link linkend="opt-security.acme.certs">certs</link> = {
|
||||
"example.org" = {
|
||||
|
||||
@@ -25,7 +25,7 @@ services.discourse = {
|
||||
};
|
||||
<link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file";
|
||||
};
|
||||
<link linkend="opt-security.acme.email">security.acme.email</link> = "me@example.com";
|
||||
<link linkend="opt-security.acme.defaults.email">security.acme.email</link> = "me@example.com";
|
||||
<link linkend="opt-security.acme.acceptTerms">security.acme.acceptTerms</link> = true;
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
};
|
||||
<link linkend="opt-services.jitsi-videobridge.openFirewall">services.jitsi-videobridge.openFirewall</link> = true;
|
||||
<link linkend="opt-networking.firewall.allowedTCPPorts">networking.firewall.allowedTCPPorts</link> = [ 80 443 ];
|
||||
<link linkend="opt-security.acme.email">security.acme.email</link> = "me@example.com";
|
||||
<link linkend="opt-security.acme.defaults.email">security.acme.email</link> = "me@example.com";
|
||||
<link linkend="opt-security.acme.acceptTerms">security.acme.acceptTerms</link> = true;
|
||||
}</programlisting>
|
||||
</para>
|
||||
@@ -46,7 +46,7 @@
|
||||
};
|
||||
<link linkend="opt-services.jitsi-videobridge.openFirewall">services.jitsi-videobridge.openFirewall</link> = true;
|
||||
<link linkend="opt-networking.firewall.allowedTCPPorts">networking.firewall.allowedTCPPorts</link> = [ 80 443 ];
|
||||
<link linkend="opt-security.acme.email">security.acme.email</link> = "me@example.com";
|
||||
<link linkend="opt-security.acme.defaults.email">security.acme.email</link> = "me@example.com";
|
||||
<link linkend="opt-security.acme.acceptTerms">security.acme.acceptTerms</link> = true;
|
||||
}</programlisting>
|
||||
</para>
|
||||
|
||||
@@ -154,7 +154,7 @@ let
|
||||
sslServerKey = if useACME then "${sslCertDir}/key.pem" else hostOpts.sslServerKey;
|
||||
sslServerChain = if useACME then "${sslCertDir}/chain.pem" else hostOpts.sslServerChain;
|
||||
|
||||
acmeChallenge = optionalString useACME ''
|
||||
acmeChallenge = optionalString (useACME && hostOpts.acmeRoot != null) ''
|
||||
Alias /.well-known/acme-challenge/ "${hostOpts.acmeRoot}/.well-known/acme-challenge/"
|
||||
<Directory "${hostOpts.acmeRoot}">
|
||||
AllowOverride None
|
||||
@@ -677,9 +677,16 @@ in
|
||||
};
|
||||
|
||||
security.acme.certs = let
|
||||
acmePairs = map (hostOpts: nameValuePair hostOpts.hostName {
|
||||
acmePairs = map (hostOpts: let
|
||||
hasRoot = hostOpts.acmeRoot != null;
|
||||
in nameValuePair hostOpts.hostName {
|
||||
group = mkDefault cfg.group;
|
||||
webroot = hostOpts.acmeRoot;
|
||||
# if acmeRoot is null inherit config.security.acme
|
||||
# Since config.security.acme.certs.<cert>.webroot's own default value
|
||||
# should take precedence set priority higher than mkOptionDefault
|
||||
webroot = mkOverride (if hasRoot then 1000 else 2000) hostOpts.acmeRoot;
|
||||
# Also nudge dnsProvider to null in case it is inherited
|
||||
dnsProvider = mkOverride (if hasRoot then 1000 else 2000) null;
|
||||
extraDomainNames = hostOpts.serverAliases;
|
||||
# Use the vhost-specific email address if provided, otherwise let
|
||||
# security.acme.email or security.acme.certs.<cert>.email be used.
|
||||
|
||||
@@ -128,9 +128,12 @@ in
|
||||
};
|
||||
|
||||
acmeRoot = mkOption {
|
||||
type = types.str;
|
||||
type = types.nullOr types.str;
|
||||
default = "/var/lib/acme/acme-challenge";
|
||||
description = "Directory for the acme challenge which is PUBLIC, don't put certs or keys in here";
|
||||
description = ''
|
||||
Directory for the acme challenge which is PUBLIC, don't put certs or keys in here.
|
||||
Set to null to inherit from config.security.acme.
|
||||
'';
|
||||
};
|
||||
|
||||
sslServerCert = mkOption {
|
||||
|
||||
@@ -278,7 +278,7 @@ let
|
||||
acmeLocation = optionalString (vhost.enableACME || vhost.useACMEHost != null) ''
|
||||
location /.well-known/acme-challenge {
|
||||
${optionalString (vhost.acmeFallbackHost != null) "try_files $uri @acme-fallback;"}
|
||||
root ${vhost.acmeRoot};
|
||||
${optionalString (vhost.acmeRoot != null) "root ${vhost.acmeRoot};"}
|
||||
auth_basic off;
|
||||
}
|
||||
${optionalString (vhost.acmeFallbackHost != null) ''
|
||||
@@ -948,9 +948,16 @@ in
|
||||
};
|
||||
|
||||
security.acme.certs = let
|
||||
acmePairs = map (vhostConfig: nameValuePair vhostConfig.serverName {
|
||||
acmePairs = map (vhostConfig: let
|
||||
hasRoot = vhostConfig.acmeRoot != null;
|
||||
in nameValuePair vhostConfig.serverName {
|
||||
group = mkDefault cfg.group;
|
||||
webroot = vhostConfig.acmeRoot;
|
||||
# if acmeRoot is null inherit config.security.acme
|
||||
# Since config.security.acme.certs.<cert>.webroot's own default value
|
||||
# should take precedence set priority higher than mkOptionDefault
|
||||
webroot = mkOverride (if hasRoot then 1000 else 2000) vhostConfig.acmeRoot;
|
||||
# Also nudge dnsProvider to null in case it is inherited
|
||||
dnsProvider = mkOverride (if hasRoot then 1000 else 2000) null;
|
||||
extraDomainNames = vhostConfig.serverAliases;
|
||||
# Filter for enableACME-only vhosts. Don't want to create dud certs
|
||||
}) (filter (vhostConfig: vhostConfig.useACMEHost == null) acmeEnabledVhosts);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# has additional options that affect the web server as a whole, like
|
||||
# the user/group to run under.)
|
||||
|
||||
{ lib, ... }:
|
||||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
{
|
||||
@@ -85,9 +85,12 @@ with lib;
|
||||
};
|
||||
|
||||
acmeRoot = mkOption {
|
||||
type = types.str;
|
||||
type = types.nullOr types.str;
|
||||
default = "/var/lib/acme/acme-challenge";
|
||||
description = "Directory for the acme challenge which is PUBLIC, don't put certs or keys in here";
|
||||
description = ''
|
||||
Directory for the acme challenge which is PUBLIC, don't put certs or keys in here.
|
||||
Set to null to inherit from config.security.acme.
|
||||
'';
|
||||
};
|
||||
|
||||
acmeFallbackHost = mkOption {
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.virtualisation.docker.rootless;
|
||||
proxy_env = config.networking.proxy.envVars;
|
||||
settingsFormat = pkgs.formats.json {};
|
||||
daemonSettingsFile = settingsFormat.generate "daemon.json" cfg.daemon.settings;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
###### interface
|
||||
|
||||
options.virtualisation.docker.rootless = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
This option enables docker in a rootless mode, a daemon that manages
|
||||
linux containers. To interact with the daemon, one needs to set
|
||||
<command>DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock</command>.
|
||||
'';
|
||||
};
|
||||
|
||||
setSocketVariable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Point <command>DOCKER_HOST</command> to rootless Docker instance for
|
||||
normal users by default.
|
||||
'';
|
||||
};
|
||||
|
||||
daemon.settings = mkOption {
|
||||
type = settingsFormat.type;
|
||||
default = { };
|
||||
example = {
|
||||
ipv6 = true;
|
||||
"fixed-cidr-v6" = "fd00::/80";
|
||||
};
|
||||
description = ''
|
||||
Configuration for docker daemon. The attributes are serialized to JSON used as daemon.conf.
|
||||
See https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file
|
||||
'';
|
||||
};
|
||||
|
||||
package = mkOption {
|
||||
default = pkgs.docker;
|
||||
defaultText = literalExpression "pkgs.docker";
|
||||
type = types.package;
|
||||
example = literalExpression "pkgs.docker-edge";
|
||||
description = ''
|
||||
Docker package to be used in the module.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
environment.extraInit = optionalString cfg.setSocketVariable ''
|
||||
if [ -z "$DOCKER_HOST" -a -n "$XDG_RUNTIME_DIR" ]; then
|
||||
export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/docker.sock"
|
||||
fi
|
||||
'';
|
||||
|
||||
# Taken from https://github.com/moby/moby/blob/master/contrib/dockerd-rootless-setuptool.sh
|
||||
systemd.user.services.docker = {
|
||||
wantedBy = [ "default.target" ];
|
||||
description = "Docker Application Container Engine (Rootless)";
|
||||
# needs newuidmap from pkgs.shadow
|
||||
path = [ "/run/wrappers" ];
|
||||
environment = proxy_env;
|
||||
unitConfig.StartLimitInterval = "60s";
|
||||
serviceConfig = {
|
||||
Type = "notify";
|
||||
ExecStart = "${cfg.package}/bin/dockerd-rootless --config-file=${daemonSettingsFile}";
|
||||
ExecReload = "${pkgs.procps}/bin/kill -s HUP $MAINPID";
|
||||
TimeoutSec = 0;
|
||||
RestartSec = 2;
|
||||
Restart = "always";
|
||||
StartLimitBurst = 3;
|
||||
LimitNOFILE = "infinity";
|
||||
LimitNPROC = "infinity";
|
||||
LimitCORE = "infinity";
|
||||
Delegate = true;
|
||||
NotifyAccess = "all";
|
||||
KillMode = "mixed";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
+366
-210
@@ -1,9 +1,9 @@
|
||||
let
|
||||
import ./make-test-python.nix ({ pkgs, lib, ... }: let
|
||||
commonConfig = ./common/acme/client;
|
||||
|
||||
dnsServerIP = nodes: nodes.dnsserver.config.networking.primaryIPAddress;
|
||||
|
||||
dnsScript = {pkgs, nodes}: let
|
||||
dnsScript = nodes: let
|
||||
dnsAddress = dnsServerIP nodes;
|
||||
in pkgs.writeShellScript "dns-hook.sh" ''
|
||||
set -euo pipefail
|
||||
@@ -15,30 +15,137 @@ let
|
||||
fi
|
||||
'';
|
||||
|
||||
documentRoot = pkgs: pkgs.runCommand "docroot" {} ''
|
||||
dnsConfig = nodes: {
|
||||
dnsProvider = "exec";
|
||||
dnsPropagationCheck = false;
|
||||
credentialsFile = pkgs.writeText "wildcard.env" ''
|
||||
EXEC_PATH=${dnsScript nodes}
|
||||
EXEC_POLLING_INTERVAL=1
|
||||
EXEC_PROPAGATION_TIMEOUT=1
|
||||
EXEC_SEQUENCE_INTERVAL=1
|
||||
'';
|
||||
};
|
||||
|
||||
documentRoot = pkgs.runCommand "docroot" {} ''
|
||||
mkdir -p "$out"
|
||||
echo hello world > "$out/index.html"
|
||||
'';
|
||||
|
||||
vhostBase = pkgs: {
|
||||
vhostBase = {
|
||||
forceSSL = true;
|
||||
locations."/".root = documentRoot pkgs;
|
||||
locations."/".root = documentRoot;
|
||||
};
|
||||
|
||||
in import ./make-test-python.nix ({ lib, ... }: {
|
||||
vhostBaseHttpd = {
|
||||
forceSSL = true;
|
||||
inherit documentRoot;
|
||||
};
|
||||
|
||||
# Base specialisation config for testing general ACME features
|
||||
webserverBasicConfig = {
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts."a.example.test" = vhostBase // {
|
||||
enableACME = true;
|
||||
};
|
||||
};
|
||||
|
||||
# Generate specialisations for testing a web server
|
||||
mkServerConfigs = { server, group, vhostBaseData, extraConfig ? {} }: let
|
||||
baseConfig = { nodes, config, specialConfig ? {} }: lib.mkMerge [
|
||||
{
|
||||
security.acme = {
|
||||
defaults = (dnsConfig nodes) // {
|
||||
inherit group;
|
||||
};
|
||||
# One manual wildcard cert
|
||||
certs."example.test" = {
|
||||
domain = "*.example.test";
|
||||
};
|
||||
};
|
||||
|
||||
services."${server}" = {
|
||||
enable = true;
|
||||
virtualHosts = {
|
||||
# Run-of-the-mill vhost using HTTP-01 validation
|
||||
"${server}-http.example.test" = vhostBaseData // {
|
||||
serverAliases = [ "${server}-http-alias.example.test" ];
|
||||
enableACME = true;
|
||||
};
|
||||
|
||||
# Another which inherits the DNS-01 config
|
||||
"${server}-dns.example.test" = vhostBaseData // {
|
||||
serverAliases = [ "${server}-dns-alias.example.test" ];
|
||||
enableACME = true;
|
||||
# Set acmeRoot to null instead of using the default of "/var/lib/acme/acme-challenge"
|
||||
# webroot + dnsProvider are mutually exclusive.
|
||||
acmeRoot = null;
|
||||
};
|
||||
|
||||
# One using the wildcard certificate
|
||||
"${server}-wildcard.example.test" = vhostBaseData // {
|
||||
serverAliases = [ "${server}-wildcard-alias.example.test" ];
|
||||
useACMEHost = "example.test";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Used to determine if service reload was triggered
|
||||
systemd.targets."test-renew-${server}" = {
|
||||
wants = [ "acme-${server}-http.example.test.service" ];
|
||||
after = [ "acme-${server}-http.example.test.service" "${server}-config-reload.service" ];
|
||||
};
|
||||
}
|
||||
specialConfig
|
||||
extraConfig
|
||||
];
|
||||
in {
|
||||
"${server}".configuration = { nodes, config, ... }: baseConfig {
|
||||
inherit nodes config;
|
||||
};
|
||||
|
||||
# Test that server reloads when an alias is removed (and subsequently test removal works in acme)
|
||||
"${server}-remove-alias".configuration = { nodes, config, ... }: baseConfig {
|
||||
inherit nodes config;
|
||||
specialConfig = {
|
||||
# Remove an alias, but create a standalone vhost in its place for testing.
|
||||
# This configuration results in certificate errors as useACMEHost does not imply
|
||||
# append extraDomains, and thus we can validate the SAN is removed.
|
||||
services."${server}" = {
|
||||
virtualHosts."${server}-http.example.test".serverAliases = lib.mkForce [];
|
||||
virtualHosts."${server}-http-alias.example.test" = vhostBaseData // {
|
||||
useACMEHost = "${server}-http.example.test";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Test that the server reloads when only the acme configuration is changed.
|
||||
"${server}-change-acme-conf".configuration = { nodes, config, ... }: baseConfig {
|
||||
inherit nodes config;
|
||||
specialConfig = {
|
||||
security.acme.certs."${server}-http.example.test" = {
|
||||
keyType = "ec384";
|
||||
# Also test that postRun is exec'd as root
|
||||
postRun = "id | grep root";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
in {
|
||||
name = "acme";
|
||||
meta.maintainers = lib.teams.acme.members;
|
||||
|
||||
nodes = {
|
||||
# The fake ACME server which will respond to client requests
|
||||
acme = { nodes, lib, ... }: {
|
||||
acme = { nodes, ... }: {
|
||||
imports = [ ./common/acme/server ];
|
||||
networking.nameservers = lib.mkForce [ (dnsServerIP nodes) ];
|
||||
};
|
||||
|
||||
# A fake DNS server which can be configured with records as desired
|
||||
# Used to test DNS-01 challenge
|
||||
dnsserver = { nodes, pkgs, ... }: {
|
||||
dnsserver = { nodes, ... }: {
|
||||
networking.firewall.allowedTCPPorts = [ 8055 53 ];
|
||||
networking.firewall.allowedUDPPorts = [ 53 ];
|
||||
systemd.services.pebble-challtestsrv = {
|
||||
@@ -54,7 +161,7 @@ in import ./make-test-python.nix ({ lib, ... }: {
|
||||
};
|
||||
|
||||
# A web server which will be the node requesting certs
|
||||
webserver = { pkgs, nodes, lib, config, ... }: {
|
||||
webserver = { nodes, config, ... }: {
|
||||
imports = [ commonConfig ];
|
||||
networking.nameservers = lib.mkForce [ (dnsServerIP nodes) ];
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
@@ -63,130 +170,142 @@ in import ./make-test-python.nix ({ lib, ... }: {
|
||||
environment.systemPackages = [ pkgs.openssl ];
|
||||
|
||||
# Set log level to info so that we can see when the service is reloaded
|
||||
services.nginx.enable = true;
|
||||
services.nginx.logError = "stderr info";
|
||||
|
||||
# First tests configure a basic cert and run a bunch of openssl checks
|
||||
services.nginx.virtualHosts."a.example.test" = (vhostBase pkgs) // {
|
||||
enableACME = true;
|
||||
};
|
||||
specialisation = {
|
||||
# First derivation used to test general ACME features
|
||||
general.configuration = { ... }: let
|
||||
caDomain = nodes.acme.config.test-support.acme.caDomain;
|
||||
email = config.security.acme.defaults.email;
|
||||
# Exit 99 to make it easier to track if this is the reason a renew failed
|
||||
accountCreateTester = ''
|
||||
test -e accounts/${caDomain}/${email}/account.json || exit 99
|
||||
'';
|
||||
in lib.mkMerge [
|
||||
webserverBasicConfig
|
||||
{
|
||||
# Used to test that account creation is collated into one service.
|
||||
# These should not run until after acme-finished-a.example.test.target
|
||||
systemd.services."b.example.test".preStart = accountCreateTester;
|
||||
systemd.services."c.example.test".preStart = accountCreateTester;
|
||||
|
||||
# Used to determine if service reload was triggered
|
||||
systemd.targets.test-renew-nginx = {
|
||||
wants = [ "acme-a.example.test.service" ];
|
||||
after = [ "acme-a.example.test.service" "nginx-config-reload.service" ];
|
||||
};
|
||||
services.nginx.virtualHosts."b.example.test" = vhostBase // {
|
||||
enableACME = true;
|
||||
};
|
||||
services.nginx.virtualHosts."c.example.test" = vhostBase // {
|
||||
enableACME = true;
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
# Test that account creation is collated into one service
|
||||
specialisation.account-creation.configuration = { nodes, pkgs, lib, ... }: let
|
||||
email = "newhostmaster@example.test";
|
||||
caDomain = nodes.acme.config.test-support.acme.caDomain;
|
||||
# Exit 99 to make it easier to track if this is the reason a renew failed
|
||||
testScript = ''
|
||||
test -e accounts/${caDomain}/${email}/account.json || exit 99
|
||||
'';
|
||||
# Test OCSP Stapling
|
||||
ocsp-stapling.configuration = { ... }: lib.mkMerge [
|
||||
webserverBasicConfig
|
||||
{
|
||||
security.acme.certs."a.example.test".ocspMustStaple = true;
|
||||
services.nginx.virtualHosts."a.example.test" = {
|
||||
extraConfig = ''
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
'';
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
# Validate service relationships by adding a slow start service to nginx' wants.
|
||||
# Reproducer for https://github.com/NixOS/nixpkgs/issues/81842
|
||||
slow-startup.configuration = { ... }: lib.mkMerge [
|
||||
webserverBasicConfig
|
||||
{
|
||||
systemd.services.my-slow-service = {
|
||||
wantedBy = [ "multi-user.target" "nginx.service" ];
|
||||
before = [ "nginx.service" ];
|
||||
preStart = "sleep 5";
|
||||
script = "${pkgs.python3}/bin/python -m http.server";
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."slow.example.test" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/".proxyPass = "http://localhost:8000";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
# Test lego internal server (listenHTTP option)
|
||||
# Also tests useRoot option
|
||||
lego-server.configuration = { ... }: {
|
||||
security.acme.useRoot = true;
|
||||
security.acme.certs."lego.example.test" = {
|
||||
listenHTTP = ":80";
|
||||
group = "nginx";
|
||||
};
|
||||
services.nginx.enable = true;
|
||||
services.nginx.virtualHosts."lego.example.test" = {
|
||||
useACMEHost = "lego.example.test";
|
||||
onlySSL = true;
|
||||
};
|
||||
};
|
||||
|
||||
# Test compatiblity with Caddy
|
||||
# It only supports useACMEHost, hence not using mkServerConfigs
|
||||
} // (let
|
||||
baseCaddyConfig = { nodes, config, ... }: {
|
||||
security.acme = {
|
||||
defaults = (dnsConfig nodes) // {
|
||||
group = config.services.caddy.group;
|
||||
};
|
||||
# One manual wildcard cert
|
||||
certs."example.test" = {
|
||||
domain = "*.example.test";
|
||||
};
|
||||
};
|
||||
|
||||
services.caddy = {
|
||||
enable = true;
|
||||
virtualHosts."a.exmaple.test" = {
|
||||
useACMEHost = "example.test";
|
||||
extraConfig = ''
|
||||
root * ${documentRoot}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
in {
|
||||
security.acme.email = lib.mkForce email;
|
||||
systemd.services."b.example.test".preStart = testScript;
|
||||
systemd.services."c.example.test".preStart = testScript;
|
||||
caddy.configuration = baseCaddyConfig;
|
||||
|
||||
services.nginx.virtualHosts."b.example.test" = (vhostBase pkgs) // {
|
||||
enableACME = true;
|
||||
};
|
||||
services.nginx.virtualHosts."c.example.test" = (vhostBase pkgs) // {
|
||||
enableACME = true;
|
||||
};
|
||||
};
|
||||
# Test that the server reloads when only the acme configuration is changed.
|
||||
"caddy-change-acme-conf".configuration = { nodes, config, ... }: lib.mkMerge [
|
||||
(baseCaddyConfig {
|
||||
inherit nodes config;
|
||||
})
|
||||
{
|
||||
security.acme.certs."example.test" = {
|
||||
keyType = "ec384";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
# Cert config changes will not cause the nginx configuration to change.
|
||||
# This tests that the reload service is correctly triggered.
|
||||
# It also tests that postRun is exec'd as root
|
||||
specialisation.cert-change.configuration = { pkgs, ... }: {
|
||||
security.acme.certs."a.example.test".keyType = "ec384";
|
||||
security.acme.certs."a.example.test".postRun = ''
|
||||
set -euo pipefail
|
||||
touch /home/test
|
||||
chown root:root /home/test
|
||||
echo testing > /home/test
|
||||
'';
|
||||
};
|
||||
# Test compatibility with Nginx
|
||||
}) // (mkServerConfigs {
|
||||
server = "nginx";
|
||||
group = "nginx";
|
||||
vhostBaseData = vhostBase;
|
||||
})
|
||||
|
||||
# Now adding an alias to ensure that the certs are updated
|
||||
specialisation.nginx-aliases.configuration = { pkgs, ... }: {
|
||||
services.nginx.virtualHosts."a.example.test" = {
|
||||
serverAliases = [ "b.example.test" ];
|
||||
};
|
||||
};
|
||||
|
||||
# Test OCSP Stapling
|
||||
specialisation.ocsp-stapling.configuration = { pkgs, ... }: {
|
||||
security.acme.certs."a.example.test" = {
|
||||
ocspMustStaple = true;
|
||||
};
|
||||
services.nginx.virtualHosts."a.example.com" = {
|
||||
extraConfig = ''
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# Test using Apache HTTPD
|
||||
specialisation.httpd-aliases.configuration = { pkgs, config, lib, ... }: {
|
||||
services.nginx.enable = lib.mkForce false;
|
||||
services.httpd.enable = true;
|
||||
services.httpd.adminAddr = config.security.acme.email;
|
||||
services.httpd.virtualHosts."c.example.test" = {
|
||||
serverAliases = [ "d.example.test" ];
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
documentRoot = documentRoot pkgs;
|
||||
};
|
||||
|
||||
# Used to determine if service reload was triggered
|
||||
systemd.targets.test-renew-httpd = {
|
||||
wants = [ "acme-c.example.test.service" ];
|
||||
after = [ "acme-c.example.test.service" "httpd-config-reload.service" ];
|
||||
};
|
||||
};
|
||||
|
||||
# Validation via DNS-01 challenge
|
||||
specialisation.dns-01.configuration = { pkgs, config, nodes, ... }: {
|
||||
security.acme.certs."example.test" = {
|
||||
domain = "*.example.test";
|
||||
group = config.services.nginx.group;
|
||||
dnsProvider = "exec";
|
||||
dnsPropagationCheck = false;
|
||||
credentialsFile = pkgs.writeText "wildcard.env" ''
|
||||
EXEC_PATH=${dnsScript { inherit pkgs nodes; }}
|
||||
'';
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."dns.example.test" = (vhostBase pkgs) // {
|
||||
useACMEHost = "example.test";
|
||||
};
|
||||
};
|
||||
|
||||
# Validate service relationships by adding a slow start service to nginx' wants.
|
||||
# Reproducer for https://github.com/NixOS/nixpkgs/issues/81842
|
||||
specialisation.slow-startup.configuration = { pkgs, config, nodes, lib, ... }: {
|
||||
systemd.services.my-slow-service = {
|
||||
wantedBy = [ "multi-user.target" "nginx.service" ];
|
||||
before = [ "nginx.service" ];
|
||||
preStart = "sleep 5";
|
||||
script = "${pkgs.python3}/bin/python -m http.server";
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."slow.example.com" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/".proxyPass = "http://localhost:8000";
|
||||
};
|
||||
};
|
||||
# Test compatibility with Apache HTTPD
|
||||
// (mkServerConfigs {
|
||||
server = "httpd";
|
||||
group = "wwwrun";
|
||||
vhostBaseData = vhostBaseHttpd;
|
||||
extraConfig = {
|
||||
services.httpd.adminAddr = config.security.acme.defaults.email;
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
# The client will be used to curl the webserver to validate configuration
|
||||
client = {nodes, lib, pkgs, ...}: {
|
||||
client = { nodes, ... }: {
|
||||
imports = [ commonConfig ];
|
||||
networking.nameservers = lib.mkForce [ (dnsServerIP nodes) ];
|
||||
|
||||
@@ -195,7 +314,7 @@ in import ./make-test-python.nix ({ lib, ... }: {
|
||||
};
|
||||
};
|
||||
|
||||
testScript = {nodes, ...}:
|
||||
testScript = { nodes, ... }:
|
||||
let
|
||||
caDomain = nodes.acme.config.test-support.acme.caDomain;
|
||||
newServerSystem = nodes.webserver.config.system.build.toplevel;
|
||||
@@ -204,23 +323,26 @@ in import ./make-test-python.nix ({ lib, ... }: {
|
||||
# Note, wait_for_unit does not work for oneshot services that do not have RemainAfterExit=true,
|
||||
# this is because a oneshot goes from inactive => activating => inactive, and never
|
||||
# reaches the active state. Targets do not have this issue.
|
||||
|
||||
''
|
||||
import time
|
||||
|
||||
|
||||
has_switched = False
|
||||
|
||||
|
||||
def switch_to(node, name):
|
||||
global has_switched
|
||||
if has_switched:
|
||||
node.succeed(
|
||||
"${switchToNewServer}"
|
||||
)
|
||||
has_switched = True
|
||||
# On first switch, this will create a symlink to the current system so that we can
|
||||
# quickly switch between derivations
|
||||
root_specs = "/tmp/specialisation"
|
||||
node.execute(
|
||||
f"test -e {root_specs}"
|
||||
f" || ln -s $(readlink /run/current-system)/specialisation {root_specs}"
|
||||
)
|
||||
|
||||
switcher_path = f"/run/current-system/specialisation/{name}/bin/switch-to-configuration"
|
||||
rc, _ = node.execute(f"test -e '{switcher_path}'")
|
||||
if rc > 0:
|
||||
switcher_path = f"/tmp/specialisation/{name}/bin/switch-to-configuration"
|
||||
|
||||
node.succeed(
|
||||
f"/run/current-system/specialisation/{name}/bin/switch-to-configuration test"
|
||||
f"{switcher_path} test"
|
||||
)
|
||||
|
||||
|
||||
@@ -310,8 +432,7 @@ in import ./make-test-python.nix ({ lib, ... }: {
|
||||
return download_ca_certs(node, retries - 1)
|
||||
|
||||
|
||||
client.start()
|
||||
dnsserver.start()
|
||||
start_all()
|
||||
|
||||
dnsserver.wait_for_unit("pebble-challtestsrv.service")
|
||||
client.wait_for_unit("default.target")
|
||||
@@ -320,19 +441,30 @@ in import ./make-test-python.nix ({ lib, ... }: {
|
||||
'curl --data \'{"host": "${caDomain}", "addresses": ["${nodes.acme.config.networking.primaryIPAddress}"]}\' http://${dnsServerIP nodes}:8055/add-a'
|
||||
)
|
||||
|
||||
acme.start()
|
||||
webserver.start()
|
||||
|
||||
acme.wait_for_unit("network-online.target")
|
||||
acme.wait_for_unit("pebble.service")
|
||||
|
||||
download_ca_certs(client)
|
||||
|
||||
with subtest("Can request certificate with HTTPS-01 challenge"):
|
||||
# Perform general tests first
|
||||
switch_to(webserver, "general")
|
||||
|
||||
with subtest("Can request certificate with HTTP-01 challenge"):
|
||||
webserver.wait_for_unit("acme-finished-a.example.test.target")
|
||||
check_fullchain(webserver, "a.example.test")
|
||||
check_issuer(webserver, "a.example.test", "pebble")
|
||||
webserver.wait_for_unit("nginx.service")
|
||||
check_connection(client, "a.example.test")
|
||||
|
||||
with subtest("Runs 1 cert for account creation before others"):
|
||||
webserver.wait_for_unit("acme-finished-b.example.test.target")
|
||||
webserver.wait_for_unit("acme-finished-c.example.test.target")
|
||||
check_connection(client, "b.example.test")
|
||||
check_connection(client, "c.example.test")
|
||||
|
||||
with subtest("Certificates and accounts have safe + valid permissions"):
|
||||
group = "${nodes.webserver.config.security.acme.certs."a.example.test".group}"
|
||||
# Nginx will set the group appropriately when enableACME is used
|
||||
group = "nginx"
|
||||
webserver.succeed(
|
||||
f"test $(stat -L -c '%a %U %G' /var/lib/acme/a.example.test/*.pem | tee /dev/stderr | grep '640 acme {group}' | wc -l) -eq 5"
|
||||
)
|
||||
@@ -346,12 +478,6 @@ in import ./make-test-python.nix ({ lib, ... }: {
|
||||
f"test $(find /var/lib/acme/accounts -type f -exec stat -L -c '%a %U %G' {{}} \\; | tee /dev/stderr | grep -v '600 acme {group}' | wc -l) -eq 0"
|
||||
)
|
||||
|
||||
with subtest("Certs are accepted by web server"):
|
||||
webserver.succeed("systemctl start nginx.service")
|
||||
check_fullchain(webserver, "a.example.test")
|
||||
check_issuer(webserver, "a.example.test", "pebble")
|
||||
check_connection(client, "a.example.test")
|
||||
|
||||
# Selfsigned certs tests happen late so we aren't fighting the system init triggering cert renewal
|
||||
with subtest("Can generate valid selfsigned certs"):
|
||||
webserver.succeed("systemctl clean acme-a.example.test.service --what=state")
|
||||
@@ -365,77 +491,107 @@ in import ./make-test-python.nix ({ lib, ... }: {
|
||||
# Will succeed if nginx can load the certs
|
||||
webserver.succeed("systemctl start nginx-config-reload.service")
|
||||
|
||||
with subtest("Can reload nginx when timer triggers renewal"):
|
||||
webserver.succeed("systemctl start test-renew-nginx.target")
|
||||
check_issuer(webserver, "a.example.test", "pebble")
|
||||
check_connection(client, "a.example.test")
|
||||
|
||||
with subtest("Runs 1 cert for account creation before others"):
|
||||
switch_to(webserver, "account-creation")
|
||||
webserver.wait_for_unit("acme-finished-a.example.test.target")
|
||||
check_connection(client, "a.example.test")
|
||||
webserver.wait_for_unit("acme-finished-b.example.test.target")
|
||||
webserver.wait_for_unit("acme-finished-c.example.test.target")
|
||||
check_connection(client, "b.example.test")
|
||||
check_connection(client, "c.example.test")
|
||||
|
||||
with subtest("Can reload web server when cert configuration changes"):
|
||||
switch_to(webserver, "cert-change")
|
||||
webserver.wait_for_unit("acme-finished-a.example.test.target")
|
||||
check_connection_key_bits(client, "a.example.test", "384")
|
||||
webserver.succeed("grep testing /home/test")
|
||||
# Clean to remove the testing file (and anything else messy we did)
|
||||
webserver.succeed("systemctl clean acme-a.example.test.service --what=state")
|
||||
|
||||
with subtest("Correctly implements OCSP stapling"):
|
||||
switch_to(webserver, "ocsp-stapling")
|
||||
webserver.wait_for_unit("acme-finished-a.example.test.target")
|
||||
check_stapling(client, "a.example.test")
|
||||
|
||||
with subtest("Can request certificate with HTTPS-01 when nginx startup is delayed"):
|
||||
switch_to(webserver, "slow-startup")
|
||||
webserver.wait_for_unit("acme-finished-slow.example.com.target")
|
||||
check_issuer(webserver, "slow.example.com", "pebble")
|
||||
check_connection(client, "slow.example.com")
|
||||
|
||||
with subtest("Can request certificate for vhost + aliases (nginx)"):
|
||||
# Check the key hash before and after adding an alias. It should not change.
|
||||
# The previous test reverts the ed384 change
|
||||
webserver.wait_for_unit("acme-finished-a.example.test.target")
|
||||
switch_to(webserver, "nginx-aliases")
|
||||
webserver.wait_for_unit("acme-finished-a.example.test.target")
|
||||
check_issuer(webserver, "a.example.test", "pebble")
|
||||
with subtest("Can request certificate with HTTP-01 using lego's internal web server"):
|
||||
switch_to(webserver, "lego-server")
|
||||
webserver.wait_for_unit("acme-finished-lego.example.test.target")
|
||||
webserver.wait_for_unit("nginx.service")
|
||||
webserver.succeed("echo HENLO && systemctl cat nginx.service")
|
||||
webserver.succeed("test \"$(stat -c '%U' /var/lib/acme/* | uniq)\" = \"root\"")
|
||||
check_connection(client, "a.example.test")
|
||||
check_connection(client, "b.example.test")
|
||||
check_connection(client, "lego.example.test")
|
||||
|
||||
with subtest("Can request certificates for vhost + aliases (apache-httpd)"):
|
||||
try:
|
||||
switch_to(webserver, "httpd-aliases")
|
||||
webserver.wait_for_unit("acme-finished-c.example.test.target")
|
||||
except Exception as err:
|
||||
_, output = webserver.execute(
|
||||
"cat /var/log/httpd/*.log && ls -al /var/lib/acme/acme-challenge"
|
||||
)
|
||||
print(output)
|
||||
raise err
|
||||
check_issuer(webserver, "c.example.test", "pebble")
|
||||
check_connection(client, "c.example.test")
|
||||
check_connection(client, "d.example.test")
|
||||
with subtest("Can request certificate with HTTP-01 when nginx startup is delayed"):
|
||||
webserver.execute("systemctl stop nginx")
|
||||
switch_to(webserver, "slow-startup")
|
||||
webserver.wait_for_unit("acme-finished-slow.example.test.target")
|
||||
check_issuer(webserver, "slow.example.test", "pebble")
|
||||
webserver.wait_for_unit("nginx.service")
|
||||
check_connection(client, "slow.example.test")
|
||||
|
||||
with subtest("Can reload httpd when timer triggers renewal"):
|
||||
# Switch to selfsigned first
|
||||
webserver.succeed("systemctl clean acme-c.example.test.service --what=state")
|
||||
webserver.succeed("systemctl start acme-selfsigned-c.example.test.service")
|
||||
check_issuer(webserver, "c.example.test", "minica")
|
||||
webserver.succeed("systemctl start httpd-config-reload.service")
|
||||
webserver.succeed("systemctl start test-renew-httpd.target")
|
||||
check_issuer(webserver, "c.example.test", "pebble")
|
||||
check_connection(client, "c.example.test")
|
||||
|
||||
with subtest("Can request wildcard certificates using DNS-01 challenge"):
|
||||
switch_to(webserver, "dns-01")
|
||||
with subtest("Works with caddy"):
|
||||
switch_to(webserver, "caddy")
|
||||
webserver.wait_for_unit("acme-finished-example.test.target")
|
||||
check_issuer(webserver, "example.test", "pebble")
|
||||
check_connection(client, "dns.example.test")
|
||||
webserver.wait_for_unit("caddy.service")
|
||||
# FIXME reloading caddy is not sufficient to load new certs.
|
||||
# Restart it manually until this is fixed.
|
||||
webserver.succeed("systemctl restart caddy.service")
|
||||
check_connection(client, "a.example.test")
|
||||
|
||||
with subtest("security.acme changes reflect on caddy"):
|
||||
switch_to(webserver, "caddy-change-acme-conf")
|
||||
webserver.wait_for_unit("acme-finished-example.test.target")
|
||||
webserver.wait_for_unit("caddy.service")
|
||||
# FIXME reloading caddy is not sufficient to load new certs.
|
||||
# Restart it manually until this is fixed.
|
||||
webserver.succeed("systemctl restart caddy.service")
|
||||
check_connection_key_bits(client, "a.example.test", "384")
|
||||
|
||||
domains = ["http", "dns", "wildcard"]
|
||||
for server, logsrc in [
|
||||
("nginx", "journalctl -n 30 -u nginx.service"),
|
||||
("httpd", "tail -n 30 /var/log/httpd/*.log"),
|
||||
]:
|
||||
wait_for_server = lambda: webserver.wait_for_unit(f"{server}.service")
|
||||
with subtest(f"Works with {server}"):
|
||||
try:
|
||||
switch_to(webserver, server)
|
||||
# Skip wildcard domain for this check ([:-1])
|
||||
for domain in domains[:-1]:
|
||||
webserver.wait_for_unit(
|
||||
f"acme-finished-{server}-{domain}.example.test.target"
|
||||
)
|
||||
except Exception as err:
|
||||
_, output = webserver.execute(
|
||||
f"{logsrc} && ls -al /var/lib/acme/acme-challenge"
|
||||
)
|
||||
print(output)
|
||||
raise err
|
||||
|
||||
wait_for_server()
|
||||
|
||||
for domain in domains[:-1]:
|
||||
check_issuer(webserver, f"{server}-{domain}.example.test", "pebble")
|
||||
for domain in domains:
|
||||
check_connection(client, f"{server}-{domain}.example.test")
|
||||
check_connection(client, f"{server}-{domain}-alias.example.test")
|
||||
|
||||
test_domain = f"{server}-{domains[0]}.example.test"
|
||||
|
||||
with subtest(f"Can reload {server} when timer triggers renewal"):
|
||||
# Switch to selfsigned first
|
||||
webserver.succeed(f"systemctl clean acme-{test_domain}.service --what=state")
|
||||
webserver.succeed(f"systemctl start acme-selfsigned-{test_domain}.service")
|
||||
check_issuer(webserver, test_domain, "minica")
|
||||
webserver.succeed(f"systemctl start {server}-config-reload.service")
|
||||
webserver.succeed(f"systemctl start test-renew-{server}.target")
|
||||
check_issuer(webserver, test_domain, "pebble")
|
||||
check_connection(client, test_domain)
|
||||
|
||||
with subtest("Can remove an alias from a domain + cert is updated"):
|
||||
test_alias = f"{server}-{domains[0]}-alias.example.test"
|
||||
switch_to(webserver, f"{server}-remove-alias")
|
||||
webserver.wait_for_unit(f"acme-finished-{test_domain}.target")
|
||||
wait_for_server()
|
||||
check_connection(client, test_domain)
|
||||
rc, _ = client.execute(
|
||||
f"openssl s_client -CAfile /tmp/ca.crt -connect {test_alias}:443"
|
||||
" </dev/null 2>/dev/null | openssl x509 -noout -text"
|
||||
f" | grep DNS: | grep {test_alias}"
|
||||
)
|
||||
assert rc > 0, "Removed extraDomainName was not removed from the cert"
|
||||
|
||||
with subtest("security.acme changes reflect on web server"):
|
||||
# Switch back to normal server config first, reset everything.
|
||||
switch_to(webserver, server)
|
||||
wait_for_server()
|
||||
switch_to(webserver, f"{server}-change-acme-conf")
|
||||
webserver.wait_for_unit(f"acme-finished-{test_domain}.target")
|
||||
wait_for_server()
|
||||
check_connection_key_bits(client, test_domain, "384")
|
||||
'';
|
||||
})
|
||||
|
||||
@@ -105,6 +105,7 @@ in
|
||||
dnscrypt-wrapper = handleTestOn ["x86_64-linux"] ./dnscrypt-wrapper {};
|
||||
doas = handleTest ./doas.nix {};
|
||||
docker = handleTestOn ["x86_64-linux"] ./docker.nix {};
|
||||
docker-rootless = handleTestOn ["x86_64-linux"] ./docker-rootless.nix {};
|
||||
docker-edge = handleTestOn ["x86_64-linux"] ./docker-edge.nix {};
|
||||
docker-registry = handleTest ./docker-registry.nix {};
|
||||
docker-tools = handleTestOn ["x86_64-linux"] ./docker-tools.nix {};
|
||||
|
||||
@@ -5,9 +5,11 @@ let
|
||||
|
||||
in {
|
||||
security.acme = {
|
||||
server = "https://${caDomain}/dir";
|
||||
email = "hostmaster@example.test";
|
||||
acceptTerms = true;
|
||||
defaults = {
|
||||
server = "https://${caDomain}/dir";
|
||||
email = "hostmaster@example.test";
|
||||
};
|
||||
};
|
||||
|
||||
security.pki.certificateFiles = [ caCert ];
|
||||
|
||||
@@ -120,6 +120,11 @@ in {
|
||||
enable = true;
|
||||
description = "Pebble ACME server";
|
||||
wantedBy = [ "network.target" ];
|
||||
environment = {
|
||||
# We're not testing lego, we're just testing our configuration.
|
||||
# No need to sleep.
|
||||
PEBBLE_VA_NOSLEEP = "1";
|
||||
};
|
||||
|
||||
serviceConfig = {
|
||||
RuntimeDirectory = "pebble";
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# This test runs docker and checks if simple container starts
|
||||
|
||||
import ./make-test-python.nix ({ lib, pkgs, ...} : {
|
||||
name = "docker-rootless";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [ abbradar ];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
machine = { pkgs, ... }: {
|
||||
virtualisation.docker.rootless.enable = true;
|
||||
|
||||
users.users.alice = {
|
||||
uid = 1000;
|
||||
isNormalUser = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = { nodes, ... }:
|
||||
let
|
||||
user = nodes.machine.config.users.users.alice;
|
||||
sudo = lib.concatStringsSep " " [
|
||||
"XDG_RUNTIME_DIR=/run/user/${toString user.uid}"
|
||||
"DOCKER_HOST=unix:///run/user/${toString user.uid}/docker.sock"
|
||||
"sudo" "--preserve-env=XDG_RUNTIME_DIR,DOCKER_HOST" "-u" "alice"
|
||||
];
|
||||
in ''
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed("loginctl enable-linger alice")
|
||||
machine.wait_until_succeeds("${sudo} systemctl --user is-active docker.service")
|
||||
|
||||
machine.succeed("tar cv --files-from /dev/null | ${sudo} docker import - scratchimg")
|
||||
machine.succeed(
|
||||
"${sudo} docker run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10"
|
||||
)
|
||||
machine.succeed("${sudo} docker ps | grep sleeping")
|
||||
machine.succeed("${sudo} docker stop sleeping")
|
||||
'';
|
||||
})
|
||||
@@ -9,6 +9,8 @@ lib.makeScope newScope (self: with self; {
|
||||
|
||||
mopidy-iris = callPackage ./iris.nix { };
|
||||
|
||||
mopidy-jellyfin = callPackage ./jellyfin.nix { };
|
||||
|
||||
mopidy-local = callPackage ./local.nix { };
|
||||
|
||||
mopidy-moped = callPackage ./moped.nix { };
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
{ lib, python3Packages, mopidy }:
|
||||
|
||||
python3Packages.buildPythonApplication rec {
|
||||
pname = "mopidy-jellyfin";
|
||||
version = "1.0.2";
|
||||
|
||||
src = python3Packages.fetchPypi {
|
||||
inherit version;
|
||||
pname = "Mopidy-Jellyfin";
|
||||
sha256 = "0j7v5xx3c401r5dw1sqm1n2263chjga1d3ml85rg79hjhhhacy75";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ mopidy python3Packages.unidecode python3Packages.websocket-client ];
|
||||
|
||||
# no tests implemented
|
||||
doCheck = false;
|
||||
pythonImportsCheck = [ "mopidy_jellyfin" ];
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/jellyfin/mopidy-jellyfin";
|
||||
description = "Mopidy extension for playing audio files from Jellyfin";
|
||||
license = licenses.asl20;
|
||||
maintainers = [ maintainers.pstn ];
|
||||
};
|
||||
}
|
||||
@@ -26,6 +26,7 @@
|
||||
, siteStart ? ./site-start.el
|
||||
, nativeComp ? false
|
||||
, withPgtk ? false
|
||||
, withXinput2 ? false
|
||||
, withImageMagick ? lib.versionOlder version "27" && (withX || withNS)
|
||||
, toolkit ? (
|
||||
if withGTK2 then "gtk2"
|
||||
@@ -152,6 +153,7 @@ let emacs = stdenv.mkDerivation (lib.optionalAttrs nativeComp {
|
||||
++ lib.optional nativeComp "--with-native-compilation"
|
||||
++ lib.optional withImageMagick "--with-imagemagick"
|
||||
++ lib.optional withPgtk "--with-pgtk"
|
||||
++ lib.optional withXinput2 "--with-xinput2"
|
||||
;
|
||||
|
||||
installTargets = [ "tags" "install" ];
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
, swig
|
||||
, python
|
||||
, wxPython
|
||||
, opencascade
|
||||
, opencascade-occt
|
||||
, libngspice
|
||||
, valgrind
|
||||
@@ -44,22 +43,16 @@
|
||||
, baseName
|
||||
, kicadSrc
|
||||
, kicadVersion
|
||||
, i18n
|
||||
, withOCE
|
||||
, withOCC
|
||||
, withNgspice
|
||||
, withScripting
|
||||
, withI18n
|
||||
, withPCM
|
||||
, debug
|
||||
, sanitizeAddress
|
||||
, sanitizeThreads
|
||||
, withI18n
|
||||
}:
|
||||
|
||||
assert lib.asserts.assertMsg (!(withOCE && stdenv.isAarch64)) "OCE fails a test on Aarch64";
|
||||
assert lib.asserts.assertMsg (!(withOCC && withOCE))
|
||||
"Only one of OCC and OCE may be enabled";
|
||||
assert lib.assertMsg (!(stable && (sanitizeAddress || sanitizeThreads)))
|
||||
"Only kicad-unstable(-small) supports address/thread sanitation";
|
||||
assert lib.assertMsg (!(sanitizeAddress && sanitizeThreads))
|
||||
"'sanitizeAddress' and 'sanitizeThreads' are mutually exclusive, use one.";
|
||||
|
||||
@@ -75,6 +68,7 @@ stdenv.mkDerivation rec {
|
||||
# tagged releases don't have "unknown"
|
||||
# kicad nightlies use git describe --dirty
|
||||
# nix removes .git, so its approximated here
|
||||
# "6.99.0" doesn't have "-unknown", yet; so leaving this in case it returns
|
||||
postPatch = ''
|
||||
substituteInPlace CMakeModules/KiCadVersion.cmake \
|
||||
--replace "unknown" "${builtins.substring 0 10 src.rev}" \
|
||||
@@ -82,23 +76,14 @@ stdenv.mkDerivation rec {
|
||||
|
||||
makeFlags = optionals (debug) [ "CFLAGS+=-Og" "CFLAGS+=-ggdb" ];
|
||||
|
||||
cmakeFlags = optionals (stable && withScripting) [
|
||||
"-DKICAD_SCRIPTING=ON"
|
||||
"-DKICAD_SCRIPTING_MODULES=ON"
|
||||
"-DKICAD_SCRIPTING_PYTHON3=ON"
|
||||
"-DKICAD_SCRIPTING_WXPYTHON_PHOENIX=ON"
|
||||
cmakeFlags = optionals (withScripting) [
|
||||
"-DKICAD_SCRIPTING_WXPYTHON=ON"
|
||||
]
|
||||
++ optionals (!withScripting) [
|
||||
"-DKICAD_SCRIPTING=OFF"
|
||||
"-DKICAD_SCRIPTING_WXPYTHON=OFF"
|
||||
]
|
||||
++ optional (withNgspice) "-DKICAD_SPICE=ON"
|
||||
++ optional (!withOCE) "-DKICAD_USE_OCE=OFF"
|
||||
++ optional (!withNgspice) "-DKICAD_SPICE=OFF"
|
||||
++ optional (!withOCC) "-DKICAD_USE_OCC=OFF"
|
||||
++ optionals (withOCE) [
|
||||
"-DKICAD_USE_OCE=ON"
|
||||
"-DOCE_DIR=${opencascade}"
|
||||
]
|
||||
++ optionals (withOCC) [
|
||||
"-DKICAD_USE_OCC=ON"
|
||||
"-DOCC_INCLUDE_DIR=${opencascade-occt}/include/opencascade"
|
||||
@@ -108,11 +93,20 @@ stdenv.mkDerivation rec {
|
||||
"-DKICAD_STDLIB_DEBUG=ON"
|
||||
"-DKICAD_USE_VALGRIND=ON"
|
||||
]
|
||||
++ optionals (!doInstallCheck) [
|
||||
"-DKICAD_BUILD_QA_TESTS=OFF"
|
||||
]
|
||||
++ optionals (sanitizeAddress) [
|
||||
"-DKICAD_SANITIZE_ADDRESS=ON"
|
||||
]
|
||||
++ optionals (sanitizeThreads) [
|
||||
"-DKICAD_SANITIZE_THREADS=ON"
|
||||
]
|
||||
++ optionals (withI18n) [
|
||||
"-DKICAD_BUILD_I18N=ON"
|
||||
]
|
||||
++ optionals (!withPCM) [
|
||||
"-DKICAD_PCM=OFF"
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
@@ -154,34 +148,27 @@ stdenv.mkDerivation rec {
|
||||
curl
|
||||
openssl
|
||||
boost
|
||||
swig
|
||||
python
|
||||
]
|
||||
# unstable requires swig and python
|
||||
# wxPython still optional
|
||||
++ optionals (withScripting || (!stable)) [ swig python ]
|
||||
++ optional (withScripting) wxPython
|
||||
++ optional (withNgspice) libngspice
|
||||
++ optional (withOCE) opencascade
|
||||
++ optional (withOCC) opencascade-occt
|
||||
++ optional (debug) valgrind
|
||||
;
|
||||
|
||||
# debug builds fail all but the python test
|
||||
# 5.1.x fails the eeschema test
|
||||
doInstallCheck = !debug && !stable;
|
||||
#doInstallCheck = !debug;
|
||||
# temporarily disabled until upstream issue 9888 is resolved
|
||||
doInstallCheck = false;
|
||||
installCheckTarget = "test";
|
||||
|
||||
dontStrip = debug;
|
||||
|
||||
postInstall = optionalString (withI18n) ''
|
||||
mkdir -p $out/share
|
||||
lndir ${i18n}/share $out/share
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Just the built source without the libraries";
|
||||
longDescription = ''
|
||||
Just the build products, optionally with the i18n linked in
|
||||
the libraries are passed via an env var in the wrapper, default.nix
|
||||
Just the build products, the libraries are passed via an env var in the wrapper, default.nix
|
||||
'';
|
||||
homepage = "https://www.kicad.org/";
|
||||
license = lib.licenses.agpl3;
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
, fetchFromGitLab
|
||||
, gnome
|
||||
, dconf
|
||||
, wxGTK30
|
||||
, wxGTK31
|
||||
, wxGTK31-gtk3
|
||||
, makeWrapper
|
||||
, gsettings-desktop-schemas
|
||||
, hicolor-icon-theme
|
||||
@@ -14,42 +13,36 @@
|
||||
|
||||
, pname ? "kicad"
|
||||
, stable ? true
|
||||
, oceSupport ? false
|
||||
, withOCE ? false
|
||||
, withOCCT ? false
|
||||
, withOCC ? true
|
||||
, ngspiceSupport ? false
|
||||
, withNgspice ? true
|
||||
, libngspice
|
||||
, scriptingSupport ? false
|
||||
, withScripting ? true
|
||||
, python3
|
||||
, debug ? false
|
||||
, sanitizeAddress ? false
|
||||
, sanitizeThreads ? false
|
||||
, with3d ? true
|
||||
, withI18n ? true
|
||||
, withI18n ? false
|
||||
, withPCM ? true # Plugin and Content Manager
|
||||
, srcs ? { }
|
||||
}:
|
||||
|
||||
# The `srcs` parameter can be used to override the kicad source code
|
||||
# and all libraries (including i18n), which are otherwise inaccessible
|
||||
# and all libraries, which are otherwise inaccessible
|
||||
# to overlays since most of the kicad build expression has been
|
||||
# refactored into base.nix, most of the library build expressions have
|
||||
# been refactored into libraries.nix, and most the i18n build
|
||||
# expression has been refactored into i18n.nix. Overrides are only
|
||||
# applied when building `kicad-unstable`. The `srcs` parameter has no
|
||||
# effect for stable `kicad`. `srcs` takes an attribute set in which
|
||||
# been refactored into libraries.nix. Overrides are only applied when
|
||||
# building `kicad-unstable`. The `srcs` parameter has
|
||||
# no effect for stable `kicad`. `srcs` takes an attribute set in which
|
||||
# any of the following attributes are meaningful (though none are
|
||||
# mandatory): "kicad", "kicadVersion", "i18n", "symbols", "templates",
|
||||
# mandatory): "kicad", "kicadVersion", "symbols", "templates",
|
||||
# "footprints", "packages3d", and "libVersion". "kicadVersion" and
|
||||
# "libVersion" should be set to a string with the desired value for
|
||||
# the version attribute in kicad's `mkDerivation` and the version
|
||||
# attribute in any of the library's or i18n's `mkDerivation`,
|
||||
# respectively. "kicad", "i18n", "symbols", "templates", "footprints",
|
||||
# and "packages3d" should be set to an appropriate fetcher (e.g.,
|
||||
# `fetchFromGitLab`). So, for example, a possible overlay for kicad
|
||||
# is:
|
||||
# attribute in any of the library's `mkDerivation`, respectively.
|
||||
# "kicad", "symbols", "templates", "footprints", and "packages3d"
|
||||
# should be set to an appropriate fetcher (e.g. `fetchFromGitLab`).
|
||||
# So, for example, a possible overlay for kicad is:
|
||||
#
|
||||
# final: prev:
|
||||
|
||||
@@ -68,15 +61,6 @@
|
||||
# });
|
||||
# }
|
||||
|
||||
assert withNgspice -> libngspice != null;
|
||||
assert lib.assertMsg (!ngspiceSupport)
|
||||
"`nspiceSupport` was renamed to `withNgspice` for the sake of consistency with other kicad nix arguments.";
|
||||
assert lib.assertMsg (!oceSupport)
|
||||
"`oceSupport` was renamed to `withOCE` for the sake of consistency with other kicad nix arguments.";
|
||||
assert lib.assertMsg (!scriptingSupport)
|
||||
"`scriptingSupport` was renamed to `withScripting` for the sake of consistency with other kicad nix arguments.";
|
||||
assert lib.assertMsg (!withOCCT)
|
||||
"`withOCCT` was renamed to `withOCC` for the sake of consistency with upstream cmake options.";
|
||||
let
|
||||
baseName = if (stable) then "kicad" else "kicad-unstable";
|
||||
versionsImport = import ./versions.nix;
|
||||
@@ -91,14 +75,6 @@ let
|
||||
sha256 = versionsImport.${baseName}.kicadVersion.src.sha256;
|
||||
};
|
||||
|
||||
i18nSrcFetch = fetchFromGitLab {
|
||||
group = "kicad";
|
||||
owner = "code";
|
||||
repo = "kicad-i18n";
|
||||
rev = versionsImport.${baseName}.libVersion.libSources.i18n.rev;
|
||||
sha256 = versionsImport.${baseName}.libVersion.libSources.i18n.sha256;
|
||||
};
|
||||
|
||||
libSrcFetch = name: fetchFromGitLab {
|
||||
group = "kicad";
|
||||
owner = "libraries";
|
||||
@@ -121,36 +97,15 @@ let
|
||||
if srcOverridep "kicadVersion" then srcs.kicadVersion
|
||||
else versionsImport.${baseName}.kicadVersion.version;
|
||||
|
||||
i18nSrc = if srcOverridep "i18n" then srcs.i18n else i18nSrcFetch;
|
||||
i18nVersion =
|
||||
if srcOverridep "i18nVersion" then srcs.i18nVersion
|
||||
else versionsImport.${baseName}.libVersion.version;
|
||||
|
||||
libSrc = name: if srcOverridep name then srcs.${name} else libSrcFetch name;
|
||||
# TODO does it make sense to only have one version for all libs?
|
||||
libVersion =
|
||||
if srcOverridep "libVersion" then srcs.libVersion
|
||||
else versionsImport.${baseName}.libVersion.version;
|
||||
|
||||
wxGTK =
|
||||
if (stable)
|
||||
# wxGTK3x may default to withGtk2 = false, see #73145
|
||||
then
|
||||
wxGTK30.override
|
||||
{
|
||||
withGtk2 = false;
|
||||
}
|
||||
# wxGTK31 currently introduces an issue with opening the python interpreter in pcbnew
|
||||
# but brings high DPI support?
|
||||
else
|
||||
wxGTK31.override {
|
||||
withGtk2 = false;
|
||||
};
|
||||
|
||||
wxGTK = wxGTK31-gtk3;
|
||||
python = python3;
|
||||
wxPython = if (stable)
|
||||
then python.pkgs.wxPython_4_0
|
||||
else python.pkgs.wxPython_4_1;
|
||||
wxPython = python.pkgs.wxPython_4_1;
|
||||
|
||||
inherit (lib) concatStringsSep flatten optionalString optionals;
|
||||
in
|
||||
@@ -158,13 +113,11 @@ stdenv.mkDerivation rec {
|
||||
|
||||
# Common libraries, referenced during runtime, via the wrapper.
|
||||
passthru.libraries = callPackages ./libraries.nix { inherit libSrc; };
|
||||
passthru.i18n = callPackage ./i18n.nix { src = i18nSrc; };
|
||||
base = callPackage ./base.nix {
|
||||
inherit stable baseName;
|
||||
inherit kicadSrc kicadVersion;
|
||||
inherit (passthru) i18n;
|
||||
inherit wxGTK python wxPython;
|
||||
inherit withI18n withOCC withOCE withNgspice withScripting;
|
||||
inherit withOCC withNgspice withScripting withI18n withPCM;
|
||||
inherit debug sanitizeAddress sanitizeThreads;
|
||||
};
|
||||
|
||||
@@ -197,27 +150,14 @@ stdenv.mkDerivation rec {
|
||||
"--prefix GIO_EXTRA_MODULES : ${dconf}/lib/gio/modules"
|
||||
# required to open a bug report link in firefox-wayland
|
||||
"--set-default MOZ_DBUS_REMOTE 1"
|
||||
]
|
||||
++ optionals (stable)
|
||||
[
|
||||
"--set-default KISYSMOD ${footprints}/share/kicad/modules"
|
||||
"--set-default KICAD_SYMBOL_DIR ${symbols}/share/kicad/library"
|
||||
"--set-default KICAD_TEMPLATE_DIR ${templates}/share/kicad/template"
|
||||
"--prefix KICAD_TEMPLATE_DIR : ${symbols}/share/kicad/template"
|
||||
"--prefix KICAD_TEMPLATE_DIR : ${footprints}/share/kicad/template"
|
||||
]
|
||||
++ optionals (stable && with3d) [ "--set-default KISYS3DMOD ${packages3d}/share/kicad/modules/packages3d" ]
|
||||
++ optionals (!stable)
|
||||
[
|
||||
"--set-default KICAD6_FOOTPRINT_DIR ${footprints}/share/kicad/footprints"
|
||||
"--set-default KICAD6_SYMBOL_DIR ${symbols}/share/kicad/symbols"
|
||||
"--set-default KICAD6_TEMPLATE_DIR ${templates}/share/kicad/template"
|
||||
"--prefix KICAD6_TEMPLATE_DIR : ${symbols}/share/kicad/template"
|
||||
"--prefix KICAD6_TEMPLATE_DIR : ${footprints}/share/kicad/template"
|
||||
]
|
||||
++ optionals (!stable && with3d)
|
||||
++ optionals (with3d)
|
||||
[
|
||||
"--set-default KISYS3DMOD ${packages3d}/share/kicad/3dmodels"
|
||||
"--set-default KICAD6_3DMODEL_DIR ${packages3d}/share/kicad/3dmodels"
|
||||
]
|
||||
++ optionals (withNgspice) [ "--prefix LD_LIBRARY_PATH : ${libngspice}/lib" ]
|
||||
@@ -259,9 +199,6 @@ stdenv.mkDerivation rec {
|
||||
ln -s ${base}/share/applications $out/share/applications
|
||||
ln -s ${base}/share/icons $out/share/icons
|
||||
ln -s ${base}/share/mime $out/share/mime
|
||||
'' + optionalString (stable) ''
|
||||
ln -s ${base}/share/appdata $out/share/appdata
|
||||
'' + optionalString (!stable) ''
|
||||
ln -s ${base}/share/metainfo $out/share/metainfo
|
||||
'';
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
{ lib, stdenv
|
||||
, cmake
|
||||
, gettext
|
||||
, src
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
inherit src;
|
||||
|
||||
pname = "kicad-i18n";
|
||||
version = builtins.substring 0 10 src.rev;
|
||||
|
||||
nativeBuildInputs = [ cmake gettext ];
|
||||
meta = with lib; {
|
||||
license = licenses.gpl2; # https://github.com/KiCad/kicad-i18n/issues/3
|
||||
platforms = platforms.all;
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p coreutils git nix curl
|
||||
# shellcheck shell=bash enable=all
|
||||
|
||||
set -e
|
||||
shopt -s inherit_errexit
|
||||
|
||||
# this script will generate versions.nix in the right location
|
||||
# this should contain the versions' revs and hashes
|
||||
@@ -25,10 +27,12 @@ export TMPDIR=/tmp
|
||||
# remove items left in /nix/store?
|
||||
|
||||
# get the latest tag that isn't an RC or *.99
|
||||
latest_tag="$(git ls-remote --tags --sort -version:refname \
|
||||
https://gitlab.com/kicad/code/kicad.git \
|
||||
| grep -o 'refs/tags/[0-9]*\.[0-9]*\.[0-9]*$' \
|
||||
| grep -v ".99" | head -n 1 | cut -d '/' -f 3)"
|
||||
latest_tags="$(git ls-remote --tags --sort -version:refname https://gitlab.com/kicad/code/kicad.git)"
|
||||
# using a scratch variable to ensure command failures get caught (SC2312)
|
||||
scratch="$(grep -o 'refs/tags/[0-9]*\.[0-9]*\.[0-9]*$' <<< "${latest_tags}")"
|
||||
scratch="$(grep -ve '\.99' -e '\.9\.9' <<< "${scratch}")"
|
||||
scratch="$(head -n 1 <<< "${scratch}")"
|
||||
latest_tag="$(cut -d '/' -f 3 <<< "${scratch}")"
|
||||
|
||||
all_versions=( "${latest_tag}" master )
|
||||
|
||||
@@ -60,15 +64,15 @@ tmp="${here}/,versions.nix.${RANDOM}"
|
||||
|
||||
libs=( symbols templates footprints packages3d )
|
||||
|
||||
get_rev="git ls-remote --heads --tags"
|
||||
get_rev() {
|
||||
git ls-remote --heads --tags "$@"
|
||||
}
|
||||
|
||||
gitlab="https://gitlab.com/kicad"
|
||||
# append commit hash or tag
|
||||
gitlab_pre="https://gitlab.com/api/v4/projects/kicad%2Fcode%2Fkicad/repository/archive.tar.gz?sha="
|
||||
|
||||
# not a lib, but separate and already moved to gitlab
|
||||
i18n="${gitlab}/code/kicad-i18n.git"
|
||||
i18n_pre="https://gitlab.com/api/v4/projects/kicad%2Fcode%2Fkicad-i18n/repository/archive.tar.gz?sha="
|
||||
src_pre="https://gitlab.com/api/v4/projects/kicad%2Fcode%2Fkicad/repository/archive.tar.gz?sha="
|
||||
lib_pre="https://gitlab.com/api/v4/projects/kicad%2Flibraries%2Fkicad-"
|
||||
lib_mid="/repository/archive.tar.gz?sha="
|
||||
|
||||
count=0
|
||||
|
||||
@@ -108,16 +112,19 @@ for version in "${all_versions[@]}"; do
|
||||
printf "%6ssrc = {\n" ""
|
||||
|
||||
echo "Checking src" >&2
|
||||
src_rev="$(${get_rev} "${gitlab}"/code/kicad.git "${version}" | cut -f1)"
|
||||
scratch="$(get_rev "${gitlab}"/code/kicad.git "${version}")"
|
||||
src_rev="$(cut -f1 <<< "${scratch}")"
|
||||
has_rev="$(grep -sm 1 "\"${pname}\"" -A 4 "${file}" | grep -sm 1 "${src_rev}" || true)"
|
||||
has_hash="$(grep -sm 1 "\"${pname}\"" -A 5 "${file}" | grep -sm 1 "sha256" || true)"
|
||||
|
||||
if [[ -n ${has_rev} && -n ${has_hash} && -z ${clean} ]]; then
|
||||
echo "Reusing old ${pname}.src.sha256, already latest .rev" >&2
|
||||
grep -sm 1 "\"${pname}\"" -A 5 "${file}" | grep -sm 1 "rev" -A 1
|
||||
scratch=$(grep -sm 1 "\"${pname}\"" -A 5 "${file}")
|
||||
grep -sm 1 "rev" -A 1 <<< "${scratch}"
|
||||
else
|
||||
prefetched="$(${prefetch} "${src_pre}${src_rev}")"
|
||||
printf "%8srev =\t\t\t\"%s\";\n" "" "${src_rev}"
|
||||
printf "%8ssha256 =\t\t\"%s\";\n" \
|
||||
"" "$(${prefetch} "${gitlab_pre}${src_rev}")"
|
||||
printf "%8ssha256 =\t\t\"%s\";\n" "" "${prefetched}"
|
||||
count=$((count+1))
|
||||
fi
|
||||
printf "%6s};\n" ""
|
||||
@@ -127,37 +134,26 @@ for version in "${all_versions[@]}"; do
|
||||
printf "%6sversion =\t\t\t\"%s\";\n" "" "${today}"
|
||||
printf "%6slibSources = {\n" ""
|
||||
|
||||
echo "Checking i18n" >&2
|
||||
i18n_rev="$(${get_rev} "${i18n}" "${version}" | cut -f1)"
|
||||
has_rev="$(grep -sm 1 "\"${pname}\"" -A 11 "${file}" | grep -sm 1 "${i18n_rev}" || true)"
|
||||
has_hash="$(grep -sm 1 "\"${pname}\"" -A 12 "${file}" | grep -sm 1 "i18n.sha256" || true)"
|
||||
if [[ -n ${has_rev} && -n ${has_hash} && -z ${clean} ]]; then
|
||||
echo "Reusing old kicad-i18n-${today}.src.sha256, already latest .rev" >&2
|
||||
grep -sm 1 "\"${pname}\"" -A 12 "${file}" | grep -sm 1 "i18n" -A 1
|
||||
else
|
||||
printf "%8si18n.rev =\t\t\"%s\";\n" "" "${i18n_rev}"
|
||||
printf "%8si18n.sha256 =\t\t\"%s\";\n" "" \
|
||||
"$(${prefetch} "${i18n_pre}${i18n_rev}")"
|
||||
count=$((count+1))
|
||||
fi
|
||||
|
||||
for lib in "${libs[@]}"; do
|
||||
echo "Checking ${lib}" >&2
|
||||
url="${gitlab}/libraries/kicad-${lib}.git"
|
||||
lib_rev="$(${get_rev} "${url}" "${version}" | cut -f1 | tail -n1)"
|
||||
scratch="$(get_rev "${url}" "${version}")"
|
||||
scratch="$(cut -f1 <<< "${scratch}")"
|
||||
lib_rev="$(tail -n1 <<< "${scratch}")"
|
||||
has_rev="$(grep -sm 1 "\"${pname}\"" -A 19 "${file}" | grep -sm 1 "${lib_rev}" || true)"
|
||||
has_hash="$(grep -sm 1 "\"${pname}\"" -A 20 "${file}" | grep -sm 1 "${lib}.sha256" || true)"
|
||||
if [[ -n ${has_rev} && -n ${has_hash} && -z ${clean} ]]; then
|
||||
echo "Reusing old kicad-${lib}-${today}.src.sha256, already latest .rev" >&2
|
||||
grep -sm 1 "\"${pname}\"" -A 20 "${file}" | grep -sm 1 "${lib}" -A 1
|
||||
scratch="$(grep -sm 1 "\"${pname}\"" -A 20 "${file}")"
|
||||
grep -sm 1 "${lib}" -A 1 <<< "${scratch}"
|
||||
else
|
||||
prefetched="$(${prefetch} "${lib_pre}${lib}${lib_mid}${lib_rev}")"
|
||||
printf "%8s%s.rev =\t" "" "${lib}"
|
||||
case "${lib}" in
|
||||
symbols|templates) printf "\t" ;; *) ;;
|
||||
esac
|
||||
printf "\"%s\";\n" "${lib_rev}"
|
||||
printf "%8s%s.sha256 =\t\"%s\";\n" "" \
|
||||
"${lib}" "$(${prefetch} "https://gitlab.com/api/v4/projects/kicad%2Flibraries%2Fkicad-${lib}/repository/archive.tar.gz?sha=${lib_rev}")"
|
||||
printf "%8s%s.sha256 =\t\"%s\";\n" "" "${lib}" "${prefetched}"
|
||||
count=$((count+1))
|
||||
fi
|
||||
done
|
||||
@@ -166,7 +162,7 @@ for version in "${all_versions[@]}"; do
|
||||
printf "%2s};\n" ""
|
||||
else
|
||||
printf "\nReusing old %s\n" "${pname}" >&2
|
||||
grep -sm 1 "\"${pname}\"" -A 23 "${file}"
|
||||
grep -sm 1 "\"${pname}\"" -A 21 "${file}"
|
||||
fi
|
||||
done
|
||||
printf "}\n"
|
||||
|
||||
@@ -3,47 +3,43 @@
|
||||
{
|
||||
"kicad" = {
|
||||
kicadVersion = {
|
||||
version = "5.1.12";
|
||||
version = "6.0.0";
|
||||
src = {
|
||||
rev = "84ad8e8a86f13c0697f5cbed8c17977b6545ddc9";
|
||||
sha256 = "0kgikchqxds3mp71nkg307mr4c1dgv8akbmksz4w9x8jg4i1mfqq";
|
||||
rev = "d3dd2cf0fa975548d027db88d19b8a88866866d8";
|
||||
sha256 = "1jrfwyi4zs0rpcpsj01z6687a433nnr56cxbnz12jfg2yafpxk23";
|
||||
};
|
||||
};
|
||||
libVersion = {
|
||||
version = "5.1.12";
|
||||
version = "6.0.0";
|
||||
libSources = {
|
||||
i18n.rev = "0ad3d7e469e31c8868ad83f90e22a9c18f16aa1f";
|
||||
i18n.sha256 = "0y51l0r62cnxkvpc21732p3cx7pjvaqjih8193502hlv9kv1j9p6";
|
||||
symbols.rev = "97c0bfdd2f5ebe952bc90c60f080a8e41da60615";
|
||||
symbols.sha256 = "1zdajim409570xzis53kmrbdcf7000v2vmc90f49h214lrx2zhr2";
|
||||
templates.rev = "eca0f632eb76c8f49de4d5a590c83543090d0b7d";
|
||||
templates.sha256 = "1fbhn1l3j2rwc29aida9b408wif55i23bp9ddcs7dvf83smjm05g";
|
||||
footprints.rev = "b65732f8ebd7ab894fd638f3f2bf4a4e9b24f653";
|
||||
footprints.sha256 = "0qpii55dgv2gxqg1qq0dngdnbb9din790qi5qv0l6qqrzx843h5s";
|
||||
packages3d.rev = "0ddd588650fede09766b704feb15d30bcb6e144f";
|
||||
packages3d.sha256 = "12w7m5nbk9kcnlnlg4sk1sd7xgb9i2kxfi0jcbd0phs89qyl7wjr";
|
||||
symbols.rev = "275f22eb9eecd5b6deabdefd82c9a826254d9f23";
|
||||
symbols.sha256 = "0wjk464l60xknvgc9d870901lqnx296dw7amlh3wg0wf78izarfr";
|
||||
templates.rev = "3a422b5b0928f3fd31579769d4dee2b009a85a11";
|
||||
templates.sha256 = "0vbjy1v5923942ma0rqcp1dhylhxk1m4vyfxjxw13sizkrpmlwr1";
|
||||
footprints.rev = "3ea7895b0817abecaa34276346749a711b0c69f6";
|
||||
footprints.sha256 = "0jv2plwzhhkfx7a2zankkjkbfzjxv43ab8rqpxzqfq2fnx83q6r5";
|
||||
packages3d.rev = "e607286d4a48ddf654585b37b45d74416a9a70c7";
|
||||
packages3d.sha256 = "0vwcbzq42hzjl4f0zjaswmiff1x59hv64g5n00mx1gl0gwngnyla";
|
||||
};
|
||||
};
|
||||
};
|
||||
"kicad-unstable" = {
|
||||
kicadVersion = {
|
||||
version = "6.0.0-rc1";
|
||||
version = "2021-12-23";
|
||||
src = {
|
||||
rev = "9fb05440b3ef3073613ecdeba6112aeb6b26c4df";
|
||||
sha256 = "1j0hd6bpmd80dyvy9mz4n4rr8f849bdwdd4vs8vfbsswf0gxj734";
|
||||
rev = "21eb92821866d558acd9e737b643b300a8b18202";
|
||||
sha256 = "01hg0byp60xzgz0xxfwvyq1hbvbllsys6lx9yfj27d3qjc3bdk42";
|
||||
};
|
||||
};
|
||||
libVersion = {
|
||||
version = "6.0.0-rc1";
|
||||
version = "2021-12-25";
|
||||
libSources = {
|
||||
i18n.rev = "e89d9a89bec59199c1ade56ee2556591412ab7b0";
|
||||
i18n.sha256 = "04zaqyhj3qr4ymyd3k5vjpcna64j8klpsygcgjcv29s3rdi8glfl";
|
||||
symbols.rev = "27b627393a7f2733e965ed82a5533a757789cbb2";
|
||||
symbols.sha256 = "0p1qay6h6ibkhcz1b8xszsihi432ddi8jgnan2xr5rl4539c4ydp";
|
||||
symbols.rev = "125a2e736504e776e4c6fb7f5131efad75edf245";
|
||||
symbols.sha256 = "0wjk464l60xknvgc9d870901lqnx296dw7amlh3wg0wf78izarfr";
|
||||
templates.rev = "8c9ff3dadb9c75cf2932f11c09a46c0c9d84784b";
|
||||
templates.sha256 = "0vbjy1v5923942ma0rqcp1dhylhxk1m4vyfxjxw13sizkrpmlwr1";
|
||||
footprints.rev = "4ce2242095912e491f1690210d9cb2328363b268";
|
||||
footprints.sha256 = "1zx13rrpiamxyv7y27mr5xsdz0d09hpwfgc2j496p3q41q2crlq0";
|
||||
footprints.rev = "ac8de318d8ef7b3eb64c78c6c2650b7b085f3271";
|
||||
footprints.sha256 = "0jv2plwzhhkfx7a2zankkjkbfzjxv43ab8rqpxzqfq2fnx83q6r5";
|
||||
packages3d.rev = "1080b6e565e56bae9be46db2278a1542092d7a2d";
|
||||
packages3d.sha256 = "0vwcbzq42hzjl4f0zjaswmiff1x59hv64g5n00mx1gl0gwngnyla";
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ rec {
|
||||
, go-md2man, go, containerd_1_4, runc, docker-proxy, tini, libtool
|
||||
, sqlite, iproute2, lvm2, systemd, docker-buildx, docker-compose_2
|
||||
, btrfs-progs, iptables, e2fsprogs, xz, util-linux, xfsprogs, git
|
||||
, procps, libseccomp
|
||||
, procps, libseccomp, rootlesskit, slirp4netns, fuse-overlayfs
|
||||
, nixosTests
|
||||
, clientOnly ? !stdenv.isLinux, symlinkJoin
|
||||
}:
|
||||
@@ -77,6 +77,8 @@ rec {
|
||||
|
||||
extraPath = optionals (stdenv.isLinux) (makeBinPath [ iproute2 iptables e2fsprogs xz xfsprogs procps util-linux git ]);
|
||||
|
||||
extraUserPath = optionals (stdenv.isLinux && !clientOnly) (makeBinPath [ rootlesskit slirp4netns fuse-overlayfs ]);
|
||||
|
||||
postPatch = ''
|
||||
patchShebangs hack/make.sh hack/make/
|
||||
'';
|
||||
@@ -109,6 +111,11 @@ rec {
|
||||
install -Dm644 ./contrib/init/systemd/docker.service $out/etc/systemd/system/docker.service
|
||||
substituteInPlace $out/etc/systemd/system/docker.service --replace /usr/bin/dockerd $out/bin/dockerd
|
||||
install -Dm644 ./contrib/init/systemd/docker.socket $out/etc/systemd/system/docker.socket
|
||||
|
||||
# rootless Docker
|
||||
install -Dm755 ./contrib/dockerd-rootless.sh $out/libexec/docker/dockerd-rootless.sh
|
||||
makeWrapper $out/libexec/docker/dockerd-rootless.sh $out/bin/dockerd-rootless \
|
||||
--prefix PATH : "$out/libexec/docker:$extraPath:$extraUserPath"
|
||||
'';
|
||||
|
||||
DOCKER_BUILDTAGS = []
|
||||
@@ -184,6 +191,7 @@ rec {
|
||||
'' + optionalString (!clientOnly) ''
|
||||
# symlink docker daemon to docker cli derivation
|
||||
ln -s ${moby}/bin/dockerd $out/bin/dockerd
|
||||
ln -s ${moby}/bin/dockerd-rootless $out/bin/dockerd-rootless
|
||||
|
||||
# systemd
|
||||
mkdir -p $out/etc/systemd/system
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
buildGraalvmNativeImage rec {
|
||||
pname = "babashka";
|
||||
version = "0.6.8";
|
||||
version = "0.7.0";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://github.com/babashka/${pname}/releases/download/v${version}/${pname}-${version}-standalone.jar";
|
||||
sha256 = "sha256-GIJXXWJZ77n2FBOLKqRSlueo63JMxo0a49dDhneO6oo=";
|
||||
sha256 = "sha256-zSjiHacetJ68U0GciIbuGET9I/51EM8JnPPUGemDfEI=";
|
||||
};
|
||||
|
||||
executable = "bb";
|
||||
|
||||
@@ -2,19 +2,21 @@
|
||||
, buildPythonPackage
|
||||
, fetchPypi
|
||||
, aiohttp
|
||||
, asyncio-throttle
|
||||
}:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "aiohue";
|
||||
version = "3.0.7";
|
||||
version = "3.0.10";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "sha256-Q01giQZytOQ+Ko7kvL0OfdDPysfvtKhW7fYmHmAv5Go=";
|
||||
sha256 = "sha256-LwtE9F5ic0aZ9/q3dSWn20O27yW/QD/Yi1NPdFmiP10=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
aiohttp
|
||||
asyncio-throttle
|
||||
];
|
||||
|
||||
pythonImportsCheck = [
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "aiopvpc";
|
||||
version = "2.2.4";
|
||||
version = "3.0.0";
|
||||
format = "pyproject";
|
||||
|
||||
disabled = pythonOlder "3.8";
|
||||
@@ -24,7 +24,7 @@ buildPythonPackage rec {
|
||||
owner = "azogue";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-39cGDbaBS5we+WbqvABe6tKwTmbgd+NYLssKQCOuBsc=";
|
||||
sha256 = "sha256-eTCQddoZIaCs7iKGNBC8aSq6ek4vwYXgIXx35UlME/k=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "bimmer-connected";
|
||||
version = "0.8.5";
|
||||
version = "0.8.7";
|
||||
format = "setuptools";
|
||||
|
||||
disabled = pythonOlder "3.6";
|
||||
@@ -22,7 +22,7 @@ buildPythonPackage rec {
|
||||
owner = "bimmerconnected";
|
||||
repo = "bimmer_connected";
|
||||
rev = version;
|
||||
hash = "sha256-twVI84YCW+t9ar2vHN1OEiY5tT4/pHP29GnpWprdeHs=";
|
||||
hash = "sha256-nLZdaV341mULXIngkEqiLQeg4G2NDFGNg/AUozgJe74=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
, pythonOlder
|
||||
, icalendar
|
||||
, lxml
|
||||
, mock
|
||||
, nose
|
||||
, pytz
|
||||
, requests
|
||||
@@ -15,23 +14,27 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "caldav";
|
||||
version = "0.8.0";
|
||||
version = "0.8.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "python-caldav";
|
||||
repo = pname;
|
||||
rev = "v${version}";
|
||||
sha256 = "11q3svns3a2ywfci739krxbh67cx691qja772wq22606blyygyjy";
|
||||
hash = "sha256-2mpE1aLipps4X/3EF0oKHXDcrgUh78/fxY6y1B1V2IU=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = lib.optionals (pythonOlder "3.5") [ mock ];
|
||||
propagatedBuildInputs = [ six requests vobject lxml ]
|
||||
++ lib.optionals (pythonOlder "3.6") [ pytz tzlocal ];
|
||||
propagatedBuildInputs = [
|
||||
vobject
|
||||
lxml
|
||||
requests
|
||||
six
|
||||
];
|
||||
|
||||
checkInputs = [
|
||||
icalendar
|
||||
nose
|
||||
tzlocal
|
||||
pytz
|
||||
];
|
||||
|
||||
checkPhase = ''
|
||||
@@ -41,7 +44,7 @@ buildPythonPackage rec {
|
||||
# xandikos and radicale is only a optional test dependency, not available for python3
|
||||
postPatch = ''
|
||||
substituteInPlace setup.py \
|
||||
--replace ", 'xandikos'" "" \
|
||||
--replace ", 'xandikos<0.2.4'" "" \
|
||||
--replace ", 'radicale'" ""
|
||||
'';
|
||||
|
||||
@@ -51,7 +54,6 @@ buildPythonPackage rec {
|
||||
description = "This project is a CalDAV (RFC4791) client library for Python.";
|
||||
homepage = "https://github.com/python-caldav/caldav";
|
||||
license = licenses.asl20;
|
||||
maintainers = with maintainers; [ marenz ];
|
||||
#broken = true; # requires radicale which is not packaged yet
|
||||
maintainers = with maintainers; [ marenz dotlambda ];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "deep-translator";
|
||||
version = "1.5.5";
|
||||
version = "1.6.0";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "sha256-XARhzRsquvKcdhPcooGIEmhGN7QJOCubcvOrZB0nhxU=";
|
||||
sha256 = "sha256-B/SnLSaCRVhQvSU2hmdKPswM2N73nHAzQfVNBMgCofI=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "django_compressor";
|
||||
version = "2.4.1";
|
||||
version = "3.1";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "3358077605c146fdcca5f9eaffb50aa5dbe15f238f8854679115ebf31c0415e0";
|
||||
sha256 = "c4a87bf65f9a534cfaf1c321a000a229c24e50c6d62ba6ab089482db42e819d9";
|
||||
};
|
||||
postPatch = ''
|
||||
substituteInPlace setup.py \
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "faraday-plugins";
|
||||
version = "1.5.8";
|
||||
version = "1.5.9";
|
||||
format = "setuptools";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "infobyte";
|
||||
repo = "faraday_plugins";
|
||||
rev = "v${version}";
|
||||
sha256 = "1r415g2f0cid8nr3y27ipx9hvwzh70l5wp0d7nv25qblc7g38mms";
|
||||
sha256 = "sha256-rU7BF1lXLgJYLed5FVKXroivxKpmmNE5woGCpAcKAwg=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "flux-led";
|
||||
version = "0.27.13";
|
||||
version = "0.27.19";
|
||||
format = "setuptools";
|
||||
|
||||
disabled = pythonOlder "3.7";
|
||||
@@ -17,7 +17,7 @@ buildPythonPackage rec {
|
||||
owner = "Danielhiversen";
|
||||
repo = "flux_led";
|
||||
rev = version;
|
||||
sha256 = "sha256-lOfEEMHuhTfti7NYeZpXc+jeYQMJd/EnvT1oHByaCbw=";
|
||||
sha256 = "sha256-QJCRBwsfQQzXQ7DDvzb9NKnZS2LqrQUygdzJ+ccjWt4=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "isodate";
|
||||
version = "0.6.0";
|
||||
version = "0.6.1";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "2e364a3d5759479cdb2d37cce6b9376ea504db2ff90252a2e5b7cc89cc9ff2d8";
|
||||
sha256 = "SMWIHefosKDWSMsCTIBi3ITnuEDtgehkx2FP08Envek=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ six ];
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "jupyterlab";
|
||||
version = "3.2.4";
|
||||
version = "3.2.5";
|
||||
disabled = pythonOlder "3.5";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "f692e0d95338d60f72dde660f16f3955a087775c59ec541ddb25952e3f97e9b1";
|
||||
sha256 = "31b28f473b0f5826d2020583973c385526f0559b5b26efac6b8035ac1562874a";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ jupyter-packaging ];
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
{ lib
|
||||
, buildPythonPackage
|
||||
, fetchPypi
|
||||
, pythonOlder
|
||||
, h5py
|
||||
, nibabel
|
||||
, numpy
|
||||
, setuptools-scm
|
||||
, toml
|
||||
}:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "nitransforms";
|
||||
version = "21.0.0";
|
||||
disabled = pythonOlder "3.7";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "njJqHqXVxldyGfmdM8GmgKdgIT4kMYLzcM5+ayR2EDo=";
|
||||
};
|
||||
|
||||
buildInputs = [ setuptools-scm toml ];
|
||||
propagatedBuildInputs = [ h5py nibabel numpy ];
|
||||
|
||||
doCheck = false;
|
||||
# relies on data repo (https://github.com/nipreps-data/nitransforms-tests);
|
||||
# probably too heavy
|
||||
pythonImportsCheck = [
|
||||
"nitransforms"
|
||||
"nitransforms.base"
|
||||
"nitransforms.io"
|
||||
"nitransforms.io.base"
|
||||
"nitransforms.linear"
|
||||
"nitransforms.manip"
|
||||
"nitransforms.nonlinear"
|
||||
"nitransforms.patched"
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
homepage = "https://nitransforms.readthedocs.io";
|
||||
description = "Geometric transformations for images and surfaces";
|
||||
license = licenses.mit;
|
||||
maintainers = with maintainers; [ bcdarwin ];
|
||||
};
|
||||
}
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "ocrmypdf";
|
||||
version = "13.1.1";
|
||||
version = "13.2.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "jbarlow83";
|
||||
@@ -39,7 +39,7 @@ buildPythonPackage rec {
|
||||
extraPostFetch = ''
|
||||
rm "$out/.git_archival.txt"
|
||||
'';
|
||||
sha256 = "sha256-NIh7eTsXQPNhrNWrTMFG7v4SFsicj1B4szEXcp5fXB4=";
|
||||
sha256 = "sha256-mVPKcxTKoRgttwJdsY7r0kF7W1+G45iCc+mFctDipSM=";
|
||||
};
|
||||
|
||||
SETUPTOOLS_SCM_PRETEND_VERSION = version;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "openai";
|
||||
version = "0.11.4";
|
||||
version = "0.11.5";
|
||||
|
||||
disabled = pythonOlder "3.7.1";
|
||||
|
||||
@@ -26,7 +26,7 @@ buildPythonPackage rec {
|
||||
owner = "openai";
|
||||
repo = "openai-python";
|
||||
rev = "v${version}";
|
||||
sha256 = "O2O4+GkyMyAxJqMNgiyPKoSXeJk0HGAst02QV6c9mJs=";
|
||||
sha256 = "sha256-6eL3/vDWyIOVjRQo4OO3OgyUG3t8dKPtxzMMTxPCglM=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
|
||||
@@ -17,7 +17,7 @@ let
|
||||
in
|
||||
buildPythonPackage rec {
|
||||
pname = "panel";
|
||||
version = "0.12.5";
|
||||
version = "0.12.6";
|
||||
|
||||
# Don't forget to also update the node packages
|
||||
# 1. retrieve the package.json file
|
||||
@@ -25,7 +25,7 @@ buildPythonPackage rec {
|
||||
# 3. node2nix
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "351481f2a2176359b28effa64c9d9fce487d6758514109cab96f9ed84787ae99";
|
||||
sha256 = "97e158e8eb941f88d71929407f9455c903b5e18d89969db8ce8af66036f46b53";
|
||||
};
|
||||
|
||||
# Since 0.10.0 panel attempts to fetch from the web.
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "phonenumbers";
|
||||
version = "8.12.39";
|
||||
version = "8.12.40";
|
||||
format = "setuptools";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "0f7745e1f108654db347d885e814cbb5f225b8c5f5ce336024b193c79291ddaa";
|
||||
sha256 = "00f2955a456b458f9b6ab0d24329049c3e7358c44dfc1979fe4908ced40f1eb8";
|
||||
};
|
||||
|
||||
checkInputs = [
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "pycarwings2";
|
||||
version = "2.12";
|
||||
version = "2.13";
|
||||
format = "setuptools";
|
||||
|
||||
disabled = pythonOlder "3.5";
|
||||
@@ -20,8 +20,8 @@ buildPythonPackage rec {
|
||||
owner = "filcole";
|
||||
repo = pname;
|
||||
# release not tagged: https://github.com/filcole/pycarwings2/issues/33
|
||||
rev = "0dc9e7e74cb119614c72c7f955801a366f303c56";
|
||||
sha256 = "sha256-3lyAgLuaNrCDvRT2yYkgaDiLPKW9Hbg05cQlMIBUs6o=";
|
||||
rev = "v${version}";
|
||||
sha256 = "04k1la7wix6sp668nqpwdhd3057b2bzcz7h2b9a57cxlifl8pjxf";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "pytile";
|
||||
version = "2021.10.0";
|
||||
version = "2021.12.0";
|
||||
format = "pyproject";
|
||||
|
||||
disabled = pythonOlder "3.7";
|
||||
@@ -22,7 +22,7 @@ buildPythonPackage rec {
|
||||
owner = "bachya";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
sha256 = "sha256-9FbcGhRmXULJgfJOmy6mhiZwQUDNmvxZI/WxjJIbnc8=";
|
||||
sha256 = "sha256-a76Qzk8ZsoV6HUOcDjMdnFVZJu/iKFbShoC9OZ0caDc=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "snowflake-connector-python";
|
||||
version = "2.7.1";
|
||||
version = "2.7.2";
|
||||
disabled = pythonOlder "3.6";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "81175ff9fe0355a7e9007a087458dddc0816985ec10dc122e690de03549afbff";
|
||||
sha256 = "b2f8f360750eefa98be09ff53c130381646f8dfc8c6e4a705387676210ff8578";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "stripe";
|
||||
version = "2.63.0";
|
||||
version = "2.64.0";
|
||||
|
||||
src = fetchPypi {
|
||||
inherit pname version;
|
||||
sha256 = "816c935e31d82737a9e4362c662e8702bdf9000ea1bd36882cd4cbd23eb81ae1";
|
||||
sha256 = "2f4b2175046104e4fcd8a2689a68bb9828a857814126d2ed13772cf2554fb93e";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ requests ];
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "xknx";
|
||||
version = "0.18.14";
|
||||
version = "0.18.15";
|
||||
format = "setuptools";
|
||||
|
||||
disabled = pythonOlder "3.8";
|
||||
@@ -20,7 +20,7 @@ buildPythonPackage rec {
|
||||
owner = "XKNX";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
sha256 = "sha256-PWBUG9sa9530cfXqpJ+0UVxOx+FxNfz4ZLazpUILvww=";
|
||||
sha256 = "sha256-k/fLUuBjXScTvlvoBLZIVPEqNGIPI04FBeTBadp5uiY=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [
|
||||
|
||||
@@ -1,34 +1,53 @@
|
||||
{ lib, buildPythonPackage, fetchFromGitHub, pytestCheckHook, pytest-xdist
|
||||
, pythonOlder, click, ruyaml }:
|
||||
{ lib
|
||||
, buildPythonPackage
|
||||
, click
|
||||
, fetchFromGitHub
|
||||
, pytest-xdist
|
||||
, pytestCheckHook
|
||||
, pythonOlder
|
||||
, ruyaml
|
||||
}:
|
||||
|
||||
buildPythonPackage rec {
|
||||
pname = "yamlfix";
|
||||
version = "0.7.2";
|
||||
version = "0.8.0";
|
||||
format = "setuptools";
|
||||
|
||||
disabled = pythonOlder "3.7";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "lyz-code";
|
||||
repo = pname;
|
||||
rev = version;
|
||||
sha256 = "sha256-qlA6TyLkOuTXCdMnpfkyN/HDIRfB6+0pQ7f0GCsIjL4=";
|
||||
sha256 = "sha256-Gkq80YMeiPy7xxLauA/nloW4znMV2tfE+e24HyZgUaQ=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = [ click ruyaml ];
|
||||
propagatedBuildInputs = [
|
||||
click
|
||||
ruyaml
|
||||
];
|
||||
|
||||
checkInputs = [ pytestCheckHook pytest-xdist ];
|
||||
checkInputs = [
|
||||
pytest-xdist
|
||||
pytestCheckHook
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
substituteInPlace pyproject.toml \
|
||||
--replace 'python_paths = "."' ""
|
||||
'';
|
||||
|
||||
pytestFlagsArray = [ "-n" "$NIX_BUILD_CORES" ];
|
||||
pytestFlagsArray = [
|
||||
"-n"
|
||||
"$NIX_BUILD_CORES"
|
||||
];
|
||||
|
||||
pythonImportsCheck = [ "yamlfix" ];
|
||||
pythonImportsCheck = [
|
||||
"yamlfix"
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
description =
|
||||
"A simple opinionated yaml formatter that keeps your comments!";
|
||||
description = "Python YAML formatter that keeps your comments";
|
||||
homepage = "https://github.com/lyz-code/yamlfix";
|
||||
license = licenses.gpl3Plus;
|
||||
maintainers = with maintainers; [ koozz ];
|
||||
|
||||
@@ -3,21 +3,23 @@
|
||||
, fetchFromGitHub
|
||||
, cmake
|
||||
, wrapQtAppsHook
|
||||
, SDL2
|
||||
, qtbase
|
||||
, qtmultimedia
|
||||
, boost17x
|
||||
, libpulseaudio
|
||||
, pkg-config
|
||||
, libusb1
|
||||
, zstd
|
||||
, libressl
|
||||
, alsa-lib
|
||||
, rapidjson
|
||||
, aacHleDecoding ? true
|
||||
, fdk_aac
|
||||
, ffmpeg-full
|
||||
, enableSdl2 ? true, SDL2
|
||||
, enableQt ? true, qtbase, qtmultimedia
|
||||
, enableQtTranslation ? enableQt, qttools
|
||||
, enableWebService ? true
|
||||
, enableCubeb ? true, libpulseaudio
|
||||
, enableFfmpegAudioDecoder ? true
|
||||
, enableFfmpegVideoDumper ? true
|
||||
, ffmpeg
|
||||
, useDiscordRichPresence ? true, rapidjson
|
||||
, enableFdk ? false, fdk_aac
|
||||
}:
|
||||
assert lib.assertMsg (!enableFfmpegAudioDecoder || !enableFdk) "Can't enable both enableFfmpegAudioDecoder and enableFdk";
|
||||
|
||||
stdenv.mkDerivation {
|
||||
pname = "citra";
|
||||
@@ -31,36 +33,43 @@ stdenv.mkDerivation {
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ cmake wrapQtAppsHook pkg-config ];
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
pkg-config
|
||||
]
|
||||
++ lib.optionals enableQt [ wrapQtAppsHook ];
|
||||
|
||||
buildInputs = [
|
||||
SDL2
|
||||
qtbase
|
||||
qtmultimedia
|
||||
libpulseaudio
|
||||
boost17x
|
||||
libusb1
|
||||
alsa-lib
|
||||
rapidjson # for discord-rpc
|
||||
] ++ lib.optional aacHleDecoding [ fdk_aac ffmpeg-full ];
|
||||
]
|
||||
++ lib.optionals enableSdl2 [ SDL2 ]
|
||||
++ lib.optionals enableQt [ qtbase qtmultimedia ]
|
||||
++ lib.optionals enableQtTranslation [ qttools ]
|
||||
++ lib.optionals enableCubeb [ libpulseaudio ]
|
||||
++ lib.optionals (enableFfmpegAudioDecoder || enableFfmpegVideoDumper) [ ffmpeg ]
|
||||
++ lib.optionals useDiscordRichPresence [ rapidjson ]
|
||||
++ lib.optionals enableFdk [ fdk_aac ];
|
||||
|
||||
cmakeFlags = [
|
||||
"-DUSE_SYSTEM_BOOST=ON"
|
||||
"-DUSE_DISCORD_PRESENCE=ON"
|
||||
] ++ lib.optionals aacHleDecoding [
|
||||
"-DENABLE_FFMPEG_AUDIO_DECODER=ON"
|
||||
"-DCITRA_USE_BUNDLED_FFMPEG=OFF"
|
||||
];
|
||||
]
|
||||
++ lib.optionals (!enableSdl2) [ "-DENABLE_SDL2=OFF" ]
|
||||
++ lib.optionals (!enableQt) [ "-DENABLE_QT=OFF" ]
|
||||
++ lib.optionals enableQtTranslation [ "-DENABLE_QT_TRANSLATION=ON" ]
|
||||
++ lib.optionals (!enableWebService) [ "-DENABLE_WEB_SERVICE=OFF" ]
|
||||
++ lib.optionals (!enableCubeb) [ "-DENABLE_CUBEB=OFF" ]
|
||||
++ lib.optionals enableFfmpegAudioDecoder [ "-DENABLE_FFMPEG_AUDIO_DECODER=ON"]
|
||||
++ lib.optionals enableFfmpegVideoDumper [ "-DENABLE_FFMPEG_VIDEO_DUMPER=ON" ]
|
||||
++ lib.optionals useDiscordRichPresence [ "-DUSE_DISCORD_PRESENCE=ON" ]
|
||||
++ lib.optionals enableFdk [ "-DENABLE_FDK=ON" ];
|
||||
|
||||
postPatch = ''
|
||||
# we already know the submodules are present
|
||||
# We already know the submodules are present
|
||||
substituteInPlace CMakeLists.txt \
|
||||
--replace "check_submodules_present()" ""
|
||||
|
||||
# Trick configure system.
|
||||
sed -n 's,^ *path = \(.*\),\1,p' .gitmodules | while read path; do
|
||||
mkdir "$path/.git"
|
||||
done
|
||||
|
||||
# Devendoring
|
||||
rm -rf externals/zstd externals/libressl
|
||||
cp -r ${zstd.src} externals/zstd
|
||||
tar xf ${libressl.src} -C externals/
|
||||
@@ -69,6 +78,7 @@ stdenv.mkDerivation {
|
||||
'';
|
||||
|
||||
# Todo: cubeb audio backend (the default one) doesn't work on the SDL interface.
|
||||
# This seems to be a problem with libpulseaudio, other applications have similar problems (e.g Duckstation).
|
||||
# Note that the two interfaces have two separate configuration files.
|
||||
|
||||
meta = with lib; {
|
||||
|
||||
@@ -2818,6 +2818,18 @@ final: prev:
|
||||
meta.homepage = "https://github.com/JuliaEditorSupport/julia-vim/";
|
||||
};
|
||||
|
||||
kanagawa-nvim = buildVimPluginFrom2Nix {
|
||||
pname = "kanagawa.nvim";
|
||||
version = "2021-12-25";
|
||||
src = fetchFromGitHub {
|
||||
owner = "rebelot";
|
||||
repo = "kanagawa.nvim";
|
||||
rev = "10bccb5e8e8530725c8059df2e6852fb01842d1c";
|
||||
sha256 = "15jji03qvpbyfk1bpc9b31rbkklfzdnhmnld4cr5ydjmz1fd5fzb";
|
||||
};
|
||||
meta.homepage = "https://github.com/rebelot/kanagawa.nvim/";
|
||||
};
|
||||
|
||||
kommentary = buildVimPluginFrom2Nix {
|
||||
pname = "kommentary";
|
||||
version = "2021-12-03";
|
||||
|
||||
@@ -642,6 +642,7 @@ rbong/vim-flog
|
||||
rcarriga/nvim-dap-ui
|
||||
rcarriga/nvim-notify
|
||||
rcarriga/vim-ultest
|
||||
rebelot/kanagawa.nvim
|
||||
rhysd/clever-f.vim
|
||||
rhysd/committia.vim
|
||||
rhysd/conflict-marker.vim
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
, esbuild
|
||||
, pkg-config
|
||||
, libsecret
|
||||
, stdenv
|
||||
, darwin
|
||||
, setDefaultServerPath ? true
|
||||
}:
|
||||
|
||||
@@ -40,6 +42,9 @@ let
|
||||
jq moreutils esbuild
|
||||
# Required by `keytar`, which is a dependency of `vsce`.
|
||||
pkg-config libsecret
|
||||
] ++ lib.optionals stdenv.isDarwin [
|
||||
darwin.apple_sdk.frameworks.AppKit
|
||||
darwin.apple_sdk.frameworks.Security
|
||||
];
|
||||
|
||||
# Follows https://github.com/rust-analyzer/rust-analyzer/blob/41949748a6123fd6061eb984a47f4fe780525e63/xtask/src/dist.rs#L39-L65
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Do not edit!
|
||||
|
||||
{
|
||||
version = "2021.12.4";
|
||||
version = "2021.12.5";
|
||||
components = {
|
||||
"abode" = ps: with ps; [ abodepy ];
|
||||
"accuweather" = ps: with ps; [ accuweather ];
|
||||
@@ -180,7 +180,7 @@
|
||||
"devolo_home_network" = ps: with ps; [ devolo-plc-api ];
|
||||
"dexcom" = ps: with ps; [ pydexcom ];
|
||||
"dhcp" = ps: with ps; [ aiodiscover scapy ];
|
||||
"dht" = ps: with ps; [ ]; # missing inputs: adafruit-circuitpython-dht
|
||||
"dht" = ps: with ps; [ ]; # missing inputs: RPi.GPIO adafruit-circuitpython-dht
|
||||
"dialogflow" = ps: with ps; [ aiohttp-cors ];
|
||||
"digital_ocean" = ps: with ps; [ digital-ocean ];
|
||||
"digitalloggers" = ps: with ps; [ ]; # missing inputs: dlipower
|
||||
@@ -706,7 +706,7 @@
|
||||
"remote" = ps: with ps; [ ];
|
||||
"remote_rpi_gpio" = ps: with ps; [ ]; # missing inputs: gpiozero
|
||||
"renault" = ps: with ps; [ renault-api ];
|
||||
"repetier" = ps: with ps; [ ]; # missing inputs: pyrepetier
|
||||
"repetier" = ps: with ps; [ ]; # missing inputs: pyrepetierng
|
||||
"rest" = ps: with ps; [ jsonpath xmltodict ];
|
||||
"rest_command" = ps: with ps; [ ];
|
||||
"rflink" = ps: with ps; [ rflink ];
|
||||
|
||||
@@ -219,6 +219,19 @@ let
|
||||
});
|
||||
})
|
||||
|
||||
# Remove with 2021.12.6 as the requirement will be 1.1.16 (at least)
|
||||
(self: super: {
|
||||
yalexs = super.yalexs.overridePythonAttrs (oldAttrs: rec {
|
||||
version = "1.1.13";
|
||||
src = fetchFromGitHub {
|
||||
owner = "bdraco";
|
||||
repo = "yalexs";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-lnx8+VyDyO7Wg+QW+CC0FUg77Ndfjar6PLsDYwEpaCQ=";
|
||||
};
|
||||
});
|
||||
})
|
||||
|
||||
# home-assistant-frontend does not exist in python3.pkgs
|
||||
(self: super: {
|
||||
home-assistant-frontend = self.callPackage ./frontend.nix { };
|
||||
@@ -252,7 +265,7 @@ let
|
||||
extraBuildInputs = extraPackages py.pkgs;
|
||||
|
||||
# Don't forget to run parse-requirements.py after updating
|
||||
hassVersion = "2021.12.4";
|
||||
hassVersion = "2021.12.5";
|
||||
|
||||
in with py.pkgs; buildPythonApplication rec {
|
||||
pname = "homeassistant";
|
||||
@@ -269,7 +282,7 @@ in with py.pkgs; buildPythonApplication rec {
|
||||
owner = "home-assistant";
|
||||
repo = "core";
|
||||
rev = version;
|
||||
hash = "sha256:NZPv6Zyy9brdArRsyGA6EMkYEY1wCf6osjek4lEsr1c=";
|
||||
hash = "sha256:116qklmzvqh3hn3i6i7lvsnqydd2qclk612rwlxs3v56kzpks62n";
|
||||
};
|
||||
|
||||
# leave this in, so users don't have to constantly update their downstream patch handling
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "radicale";
|
||||
version = "3.0.6";
|
||||
version = "3.1.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Kozea";
|
||||
repo = "Radicale";
|
||||
rev = version;
|
||||
sha256 = "1xlsvrmx6jhi71j6j8z9sli5vwxasivzjyqf8zq8r0l5p7350clf";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-LtPv+3FQMGC2YP2+1cSPZVUIzrUhteJTl58+JdvGcQg=";
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
, icu66
|
||||
, krb5
|
||||
, lib
|
||||
, libtasn1
|
||||
, makeWrapper
|
||||
, stdenv
|
||||
, openssl
|
||||
}:
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "roon-server";
|
||||
version = "1.8-850";
|
||||
version = "1.8-880";
|
||||
|
||||
src =
|
||||
let
|
||||
@@ -22,13 +23,17 @@ stdenv.mkDerivation rec {
|
||||
in
|
||||
fetchurl {
|
||||
url = "http://download.roonlabs.com/builds/RoonServer_linuxx64_${urlVersion}.tar.bz2";
|
||||
sha256 = "sha256-NSNaL0ERYTSYn9ETjWcQiuI4hY+w/lWVOz3n9lt6O+4=";
|
||||
sha256 = "sha256-Td3iRYGmTg8Vx9c4e4ugIIbAqhDFPax9vR2BsCIQCZA=";
|
||||
};
|
||||
|
||||
dontConfigure = true;
|
||||
dontBuild = true;
|
||||
|
||||
buildInputs = [
|
||||
alsa-lib
|
||||
freetype
|
||||
krb5
|
||||
libtasn1
|
||||
stdenv.cc.cc.lib
|
||||
];
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
}@args:
|
||||
|
||||
let
|
||||
version = "2.8.0.beta9";
|
||||
version = "2.8.0.beta10";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse";
|
||||
rev = "v${version}";
|
||||
sha256 = "sha256-cTedMbf0N50ysRQqA9Fm1WQmI5J5hsqDSi2JZIa49jg=";
|
||||
sha256 = "sha256-mlTOsHR8p0mTdhZHBESyDAa1XtMJ4uIht0VUcGD6Ses=";
|
||||
};
|
||||
|
||||
runtimeDeps = [
|
||||
@@ -313,7 +313,11 @@ let
|
||||
enabledPlugins = plugins;
|
||||
plugins = callPackage ./plugins/all-plugins.nix { inherit mkDiscoursePlugin; };
|
||||
ruby = rubyEnv.wrappedRuby;
|
||||
tests = import ../../../../nixos/tests/discourse.nix { package = pkgs.discourse.override args; };
|
||||
tests = import ../../../../nixos/tests/discourse.nix {
|
||||
inherit (stdenv) system;
|
||||
inherit pkgs;
|
||||
package = pkgs.discourse.override args;
|
||||
};
|
||||
};
|
||||
};
|
||||
in discourse
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-assign";
|
||||
rev = "91d0712b0440b6bb0c2fedbf6c31191cdeb991fe";
|
||||
sha256 = "sha256-ATWLu0vJZFquRcAUpFKaU8mqjjVOv3PziAsHR3aemWk=";
|
||||
rev = "920503f5fc2cbec1b3ba4d431cffda2281e12509";
|
||||
sha256 = "sha256-qMUlJwETu99Qmbh4sn/1Vn7Xgaj3Jhi+/E8ecIbnVH8=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-docs";
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (6.1.4.1)
|
||||
activesupport (7.0.0)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
tzinfo (~> 2.0)
|
||||
zeitwerk (~> 2.3)
|
||||
concurrent-ruby (1.1.9)
|
||||
i18n (1.8.11)
|
||||
concurrent-ruby (~> 1.0)
|
||||
minitest (5.14.4)
|
||||
minitest (5.15.0)
|
||||
rrule (0.4.2)
|
||||
activesupport (>= 4.1)
|
||||
tzinfo (2.0.4)
|
||||
concurrent-ruby (~> 1.0)
|
||||
zeitwerk (2.5.1)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
@@ -6,8 +6,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-calendar";
|
||||
rev = "fbc617a5fa9f3a22bcc72bc2b32ea3cbdf6087c5";
|
||||
sha256 = "sha256-qBtq8IvxdKYIFNL9DwdRqZceMMO/qgd6jTr3kk3so3Y=";
|
||||
rev = "9c5516ff039225be04b1302c5c67837ce64fba9c";
|
||||
sha256 = "sha256-tfQWhkQvHrIUl0+tIv8X65MvoUhUnKD7KHwQbBm3p7U=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-calendar";
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
activesupport = {
|
||||
dependencies = ["concurrent-ruby" "i18n" "minitest" "tzinfo" "zeitwerk"];
|
||||
dependencies = ["concurrent-ruby" "i18n" "minitest" "tzinfo"];
|
||||
groups = ["default"];
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "19gx1jcq46x9d1pi1w8xq0bgvvfw239y4lalr8asm291gj3q3ds4";
|
||||
sha256 = "04bsr3420wb8y5pagg3s0rkx44fix47wrjvfby2d205l9bq6azyk";
|
||||
type = "gem";
|
||||
};
|
||||
version = "6.1.4.1";
|
||||
version = "7.0.0";
|
||||
};
|
||||
concurrent-ruby = {
|
||||
groups = ["default"];
|
||||
@@ -36,10 +36,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "19z7wkhg59y8abginfrm2wzplz7py3va8fyngiigngqvsws6cwgl";
|
||||
sha256 = "06xf558gid4w8lwx13jwfdafsch9maz8m0g85wnfymqj63x5nbbd";
|
||||
type = "gem";
|
||||
};
|
||||
version = "5.14.4";
|
||||
version = "5.15.0";
|
||||
};
|
||||
rrule = {
|
||||
dependencies = ["activesupport"];
|
||||
@@ -63,14 +63,4 @@
|
||||
};
|
||||
version = "2.0.4";
|
||||
};
|
||||
zeitwerk = {
|
||||
groups = ["default"];
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "18l4r6layck0d80ydc692mv1lxak5xbf6w2paj1x7m2ggbggzxgj";
|
||||
type = "gem";
|
||||
};
|
||||
version = "2.5.1";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-canned-replies";
|
||||
rev = "1bb77ebbe0577f257bc16783dc8b7bbf2d915092";
|
||||
sha256 = "0qvx8k9jsxjllqsqpf4k0j4niv1k2sggy6ak067wigs8ha3dkcr0";
|
||||
rev = "dbbb8740287e44b5e9f0d8c968e3d237154e1f3c";
|
||||
sha256 = "sha256-o4yZaXiQpt7Bb29kVKJOiIdNgcSEOnSiFAIhZtiX6ys=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-canned-replies";
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-chat-integration";
|
||||
rev = "ae0389ca89f26401a6c4cffaaae6adcf14af0e15";
|
||||
sha256 = "sha256-wT9S2mMz2MOpWpYv/FrHYhZibStRIGC4P2Vrqs04bkA=";
|
||||
rev = "46b2c05cbd00dbc49bff87d78f8e1ec4fdd43735";
|
||||
sha256 = "sha256-G17obAc03FR3Qzn/IR++Y5Z1TkpP6lY5UDJsm4Lmj0M=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-chat-integration";
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-checklist";
|
||||
rev = "d8012abd3d6dccb72eec83e6a96ef4809dcad681";
|
||||
sha256 = "1ngjql65939c571gyaqj8ydcxy5kkril2qlkxqf579vvwzpvxw13";
|
||||
rev = "b4e14bdac40131bd70a698015b35a111a18c9f88";
|
||||
sha256 = "sha256-okxcLu6gXvEY37ylnhit5B+LwCdV5gMKBpC/m/PaGtc=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-checklist";
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-data-explorer";
|
||||
rev = "3ce778ec6d96a300a06ffe0581f4681fbed8df7f";
|
||||
sha256 = "1555k1anrijfbm0qfraby3ivh6h76177d541nxhnarj85mjx0hjb";
|
||||
rev = "f77f5999069dbe98c49302566c82e5f77bb72db2";
|
||||
sha256 = "sha256-N9LmFnza1pA3JRBE9bT9b/NhdYMKoF5GOUpq9XYdokY=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-data-explorer";
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-docs";
|
||||
rev = "d3eee7008b7a703774331808e302e36f2f8b4eae";
|
||||
sha256 = "1p3aqfpv207pvlbis43znwgw56yqsn41320yaw1gdcaakf5s2rsx";
|
||||
rev = "e56816eb502b5ea37606f65a8df188e233f77240";
|
||||
sha256 = "sha256-qvuoFsVXKa2IZgjVeqCca7X9jfohEBaoieZRsSFJCto=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-docs";
|
||||
|
||||
@@ -6,8 +6,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-github";
|
||||
rev = "8cd8c0703991c16cb2fa8cb1fd22a9c3849c7ae2";
|
||||
sha256 = "17ga31a10sm3fqjpf40mz7fk62vynyng2a243pia9fjdq9py8slx";
|
||||
rev = "9fae5e365c1330bc25265e3bb2a06d29adb38266";
|
||||
sha256 = "sha256-0HUrhO78XbTr6ygNFT+Uh70n2z9dFpimawh4u8fpNjg=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-github";
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-math";
|
||||
rev = "cacbd04bb239db3c772ff5a37c19fe39d127ff3d";
|
||||
sha256 = "1bhs7wslb4rdf2b6h6klw1mpjf9pjpfpf2zg2mj8vg0acyaqvv9d";
|
||||
rev = "3de98fc75b7d06d06651edc48449b1bb71d2171b";
|
||||
sha256 = "sha256-HDhy6uvfmBxJq9UobLhAUdFcYULFvPZbb5vT1Sg7ung=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-math";
|
||||
|
||||
@@ -6,8 +6,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-openid-connect";
|
||||
rev = "0e1511fcec2bbb26ef08e453920e955d4140df42";
|
||||
sha256 = "02knx3z0ycz83cdarld2hmmpl6f9nkd2snp0qsbk9mjvbfvpfkni";
|
||||
rev = "aa6a628687edc041bd6f46eb2a38e9a71644bdda";
|
||||
sha256 = "sha256-VdaeueESr7X4gB1pW9e//nDLz62GTaZEPyFIvvCfg18=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-openid-connect";
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-prometheus";
|
||||
rev = "08138ae4f89da76dd577781a2116b2ab66f8f547";
|
||||
sha256 = "1x4awgx9fj0a6drsix3mi39ynj56rca3km0fz2xb3g6vxgc7d2z1";
|
||||
rev = "aaaf3eda30e5fc03c880c056c1f2388739569fb0";
|
||||
sha256 = "sha256-8bfjPCcwDjEC7Tu0Jr9VZRpaDlP2nlIOWBH8pUQakxo=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-saved-searches";
|
||||
rev = "b59e0b60afdd5133e60c5cc6169f42f1edd746be";
|
||||
sha256 = "0yhr7gx35q2nshvfxkplplkq73l7sgqlm8r3g1apniqicpk5flqy";
|
||||
rev = "0c14b9080306c2e35abf32f8211076286fdfbd2f";
|
||||
sha256 = "sha256-ahNw2WL5J4qAyUBgpYWTiS4G+QmQa+gloG2Vu67qXR8=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-saved-searches";
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-solved";
|
||||
rev = "40277e50d43e4bdaab99efab44f59f6e33d74740";
|
||||
sha256 = "02n266swdslws8r26xf99l3ghpqd3dryd0qfp7kiqk3ksy8hh5n2";
|
||||
rev = "6f50e2633545e160c01188bdfa9e57adf1d18adc";
|
||||
sha256 = "sha256-+L4GzJrt15vYY29iYxVpPZFYhLygZJK4I5fqvhdI/HI=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-solved";
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-spoiler-alert";
|
||||
rev = "790380d9d321f9368c7a16d8ed87718fc6047bf2";
|
||||
sha256 = "079w4x2wlbsx164wv0zb373r8552wb5fvrb9pqzmrfvy0ybwf328";
|
||||
rev = "f9545afaa557829f8f0c17a856e028a5be7407cf";
|
||||
sha256 = "sha256-VhA7tK+uE2r6E66yn5FbT+Mdp9Ckj92xCF3Q9Wp60T8=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-spoiler-alert";
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-voting";
|
||||
rev = "36a41c2969c1ddfd8980e3f766b730b849726a08";
|
||||
sha256 = "0ns2i8liwpd29kbn44wzx9yb0jfpyz70h0hmrs71hz6fdalzm4ph";
|
||||
rev = "c2d8b9456834796e90f2e13e7d11a08f389531e1";
|
||||
sha256 = "sha256-z6JBsuq4nj1eqfU/xoU4xWcVNphuyr3C3iKO0chcSz4=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-voting";
|
||||
|
||||
@@ -5,8 +5,8 @@ mkDiscoursePlugin {
|
||||
src = fetchFromGitHub {
|
||||
owner = "discourse";
|
||||
repo = "discourse-yearly-review";
|
||||
rev = "683327574ea1a67c9c4182c887d6ba85171ca02b";
|
||||
sha256 = "0y0hvb2ir9254ilpf7mnbn9xvv9anyqj4qwh97cw7jly7n2mga4m";
|
||||
rev = "e42f48a576b753cb1e042e9693af35214333bb0f";
|
||||
sha256 = "sha256-8+pwiQE0Ytva0t80bRDs+7mTZ82fPpmwb7Nk9boPFt8=";
|
||||
};
|
||||
meta = with lib; {
|
||||
homepage = "https://github.com/discourse/discourse-yearly-review";
|
||||
|
||||
@@ -83,7 +83,7 @@ GEM
|
||||
bootsnap (1.9.3)
|
||||
msgpack (~> 1.0)
|
||||
builder (3.2.4)
|
||||
bullet (6.1.5)
|
||||
bullet (7.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11)
|
||||
byebug (11.1.3)
|
||||
@@ -101,7 +101,7 @@ GEM
|
||||
crack (0.4.5)
|
||||
rexml
|
||||
crass (1.0.6)
|
||||
css_parser (1.10.0)
|
||||
css_parser (1.11.0)
|
||||
addressable
|
||||
debug_inspector (1.1.0)
|
||||
diff-lcs (1.4.4)
|
||||
@@ -129,10 +129,10 @@ GEM
|
||||
sprockets (>= 3.3, < 4.1)
|
||||
ember-source (2.18.2)
|
||||
erubi (1.10.0)
|
||||
excon (0.88.0)
|
||||
excon (0.89.0)
|
||||
execjs (2.8.1)
|
||||
exifr (1.3.9)
|
||||
fabrication (2.22.0)
|
||||
fabrication (2.23.1)
|
||||
faker (2.19.0)
|
||||
i18n (>= 1.6, < 2)
|
||||
fakeweb (1.3.0)
|
||||
@@ -157,7 +157,7 @@ GEM
|
||||
faraday-rack (1.0.0)
|
||||
fast_blank (1.0.1)
|
||||
fast_xs (0.8.0)
|
||||
fastimage (2.2.5)
|
||||
fastimage (2.2.6)
|
||||
ffi (1.15.4)
|
||||
fspath (3.1.2)
|
||||
gc_tracer (1.5.1)
|
||||
@@ -198,7 +198,6 @@ GEM
|
||||
jwt (2.3.0)
|
||||
kgio (2.11.4)
|
||||
libv8-node (16.10.0.0)
|
||||
libv8-node (16.10.0.0-aarch64-linux)
|
||||
listen (3.7.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
@@ -211,15 +210,15 @@ GEM
|
||||
logstash-event (1.2.02)
|
||||
logstash-logger (0.26.1)
|
||||
logstash-event (~> 1.2)
|
||||
logster (2.10.0)
|
||||
loofah (2.12.0)
|
||||
logster (2.10.1)
|
||||
loofah (2.13.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
lru_redux (1.1.0)
|
||||
lz4-ruby (0.3.3)
|
||||
maxminddb (0.1.22)
|
||||
memory_profiler (1.0.0)
|
||||
message_bus (3.3.6)
|
||||
message_bus (3.3.8)
|
||||
rack (>= 1.1.3)
|
||||
method_source (1.0.0)
|
||||
mini_mime (1.1.2)
|
||||
@@ -229,9 +228,9 @@ GEM
|
||||
mini_scheduler (0.13.0)
|
||||
sidekiq (>= 4.2.3)
|
||||
mini_sql (1.1.3)
|
||||
mini_suffix (0.3.2)
|
||||
mini_suffix (0.3.3)
|
||||
ffi (~> 1.9)
|
||||
minitest (5.14.4)
|
||||
minitest (5.15.0)
|
||||
mocha (1.13.0)
|
||||
mock_redis (0.29.0)
|
||||
ruby2_keywords
|
||||
@@ -282,7 +281,7 @@ GEM
|
||||
parallel (1.21.0)
|
||||
parallel_tests (3.7.3)
|
||||
parallel
|
||||
parser (3.0.3.1)
|
||||
parser (3.0.3.2)
|
||||
ast (~> 2.4.1)
|
||||
pg (1.2.3)
|
||||
progress (3.6.0)
|
||||
@@ -325,7 +324,7 @@ GEM
|
||||
rake (>= 0.13)
|
||||
thor (~> 1.0)
|
||||
rainbow (3.0.0)
|
||||
raindrops (0.19.2)
|
||||
raindrops (0.20.0)
|
||||
rake (13.0.6)
|
||||
rb-fsevent (0.11.0)
|
||||
rb-inotify (0.10.1)
|
||||
@@ -338,7 +337,7 @@ GEM
|
||||
redis (4.5.1)
|
||||
redis-namespace (1.8.1)
|
||||
redis (>= 3.0.4)
|
||||
regexp_parser (2.1.1)
|
||||
regexp_parser (2.2.0)
|
||||
request_store (1.5.0)
|
||||
rack (>= 1.4)
|
||||
rexml (3.2.5)
|
||||
@@ -388,9 +387,9 @@ GEM
|
||||
rubocop-ast (>= 1.12.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 3.0)
|
||||
rubocop-ast (1.13.0)
|
||||
rubocop-ast (1.15.0)
|
||||
parser (>= 3.0.1.1)
|
||||
rubocop-discourse (2.4.2)
|
||||
rubocop-discourse (2.5.0)
|
||||
rubocop (>= 1.1.0)
|
||||
rubocop-rspec (>= 2.0.0)
|
||||
rubocop-rspec (2.6.0)
|
||||
@@ -432,7 +431,7 @@ GEM
|
||||
sprockets (3.7.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (3.4.1)
|
||||
sprockets-rails (3.4.2)
|
||||
actionpack (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
sprockets (>= 3.0.0)
|
||||
@@ -466,7 +465,6 @@ GEM
|
||||
zeitwerk (2.5.1)
|
||||
|
||||
PLATFORMS
|
||||
aarch64-linux
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
|
||||
@@ -273,10 +273,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "01xachwsyykmp153514vz2khanbsz1n27j09za5gcxj54srh5l4p";
|
||||
sha256 = "0w3jk595azcc9fvklrk2klkljwhgzjhnns7l5iqhnafvr8q60xnr";
|
||||
type = "gem";
|
||||
};
|
||||
version = "6.1.5";
|
||||
version = "7.0.0";
|
||||
};
|
||||
byebug = {
|
||||
groups = ["development" "test"];
|
||||
@@ -414,10 +414,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1q8gj3wkc2mbzsqw5zcsr3kyzrrb2pda03pi769rjbvqr94g3bm5";
|
||||
sha256 = "1qbdgp36dhcyljhmfxrvbgp1ha9yqxhxgyg3sdm48y9m371jd2an";
|
||||
type = "gem";
|
||||
};
|
||||
version = "1.10.0";
|
||||
version = "1.11.0";
|
||||
};
|
||||
debug_inspector = {
|
||||
groups = ["default" "development"];
|
||||
@@ -573,10 +573,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "15yrwawhvkjvfg0dsf8z81876ddj6161q0wh5s7pw4sim8z8pspr";
|
||||
sha256 = "0153rr745g48h48vaplgmx7xkfjbc79acpq5jsl7agdrk4yf75ih";
|
||||
type = "gem";
|
||||
};
|
||||
version = "0.88.0";
|
||||
version = "0.89.0";
|
||||
};
|
||||
execjs = {
|
||||
groups = ["assets" "default"];
|
||||
@@ -603,10 +603,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1a1zv94hcss44n1b04w0rg0swg8npigrj3nva9h0y2f1iflj124k";
|
||||
sha256 = "1i4pcqmf8q0gkjzhndcbzgg8bg4rkvbpp2gapnqxc8j8gcxzi1fi";
|
||||
type = "gem";
|
||||
};
|
||||
version = "2.22.0";
|
||||
version = "2.23.1";
|
||||
};
|
||||
faker = {
|
||||
dependencies = ["i18n"];
|
||||
@@ -757,10 +757,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "05i1fgqy4l40niwm9y56d04f876sm0cvc7q3w2rpddf8gya4lcs9";
|
||||
sha256 = "0nnggg20za5vamdpkgrxxa32z33d8hf0g2bciswkhqnc6amb3yjr";
|
||||
type = "gem";
|
||||
};
|
||||
version = "2.2.5";
|
||||
version = "2.2.6";
|
||||
};
|
||||
ffi = {
|
||||
groups = ["default" "development" "test"];
|
||||
@@ -1090,10 +1090,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "13k73ap18p09bxwgw24xc1lb5bxnky8p0xpx7yrlk74xlffasw30";
|
||||
sha256 = "09l4rdq5gsnhr7ma7i5ddg8sagkqn122kz8cb244q4hyk9rwmd2w";
|
||||
type = "gem";
|
||||
};
|
||||
version = "2.10.0";
|
||||
version = "2.10.1";
|
||||
};
|
||||
loofah = {
|
||||
dependencies = ["crass" "nokogiri"];
|
||||
@@ -1101,10 +1101,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1nqcya57x2n58y1dify60i0dpla40n4yir928khp4nj5jrn9mgmw";
|
||||
sha256 = "17rvbrqcci1579d7dpbsfmz1f9g7msk82lyh9ip5h29dkrnixcgg";
|
||||
type = "gem";
|
||||
};
|
||||
version = "2.12.0";
|
||||
version = "2.13.0";
|
||||
};
|
||||
lru_redux = {
|
||||
groups = ["default"];
|
||||
@@ -1175,10 +1175,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1d0cdx4cszsa0wgnch1b5dcyalg6x9niyydik8yyampnpjghwfnk";
|
||||
sha256 = "0xf3r47qpigg661krwa8z7k4f0z0rx9r5g2mgahrrwgjn67d332l";
|
||||
type = "gem";
|
||||
};
|
||||
version = "3.3.6";
|
||||
version = "3.3.8";
|
||||
};
|
||||
method_source = {
|
||||
groups = ["default" "development" "test"];
|
||||
@@ -1248,20 +1248,20 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1r6pwyv1vpyza0rn1pyxls4qdw5jd3vg4k5dp1iaqa57n6fiqrvi";
|
||||
sha256 = "1rr2nx1kixd7ccxqdnswjnflg46s6lr1f9vxkdy298k95zwk67cd";
|
||||
type = "gem";
|
||||
};
|
||||
version = "0.3.2";
|
||||
version = "0.3.3";
|
||||
};
|
||||
minitest = {
|
||||
groups = ["default" "development" "test"];
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "19z7wkhg59y8abginfrm2wzplz7py3va8fyngiigngqvsws6cwgl";
|
||||
sha256 = "06xf558gid4w8lwx13jwfdafsch9maz8m0g85wnfymqj63x5nbbd";
|
||||
type = "gem";
|
||||
};
|
||||
version = "5.14.4";
|
||||
version = "5.15.0";
|
||||
};
|
||||
mocha = {
|
||||
groups = ["development" "test"];
|
||||
@@ -1530,10 +1530,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1skkdjawwigi9vs5zkp03jkpx2f11drfjz483g1xw2dnjdsq22c3";
|
||||
sha256 = "0sszdl9mpzqzn9kxrp28sqmg47mjxcwypr4d60vbajqba4v885di";
|
||||
type = "gem";
|
||||
};
|
||||
version = "3.0.3.1";
|
||||
version = "3.0.3.2";
|
||||
};
|
||||
pg = {
|
||||
groups = ["default"];
|
||||
@@ -1752,10 +1752,10 @@
|
||||
}];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "07nikrdnsf6g55225njnzs1lm9s0lnbv2krvqd2gldwl49l7vl9x";
|
||||
sha256 = "0wb2x51parf6v78w0cic90m33bdc92y5h8rj4wqs75dhw1b69hc7";
|
||||
type = "gem";
|
||||
};
|
||||
version = "0.19.2";
|
||||
version = "0.20.0";
|
||||
};
|
||||
rake = {
|
||||
groups = ["default" "development" "test"];
|
||||
@@ -1839,10 +1839,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "0vg7imjnfcqjx7kw94ccj5r78j4g190cqzi1i59sh4a0l940b9cr";
|
||||
sha256 = "008yn8j44414qxhn1c0nxp4a70rq0bqhz70hnjpgx8cjh2g0makp";
|
||||
type = "gem";
|
||||
};
|
||||
version = "2.1.1";
|
||||
version = "2.2.0";
|
||||
};
|
||||
request_store = {
|
||||
dependencies = ["rack"];
|
||||
@@ -2031,10 +2031,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "06krbzlj49gjfmxpjwadfwqsqg5bgcp9k1fahyxxk3f6idqhkjbv";
|
||||
sha256 = "0bj8ppl4143f7pkcwm4l5wcahid6yzracdlzh1w2fpss89pic2rf";
|
||||
type = "gem";
|
||||
};
|
||||
version = "1.13.0";
|
||||
version = "1.15.0";
|
||||
};
|
||||
rubocop-discourse = {
|
||||
dependencies = ["rubocop" "rubocop-rspec"];
|
||||
@@ -2042,10 +2042,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "1agjjqdzajlssw2lxpchz5gr2sll9lh5yldccgmghxh39l01cr0a";
|
||||
sha256 = "01f4y7am9cq276zl8vsgv64w8wfmhpbzg7vzsifhgnnh92g6s04g";
|
||||
type = "gem";
|
||||
};
|
||||
version = "2.4.2";
|
||||
version = "2.5.0";
|
||||
};
|
||||
rubocop-rspec = {
|
||||
dependencies = ["rubocop"];
|
||||
@@ -2227,10 +2227,10 @@
|
||||
platforms = [];
|
||||
source = {
|
||||
remotes = ["https://rubygems.org"];
|
||||
sha256 = "0pjz4lbv2v0p9fa5nsrxy5lphsixb9a69gq2rxp0h5sr61m18mdq";
|
||||
sha256 = "1b9i14qb27zs56hlcc2hf139l0ghbqnjpmfi0054dxycaxvk5min";
|
||||
type = "gem";
|
||||
};
|
||||
version = "3.4.1";
|
||||
version = "3.4.2";
|
||||
};
|
||||
sshkey = {
|
||||
groups = ["default"];
|
||||
|
||||
@@ -164,7 +164,7 @@ def _diff_file(filepath: str, old_version: DiscourseVersion, new_version: Discou
|
||||
def _remove_platforms(rubyenv_dir: Path):
|
||||
for platform in ['arm64-darwin-20', 'x86_64-darwin-18',
|
||||
'x86_64-darwin-19', 'x86_64-darwin-20',
|
||||
'x86_64-linux']:
|
||||
'x86_64-linux', 'aarch64-linux']:
|
||||
with open(rubyenv_dir / 'Gemfile.lock', 'r') as f:
|
||||
for line in f:
|
||||
if platform in line:
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "calendar-cli";
|
||||
version = "0.12.0";
|
||||
version = "0.13.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "tobixen";
|
||||
repo = "calendar-cli";
|
||||
rev = "v${version}";
|
||||
sha256 = "0qjld2m7hl3dx90491pqbjcja82c1f5gwx274kss4lkb8aw0kmlv";
|
||||
hash = "sha256-wGigrBl5PJL+fVfnFnHDJ5zyB+Rq3Fm+q9vMvLuBBys=";
|
||||
};
|
||||
|
||||
propagatedBuildInputs = with python3.pkgs; [
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "crowdin-cli";
|
||||
version = "3.7.2";
|
||||
version = "3.7.4";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://github.com/crowdin/${pname}/releases/download/${version}/${pname}.zip";
|
||||
sha256 = "sha256-7p+Di4GcztwzybJTcFXlun15NFYbJN8eGmJ0y9bify0=";
|
||||
sha256 = "sha256-zsd95dkKzuhqtWFwc84tjZ05MnzE25UvfF459gfp+lA=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ installShellFiles makeWrapper unzip ];
|
||||
|
||||
@@ -27154,6 +27154,7 @@ with pkgs;
|
||||
inherit (mopidyPackages)
|
||||
mopidy
|
||||
mopidy-iris
|
||||
mopidy-jellyfin
|
||||
mopidy-local
|
||||
mopidy-moped
|
||||
mopidy-mopify
|
||||
|
||||
@@ -6312,6 +6312,13 @@ let
|
||||
url = "mirror://cpan/authors/id/R/RI/RIBASUSHI/DBIx-Class-0.082842.tar.gz";
|
||||
sha256 = "1rh7idjjbibc1zmiaaarask434lh0lx7f2xyfwmy37k9fa0xcpmh";
|
||||
};
|
||||
patches = [
|
||||
# https://github.com/Perl5/DBIx-Class/pull/141
|
||||
(fetchpatch {
|
||||
url = "https://github.com/Perl5/DBIx-Class/commit/fb896701d23fa4da622b5b1b2afbbba3da2dd8f3.patch";
|
||||
sha256 = "sha256-MSbV9UfHu90NCdC5IFwuy/vpSDw4atfellYh7Ydvkm4=";
|
||||
})
|
||||
];
|
||||
buildInputs = [ DBDSQLite TestDeep TestException TestWarn ];
|
||||
propagatedBuildInputs = [ ClassAccessorGrouped ClassC3Componentised ConfigAny ContextPreserve DBI DataDumperConcise DataPage DevelGlobalDestruction ModuleFind PathClass SQLAbstractClassic ScopeGuard SubName namespaceclean ];
|
||||
meta = {
|
||||
|
||||
@@ -5296,6 +5296,8 @@ in {
|
||||
|
||||
nitpick = callPackage ../applications/version-management/nitpick { };
|
||||
|
||||
nitransforms = callPackage ../development/python-modules/nitransforms { };
|
||||
|
||||
nix-kernel = callPackage ../development/python-modules/nix-kernel {
|
||||
inherit (pkgs) nix;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user