Merge staging-next into staging
This commit is contained in:
commit
be61518b91
@ -394,6 +394,20 @@ php.override {
|
|||||||
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The ACME module has been overhauled for simplicity and maintainability.
|
||||||
|
Cert generation now implicitly uses the <literal>acme</literal>
|
||||||
|
user, and the <literal>security.acme.certs._name_.user</literal> option
|
||||||
|
has been removed. Instead, certificate access from other services is now
|
||||||
|
managed through group permissions. The module no longer runs lego
|
||||||
|
twice under certain conditions, and will correctly renew certificates if
|
||||||
|
their configuration is changed. Services which reload nginx and httpd after
|
||||||
|
certificate renewal are now properly configured too so you no longer have
|
||||||
|
to do this manually if you are using HTTPS enabled virtual hosts. A mechanism
|
||||||
|
for regenerating certs on demand has also been added and documented.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Gollum received a major update to version 5.x and you may have to change
|
Gollum received a major update to version 5.x and you may have to change
|
||||||
|
@ -1,11 +1,314 @@
|
|||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, options, ... }:
|
||||||
with lib;
|
with lib;
|
||||||
let
|
let
|
||||||
|
|
||||||
cfg = config.security.acme;
|
cfg = config.security.acme;
|
||||||
|
|
||||||
|
# Used to calculate timer accuracy for coalescing
|
||||||
|
numCerts = length (builtins.attrNames cfg.certs);
|
||||||
|
_24hSecs = 60 * 60 * 24;
|
||||||
|
|
||||||
|
# There are many services required to make cert renewals work.
|
||||||
|
# They all follow a common structure:
|
||||||
|
# - They inherit this commonServiceConfig
|
||||||
|
# - They all run as the acme user
|
||||||
|
# - They all use BindPath and StateDirectory where possible
|
||||||
|
# to set up a sort of build environment in /tmp
|
||||||
|
# The Group can vary depending on what the user has specified in
|
||||||
|
# security.acme.certs.<cert>.group on some of the services.
|
||||||
|
commonServiceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
User = "acme";
|
||||||
|
Group = mkDefault "acme";
|
||||||
|
UMask = 0027;
|
||||||
|
StateDirectoryMode = 750;
|
||||||
|
ProtectSystem = "full";
|
||||||
|
PrivateTmp = true;
|
||||||
|
|
||||||
|
WorkingDirectory = "/tmp";
|
||||||
|
};
|
||||||
|
|
||||||
|
# In order to avoid race conditions creating the CA for selfsigned certs,
|
||||||
|
# we have a separate service which will create the necessary files.
|
||||||
|
selfsignCAService = {
|
||||||
|
description = "Generate self-signed certificate authority";
|
||||||
|
|
||||||
|
path = with pkgs; [ minica ];
|
||||||
|
|
||||||
|
unitConfig = {
|
||||||
|
ConditionPathExists = "!/var/lib/acme/.minica/key.pem";
|
||||||
|
};
|
||||||
|
|
||||||
|
serviceConfig = commonServiceConfig // {
|
||||||
|
StateDirectory = "acme/.minica";
|
||||||
|
BindPaths = "/var/lib/acme/.minica:/tmp/ca";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Working directory will be /tmp
|
||||||
|
script = ''
|
||||||
|
minica \
|
||||||
|
--ca-key ca/key.pem \
|
||||||
|
--ca-cert ca/cert.pem \
|
||||||
|
--domains selfsigned.local
|
||||||
|
|
||||||
|
chmod 600 ca/*
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Previously, all certs were owned by whatever user was configured in
|
||||||
|
# config.security.acme.certs.<cert>.user. Now everything is owned by and
|
||||||
|
# run by the acme user.
|
||||||
|
userMigrationService = {
|
||||||
|
description = "Fix owner and group of all ACME certificates";
|
||||||
|
|
||||||
|
script = with builtins; concatStringsSep "\n" (mapAttrsToList (cert: data: ''
|
||||||
|
for fixpath in /var/lib/acme/${escapeShellArg cert} /var/lib/acme/.lego/${escapeShellArg cert}; do
|
||||||
|
if [ -d "$fixpath" ]; then
|
||||||
|
chmod -R 750 "$fixpath"
|
||||||
|
chown -R acme:${data.group} "$fixpath"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
'') certConfigs);
|
||||||
|
|
||||||
|
# We don't want this to run every time a renewal happens
|
||||||
|
serviceConfig.RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
certToConfig = cert: data: let
|
||||||
|
acmeServer = if data.server != null then data.server else cfg.server;
|
||||||
|
useDns = data.dnsProvider != null;
|
||||||
|
destPath = "/var/lib/acme/${cert}";
|
||||||
|
selfsignedDeps = optionals (cfg.preliminarySelfsigned) [ "acme-selfsigned-${cert}.service" ];
|
||||||
|
|
||||||
|
# Minica and lego have a "feature" which replaces * with _. We need
|
||||||
|
# to make this substitution to reference the output files from both programs.
|
||||||
|
# End users never see this since we rename the certs.
|
||||||
|
keyName = builtins.replaceStrings ["*"] ["_"] data.domain;
|
||||||
|
|
||||||
|
# FIXME when mkChangedOptionModule supports submodules, change to that.
|
||||||
|
# This is a workaround
|
||||||
|
extraDomains = data.extraDomainNames ++ (
|
||||||
|
optionals
|
||||||
|
(data.extraDomains != "_mkMergedOptionModule")
|
||||||
|
(builtins.attrNames data.extraDomains)
|
||||||
|
);
|
||||||
|
|
||||||
|
# Create hashes for cert data directories based on configuration
|
||||||
|
# Flags are separated to avoid collisions
|
||||||
|
hashData = with builtins; ''
|
||||||
|
${concatStringsSep " " data.extraLegoFlags} -
|
||||||
|
${concatStringsSep " " data.extraLegoRunFlags} -
|
||||||
|
${concatStringsSep " " data.extraLegoRenewFlags} -
|
||||||
|
${toString acmeServer} ${toString data.dnsProvider}
|
||||||
|
${toString data.ocspMustStaple} ${data.keyType}
|
||||||
|
'';
|
||||||
|
mkHash = with builtins; val: substring 0 20 (hashString "sha256" val);
|
||||||
|
certDir = mkHash hashData;
|
||||||
|
domainHash = mkHash "${concatStringsSep " " extraDomains} ${data.domain}";
|
||||||
|
othersHash = mkHash "${toString acmeServer} ${data.keyType}";
|
||||||
|
accountDir = "/var/lib/acme/.lego/accounts/" + othersHash;
|
||||||
|
|
||||||
|
protocolOpts = if useDns then (
|
||||||
|
[ "--dns" data.dnsProvider ]
|
||||||
|
++ optionals (!data.dnsPropagationCheck) [ "--dns.disable-cp" ]
|
||||||
|
) else (
|
||||||
|
[ "--http" "--http.webroot" data.webroot ]
|
||||||
|
);
|
||||||
|
|
||||||
|
commonOpts = [
|
||||||
|
"--accept-tos" # Checking the option is covered by the assertions
|
||||||
|
"--path" "."
|
||||||
|
"-d" data.domain
|
||||||
|
"--email" data.email
|
||||||
|
"--key-type" data.keyType
|
||||||
|
] ++ protocolOpts
|
||||||
|
++ optionals data.ocspMustStaple [ "--must-staple" ]
|
||||||
|
++ optionals (acmeServer != null) [ "--server" acmeServer ]
|
||||||
|
++ concatMap (name: [ "-d" name ]) extraDomains
|
||||||
|
++ data.extraLegoFlags;
|
||||||
|
|
||||||
|
runOpts = escapeShellArgs (
|
||||||
|
commonOpts
|
||||||
|
++ [ "run" ]
|
||||||
|
++ data.extraLegoRunFlags
|
||||||
|
);
|
||||||
|
renewOpts = escapeShellArgs (
|
||||||
|
commonOpts
|
||||||
|
++ [ "renew" "--reuse-key" ]
|
||||||
|
++ data.extraLegoRenewFlags
|
||||||
|
);
|
||||||
|
|
||||||
|
in {
|
||||||
|
inherit accountDir selfsignedDeps;
|
||||||
|
|
||||||
|
webroot = data.webroot;
|
||||||
|
group = data.group;
|
||||||
|
|
||||||
|
renewTimer = {
|
||||||
|
description = "Renew ACME Certificate for ${cert}";
|
||||||
|
wantedBy = [ "timers.target" ];
|
||||||
|
timerConfig = {
|
||||||
|
OnCalendar = cfg.renewInterval;
|
||||||
|
Unit = "acme-${cert}.service";
|
||||||
|
Persistent = "yes";
|
||||||
|
|
||||||
|
# Allow systemd to pick a convenient time within the day
|
||||||
|
# to run the check.
|
||||||
|
# This allows the coalescing of multiple timer jobs.
|
||||||
|
# We divide by the number of certificates so that if you
|
||||||
|
# have many certificates, the renewals are distributed over
|
||||||
|
# the course of the day to avoid rate limits.
|
||||||
|
AccuracySec = "${toString (_24hSecs / numCerts)}s";
|
||||||
|
|
||||||
|
# Skew randomly within the day, per https://letsencrypt.org/docs/integration-guide/.
|
||||||
|
RandomizedDelaySec = "24h";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
selfsignService = {
|
||||||
|
description = "Generate self-signed certificate for ${cert}";
|
||||||
|
after = [ "acme-selfsigned-ca.service" "acme-fixperms.service" ];
|
||||||
|
requires = [ "acme-selfsigned-ca.service" "acme-fixperms.service" ];
|
||||||
|
|
||||||
|
path = with pkgs; [ minica ];
|
||||||
|
|
||||||
|
unitConfig = {
|
||||||
|
ConditionPathExists = "!/var/lib/acme/${cert}/key.pem";
|
||||||
|
};
|
||||||
|
|
||||||
|
serviceConfig = commonServiceConfig // {
|
||||||
|
Group = data.group;
|
||||||
|
|
||||||
|
StateDirectory = "acme/${cert}";
|
||||||
|
|
||||||
|
BindPaths = "/var/lib/acme/.minica:/tmp/ca /var/lib/acme/${cert}:/tmp/${keyName}";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Working directory will be /tmp
|
||||||
|
# minica will output to a folder sharing the name of the first domain
|
||||||
|
# in the list, which will be ${data.domain}
|
||||||
|
script = ''
|
||||||
|
minica \
|
||||||
|
--ca-key ca/key.pem \
|
||||||
|
--ca-cert ca/cert.pem \
|
||||||
|
--domains ${escapeShellArg (builtins.concatStringsSep "," ([ data.domain ] ++ extraDomains))}
|
||||||
|
|
||||||
|
# Create files to match directory layout for real certificates
|
||||||
|
cd '${keyName}'
|
||||||
|
cp ../ca/cert.pem chain.pem
|
||||||
|
cat cert.pem chain.pem > fullchain.pem
|
||||||
|
cat key.pem fullchain.pem > full.pem
|
||||||
|
|
||||||
|
chmod 640 *
|
||||||
|
|
||||||
|
# Group might change between runs, re-apply it
|
||||||
|
chown 'acme:${data.group}' *
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
renewService = {
|
||||||
|
description = "Renew ACME certificate for ${cert}";
|
||||||
|
after = [ "network.target" "network-online.target" "acme-fixperms.service" ] ++ selfsignedDeps;
|
||||||
|
wants = [ "network-online.target" "acme-fixperms.service" ] ++ selfsignedDeps;
|
||||||
|
|
||||||
|
# https://github.com/NixOS/nixpkgs/pull/81371#issuecomment-605526099
|
||||||
|
wantedBy = optionals (!config.boot.isContainer) [ "multi-user.target" ];
|
||||||
|
|
||||||
|
path = with pkgs; [ lego coreutils diffutils ];
|
||||||
|
|
||||||
|
serviceConfig = commonServiceConfig // {
|
||||||
|
Group = data.group;
|
||||||
|
|
||||||
|
# AccountDir dir will be created by tmpfiles to ensure correct permissions
|
||||||
|
# And to avoid deletion during systemctl clean
|
||||||
|
# acme/.lego/${cert} is listed so that it is deleted during systemctl clean
|
||||||
|
StateDirectory = "acme/${cert} acme/.lego/${cert} acme/.lego/${cert}/${certDir}";
|
||||||
|
|
||||||
|
# Needs to be space separated, but can't use a multiline string because that'll include newlines
|
||||||
|
BindPaths =
|
||||||
|
"${accountDir}:/tmp/accounts " +
|
||||||
|
"/var/lib/acme/${cert}:/tmp/out " +
|
||||||
|
"/var/lib/acme/.lego/${cert}/${certDir}:/tmp/certificates ";
|
||||||
|
|
||||||
|
# Only try loading the credentialsFile if the dns challenge is enabled
|
||||||
|
EnvironmentFile = mkIf useDns data.credentialsFile;
|
||||||
|
|
||||||
|
# Run as root (Prefixed with +)
|
||||||
|
ExecStartPost = "+" + (pkgs.writeShellScript "acme-postrun" ''
|
||||||
|
cd /var/lib/acme/${escapeShellArg cert}
|
||||||
|
if [ -e renewed ]; then
|
||||||
|
rm renewed
|
||||||
|
${data.postRun}
|
||||||
|
fi
|
||||||
|
'');
|
||||||
|
};
|
||||||
|
|
||||||
|
# Working directory will be /tmp
|
||||||
|
script = ''
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo '${domainHash}' > domainhash.txt
|
||||||
|
|
||||||
|
# Check if we can renew
|
||||||
|
if [ -e 'certificates/${keyName}.key' -a -e 'certificates/${keyName}.crt' ]; 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
|
||||||
|
lego ${renewOpts} --days ${toString cfg.validMinDays}
|
||||||
|
else
|
||||||
|
# Any number > 90 works, but this one is over 9000 ;-)
|
||||||
|
lego ${renewOpts} --days 9001
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Otherwise do a full run
|
||||||
|
else
|
||||||
|
lego ${runOpts}
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv domainhash.txt certificates/
|
||||||
|
chmod 640 certificates/*
|
||||||
|
chmod -R 700 accounts/*
|
||||||
|
|
||||||
|
# Group might change between runs, re-apply it
|
||||||
|
chown 'acme:${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
|
||||||
|
touch out/renewed
|
||||||
|
echo Installing new certificate
|
||||||
|
cp -vp 'certificates/${keyName}.crt' out/fullchain.pem
|
||||||
|
cp -vp 'certificates/${keyName}.key' out/key.pem
|
||||||
|
cp -vp 'certificates/${keyName}.issuer.crt' out/chain.pem
|
||||||
|
ln -sf fullchain.pem out/cert.pem
|
||||||
|
cat out/key.pem out/fullchain.pem > out/full.pem
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
certConfigs = mapAttrs certToConfig cfg.certs;
|
||||||
|
|
||||||
certOpts = { name, ... }: {
|
certOpts = { name, ... }: {
|
||||||
options = {
|
options = {
|
||||||
|
# user option has been removed
|
||||||
|
user = mkOption {
|
||||||
|
visible = false;
|
||||||
|
default = "_mkRemovedOptionModule";
|
||||||
|
};
|
||||||
|
|
||||||
|
# allowKeysForGroup option has been removed
|
||||||
|
allowKeysForGroup = mkOption {
|
||||||
|
visible = false;
|
||||||
|
default = "_mkRemovedOptionModule";
|
||||||
|
};
|
||||||
|
|
||||||
|
# extraDomains was replaced with extraDomainNames
|
||||||
|
extraDomains = mkOption {
|
||||||
|
visible = false;
|
||||||
|
default = "_mkMergedOptionModule";
|
||||||
|
};
|
||||||
|
|
||||||
webroot = mkOption {
|
webroot = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
@ -41,35 +344,19 @@ let
|
|||||||
description = "Contact email address for the CA to be able to reach you.";
|
description = "Contact email address for the CA to be able to reach you.";
|
||||||
};
|
};
|
||||||
|
|
||||||
user = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "root";
|
|
||||||
description = "User running the ACME client.";
|
|
||||||
};
|
|
||||||
|
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "root";
|
default = "acme";
|
||||||
description = "Group running the ACME client.";
|
description = "Group running the ACME client.";
|
||||||
};
|
};
|
||||||
|
|
||||||
allowKeysForGroup = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
description = ''
|
|
||||||
Give read permissions to the specified group
|
|
||||||
(<option>security.acme.cert.<name>.group</option>) to read SSL private certificates.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
postRun = mkOption {
|
postRun = mkOption {
|
||||||
type = types.lines;
|
type = types.lines;
|
||||||
default = "";
|
default = "";
|
||||||
example = "systemctl reload nginx.service";
|
example = "cp full.pem backup.pem";
|
||||||
description = ''
|
description = ''
|
||||||
Commands to run after new certificates go live. Typically
|
Commands to run after new certificates go live. Note that
|
||||||
the web server and other servers using certificates need to
|
these commands run as the root user.
|
||||||
be reloaded.
|
|
||||||
|
|
||||||
Executed in the same directory with the new certificate.
|
Executed in the same directory with the new certificate.
|
||||||
'';
|
'';
|
||||||
@ -82,18 +369,17 @@ let
|
|||||||
description = "Directory where certificate and other state is stored.";
|
description = "Directory where certificate and other state is stored.";
|
||||||
};
|
};
|
||||||
|
|
||||||
extraDomains = mkOption {
|
extraDomainNames = mkOption {
|
||||||
type = types.attrsOf (types.nullOr types.str);
|
type = types.listOf types.str;
|
||||||
default = {};
|
default = [];
|
||||||
example = literalExample ''
|
example = literalExample ''
|
||||||
{
|
[
|
||||||
"example.org" = null;
|
"example.org"
|
||||||
"mydomain.org" = null;
|
"mydomain.org"
|
||||||
}
|
]
|
||||||
'';
|
'';
|
||||||
description = ''
|
description = ''
|
||||||
A list of extra domain names, which are included in the one certificate to be issued.
|
A list of extra domain names, which are included in the one certificate to be issued.
|
||||||
Setting a distinct server root is deprecated and not functional in 20.03+
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -176,24 +462,8 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
in {
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
###### interface
|
|
||||||
imports = [
|
|
||||||
(mkRemovedOptionModule [ "security" "acme" "production" ] ''
|
|
||||||
Use security.acme.server to define your staging ACME server URL instead.
|
|
||||||
|
|
||||||
To use Let's Encrypt's 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)))
|
|
||||||
];
|
|
||||||
options = {
|
options = {
|
||||||
security.acme = {
|
security.acme = {
|
||||||
|
|
||||||
@ -266,7 +536,7 @@ in
|
|||||||
"example.com" = {
|
"example.com" = {
|
||||||
webroot = "/var/www/challenges/";
|
webroot = "/var/www/challenges/";
|
||||||
email = "foo@example.com";
|
email = "foo@example.com";
|
||||||
extraDomains = { "www.example.com" = null; "foo.example.com" = null; };
|
extraDomainNames = [ "www.example.com" "foo.example.com" ];
|
||||||
};
|
};
|
||||||
"bar.example.com" = {
|
"bar.example.com" = {
|
||||||
webroot = "/var/www/challenges/";
|
webroot = "/var/www/challenges/";
|
||||||
@ -278,25 +548,40 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
###### implementation
|
imports = [
|
||||||
|
(mkRemovedOptionModule [ "security" "acme" "production" ] ''
|
||||||
|
Use security.acme.server to define your staging ACME server URL instead.
|
||||||
|
|
||||||
|
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)))
|
||||||
|
];
|
||||||
|
|
||||||
config = mkMerge [
|
config = mkMerge [
|
||||||
(mkIf (cfg.certs != { }) {
|
(mkIf (cfg.certs != { }) {
|
||||||
|
|
||||||
|
# FIXME Most of these custom warnings and filters for security.acme.certs.* are required
|
||||||
|
# because using mkRemovedOptionModule/mkChangedOptionModule with attrsets isn't possible.
|
||||||
|
warnings = filter (w: w != "") (mapAttrsToList (cert: data: if data.extraDomains != "_mkMergedOptionModule" then ''
|
||||||
|
The option definition `security.acme.certs.${cert}.extraDomains` has changed
|
||||||
|
to `security.acme.certs.${cert}.extraDomainNames` and is now a list of strings.
|
||||||
|
Setting a custom webroot for extra domains is not possible, instead use separate certs.
|
||||||
|
'' else "") cfg.certs);
|
||||||
|
|
||||||
assertions = let
|
assertions = let
|
||||||
certs = (mapAttrsToList (k: v: v) cfg.certs);
|
certs = attrValues cfg.certs;
|
||||||
in [
|
in [
|
||||||
{
|
|
||||||
assertion = all (certOpts: certOpts.dnsProvider == null || certOpts.webroot == null) certs;
|
|
||||||
message = ''
|
|
||||||
Options `security.acme.certs.<name>.dnsProvider` and
|
|
||||||
`security.acme.certs.<name>.webroot` are mutually exclusive.
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
assertion = cfg.email != null || all (certOpts: certOpts.email != null) certs;
|
assertion = cfg.email != null || all (certOpts: certOpts.email != null) certs;
|
||||||
message = ''
|
message = ''
|
||||||
You must define `security.acme.certs.<name>.email` or
|
You must define `security.acme.certs.<name>.email` or
|
||||||
`security.acme.email` to register with the CA.
|
`security.acme.email` to register with the CA. Note that using
|
||||||
|
many different addresses for certs may trigger account rate limits.
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -307,184 +592,78 @@ in
|
|||||||
to `true`. For Let's Encrypt's ToS see https://letsencrypt.org/repository/
|
to `true`. For Let's Encrypt's ToS see https://letsencrypt.org/repository/
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
];
|
] ++ (builtins.concatLists (mapAttrsToList (cert: data: [
|
||||||
|
{
|
||||||
|
assertion = data.user == "_mkRemovedOptionModule";
|
||||||
|
message = ''
|
||||||
|
The option definition `security.acme.certs.${cert}.user' no longer has any effect; Please remove it.
|
||||||
|
Certificate user is now hard coded to the "acme" user. If you would
|
||||||
|
like another user to have access, consider adding them to the
|
||||||
|
"acme" group or changing security.acme.certs.${cert}.group.
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = data.allowKeysForGroup == "_mkRemovedOptionModule";
|
||||||
|
message = ''
|
||||||
|
The option definition `security.acme.certs.${cert}.allowKeysForGroup' no longer has any effect; Please remove it.
|
||||||
|
All certs are readable by the configured group. If this is undesired,
|
||||||
|
consider changing security.acme.certs.${cert}.group to an unused group.
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
# * in the cert value breaks building of systemd services, and makes
|
||||||
|
# referencing them as a user quite weird too. Best practice is to use
|
||||||
|
# the domain option.
|
||||||
|
{
|
||||||
|
assertion = ! hasInfix "*" cert;
|
||||||
|
message = ''
|
||||||
|
The cert option path `security.acme.certs.${cert}.dnsProvider`
|
||||||
|
cannot contain a * character.
|
||||||
|
Instead, set `security.acme.certs.${cert}.domain = "${cert}";`
|
||||||
|
and remove the wildcard from the path.
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = data.dnsProvider == null || data.webroot == null;
|
||||||
|
message = ''
|
||||||
|
Options `security.acme.certs.${cert}.dnsProvider` and
|
||||||
|
`security.acme.certs.${cert}.webroot` are mutually exclusive.
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
]) cfg.certs));
|
||||||
|
|
||||||
systemd.services = let
|
users.users.acme = {
|
||||||
services = concatLists servicesLists;
|
home = "/var/lib/acme";
|
||||||
servicesLists = mapAttrsToList certToServices cfg.certs;
|
group = "acme";
|
||||||
certToServices = cert: data:
|
isSystemUser = true;
|
||||||
let
|
};
|
||||||
# StateDirectory must be relative, and will be created under /var/lib by systemd
|
|
||||||
lpath = "acme/${cert}";
|
|
||||||
apath = "/var/lib/${lpath}";
|
|
||||||
spath = "/var/lib/acme/.lego/${cert}";
|
|
||||||
keyName = builtins.replaceStrings ["*"] ["_"] data.domain;
|
|
||||||
requestedDomains = pipe ([ data.domain ] ++ (attrNames data.extraDomains)) [
|
|
||||||
(domains: sort builtins.lessThan domains)
|
|
||||||
(domains: concatStringsSep "," domains)
|
|
||||||
];
|
|
||||||
fileMode = if data.allowKeysForGroup then "640" else "600";
|
|
||||||
globalOpts = [ "-d" data.domain "--email" data.email "--path" "." "--key-type" data.keyType ]
|
|
||||||
++ optionals (cfg.acceptTerms) [ "--accept-tos" ]
|
|
||||||
++ optionals (data.dnsProvider != null && !data.dnsPropagationCheck) [ "--dns.disable-cp" ]
|
|
||||||
++ concatLists (mapAttrsToList (name: root: [ "-d" name ]) data.extraDomains)
|
|
||||||
++ (if data.dnsProvider != null then [ "--dns" data.dnsProvider ] else [ "--http" "--http.webroot" data.webroot ])
|
|
||||||
++ optionals (cfg.server != null || data.server != null) ["--server" (if data.server == null then cfg.server else data.server)]
|
|
||||||
++ data.extraLegoFlags;
|
|
||||||
certOpts = optionals data.ocspMustStaple [ "--must-staple" ];
|
|
||||||
runOpts = escapeShellArgs (globalOpts ++ [ "run" ] ++ certOpts ++ data.extraLegoRunFlags);
|
|
||||||
renewOpts = escapeShellArgs (globalOpts ++
|
|
||||||
[ "renew" "--days" (toString cfg.validMinDays) ] ++
|
|
||||||
certOpts ++ data.extraLegoRenewFlags);
|
|
||||||
acmeService = {
|
|
||||||
description = "Renew ACME Certificate for ${cert}";
|
|
||||||
path = with pkgs; [ openssl ];
|
|
||||||
after = [ "network.target" "network-online.target" ];
|
|
||||||
wants = [ "network-online.target" ];
|
|
||||||
wantedBy = mkIf (!config.boot.isContainer) [ "multi-user.target" ];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
User = data.user;
|
|
||||||
Group = data.group;
|
|
||||||
PrivateTmp = true;
|
|
||||||
StateDirectory = "acme/.lego/${cert} acme/.lego/accounts ${lpath}";
|
|
||||||
StateDirectoryMode = if data.allowKeysForGroup then "750" else "700";
|
|
||||||
WorkingDirectory = spath;
|
|
||||||
# Only try loading the credentialsFile if the dns challenge is enabled
|
|
||||||
EnvironmentFile = if data.dnsProvider != null then data.credentialsFile else null;
|
|
||||||
ExecStart = pkgs.writeScript "acme-start" ''
|
|
||||||
#!${pkgs.runtimeShell} -e
|
|
||||||
test -L ${spath}/accounts -o -d ${spath}/accounts || ln -s ../accounts ${spath}/accounts
|
|
||||||
LEGO_ARGS=(${runOpts})
|
|
||||||
if [ -e ${spath}/certificates/${keyName}.crt ]; then
|
|
||||||
REQUESTED_DOMAINS="${requestedDomains}"
|
|
||||||
EXISTING_DOMAINS="$(openssl x509 -in ${spath}/certificates/${keyName}.crt -noout -ext subjectAltName | tail -n1 | sed -e 's/ *DNS://g')"
|
|
||||||
if [ "''${REQUESTED_DOMAINS}" == "''${EXISTING_DOMAINS}" ]; then
|
|
||||||
LEGO_ARGS=(${renewOpts})
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
${pkgs.lego}/bin/lego ''${LEGO_ARGS[@]}
|
|
||||||
'';
|
|
||||||
ExecStartPost =
|
|
||||||
let
|
|
||||||
script = pkgs.writeScript "acme-post-start" ''
|
|
||||||
#!${pkgs.runtimeShell} -e
|
|
||||||
cd ${apath}
|
|
||||||
|
|
||||||
# Test that existing cert is older than new cert
|
users.groups.acme = {};
|
||||||
KEY=${spath}/certificates/${keyName}.key
|
|
||||||
KEY_CHANGED=no
|
|
||||||
if [ -e $KEY -a $KEY -nt key.pem ]; then
|
|
||||||
KEY_CHANGED=yes
|
|
||||||
cp -p ${spath}/certificates/${keyName}.key key.pem
|
|
||||||
cp -p ${spath}/certificates/${keyName}.crt fullchain.pem
|
|
||||||
cp -p ${spath}/certificates/${keyName}.issuer.crt chain.pem
|
|
||||||
ln -sf fullchain.pem cert.pem
|
|
||||||
cat key.pem fullchain.pem > full.pem
|
|
||||||
fi
|
|
||||||
|
|
||||||
chmod ${fileMode} *.pem
|
systemd.services = {
|
||||||
chown '${data.user}:${data.group}' *.pem
|
"acme-fixperms" = userMigrationService;
|
||||||
|
} // (mapAttrs' (cert: conf: nameValuePair "acme-${cert}" conf.renewService) certConfigs)
|
||||||
|
// (optionalAttrs (cfg.preliminarySelfsigned) ({
|
||||||
|
"acme-selfsigned-ca" = selfsignCAService;
|
||||||
|
} // (mapAttrs' (cert: conf: nameValuePair "acme-selfsigned-${cert}" conf.selfsignService) certConfigs)));
|
||||||
|
|
||||||
if [ "$KEY_CHANGED" = "yes" ]; then
|
systemd.timers = mapAttrs' (cert: conf: nameValuePair "acme-${cert}" conf.renewTimer) certConfigs;
|
||||||
: # noop in case postRun is empty
|
|
||||||
${data.postRun}
|
|
||||||
fi
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
"+${script}";
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
# .lego and .lego/accounts specified to fix any incorrect permissions
|
||||||
selfsignedService = {
|
systemd.tmpfiles.rules = [
|
||||||
description = "Create preliminary self-signed certificate for ${cert}";
|
"d /var/lib/acme/.lego - acme acme"
|
||||||
path = [ pkgs.openssl ];
|
"d /var/lib/acme/.lego/accounts - acme acme"
|
||||||
script =
|
] ++ (unique (concatMap (conf: [
|
||||||
''
|
"d ${conf.accountDir} - acme acme"
|
||||||
workdir="$(mktemp -d)"
|
] ++ (optional (conf.webroot != null) "d ${conf.webroot}/.well-known/acme-challenge - acme ${conf.group}")
|
||||||
|
) (attrValues certConfigs)));
|
||||||
|
|
||||||
# Create CA
|
# Create some targets which can be depended on to be "active" after cert renewals
|
||||||
openssl genrsa -des3 -passout pass:xxxx -out $workdir/ca.pass.key 2048
|
systemd.targets = mapAttrs' (cert: conf: nameValuePair "acme-finished-${cert}" {
|
||||||
openssl rsa -passin pass:xxxx -in $workdir/ca.pass.key -out $workdir/ca.key
|
wantedBy = [ "default.target" ];
|
||||||
openssl req -new -key $workdir/ca.key -out $workdir/ca.csr \
|
requires = [ "acme-${cert}.service" ] ++ conf.selfsignedDeps;
|
||||||
-subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=Security Department/CN=example.com"
|
after = [ "acme-${cert}.service" ] ++ conf.selfsignedDeps;
|
||||||
openssl x509 -req -days 1 -in $workdir/ca.csr -signkey $workdir/ca.key -out $workdir/ca.crt
|
}) certConfigs;
|
||||||
|
|
||||||
# Create key
|
|
||||||
openssl genrsa -des3 -passout pass:xxxx -out $workdir/server.pass.key 2048
|
|
||||||
openssl rsa -passin pass:xxxx -in $workdir/server.pass.key -out $workdir/server.key
|
|
||||||
openssl req -new -key $workdir/server.key -out $workdir/server.csr \
|
|
||||||
-subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=IT Department/CN=example.com"
|
|
||||||
openssl x509 -req -days 1 -in $workdir/server.csr -CA $workdir/ca.crt \
|
|
||||||
-CAkey $workdir/ca.key -CAserial $workdir/ca.srl -CAcreateserial \
|
|
||||||
-out $workdir/server.crt
|
|
||||||
|
|
||||||
# Copy key to destination
|
|
||||||
cp $workdir/server.key ${apath}/key.pem
|
|
||||||
|
|
||||||
# Create fullchain.pem (same format as "simp_le ... -f fullchain.pem" creates)
|
|
||||||
cat $workdir/{server.crt,ca.crt} > "${apath}/fullchain.pem"
|
|
||||||
|
|
||||||
# Create full.pem for e.g. lighttpd
|
|
||||||
cat $workdir/{server.key,server.crt,ca.crt} > "${apath}/full.pem"
|
|
||||||
|
|
||||||
# Give key acme permissions
|
|
||||||
chown '${data.user}:${data.group}' "${apath}/"{key,fullchain,full}.pem
|
|
||||||
chmod ${fileMode} "${apath}/"{key,fullchain,full}.pem
|
|
||||||
'';
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
PrivateTmp = true;
|
|
||||||
StateDirectory = lpath;
|
|
||||||
User = data.user;
|
|
||||||
Group = data.group;
|
|
||||||
};
|
|
||||||
unitConfig = {
|
|
||||||
# Do not create self-signed key when key already exists
|
|
||||||
ConditionPathExists = "!${apath}/key.pem";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in (
|
|
||||||
[ { name = "acme-${cert}"; value = acmeService; } ]
|
|
||||||
++ optional cfg.preliminarySelfsigned { name = "acme-selfsigned-${cert}"; value = selfsignedService; }
|
|
||||||
);
|
|
||||||
servicesAttr = listToAttrs services;
|
|
||||||
in
|
|
||||||
servicesAttr;
|
|
||||||
|
|
||||||
systemd.tmpfiles.rules =
|
|
||||||
map (data: "d ${data.webroot}/.well-known/acme-challenge - ${data.user} ${data.group}") (filter (data: data.webroot != null) (attrValues cfg.certs));
|
|
||||||
|
|
||||||
systemd.timers = let
|
|
||||||
# Allow systemd to pick a convenient time within the day
|
|
||||||
# to run the check.
|
|
||||||
# This allows the coalescing of multiple timer jobs.
|
|
||||||
# We divide by the number of certificates so that if you
|
|
||||||
# have many certificates, the renewals are distributed over
|
|
||||||
# the course of the day to avoid rate limits.
|
|
||||||
numCerts = length (attrNames cfg.certs);
|
|
||||||
_24hSecs = 60 * 60 * 24;
|
|
||||||
AccuracySec = "${toString (_24hSecs / numCerts)}s";
|
|
||||||
in flip mapAttrs' cfg.certs (cert: data: nameValuePair
|
|
||||||
("acme-${cert}")
|
|
||||||
({
|
|
||||||
description = "Renew ACME Certificate for ${cert}";
|
|
||||||
wantedBy = [ "timers.target" ];
|
|
||||||
timerConfig = {
|
|
||||||
OnCalendar = cfg.renewInterval;
|
|
||||||
Unit = "acme-${cert}.service";
|
|
||||||
Persistent = "yes";
|
|
||||||
inherit AccuracySec;
|
|
||||||
# Skew randomly within the day, per https://letsencrypt.org/docs/integration-guide/.
|
|
||||||
RandomizedDelaySec = "24h";
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
systemd.targets.acme-selfsigned-certificates = mkIf cfg.preliminarySelfsigned {};
|
|
||||||
systemd.targets.acme-certificates = {};
|
|
||||||
})
|
})
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
|
@ -72,7 +72,7 @@ services.nginx = {
|
|||||||
"foo.example.com" = {
|
"foo.example.com" = {
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
|
<link linkend="opt-services.nginx.virtualHosts._name_.enableACME">enableACME</link> = true;
|
||||||
# All serverAliases will be added as <link linkend="opt-security.acme.certs._name_.extraDomains">extra domains</link> on the certificate.
|
# All serverAliases will be added as <link linkend="opt-security.acme.certs._name_.extraDomainNames">extra domain names</link> on the certificate.
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.serverAliases">serverAliases</link> = [ "bar.example.com" ];
|
<link linkend="opt-services.nginx.virtualHosts._name_.serverAliases">serverAliases</link> = [ "bar.example.com" ];
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.root">root</link> = "/var/www";
|
<link linkend="opt-services.nginx.virtualHosts._name_.locations._name_.root">root</link> = "/var/www";
|
||||||
@ -80,8 +80,8 @@ services.nginx = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
# We can also add a different vhost and reuse the same certificate
|
# We can also add a different vhost and reuse the same certificate
|
||||||
# but we have to append extraDomains manually.
|
# but we have to append extraDomainNames manually.
|
||||||
<link linkend="opt-security.acme.certs._name_.extraDomains">security.acme.certs."foo.example.com".extraDomains."baz.example.com"</link> = null;
|
<link linkend="opt-security.acme.certs._name_.extraDomainNames">security.acme.certs."foo.example.com".extraDomainNames</link> = [ "baz.example.com" ];
|
||||||
"baz.example.com" = {
|
"baz.example.com" = {
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
<link linkend="opt-services.nginx.virtualHosts._name_.forceSSL">forceSSL</link> = true;
|
||||||
<link linkend="opt-services.nginx.virtualHosts._name_.useACMEHost">useACMEHost</link> = "foo.example.com";
|
<link linkend="opt-services.nginx.virtualHosts._name_.useACMEHost">useACMEHost</link> = "foo.example.com";
|
||||||
@ -165,7 +165,7 @@ services.httpd = {
|
|||||||
# Since we have a wildcard vhost to handle port 80,
|
# Since we have a wildcard vhost to handle port 80,
|
||||||
# we can generate certs for anything!
|
# we can generate certs for anything!
|
||||||
# Just make sure your DNS resolves them.
|
# Just make sure your DNS resolves them.
|
||||||
<link linkend="opt-security.acme.certs._name_.extraDomains">extraDomains</link> = [ "mail.example.com" ];
|
<link linkend="opt-security.acme.certs._name_.extraDomainNames">extraDomainNames</link> = [ "mail.example.com" ];
|
||||||
};
|
};
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
@ -251,4 +251,16 @@ chmod 400 /var/lib/secrets/certs.secret
|
|||||||
journalctl -fu acme-example.com.service</literal> and watching its log output.
|
journalctl -fu acme-example.com.service</literal> and watching its log output.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
<section xml:id="module-security-acme-regenerate">
|
||||||
|
<title>Regenerating certificates</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Should you need to regenerate a particular certificate in a hurry, such
|
||||||
|
as when a vulnerability is found in Let's Encrypt, there is now a convenient
|
||||||
|
mechanism for doing so. Running <literal>systemctl clean acme-example.com.service</literal>
|
||||||
|
will remove all certificate files for the given domain, allowing you to then
|
||||||
|
<literal>systemctl start acme-example.com.service</literal> to generate fresh
|
||||||
|
ones.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
@ -197,26 +197,8 @@ sudo borg init --encryption=repokey-blake2 \
|
|||||||
disk failure, ransomware and theft.
|
disk failure, ransomware and theft.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
It is available as a flatpak package. To enable it you must set the
|
It can be installed in NixOS e.g. by adding <package>pkgs.vorta</package>
|
||||||
following two configuration items.
|
to <xref linkend="opt-environment.systemPackages" />.
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
services.flatpak.enable = true ;
|
|
||||||
# next line is needed to avoid the Error
|
|
||||||
# Error deploying: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown:
|
|
||||||
services.accounts-daemon.enable = true;
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>As a normal user you must first install, then run vorta using the
|
|
||||||
following commands:
|
|
||||||
<programlisting>
|
|
||||||
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
|
||||||
flatpak install flathub com.borgbase.Vorta
|
|
||||||
flatpak run --branch=stable --arch=x86_64 --command=vorta com.borgbase.Vorta
|
|
||||||
</programlisting>
|
|
||||||
After running <code>flatpak install</code> you can start Vorta also via
|
|
||||||
the KDE application menu.
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Details about using Vorta can be found under <link
|
Details about using Vorta can be found under <link
|
||||||
|
@ -15,6 +15,15 @@ in {
|
|||||||
issued by the `lorri` command.
|
issued by the `lorri` command.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
package = lib.mkOption {
|
||||||
|
default = pkgs.lorri;
|
||||||
|
type = lib.types.package;
|
||||||
|
description = ''
|
||||||
|
The lorri package to use.
|
||||||
|
'';
|
||||||
|
defaultText = lib.literalExample "pkgs.lorri";
|
||||||
|
example = lib.literalExample "pkgs.lorri";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -34,7 +43,7 @@ in {
|
|||||||
after = [ "lorri.socket" ];
|
after = [ "lorri.socket" ];
|
||||||
path = with pkgs; [ config.nix.package git gnutar gzip ];
|
path = with pkgs; [ config.nix.package git gnutar gzip ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${pkgs.lorri}/bin/lorri daemon";
|
ExecStart = "${cfg.package}/bin/lorri daemon";
|
||||||
PrivateTmp = true;
|
PrivateTmp = true;
|
||||||
ProtectSystem = "strict";
|
ProtectSystem = "strict";
|
||||||
ProtectHome = "read-only";
|
ProtectHome = "read-only";
|
||||||
@ -42,6 +51,6 @@ in {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.lorri ];
|
environment.systemPackages = [ cfg.package ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,8 @@ let
|
|||||||
};
|
};
|
||||||
firewallFilter = mkOption {
|
firewallFilter = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "-p tcp -m tcp --dport ${toString port}";
|
default = "-p tcp -m tcp --dport ${toString cfg.${name}.port}";
|
||||||
|
defaultText = "-p tcp -m tcp --dport ${toString port}";
|
||||||
example = literalExample ''
|
example = literalExample ''
|
||||||
"-i eth0 -p tcp -m tcp --dport ${toString port}"
|
"-i eth0 -p tcp -m tcp --dport ${toString port}"
|
||||||
'';
|
'';
|
||||||
|
@ -65,7 +65,7 @@ services.prosody = {
|
|||||||
you'll need a single TLS certificate covering your main endpoint,
|
you'll need a single TLS certificate covering your main endpoint,
|
||||||
the MUC one as well as the HTTP Upload one. We can generate such a
|
the MUC one as well as the HTTP Upload one. We can generate such a
|
||||||
certificate by leveraging the ACME
|
certificate by leveraging the ACME
|
||||||
<link linkend="opt-security.acme.certs._name_.extraDomains">extraDomains</link> module option.
|
<link linkend="opt-security.acme.certs._name_.extraDomainNames">extraDomainNames</link> module option.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Provided the setup detailed in the previous section, you'll need the following acme configuration to generate
|
Provided the setup detailed in the previous section, you'll need the following acme configuration to generate
|
||||||
@ -78,8 +78,7 @@ security.acme = {
|
|||||||
"example.org" = {
|
"example.org" = {
|
||||||
<link linkend="opt-security.acme.certs._name_.webroot">webroot</link> = "/var/www/example.org";
|
<link linkend="opt-security.acme.certs._name_.webroot">webroot</link> = "/var/www/example.org";
|
||||||
<link linkend="opt-security.acme.certs._name_.email">email</link> = "root@example.org";
|
<link linkend="opt-security.acme.certs._name_.email">email</link> = "root@example.org";
|
||||||
<link linkend="opt-security.acme.certs._name_.extraDomains">extraDomains."conference.example.org"</link> = null;
|
<link linkend="opt-security.acme.certs._name_.extraDomainNames">extraDomainNames</link> = [ "conference.example.org" "upload.example.org" ];
|
||||||
<link linkend="opt-security.acme.certs._name_.extraDomains">extraDomains."upload.example.org"</link> = null;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};</programlisting>
|
};</programlisting>
|
||||||
|
@ -232,6 +232,14 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
banner = mkOption {
|
||||||
|
type = types.nullOr types.lines;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Message to display to the remote user before authentication is allowed.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
authorizedKeysFiles = mkOption {
|
authorizedKeysFiles = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [];
|
default = [];
|
||||||
@ -474,6 +482,8 @@ in
|
|||||||
''
|
''
|
||||||
UsePAM yes
|
UsePAM yes
|
||||||
|
|
||||||
|
Banner ${if cfg.banner == null then "none" else pkgs.writeText "ssh_banner" cfg.banner}
|
||||||
|
|
||||||
AddressFamily ${if config.networking.enableIPv6 then "any" else "inet"}
|
AddressFamily ${if config.networking.enableIPv6 then "any" else "inet"}
|
||||||
${concatMapStrings (port: ''
|
${concatMapStrings (port: ''
|
||||||
Port ${toString port}
|
Port ${toString port}
|
||||||
|
@ -6,6 +6,8 @@ let
|
|||||||
|
|
||||||
cfg = config.services.httpd;
|
cfg = config.services.httpd;
|
||||||
|
|
||||||
|
certs = config.security.acme.certs;
|
||||||
|
|
||||||
runtimeDir = "/run/httpd";
|
runtimeDir = "/run/httpd";
|
||||||
|
|
||||||
pkg = cfg.package.out;
|
pkg = cfg.package.out;
|
||||||
@ -26,6 +28,13 @@ let
|
|||||||
|
|
||||||
vhosts = attrValues cfg.virtualHosts;
|
vhosts = attrValues cfg.virtualHosts;
|
||||||
|
|
||||||
|
# certName is used later on to determine systemd service names.
|
||||||
|
acmeEnabledVhosts = map (hostOpts: hostOpts // {
|
||||||
|
certName = if hostOpts.useACMEHost != null then hostOpts.useACMEHost else hostOpts.hostName;
|
||||||
|
}) (filter (hostOpts: hostOpts.enableACME || hostOpts.useACMEHost != null) vhosts);
|
||||||
|
|
||||||
|
dependentCertNames = unique (map (hostOpts: hostOpts.certName) acmeEnabledVhosts);
|
||||||
|
|
||||||
mkListenInfo = hostOpts:
|
mkListenInfo = hostOpts:
|
||||||
if hostOpts.listen != [] then hostOpts.listen
|
if hostOpts.listen != [] then hostOpts.listen
|
||||||
else (
|
else (
|
||||||
@ -125,13 +134,13 @@ let
|
|||||||
|
|
||||||
useACME = hostOpts.enableACME || hostOpts.useACMEHost != null;
|
useACME = hostOpts.enableACME || hostOpts.useACMEHost != null;
|
||||||
sslCertDir =
|
sslCertDir =
|
||||||
if hostOpts.enableACME then config.security.acme.certs.${hostOpts.hostName}.directory
|
if hostOpts.enableACME then certs.${hostOpts.hostName}.directory
|
||||||
else if hostOpts.useACMEHost != null then config.security.acme.certs.${hostOpts.useACMEHost}.directory
|
else if hostOpts.useACMEHost != null then certs.${hostOpts.useACMEHost}.directory
|
||||||
else abort "This case should never happen.";
|
else abort "This case should never happen.";
|
||||||
|
|
||||||
sslServerCert = if useACME then "${sslCertDir}/full.pem" else hostOpts.sslServerCert;
|
sslServerCert = if useACME then "${sslCertDir}/fullchain.pem" else hostOpts.sslServerCert;
|
||||||
sslServerKey = if useACME then "${sslCertDir}/key.pem" else hostOpts.sslServerKey;
|
sslServerKey = if useACME then "${sslCertDir}/key.pem" else hostOpts.sslServerKey;
|
||||||
sslServerChain = if useACME then "${sslCertDir}/fullchain.pem" else hostOpts.sslServerChain;
|
sslServerChain = if useACME then "${sslCertDir}/chain.pem" else hostOpts.sslServerChain;
|
||||||
|
|
||||||
acmeChallenge = optionalString useACME ''
|
acmeChallenge = optionalString useACME ''
|
||||||
Alias /.well-known/acme-challenge/ "${hostOpts.acmeRoot}/.well-known/acme-challenge/"
|
Alias /.well-known/acme-challenge/ "${hostOpts.acmeRoot}/.well-known/acme-challenge/"
|
||||||
@ -347,7 +356,6 @@ let
|
|||||||
cat ${php.phpIni} > $out
|
cat ${php.phpIni} > $out
|
||||||
echo "$options" >> $out
|
echo "$options" >> $out
|
||||||
'';
|
'';
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
|
|
||||||
@ -647,14 +655,17 @@ in
|
|||||||
wwwrun.gid = config.ids.gids.wwwrun;
|
wwwrun.gid = config.ids.gids.wwwrun;
|
||||||
};
|
};
|
||||||
|
|
||||||
security.acme.certs = mapAttrs (name: hostOpts: {
|
security.acme.certs = let
|
||||||
user = cfg.user;
|
acmePairs = map (hostOpts: nameValuePair hostOpts.hostName {
|
||||||
group = mkDefault cfg.group;
|
group = mkDefault cfg.group;
|
||||||
email = if hostOpts.adminAddr != null then hostOpts.adminAddr else cfg.adminAddr;
|
webroot = hostOpts.acmeRoot;
|
||||||
webroot = hostOpts.acmeRoot;
|
extraDomainNames = hostOpts.serverAliases;
|
||||||
extraDomains = genAttrs hostOpts.serverAliases (alias: null);
|
# Use the vhost-specific email address if provided, otherwise let
|
||||||
postRun = "systemctl reload httpd.service";
|
# security.acme.email or security.acme.certs.<cert>.email be used.
|
||||||
}) (filterAttrs (name: hostOpts: hostOpts.enableACME) cfg.virtualHosts);
|
email = mkOverride 2000 (if hostOpts.adminAddr != null then hostOpts.adminAddr else cfg.adminAddr);
|
||||||
|
# Filter for enableACME-only vhosts. Don't want to create dud certs
|
||||||
|
}) (filter (hostOpts: hostOpts.useACMEHost == null) acmeEnabledVhosts);
|
||||||
|
in listToAttrs acmePairs;
|
||||||
|
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
apachectl
|
apachectl
|
||||||
@ -724,16 +735,12 @@ in
|
|||||||
"Z '${cfg.logDir}' - ${svc.User} ${svc.Group}"
|
"Z '${cfg.logDir}' - ${svc.User} ${svc.Group}"
|
||||||
];
|
];
|
||||||
|
|
||||||
systemd.services.httpd =
|
systemd.services.httpd = {
|
||||||
let
|
description = "Apache HTTPD";
|
||||||
vhostsACME = filter (hostOpts: hostOpts.enableACME) vhosts;
|
|
||||||
in
|
|
||||||
{ description = "Apache HTTPD";
|
|
||||||
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
wants = concatLists (map (hostOpts: [ "acme-${hostOpts.hostName}.service" "acme-selfsigned-${hostOpts.hostName}.service" ]) vhostsACME);
|
wants = concatLists (map (certName: [ "acme-finished-${certName}.target" ]) dependentCertNames);
|
||||||
after = [ "network.target" "fs.target" ] ++ map (hostOpts: "acme-selfsigned-${hostOpts.hostName}.service") vhostsACME;
|
after = [ "network.target" ] ++ map (certName: "acme-selfsigned-${certName}.service") dependentCertNames;
|
||||||
before = map (hostOpts: "acme-${hostOpts.hostName}.service") vhostsACME;
|
before = map (certName: "acme-${certName}.service") dependentCertNames;
|
||||||
|
|
||||||
path = [ pkg pkgs.coreutils pkgs.gnugrep ];
|
path = [ pkg pkgs.coreutils pkgs.gnugrep ];
|
||||||
|
|
||||||
@ -767,5 +774,31 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# postRun hooks on cert renew can't be used to restart Apache since renewal
|
||||||
|
# runs as the unprivileged acme user. sslTargets are added to wantedBy + before
|
||||||
|
# which allows the acme-finished-$cert.target to signify the successful updating
|
||||||
|
# of certs end-to-end.
|
||||||
|
systemd.services.httpd-config-reload = let
|
||||||
|
sslServices = map (certName: "acme-${certName}.service") dependentCertNames;
|
||||||
|
sslTargets = map (certName: "acme-finished-${certName}.target") dependentCertNames;
|
||||||
|
in mkIf (sslServices != []) {
|
||||||
|
wantedBy = sslServices ++ [ "multi-user.target" ];
|
||||||
|
# Before the finished targets, after the renew services.
|
||||||
|
# This service might be needed for HTTP-01 challenges, but we only want to confirm
|
||||||
|
# certs are updated _after_ config has been reloaded.
|
||||||
|
before = sslTargets;
|
||||||
|
after = sslServices;
|
||||||
|
# Block reloading if not all certs exist yet.
|
||||||
|
# Happens when config changes add new vhosts/certs.
|
||||||
|
unitConfig.ConditionPathExists = map (certName: certs.${certName}.directory + "/fullchain.pem") dependentCertNames;
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
TimeoutSec = 60;
|
||||||
|
ExecCondition = "/run/current-system/systemd/bin/systemctl -q is-active httpd.service";
|
||||||
|
ExecStartPre = "${pkg}/bin/httpd -f ${httpdConf} -t";
|
||||||
|
ExecStart = "/run/current-system/systemd/bin/systemctl reload httpd.service";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -6,23 +6,23 @@ let
|
|||||||
cfg = config.services.nginx;
|
cfg = config.services.nginx;
|
||||||
certs = config.security.acme.certs;
|
certs = config.security.acme.certs;
|
||||||
vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts;
|
vhostsConfigs = mapAttrsToList (vhostName: vhostConfig: vhostConfig) virtualHosts;
|
||||||
acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME && vhostConfig.useACMEHost == null) vhostsConfigs;
|
acmeEnabledVhosts = filter (vhostConfig: vhostConfig.enableACME || vhostConfig.useACMEHost != null) vhostsConfigs;
|
||||||
|
dependentCertNames = unique (map (hostOpts: hostOpts.certName) acmeEnabledVhosts);
|
||||||
virtualHosts = mapAttrs (vhostName: vhostConfig:
|
virtualHosts = mapAttrs (vhostName: vhostConfig:
|
||||||
let
|
let
|
||||||
serverName = if vhostConfig.serverName != null
|
serverName = if vhostConfig.serverName != null
|
||||||
then vhostConfig.serverName
|
then vhostConfig.serverName
|
||||||
else vhostName;
|
else vhostName;
|
||||||
|
certName = if vhostConfig.useACMEHost != null
|
||||||
|
then vhostConfig.useACMEHost
|
||||||
|
else serverName;
|
||||||
in
|
in
|
||||||
vhostConfig // {
|
vhostConfig // {
|
||||||
inherit serverName;
|
inherit serverName certName;
|
||||||
} // (optionalAttrs vhostConfig.enableACME {
|
} // (optionalAttrs (vhostConfig.enableACME || vhostConfig.useACMEHost != null) {
|
||||||
sslCertificate = "${certs.${serverName}.directory}/fullchain.pem";
|
sslCertificate = "${certs.${certName}.directory}/fullchain.pem";
|
||||||
sslCertificateKey = "${certs.${serverName}.directory}/key.pem";
|
sslCertificateKey = "${certs.${certName}.directory}/key.pem";
|
||||||
sslTrustedCertificate = "${certs.${serverName}.directory}/full.pem";
|
sslTrustedCertificate = "${certs.${certName}.directory}/chain.pem";
|
||||||
}) // (optionalAttrs (vhostConfig.useACMEHost != null) {
|
|
||||||
sslCertificate = "${certs.${vhostConfig.useACMEHost}.directory}/fullchain.pem";
|
|
||||||
sslCertificateKey = "${certs.${vhostConfig.useACMEHost}.directory}/key.pem";
|
|
||||||
sslTrustedCertificate = "${certs.${vhostConfig.useACMEHost}.directory}/fullchain.pem";
|
|
||||||
})
|
})
|
||||||
) cfg.virtualHosts;
|
) cfg.virtualHosts;
|
||||||
enableIPv6 = config.networking.enableIPv6;
|
enableIPv6 = config.networking.enableIPv6;
|
||||||
@ -691,12 +691,12 @@ in
|
|||||||
systemd.services.nginx = {
|
systemd.services.nginx = {
|
||||||
description = "Nginx Web Server";
|
description = "Nginx Web Server";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
wants = concatLists (map (vhostConfig: ["acme-${vhostConfig.serverName}.service" "acme-selfsigned-${vhostConfig.serverName}.service"]) acmeEnabledVhosts);
|
wants = concatLists (map (certName: [ "acme-finished-${certName}.target" ]) dependentCertNames);
|
||||||
after = [ "network.target" ] ++ map (vhostConfig: "acme-selfsigned-${vhostConfig.serverName}.service") acmeEnabledVhosts;
|
after = [ "network.target" ] ++ map (certName: "acme-selfsigned-${certName}.service") dependentCertNames;
|
||||||
# Nginx needs to be started in order to be able to request certificates
|
# Nginx needs to be started in order to be able to request certificates
|
||||||
# (it's hosting the acme challenge after all)
|
# (it's hosting the acme challenge after all)
|
||||||
# This fixes https://github.com/NixOS/nixpkgs/issues/81842
|
# This fixes https://github.com/NixOS/nixpkgs/issues/81842
|
||||||
before = map (vhostConfig: "acme-${vhostConfig.serverName}.service") acmeEnabledVhosts;
|
before = map (certName: "acme-${certName}.service") dependentCertNames;
|
||||||
stopIfChanged = false;
|
stopIfChanged = false;
|
||||||
preStart = ''
|
preStart = ''
|
||||||
${cfg.preStart}
|
${cfg.preStart}
|
||||||
@ -753,37 +753,41 @@ in
|
|||||||
source = configFile;
|
source = configFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.nginx-config-reload = mkIf cfg.enableReload {
|
# postRun hooks on cert renew can't be used to restart Nginx since renewal
|
||||||
wants = [ "nginx.service" ];
|
# runs as the unprivileged acme user. sslTargets are added to wantedBy + before
|
||||||
wantedBy = [ "multi-user.target" ];
|
# which allows the acme-finished-$cert.target to signify the successful updating
|
||||||
restartTriggers = [ configFile ];
|
# of certs end-to-end.
|
||||||
# commented, because can cause extra delays during activate for this config:
|
systemd.services.nginx-config-reload = let
|
||||||
# services.nginx.virtualHosts."_".locations."/".proxyPass = "http://blabla:3000";
|
sslServices = map (certName: "acme-${certName}.service") dependentCertNames;
|
||||||
# stopIfChanged = false;
|
sslTargets = map (certName: "acme-finished-${certName}.target") dependentCertNames;
|
||||||
serviceConfig.Type = "oneshot";
|
in mkIf (cfg.enableReload || sslServices != []) {
|
||||||
serviceConfig.TimeoutSec = 60;
|
wants = optionals (cfg.enableReload) [ "nginx.service" ];
|
||||||
script = ''
|
wantedBy = sslServices ++ [ "multi-user.target" ];
|
||||||
if /run/current-system/systemd/bin/systemctl -q is-active nginx.service ; then
|
# Before the finished targets, after the renew services.
|
||||||
/run/current-system/systemd/bin/systemctl reload nginx.service
|
# This service might be needed for HTTP-01 challenges, but we only want to confirm
|
||||||
fi
|
# certs are updated _after_ config has been reloaded.
|
||||||
'';
|
before = sslTargets;
|
||||||
serviceConfig.RemainAfterExit = true;
|
after = sslServices;
|
||||||
|
restartTriggers = optionals (cfg.enableReload) [ configFile ];
|
||||||
|
# Block reloading if not all certs exist yet.
|
||||||
|
# Happens when config changes add new vhosts/certs.
|
||||||
|
unitConfig.ConditionPathExists = optionals (sslServices != []) (map (certName: certs.${certName}.directory + "/fullchain.pem") dependentCertNames);
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
TimeoutSec = 60;
|
||||||
|
ExecCondition = "/run/current-system/systemd/bin/systemctl -q is-active nginx.service";
|
||||||
|
ExecStart = "/run/current-system/systemd/bin/systemctl reload nginx.service";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
security.acme.certs = filterAttrs (n: v: v != {}) (
|
security.acme.certs = let
|
||||||
let
|
acmePairs = map (vhostConfig: nameValuePair vhostConfig.serverName {
|
||||||
acmePairs = map (vhostConfig: { name = vhostConfig.serverName; value = {
|
group = mkDefault cfg.group;
|
||||||
user = cfg.user;
|
webroot = vhostConfig.acmeRoot;
|
||||||
group = lib.mkDefault cfg.group;
|
extraDomainNames = vhostConfig.serverAliases;
|
||||||
webroot = vhostConfig.acmeRoot;
|
# Filter for enableACME-only vhosts. Don't want to create dud certs
|
||||||
extraDomains = genAttrs vhostConfig.serverAliases (alias: null);
|
}) (filter (vhostConfig: vhostConfig.useACMEHost == null) acmeEnabledVhosts);
|
||||||
postRun = ''
|
in listToAttrs acmePairs;
|
||||||
/run/current-system/systemd/bin/systemctl reload nginx
|
|
||||||
'';
|
|
||||||
}; }) acmeEnabledVhosts;
|
|
||||||
in
|
|
||||||
listToAttrs acmePairs
|
|
||||||
);
|
|
||||||
|
|
||||||
users.users = optionalAttrs (cfg.user == "nginx") {
|
users.users = optionalAttrs (cfg.user == "nginx") {
|
||||||
nginx = {
|
nginx = {
|
||||||
|
@ -1,29 +1,43 @@
|
|||||||
let
|
let
|
||||||
commonConfig = ./common/acme/client;
|
commonConfig = ./common/acme/client;
|
||||||
|
|
||||||
dnsScript = {writeScript, dnsAddress, bash, curl}: writeScript "dns-hook.sh" ''
|
dnsServerIP = nodes: nodes.dnsserver.config.networking.primaryIPAddress;
|
||||||
#!${bash}/bin/bash
|
|
||||||
|
dnsScript = {pkgs, nodes}: let
|
||||||
|
dnsAddress = dnsServerIP nodes;
|
||||||
|
in pkgs.writeShellScript "dns-hook.sh" ''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
echo '[INFO]' "[$2]" 'dns-hook.sh' $*
|
echo '[INFO]' "[$2]" 'dns-hook.sh' $*
|
||||||
if [ "$1" = "present" ]; then
|
if [ "$1" = "present" ]; then
|
||||||
${curl}/bin/curl --data '{"host": "'"$2"'", "value": "'"$3"'"}' http://${dnsAddress}:8055/set-txt
|
${pkgs.curl}/bin/curl --data '{"host": "'"$2"'", "value": "'"$3"'"}' http://${dnsAddress}:8055/set-txt
|
||||||
else
|
else
|
||||||
${curl}/bin/curl --data '{"host": "'"$2"'"}' http://${dnsAddress}:8055/clear-txt
|
${pkgs.curl}/bin/curl --data '{"host": "'"$2"'"}' http://${dnsAddress}:8055/clear-txt
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
documentRoot = pkgs: pkgs.runCommand "docroot" {} ''
|
||||||
|
mkdir -p "$out"
|
||||||
|
echo hello world > "$out/index.html"
|
||||||
|
'';
|
||||||
|
|
||||||
|
vhostBase = pkgs: {
|
||||||
|
forceSSL = true;
|
||||||
|
locations."/".root = documentRoot pkgs;
|
||||||
|
};
|
||||||
|
|
||||||
in import ./make-test-python.nix ({ lib, ... }: {
|
in import ./make-test-python.nix ({ lib, ... }: {
|
||||||
name = "acme";
|
name = "acme";
|
||||||
meta.maintainers = lib.teams.acme.members;
|
meta.maintainers = lib.teams.acme.members;
|
||||||
|
|
||||||
nodes = rec {
|
nodes = {
|
||||||
|
# The fake ACME server which will respond to client requests
|
||||||
acme = { nodes, lib, ... }: {
|
acme = { nodes, lib, ... }: {
|
||||||
imports = [ ./common/acme/server ];
|
imports = [ ./common/acme/server ];
|
||||||
networking.nameservers = lib.mkForce [
|
networking.nameservers = lib.mkForce [ (dnsServerIP nodes) ];
|
||||||
nodes.dnsserver.config.networking.primaryIPAddress
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# A fake DNS server which can be configured with records as desired
|
||||||
|
# Used to test DNS-01 challenge
|
||||||
dnsserver = { nodes, pkgs, ... }: {
|
dnsserver = { nodes, pkgs, ... }: {
|
||||||
networking.firewall.allowedTCPPorts = [ 8055 53 ];
|
networking.firewall.allowedTCPPorts = [ 8055 53 ];
|
||||||
networking.firewall.allowedUDPPorts = [ 53 ];
|
networking.firewall.allowedUDPPorts = [ 53 ];
|
||||||
@ -39,112 +53,97 @@ in import ./make-test-python.nix ({ lib, ... }: {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
acmeStandalone = { nodes, lib, config, pkgs, ... }: {
|
# A web server which will be the node requesting certs
|
||||||
imports = [ commonConfig ];
|
webserver = { pkgs, nodes, lib, config, ... }: {
|
||||||
networking.nameservers = lib.mkForce [
|
|
||||||
nodes.dnsserver.config.networking.primaryIPAddress
|
|
||||||
];
|
|
||||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
|
||||||
security.acme.certs."standalone.test" = {
|
|
||||||
webroot = "/var/lib/acme/acme-challenges";
|
|
||||||
};
|
|
||||||
systemd.targets."acme-finished-standalone.test" = {
|
|
||||||
after = [ "acme-standalone.test.service" ];
|
|
||||||
wantedBy = [ "acme-standalone.test.service" ];
|
|
||||||
};
|
|
||||||
services.nginx.enable = true;
|
|
||||||
services.nginx.virtualHosts."standalone.test" = {
|
|
||||||
locations."/.well-known/acme-challenge".root = "/var/lib/acme/acme-challenges";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
webserver = { nodes, config, pkgs, lib, ... }: {
|
|
||||||
imports = [ commonConfig ];
|
imports = [ commonConfig ];
|
||||||
|
networking.nameservers = lib.mkForce [ (dnsServerIP nodes) ];
|
||||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
networking.nameservers = lib.mkForce [
|
|
||||||
nodes.dnsserver.config.networking.primaryIPAddress
|
|
||||||
];
|
|
||||||
|
|
||||||
# A target remains active. Use this to probe the fact that
|
# OpenSSL will be used for more thorough certificate validation
|
||||||
# a service fired eventhough it is not RemainAfterExit
|
environment.systemPackages = [ pkgs.openssl ];
|
||||||
systemd.targets."acme-finished-a.example.test" = {
|
|
||||||
after = [ "acme-a.example.test.service" ];
|
# Set log level to info so that we can see when the service is reloaded
|
||||||
wantedBy = [ "acme-a.example.test.service" ];
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.enable = true;
|
# 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."a.example.test" = {
|
# Cert config changes will not cause the nginx configuration to change.
|
||||||
enableACME = true;
|
# This tests that the reload service is correctly triggered.
|
||||||
forceSSL = true;
|
# It also tests that postRun is exec'd as root
|
||||||
locations."/".root = pkgs.runCommand "docroot" {} ''
|
specialisation.cert-change.configuration = { pkgs, ... }: {
|
||||||
mkdir -p "$out"
|
security.acme.certs."a.example.test".keyType = "ec384";
|
||||||
echo hello world > "$out/index.html"
|
security.acme.certs."a.example.test".postRun = ''
|
||||||
|
set -euo pipefail
|
||||||
|
touch test
|
||||||
|
chown root:root test
|
||||||
|
echo testing > test
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
security.acme.server = "https://acme.test/dir";
|
# Now adding an alias to ensure that the certs are updated
|
||||||
|
specialisation.nginx-aliases.configuration = { pkgs, ... }: {
|
||||||
specialisation.second-cert.configuration = {pkgs, ...}: {
|
services.nginx.virtualHosts."a.example.test" = {
|
||||||
systemd.targets."acme-finished-b.example.test" = {
|
serverAliases = [ "b.example.test" ];
|
||||||
after = [ "acme-b.example.test.service" ];
|
|
||||||
wantedBy = [ "acme-b.example.test.service" ];
|
|
||||||
};
|
|
||||||
services.nginx.virtualHosts."b.example.test" = {
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
locations."/".root = pkgs.runCommand "docroot" {} ''
|
|
||||||
mkdir -p "$out"
|
|
||||||
echo hello world > "$out/index.html"
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
specialisation.dns-01.configuration = {pkgs, config, nodes, lib, ...}: {
|
# 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" = {
|
security.acme.certs."example.test" = {
|
||||||
domain = "*.example.test";
|
domain = "*.example.test";
|
||||||
|
group = config.services.nginx.group;
|
||||||
dnsProvider = "exec";
|
dnsProvider = "exec";
|
||||||
dnsPropagationCheck = false;
|
dnsPropagationCheck = false;
|
||||||
credentialsFile = with pkgs; writeText "wildcard.env" ''
|
credentialsFile = pkgs.writeText "wildcard.env" ''
|
||||||
EXEC_PATH=${dnsScript { inherit writeScript bash curl; dnsAddress = nodes.dnsserver.config.networking.primaryIPAddress; }}
|
EXEC_PATH=${dnsScript { inherit pkgs nodes; }}
|
||||||
'';
|
'';
|
||||||
user = config.services.nginx.user;
|
|
||||||
group = config.services.nginx.group;
|
|
||||||
};
|
};
|
||||||
systemd.targets."acme-finished-example.test" = {
|
|
||||||
after = [ "acme-example.test.service" ];
|
services.nginx.virtualHosts."dns.example.test" = (vhostBase pkgs) // {
|
||||||
wantedBy = [ "acme-example.test.service" ];
|
useACMEHost = "example.test";
|
||||||
};
|
|
||||||
systemd.services."acme-example.test" = {
|
|
||||||
before = [ "nginx.service" ];
|
|
||||||
wantedBy = [ "nginx.service" ];
|
|
||||||
};
|
|
||||||
services.nginx.virtualHosts."c.example.test" = {
|
|
||||||
forceSSL = true;
|
|
||||||
sslCertificate = config.security.acme.certs."example.test".directory + "/cert.pem";
|
|
||||||
sslTrustedCertificate = config.security.acme.certs."example.test".directory + "/full.pem";
|
|
||||||
sslCertificateKey = config.security.acme.certs."example.test".directory + "/key.pem";
|
|
||||||
locations."/".root = pkgs.runCommand "docroot" {} ''
|
|
||||||
mkdir -p "$out"
|
|
||||||
echo hello world > "$out/index.html"
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# When nginx depends on a service that is slow to start up, requesting used to fail
|
# Validate service relationships by adding a slow start service to nginx' wants.
|
||||||
# certificates fail. Reproducer for https://github.com/NixOS/nixpkgs/issues/81842
|
# Reproducer for https://github.com/NixOS/nixpkgs/issues/81842
|
||||||
specialisation.slow-startup.configuration = { pkgs, config, nodes, lib, ...}: {
|
specialisation.slow-startup.configuration = { pkgs, config, nodes, lib, ... }: {
|
||||||
systemd.services.my-slow-service = {
|
systemd.services.my-slow-service = {
|
||||||
wantedBy = [ "multi-user.target" "nginx.service" ];
|
wantedBy = [ "multi-user.target" "nginx.service" ];
|
||||||
before = [ "nginx.service" ];
|
before = [ "nginx.service" ];
|
||||||
preStart = "sleep 5";
|
preStart = "sleep 5";
|
||||||
script = "${pkgs.python3}/bin/python -m http.server";
|
script = "${pkgs.python3}/bin/python -m http.server";
|
||||||
};
|
};
|
||||||
systemd.targets."acme-finished-d.example.com" = {
|
|
||||||
after = [ "acme-d.example.com.service" ];
|
services.nginx.virtualHosts."slow.example.com" = {
|
||||||
wantedBy = [ "acme-d.example.com.service" ];
|
|
||||||
};
|
|
||||||
services.nginx.virtualHosts."d.example.com" = {
|
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
locations."/".proxyPass = "http://localhost:8000";
|
locations."/".proxyPass = "http://localhost:8000";
|
||||||
@ -152,11 +151,13 @@ in import ./make-test-python.nix ({ lib, ... }: {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
client = {nodes, lib, ...}: {
|
# The client will be used to curl the webserver to validate configuration
|
||||||
|
client = {nodes, lib, pkgs, ...}: {
|
||||||
imports = [ commonConfig ];
|
imports = [ commonConfig ];
|
||||||
networking.nameservers = lib.mkForce [
|
networking.nameservers = lib.mkForce [ (dnsServerIP nodes) ];
|
||||||
nodes.dnsserver.config.networking.primaryIPAddress
|
|
||||||
];
|
# OpenSSL will be used for more thorough certificate validation
|
||||||
|
environment.systemPackages = [ pkgs.openssl ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -167,73 +168,168 @@ in import ./make-test-python.nix ({ lib, ... }: {
|
|||||||
in
|
in
|
||||||
# Note, wait_for_unit does not work for oneshot services that do not have RemainAfterExit=true,
|
# 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
|
# this is because a oneshot goes from inactive => activating => inactive, and never
|
||||||
# reaches the active state. To work around this, we create some mock target units which
|
# reaches the active state. Targets do not have this issue.
|
||||||
# get pulled in by the oneshot units. The target units linger after activation, and hence we
|
|
||||||
# can use them to probe that a oneshot fired. It is a bit ugly, but it is the best we can do
|
|
||||||
''
|
''
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
has_switched = False
|
||||||
|
|
||||||
|
|
||||||
|
def switch_to(node, name):
|
||||||
|
global has_switched
|
||||||
|
if has_switched:
|
||||||
|
node.succeed(
|
||||||
|
"${switchToNewServer}"
|
||||||
|
)
|
||||||
|
has_switched = True
|
||||||
|
node.succeed(
|
||||||
|
f"/run/current-system/specialisation/{name}/bin/switch-to-configuration test"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Ensures the issuer of our cert matches the chain
|
||||||
|
# and matches the issuer we expect it to be.
|
||||||
|
# It's a good validation to ensure the cert.pem and fullchain.pem
|
||||||
|
# are not still selfsigned afer verification
|
||||||
|
def check_issuer(node, cert_name, issuer):
|
||||||
|
for fname in ("cert.pem", "fullchain.pem"):
|
||||||
|
actual_issuer = node.succeed(
|
||||||
|
f"openssl x509 -noout -issuer -in /var/lib/acme/{cert_name}/{fname}"
|
||||||
|
).partition("=")[2]
|
||||||
|
print(f"{fname} issuer: {actual_issuer}")
|
||||||
|
assert issuer.lower() in actual_issuer.lower()
|
||||||
|
|
||||||
|
|
||||||
|
# Ensure cert comes before chain in fullchain.pem
|
||||||
|
def check_fullchain(node, cert_name):
|
||||||
|
subject_data = node.succeed(
|
||||||
|
f"openssl crl2pkcs7 -nocrl -certfile /var/lib/acme/{cert_name}/fullchain.pem"
|
||||||
|
" | openssl pkcs7 -print_certs -noout"
|
||||||
|
)
|
||||||
|
for line in subject_data.lower().split("\n"):
|
||||||
|
if "subject" in line:
|
||||||
|
print(f"First subject in fullchain.pem: ", line)
|
||||||
|
assert cert_name.lower() in line
|
||||||
|
return
|
||||||
|
|
||||||
|
assert False
|
||||||
|
|
||||||
|
|
||||||
|
def check_connection(node, domain, retries=3):
|
||||||
|
assert retries >= 0
|
||||||
|
|
||||||
|
result = node.succeed(
|
||||||
|
"openssl s_client -brief -verify 2 -CAfile /tmp/ca.crt"
|
||||||
|
f" -servername {domain} -connect {domain}:443 < /dev/null 2>&1"
|
||||||
|
)
|
||||||
|
|
||||||
|
for line in result.lower().split("\n"):
|
||||||
|
if "verification" in line and "error" in line:
|
||||||
|
time.sleep(1)
|
||||||
|
return check_connection(node, domain, retries - 1)
|
||||||
|
|
||||||
|
|
||||||
|
def check_connection_key_bits(node, domain, bits, retries=3):
|
||||||
|
assert retries >= 0
|
||||||
|
|
||||||
|
result = node.succeed(
|
||||||
|
"openssl s_client -CAfile /tmp/ca.crt"
|
||||||
|
f" -servername {domain} -connect {domain}:443 < /dev/null"
|
||||||
|
" | openssl x509 -noout -text | grep -i Public-Key"
|
||||||
|
)
|
||||||
|
print("Key type:", result)
|
||||||
|
|
||||||
|
if bits not in result:
|
||||||
|
time.sleep(1)
|
||||||
|
return check_connection_key_bits(node, domain, bits, retries - 1)
|
||||||
|
|
||||||
|
|
||||||
client.start()
|
client.start()
|
||||||
dnsserver.start()
|
dnsserver.start()
|
||||||
|
|
||||||
acme.wait_for_unit("default.target")
|
|
||||||
dnsserver.wait_for_unit("pebble-challtestsrv.service")
|
dnsserver.wait_for_unit("pebble-challtestsrv.service")
|
||||||
|
client.wait_for_unit("default.target")
|
||||||
|
|
||||||
client.succeed(
|
client.succeed(
|
||||||
'curl --data \'{"host": "acme.test", "addresses": ["${nodes.acme.config.networking.primaryIPAddress}"]}\' http://${nodes.dnsserver.config.networking.primaryIPAddress}:8055/add-a'
|
'curl --data \'{"host": "acme.test", "addresses": ["${nodes.acme.config.networking.primaryIPAddress}"]}\' http://${dnsServerIP nodes}:8055/add-a'
|
||||||
)
|
|
||||||
client.succeed(
|
|
||||||
'curl --data \'{"host": "standalone.test", "addresses": ["${nodes.acmeStandalone.config.networking.primaryIPAddress}"]}\' http://${nodes.dnsserver.config.networking.primaryIPAddress}:8055/add-a'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
acme.start()
|
acme.start()
|
||||||
acmeStandalone.start()
|
webserver.start()
|
||||||
|
|
||||||
acme.wait_for_unit("default.target")
|
acme.wait_for_unit("default.target")
|
||||||
acme.wait_for_unit("pebble.service")
|
acme.wait_for_unit("pebble.service")
|
||||||
|
|
||||||
with subtest("can request certificate with HTTPS-01 challenge"):
|
|
||||||
acmeStandalone.wait_for_unit("default.target")
|
|
||||||
acmeStandalone.succeed("systemctl start acme-standalone.test.service")
|
|
||||||
acmeStandalone.wait_for_unit("acme-finished-standalone.test.target")
|
|
||||||
|
|
||||||
client.wait_for_unit("default.target")
|
|
||||||
|
|
||||||
client.succeed("curl https://acme.test:15000/roots/0 > /tmp/ca.crt")
|
client.succeed("curl https://acme.test:15000/roots/0 > /tmp/ca.crt")
|
||||||
client.succeed("curl https://acme.test:15000/intermediate-keys/0 >> /tmp/ca.crt")
|
client.succeed("curl https://acme.test:15000/intermediate-keys/0 >> /tmp/ca.crt")
|
||||||
|
|
||||||
with subtest("Can request certificate for nginx service"):
|
with subtest("Can request certificate with HTTPS-01 challenge"):
|
||||||
webserver.wait_for_unit("acme-finished-a.example.test.target")
|
webserver.wait_for_unit("acme-finished-a.example.test.target")
|
||||||
client.succeed(
|
check_fullchain(webserver, "a.example.test")
|
||||||
"curl --cacert /tmp/ca.crt https://a.example.test/ | grep -qF 'hello world'"
|
check_issuer(webserver, "a.example.test", "pebble")
|
||||||
)
|
check_connection(client, "a.example.test")
|
||||||
|
|
||||||
with subtest("Can add another certificate for nginx service"):
|
with subtest("Can generate valid selfsigned certs"):
|
||||||
webserver.succeed(
|
webserver.succeed("systemctl clean acme-a.example.test.service --what=state")
|
||||||
"/run/current-system/specialisation/second-cert/bin/switch-to-configuration test"
|
webserver.succeed("systemctl start acme-selfsigned-a.example.test.service")
|
||||||
)
|
check_fullchain(webserver, "a.example.test")
|
||||||
webserver.wait_for_unit("acme-finished-b.example.test.target")
|
check_issuer(webserver, "a.example.test", "minica")
|
||||||
client.succeed(
|
# Will succeed if nginx can load the certs
|
||||||
"curl --cacert /tmp/ca.crt https://b.example.test/ | grep -qF 'hello world'"
|
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("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 /var/lib/acme/a.example.test/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")
|
||||||
|
keyhash_old = webserver.succeed("md5sum /var/lib/acme/a.example.test/key.pem")
|
||||||
|
switch_to(webserver, "nginx-aliases")
|
||||||
|
webserver.wait_for_unit("acme-finished-a.example.test.target")
|
||||||
|
check_issuer(webserver, "a.example.test", "pebble")
|
||||||
|
check_connection(client, "a.example.test")
|
||||||
|
check_connection(client, "b.example.test")
|
||||||
|
keyhash_new = webserver.succeed("md5sum /var/lib/acme/a.example.test/key.pem")
|
||||||
|
assert keyhash_old == keyhash_new
|
||||||
|
|
||||||
|
with subtest("Can request certificates for vhost + aliases (apache-httpd)"):
|
||||||
|
switch_to(webserver, "httpd-aliases")
|
||||||
|
webserver.wait_for_unit("acme-finished-c.example.test.target")
|
||||||
|
check_issuer(webserver, "c.example.test", "pebble")
|
||||||
|
check_connection(client, "c.example.test")
|
||||||
|
check_connection(client, "d.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"):
|
with subtest("Can request wildcard certificates using DNS-01 challenge"):
|
||||||
webserver.succeed(
|
switch_to(webserver, "dns-01")
|
||||||
"${switchToNewServer}"
|
|
||||||
)
|
|
||||||
webserver.succeed(
|
|
||||||
"/run/current-system/specialisation/dns-01/bin/switch-to-configuration test"
|
|
||||||
)
|
|
||||||
webserver.wait_for_unit("acme-finished-example.test.target")
|
webserver.wait_for_unit("acme-finished-example.test.target")
|
||||||
client.succeed(
|
check_issuer(webserver, "example.test", "pebble")
|
||||||
"curl --cacert /tmp/ca.crt https://c.example.test/ | grep -qF 'hello world'"
|
check_connection(client, "dns.example.test")
|
||||||
)
|
|
||||||
|
|
||||||
with subtest("Can request certificate of nginx when startup is delayed"):
|
|
||||||
webserver.succeed(
|
|
||||||
"${switchToNewServer}"
|
|
||||||
)
|
|
||||||
webserver.succeed(
|
|
||||||
"/run/current-system/specialisation/slow-startup/bin/switch-to-configuration test"
|
|
||||||
)
|
|
||||||
webserver.wait_for_unit("acme-finished-d.example.com.target")
|
|
||||||
client.succeed("curl --cacert /tmp/ca.crt https://d.example.com/")
|
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
|
@ -325,6 +325,7 @@ in
|
|||||||
sonarr = handleTest ./sonarr.nix {};
|
sonarr = handleTest ./sonarr.nix {};
|
||||||
sslh = handleTest ./sslh.nix {};
|
sslh = handleTest ./sslh.nix {};
|
||||||
sssd = handleTestOn ["x86_64-linux"] ./sssd.nix {};
|
sssd = handleTestOn ["x86_64-linux"] ./sssd.nix {};
|
||||||
|
sssd-ldap = handleTestOn ["x86_64-linux"] ./sssd-ldap.nix {};
|
||||||
strongswan-swanctl = handleTest ./strongswan-swanctl.nix {};
|
strongswan-swanctl = handleTest ./strongswan-swanctl.nix {};
|
||||||
sudo = handleTest ./sudo.nix {};
|
sudo = handleTest ./sudo.nix {};
|
||||||
switchTest = handleTest ./switch-test.nix {};
|
switchTest = handleTest ./switch-test.nix {};
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
{ lib, nodes, pkgs, ... }:
|
{ lib, nodes, pkgs, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
acme-ca = nodes.acme.config.test-support.acme.caCert;
|
caCert = nodes.acme.config.test-support.acme.caCert;
|
||||||
in
|
caDomain = nodes.acme.config.test-support.acme.caDomain;
|
||||||
|
|
||||||
{
|
in {
|
||||||
security.acme = {
|
security.acme = {
|
||||||
server = "https://acme.test/dir";
|
server = "https://${caDomain}/dir";
|
||||||
email = "hostmaster@example.test";
|
email = "hostmaster@example.test";
|
||||||
acceptTerms = true;
|
acceptTerms = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
security.pki.certificateFiles = [ acme-ca ];
|
security.pki.certificateFiles = [ caCert ];
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
# config.test-support.acme.caCert
|
# config.test-support.acme.caCert
|
||||||
#
|
#
|
||||||
# This value can be used inside the configuration of other test nodes to inject
|
# This value can be used inside the configuration of other test nodes to inject
|
||||||
# the snakeoil certificate into security.pki.certificateFiles or into package
|
# the test certificate into security.pki.certificateFiles or into package
|
||||||
# overlays.
|
# overlays.
|
||||||
#
|
#
|
||||||
# Another value that's needed if you don't use a custom resolver (see below for
|
# Another value that's needed if you don't use a custom resolver (see below for
|
||||||
@ -50,19 +50,13 @@
|
|||||||
# Also make sure that whenever you use a resolver from a different test node
|
# Also make sure that whenever you use a resolver from a different test node
|
||||||
# that it has to be started _before_ the ACME service.
|
# that it has to be started _before_ the ACME service.
|
||||||
{ config, pkgs, lib, ... }:
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
|
||||||
let
|
let
|
||||||
snakeOilCerts = import ./snakeoil-certs.nix;
|
testCerts = import ./snakeoil-certs.nix {
|
||||||
|
minica = pkgs.minica;
|
||||||
|
mkDerivation = pkgs.stdenv.mkDerivation;
|
||||||
|
};
|
||||||
|
domain = testCerts.domain;
|
||||||
|
|
||||||
wfeDomain = "acme.test";
|
|
||||||
wfeCertFile = snakeOilCerts.${wfeDomain}.cert;
|
|
||||||
wfeKeyFile = snakeOilCerts.${wfeDomain}.key;
|
|
||||||
|
|
||||||
siteDomain = "acme.test";
|
|
||||||
siteCertFile = snakeOilCerts.${siteDomain}.cert;
|
|
||||||
siteKeyFile = snakeOilCerts.${siteDomain}.key;
|
|
||||||
pebble = pkgs.pebble;
|
|
||||||
resolver = let
|
resolver = let
|
||||||
message = "You need to define a resolver for the acme test module.";
|
message = "You need to define a resolver for the acme test module.";
|
||||||
firstNS = lib.head config.networking.nameservers;
|
firstNS = lib.head config.networking.nameservers;
|
||||||
@ -71,8 +65,9 @@ let
|
|||||||
pebbleConf.pebble = {
|
pebbleConf.pebble = {
|
||||||
listenAddress = "0.0.0.0:443";
|
listenAddress = "0.0.0.0:443";
|
||||||
managementListenAddress = "0.0.0.0:15000";
|
managementListenAddress = "0.0.0.0:15000";
|
||||||
certificate = snakeOilCerts.${wfeDomain}.cert;
|
# These certs and keys are used for the Web Front End (WFE)
|
||||||
privateKey = snakeOilCerts.${wfeDomain}.key;
|
certificate = testCerts.${domain}.cert;
|
||||||
|
privateKey = testCerts.${domain}.key;
|
||||||
httpPort = 80;
|
httpPort = 80;
|
||||||
tlsPort = 443;
|
tlsPort = 443;
|
||||||
ocspResponderURL = "http://0.0.0.0:4002";
|
ocspResponderURL = "http://0.0.0.0:4002";
|
||||||
@ -80,18 +75,30 @@ let
|
|||||||
};
|
};
|
||||||
|
|
||||||
pebbleConfFile = pkgs.writeText "pebble.conf" (builtins.toJSON pebbleConf);
|
pebbleConfFile = pkgs.writeText "pebble.conf" (builtins.toJSON pebbleConf);
|
||||||
pebbleDataDir = "/root/pebble";
|
|
||||||
|
|
||||||
in {
|
in {
|
||||||
imports = [ ../../resolver.nix ];
|
imports = [ ../../resolver.nix ];
|
||||||
|
|
||||||
options.test-support.acme.caCert = lib.mkOption {
|
options.test-support.acme = with lib; {
|
||||||
type = lib.types.path;
|
caDomain = mkOption {
|
||||||
description = ''
|
type = types.str;
|
||||||
A certificate file to use with the <literal>nodes</literal> attribute to
|
readOnly = true;
|
||||||
inject the snakeoil CA certificate used in the ACME server into
|
default = domain;
|
||||||
<option>security.pki.certificateFiles</option>.
|
description = ''
|
||||||
'';
|
A domain name to use with the <literal>nodes</literal> attribute to
|
||||||
|
identify the CA server.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
caCert = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
readOnly = true;
|
||||||
|
default = testCerts.ca.cert;
|
||||||
|
description = ''
|
||||||
|
A certificate file to use with the <literal>nodes</literal> attribute to
|
||||||
|
inject the test CA certificate used in the ACME server into
|
||||||
|
<option>security.pki.certificateFiles</option>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
@ -99,35 +106,32 @@ in {
|
|||||||
resolver.enable = let
|
resolver.enable = let
|
||||||
isLocalResolver = config.networking.nameservers == [ "127.0.0.1" ];
|
isLocalResolver = config.networking.nameservers == [ "127.0.0.1" ];
|
||||||
in lib.mkOverride 900 isLocalResolver;
|
in lib.mkOverride 900 isLocalResolver;
|
||||||
acme.caCert = snakeOilCerts.ca.cert;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# This has priority 140, because modules/testing/test-instrumentation.nix
|
# This has priority 140, because modules/testing/test-instrumentation.nix
|
||||||
# already overrides this with priority 150.
|
# already overrides this with priority 150.
|
||||||
networking.nameservers = lib.mkOverride 140 [ "127.0.0.1" ];
|
networking.nameservers = lib.mkOverride 140 [ "127.0.0.1" ];
|
||||||
networking.firewall.enable = false;
|
networking.firewall.allowedTCPPorts = [ 80 443 15000 4002 ];
|
||||||
|
|
||||||
networking.extraHosts = ''
|
networking.extraHosts = ''
|
||||||
127.0.0.1 ${wfeDomain}
|
127.0.0.1 ${domain}
|
||||||
${config.networking.primaryIPAddress} ${wfeDomain} ${siteDomain}
|
${config.networking.primaryIPAddress} ${domain}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
systemd.services = {
|
systemd.services = {
|
||||||
pebble = {
|
pebble = {
|
||||||
enable = true;
|
enable = true;
|
||||||
description = "Pebble ACME server";
|
description = "Pebble ACME server";
|
||||||
requires = [ ];
|
|
||||||
wantedBy = [ "network.target" ];
|
wantedBy = [ "network.target" ];
|
||||||
preStart = ''
|
|
||||||
mkdir ${pebbleDataDir}
|
|
||||||
'';
|
|
||||||
script = ''
|
|
||||||
cd ${pebbleDataDir}
|
|
||||||
${pebble}/bin/pebble -config ${pebbleConfFile}
|
|
||||||
'';
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
|
RuntimeDirectory = "pebble";
|
||||||
|
WorkingDirectory = "/run/pebble";
|
||||||
|
|
||||||
# Required to bind on privileged ports.
|
# Required to bind on privileged ports.
|
||||||
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
|
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
|
||||||
|
|
||||||
|
ExecStart = "${pkgs.pebble}/bin/pebble -config ${pebbleConfFile}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
{ pkgs ? import <nixpkgs> {}
|
|
||||||
, lib ? pkgs.lib
|
|
||||||
, domains ? [ "acme.test" ]
|
|
||||||
}:
|
|
||||||
|
|
||||||
pkgs.runCommand "acme-snakeoil-ca" {
|
|
||||||
nativeBuildInputs = [ pkgs.openssl ];
|
|
||||||
} ''
|
|
||||||
addpem() {
|
|
||||||
local file="$1"; shift
|
|
||||||
local storeFileName="$(IFS=.; echo "$*")"
|
|
||||||
|
|
||||||
echo -n " " >> "$out"
|
|
||||||
|
|
||||||
# Every following argument is an attribute, so let's recurse and check
|
|
||||||
# every attribute whether it must be quoted and write it into $out.
|
|
||||||
while [ -n "$1" ]; do
|
|
||||||
if expr match "$1" '^[a-zA-Z][a-zA-Z0-9]*$' > /dev/null; then
|
|
||||||
echo -n "$1" >> "$out"
|
|
||||||
else
|
|
||||||
echo -n '"' >> "$out"
|
|
||||||
echo -n "$1" | sed -e 's/["$]/\\&/g' >> "$out"
|
|
||||||
echo -n '"' >> "$out"
|
|
||||||
fi
|
|
||||||
shift
|
|
||||||
[ -z "$1" ] || echo -n . >> "$out"
|
|
||||||
done
|
|
||||||
|
|
||||||
echo " = builtins.toFile \"$storeFileName\" '''" >> "$out"
|
|
||||||
sed -e 's/^/ /' "$file" >> "$out"
|
|
||||||
|
|
||||||
echo " ''';" >> "$out"
|
|
||||||
}
|
|
||||||
|
|
||||||
echo '# Generated via mkcert.sh in the same directory.' > "$out"
|
|
||||||
echo '{' >> "$out"
|
|
||||||
|
|
||||||
openssl req -newkey rsa:4096 -x509 -sha256 -days 36500 \
|
|
||||||
-subj '/CN=Snakeoil CA' -nodes -out ca.pem -keyout ca.key
|
|
||||||
|
|
||||||
addpem ca.key ca key
|
|
||||||
addpem ca.pem ca cert
|
|
||||||
|
|
||||||
${lib.concatMapStrings (fqdn: let
|
|
||||||
opensslConfig = pkgs.writeText "snakeoil.cnf" ''
|
|
||||||
[req]
|
|
||||||
default_bits = 4096
|
|
||||||
prompt = no
|
|
||||||
default_md = sha256
|
|
||||||
req_extensions = req_ext
|
|
||||||
distinguished_name = dn
|
|
||||||
[dn]
|
|
||||||
CN = ${fqdn}
|
|
||||||
[req_ext]
|
|
||||||
subjectAltName = DNS:${fqdn}
|
|
||||||
'';
|
|
||||||
in ''
|
|
||||||
export OPENSSL_CONF=${lib.escapeShellArg opensslConfig}
|
|
||||||
openssl genrsa -out snakeoil.key 4096
|
|
||||||
openssl req -new -key snakeoil.key -out snakeoil.csr
|
|
||||||
openssl x509 -req -in snakeoil.csr -sha256 -set_serial 666 \
|
|
||||||
-CA ca.pem -CAkey ca.key -out snakeoil.pem -days 36500 \
|
|
||||||
-extfile "$OPENSSL_CONF" -extensions req_ext
|
|
||||||
addpem snakeoil.key ${lib.escapeShellArg fqdn} key
|
|
||||||
addpem snakeoil.pem ${lib.escapeShellArg fqdn} cert
|
|
||||||
'') domains}
|
|
||||||
|
|
||||||
echo '}' >> "$out"
|
|
||||||
''
|
|
@ -1,6 +0,0 @@
|
|||||||
#!/usr/bin/env nix-shell
|
|
||||||
#!nix-shell -p nix bash -i bash
|
|
||||||
set -e
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
storepath="$(nix-build --no-out-link mkcerts.nix)"
|
|
||||||
cat "$storepath" > snakeoil-certs.nix
|
|
@ -1,172 +1,37 @@
|
|||||||
# Generated via mkcert.sh in the same directory.
|
# Minica can provide a CA key and cert, plus a key
|
||||||
{
|
# and cert for our fake CA server's Web Front End (WFE).
|
||||||
ca.key = builtins.toFile "ca.key" ''
|
{ minica, mkDerivation }:
|
||||||
-----BEGIN PRIVATE KEY-----
|
let
|
||||||
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDd1G7OFpXIoHnr
|
domain = "acme.test";
|
||||||
rxdw+hiJVDY6nQDDKFt9FBKwlv7x2hCvX7bnyvHaL7H61c+80McGPISrQn3+MjuR
|
|
||||||
Zuqwax49DddNXbGt4WqGlx4LAeI37OgNUUz9foNr2rDDV744vwp14/PD1f3nqpWf
|
selfSignedCertData = mkDerivation {
|
||||||
Ogzzsh8rxac0mZ5Se9HxOIpI7NRNuHJjj7HWZ4YxeOvi289rmpu0JPcp25njw7h6
|
name = "test-certs";
|
||||||
FNfHu8GGp34Uj6wAxubdRyfViV8z9FMfbglLuA9i1OiSy3NQpq8VwBG+u/0iC7PQ
|
buildInputs = [ minica ];
|
||||||
sQjxSragQu25sfATYIrFJQ4ZCvh0nxqKMeyPPBi6dAcMpa2AZAqtqv+CwWdo36Bt
|
phases = [ "buildPhase" "installPhase" ];
|
||||||
S5XiC7rApgYn+yteKQHSbnCiG2W/boSbfg9lRk3w41dESENCADVajLb3Eovvp0tB
|
|
||||||
O/BALudvWjzAPbpXleVNr6ngWtGlsZTC7LXDgBqdW2KlzpZGcz+PW3ATlwip/ZFR
|
buildPhase = ''
|
||||||
t7A15u5dVkWPVoPuQ0w1Tw+g9dxWFTNk3h+2d7K87IxQbcvqxeIDSEVFMrxo0e4C
|
mkdir ca
|
||||||
G2udMcelZwARl6iNTAETa2zJW0XtAdGVM+HY1S/kU6U9J3nubDttAkAMABjPwyjL
|
minica \
|
||||||
G7hfyWqUHf9yPs49GsftAVvIy8XIeu0shD1BG11/VzvwpUCiRc+btuWi2erZ4ZfP
|
--ca-key ca/key.pem \
|
||||||
oQ5YoS9gt4S+Ipz7TPGBl+AUk9HO2QIDAQABAoICAGW+aLAXxc2GZUVHQp4r55Md
|
--ca-cert ca/cert.pem \
|
||||||
T94kYtQgL4435bafGwH8vchiQzcfazxiweRFqwl0TMS8fzE5xyYPDilLpfsStoTU
|
--domains ${domain}
|
||||||
U1sFzVfuWviuWTY9P+/ctjZdgs2F+GtAm/CMzw+h9/9IdWbuQI3APO4SJxyjJw7h
|
chmod 600 ca/*
|
||||||
kiZbCzXT2uAjybFXBq07GyQ1JSEszGzmhHLB1OoKuL2wcrj9IyFHhNZhtvLCWCoV
|
chmod 640 ${domain}/*.pem
|
||||||
qotttjuI/xyg5VFYt5TRzEpPIu5a1pvDAYVK0XI9cXKtbLYp7RlveqMOgAaD+S2a
|
'';
|
||||||
ZQTV60JH9n4j18p+sKR00SxvZ4vuyXzDePRBDUolGIy9MIJdiLueTiuzDmTmclnM
|
|
||||||
8Yy7oliawW2Bn+1gaWpqmgzEUw9bXRSqIp2zGZ7HaQ+5c/MhS002+/i8WQyssfeg
|
installPhase = ''
|
||||||
9EfI+Vl0D2avTxCECmsfjUxtkhzMYPVNbRPjt0QBEM+s8lDoNsP2zhMO441+TKpe
|
mkdir -p $out
|
||||||
/5KZHIW+Y0US6GMIUs1o1byKfNz8Nj5HjEKO9CMyK6SBMJnCMroPD4H6opqk3lw9
|
mv ${domain} ca $out/
|
||||||
4mk04BdN556EzyJDT0a5/VpXG2DUYwFaNwE1ZPMu3Yx6IBoM1xx8mR80vHQCddmF
|
'';
|
||||||
NP+BzkpUiHf0Txyy0YQWECZ/anTt0Bo0XqY5tirIM2dkG0ngNl9tGlw6gVAY1ky8
|
};
|
||||||
+cr7qKmhhwMWojaX/L+9AoIBAQD/BZAeF3l9I5RBh6ktWA+opzVyd6ejdLpc2Q1z
|
in {
|
||||||
fmSmtUKRsEe51sWaIf6Sez408UaCMT2IQuppPgMnV8xfMM1/og75Cs8aPyAohwKo
|
inherit domain;
|
||||||
IbOenXhLfFZiYB4y/Pac3F+FzNKsTT6n+fsE+82UHafY5ZI2FlPb2L0lfyx09zXv
|
ca = {
|
||||||
fBYhcXgwSx5ymJLJSl8zFaEGn9qi3UB5ss44SaNM0n8SFGUQUk3PR7SFWSWgNxtl
|
cert = "${selfSignedCertData}/ca/cert.pem";
|
||||||
CP7LWTsjXYoC/qBMe7b8JieK5aFk1EkkG1EkJvdiMnulMcMJzl+kj6LqVPmVDoZS
|
key = "${selfSignedCertData}/ca/key.pem";
|
||||||
mMGvgKGJPpFgrbJ5wlA7uOhucGmMpFWP9RCav66DY4GHrLJPAoIBAQDerkZQ03AN
|
};
|
||||||
i2iJVjtL97TvDjrE8vtNFS/Auh8JyDIW4GGK3Y/ZoMedQpuu3e6NYM9aMjh+QJoA
|
"${domain}" = {
|
||||||
kqhaiZ/tMXjEXJByglpc3a43g2ceWtJg5yLgexGgRtegbA57PRCo35Vhc6WycD1l
|
cert = "${selfSignedCertData}/${domain}/cert.pem";
|
||||||
6FZNxpTkd2BXX/69KWZ6PpSiLYPvdzxP5ZkYqoWRQIa4ee4orHfz/lUXJm1XwmyG
|
key = "${selfSignedCertData}/${domain}/key.pem";
|
||||||
mx3hN9Z9m8Q/PGMGfwrorcp4DK53lmmhTZyPh+X5T5/KkVmrw/v5HEEB3JsknStR
|
};
|
||||||
3DAqp2XZcRHsGQef9R7H+PINJm9nebjCraataaE4gr76znXKT23P80Ce5Lw6OQUW
|
|
||||||
XHhoL16gS+pXAoIBADTuz6ofTz01PFmZsfjSdXWZN1PKGEaqPOB2wP7+9h9QMkAR
|
|
||||||
KeId/Sfv9GotII1Woz70v4Pf983ebEMnSyla9NyQI7F3l+MnxSIEW/3P+PtsTgLF
|
|
||||||
DR0gPERzEzEd4Mnh6LyQz/eHwJ2ZMmOTADrZ8848Ni3EwAXfbrfcdBqAVAufBMZp
|
|
||||||
YSmCF72mLTpqO+EnHvd9GxvnjDxMtJOGgY+cIhoQK0xh4stm5JNrvMjs5A4LOGYv
|
|
||||||
zSyv80/Mwf92X/DJlwVZttDCxsXNPL3qIpX4TTZk2p9KnRMsjh1tRV4xjMpD1cOp
|
|
||||||
8/zwMMJrHcI3sC70MERb+9KEmGy2ap+k8MbbhqsCggEAUAqqocDupR+4Kq2BUPQv
|
|
||||||
6EHgJA0HAZUc/hSotXZtcsWiqiyr2Vkuhzt7BGcnqU/kGJK2tcL42D3fH/QaNUM0
|
|
||||||
Grj+/voWCw1v4uprtYCF4GkUo0X5dvgf570Pk4LGqzz6z/Wm2LX5i9jwtLItsNWs
|
|
||||||
HpwVz97CxCwcdxMPOpNMbZek6TXaHvTnuAWz8pDT6TNBWLnqUcJECjpVii/s/Gdy
|
|
||||||
KhzFp38g57QYdABy8e9x9pYUMY9yvaO+VyzZ46DlwIxEXavzZDzOZnVUJvDW7krz
|
|
||||||
Wz8/+2I7dzvnnYx0POiG3gtXPzwZxFtS1IpD0r2sRjQ0xSiI9BCs4HXKngBw7gN7
|
|
||||||
rwKCAQEAloJOFw4bafVXZVXuQVnLDm0/MNTfqxUzFE6V2WkMVkJqcpKt+ndApM8P
|
|
||||||
MJvojHWw1fmxDzIAwqZ9rXgnwWKydjSZBDYNjhGFUACVywHe5AjC4PPMUdltGptU
|
|
||||||
lY0BjC7qtwkVugr65goQkEzU61y9JgTqKpYsr3D+qXcoiDvWRuqk5Q0WfYJrUlE0
|
|
||||||
APWaqbxmkqUVDRrXXrifiluupk+BCV7cFSnnknSYbd9FZd9DuKaoNBlkp2J9LZE+
|
|
||||||
Ux74Cfro8SHINHmvqL+YLFUPVDWNeuXh5Kl6AaJ7yclCLXLxAIix3/rIf6mJeIGc
|
|
||||||
s9o9Sr49cibZ3CbMjCSNE3AOeVE1/Q==
|
|
||||||
-----END PRIVATE KEY-----
|
|
||||||
'';
|
|
||||||
ca.cert = builtins.toFile "ca.cert" ''
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIFDzCCAvegAwIBAgIUX0P6NfX4gRUpFz+TNV/f26GHokgwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwFjEUMBIGA1UEAwwLU25ha2VvaWwgQ0EwIBcNMjAwODI0MDc0MjEyWhgPMjEy
|
|
||||||
MDA3MzEwNzQyMTJaMBYxFDASBgNVBAMMC1NuYWtlb2lsIENBMIICIjANBgkqhkiG
|
|
||||||
9w0BAQEFAAOCAg8AMIICCgKCAgEA3dRuzhaVyKB5668XcPoYiVQ2Op0AwyhbfRQS
|
|
||||||
sJb+8doQr1+258rx2i+x+tXPvNDHBjyEq0J9/jI7kWbqsGsePQ3XTV2xreFqhpce
|
|
||||||
CwHiN+zoDVFM/X6Da9qww1e+OL8KdePzw9X956qVnzoM87IfK8WnNJmeUnvR8TiK
|
|
||||||
SOzUTbhyY4+x1meGMXjr4tvPa5qbtCT3KduZ48O4ehTXx7vBhqd+FI+sAMbm3Ucn
|
|
||||||
1YlfM/RTH24JS7gPYtTokstzUKavFcARvrv9Iguz0LEI8Uq2oELtubHwE2CKxSUO
|
|
||||||
GQr4dJ8aijHsjzwYunQHDKWtgGQKrar/gsFnaN+gbUuV4gu6wKYGJ/srXikB0m5w
|
|
||||||
ohtlv26Em34PZUZN8ONXREhDQgA1Woy29xKL76dLQTvwQC7nb1o8wD26V5XlTa+p
|
|
||||||
4FrRpbGUwuy1w4AanVtipc6WRnM/j1twE5cIqf2RUbewNebuXVZFj1aD7kNMNU8P
|
|
||||||
oPXcVhUzZN4ftneyvOyMUG3L6sXiA0hFRTK8aNHuAhtrnTHHpWcAEZeojUwBE2ts
|
|
||||||
yVtF7QHRlTPh2NUv5FOlPSd57mw7bQJADAAYz8Moyxu4X8lqlB3/cj7OPRrH7QFb
|
|
||||||
yMvFyHrtLIQ9QRtdf1c78KVAokXPm7blotnq2eGXz6EOWKEvYLeEviKc+0zxgZfg
|
|
||||||
FJPRztkCAwEAAaNTMFEwHQYDVR0OBBYEFNhBZxryvykCjfPO85xB3wof2enAMB8G
|
|
||||||
A1UdIwQYMBaAFNhBZxryvykCjfPO85xB3wof2enAMA8GA1UdEwEB/wQFMAMBAf8w
|
|
||||||
DQYJKoZIhvcNAQELBQADggIBAEZwlsQ+3yd1MVxLRy9RjoA8hI7iWBNmvPUyNjlb
|
|
||||||
l/L9N+dZgdx9G5h/KPRUyzvUc/uk/ZxTWVPIOp13WI65qwsBKrwvYKiXiwzjt+9V
|
|
||||||
CKDRc1sOghTSXk4FD3L5UcKvTQ2lRcFsqxbkopEwQWhoCuhe4vFyt3Nx8ZGLCBUD
|
|
||||||
3I5zMHtO8FtpZWKJPw46Yc1kasv0nlfly/vUbnErYfgjWX1hgWUcRgYdKwO4sOZ7
|
|
||||||
KbNma0WUsX5mWhXo4Kk7D15wATHO+j9s+j8m86duBL3A4HzpTo1DhHvBi0dkg0CO
|
|
||||||
XuSdByIzVLIPh3yhCHN1loRCP2rbzKM8IQeU/X5Q4UJeC/x9ew8Kk+RKXoHc8Y2C
|
|
||||||
JQO1DxuidyDJRhbb98wZo2YfIsdWQGjYZBe1XQRwBD28JnB+Rb9shml6lORWQn9y
|
|
||||||
P/STo9uWm5zvOCfqwbnCoetljDweItINx622G9SafBwPZc3o79oL7QSl8DgCtN6g
|
|
||||||
p0wGIlIBx+25w/96PqZcrYb8B7/uBHJviiKjBXDoIJWNiNRhW5HaFjeJdSKq7KIL
|
|
||||||
I/PO9KuHafif36ksG69X02Rio2/cTjgjEW1hGHcDRyyJWWaj7bd2eWuouh6FF22b
|
|
||||||
PA6FGY4vewDPnbLKLaix2ZIKxtedUDOH/qru3Mv58IFXmQ4iyM8oC8aOxYSQLZDn
|
|
||||||
1yJD
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
'';
|
|
||||||
"acme.test".key = builtins.toFile "acme.test.key" ''
|
|
||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIJKgIBAAKCAgEA3dJl4ByHHRcqbZzblszHIS5eEW3TcXTvllqC1nedGLGU9dnA
|
|
||||||
YbdpDUYhvWz/y9AfRZ1d8jYz01jZtt5xWYG0QoQUdkCc9QPPh0Axrl38cGliB6IZ
|
|
||||||
IY0qftW9zrLSgCOUnXL/45JqSpD57DHMSSiJl3hoOo4keBaMRN/UK6F3DxD/nZEs
|
|
||||||
h+yBBh2js3qxleExqkX8InmjK9pG8j7qa4Be5Lh4iILBHbGAMaxM7ViNAg4KgWyg
|
|
||||||
d5+4qB86JFtE/cJ+r3D62ARjVaxU6ePOL0AwS/vx5ls6DFQC7+1CpGCNemgLPzcc
|
|
||||||
70s0V0SAnF73xHYqRWjJFtumyvyTkiQWLg0zDQOugWd3B9ADuaIEx2nviPyphAtj
|
|
||||||
M3ZKrL2zN1aIfqzbxJ/L8TQFa2WPsPU2+iza/m9kMfLXZ4XPF/SJxQ+5yVH+rxx5
|
|
||||||
OWrXZ13nCMyeVoaXQofmG7oZvOQbtuT9r5DQZd9WN0P3G3sy0/dNnlNVn8uCBvXJ
|
|
||||||
TQhRKsy1FESZdgcFNtpJEG7BRG9Gc6i0V39aSRzShZyKJSBQhlc0FMTlX445EYsh
|
|
||||||
PKjEC/+Suq9wy/LuLjIkkqBbVg4617IlibLz0fDY/yrZqkfSqhCVsWnra21Ty3Mp
|
|
||||||
vD+wnskTzuGrvCVTe3KcWp+wkeH0xvhr8FXX6nn492YCfvZSITO3FF+qWt8CAwEA
|
|
||||||
AQKCAgEAk2xV0NCk66yNwjPRrTOD1IWgdyzqrijtYpvdAPSWL+c1/P8vYMIoy22k
|
|
||||||
1uQuTSKQ5g9kdKmZYAlZCLRl2Pre9qYZg04GAsD5mAYN/rjwITWotTICSc4sRAeC
|
|
||||||
EnG+fPMovkvDzVdt1QjtURD3mFeculKH0wLNMhKqPswTkrvJCPZfLDVjxyJjzdC9
|
|
||||||
D3enttjnzSaeH7t/upFjPXSbD79NUe1YDkH4XuetL1Y3+jYz4P279bBgJaC9dN7s
|
|
||||||
IWWXQJ+W2rrXu+GOs03JUXjZe4XJk3ZqmpJezfq3yQWCmQSigovLjcPvMwpkSut4
|
|
||||||
HnTvbl6qUV8G5m4tOBMNcL8TDqAvIGY8Q2NAT0iKJN187FbHpjSwQL/Ckgqz/taJ
|
|
||||||
Q82LfIA1+IjwW372gY2Wge8tM/s3+2vOEn2k91sYfiKtrRFfrHBurehVQSpJb2gL
|
|
||||||
YPoUhUGu4C1nx44sQw+DgugOBp1BTKA1ZOBIk6NyS/J9sU3jSgMr88n10TyepP6w
|
|
||||||
OVk9kcNomnm/QIOyTDW4m76uoaxslg7kwOJ4j6wycddS8JtvEO4ZPk/fHZCbvlMv
|
|
||||||
/dAKsC3gigO2zW6IYYb7mSXI07Ew/rFH1NfSILiGw8GofJHDq3plGHZo9ycB6JC+
|
|
||||||
9C8n9IWjn8ahwbulCoQQhdHwXvf61t+RzNFuFiyAT0PF2FtD/eECggEBAPYBNSEY
|
|
||||||
DSQc/Wh+UlnwQsevxfzatohgQgQJRU1ZpbHQrl2uxk1ISEwrfqZwFmFotdjjzSYe
|
|
||||||
e1WQ0uFYtdm1V/QeQK+8W0u7E7/fof4dR6XxrzJ2QmtWEmCnLOBUKCfPc7/4p4IU
|
|
||||||
7Q8PDwuwvXgaASZDaEsyTxL9bBrNMLFx9hIScQ9CaygpKvufilCHG79maoKArLwX
|
|
||||||
s7G16qlT4YeEdiNuLGv0Ce0txJuFYp7cGClWQhruw+jIbr+Sn9pL9cn8GboCiUAq
|
|
||||||
VgZKsofhEkKIEbP1uFypX2JnyRSE/h0qDDcH1sEXjR9zYYpQjVpk3Jiipgw4PXis
|
|
||||||
79uat5/QzUqVc1sCggEBAObVp686K9NpxYNoEliMijIdzFnK5J/TvoX9BBMz0dXc
|
|
||||||
CgQW40tBcroU5nRl3oCjT1Agn8mxWLXH3czx6cPlSA8fnMTJmev8FaLnEcM15pGI
|
|
||||||
8/VCBbTegdezJ8vPRS/T9c4CViXo7d0qDMkjNyn22ojPPFYh8M1KVNhibDTEpXMQ
|
|
||||||
vJxBJgvHePj+5pMOIKwAvQicqD07fNp6jVPmB/GnprBkjcCQZtshNJzWrW3jk7Fr
|
|
||||||
xWpQJ8nam8wHdMvfKhpzvD6azahwmfKKaQmh/RwmH4xdtIKdh4j+u+Ax+Bxi0g7V
|
|
||||||
GQfusIFB1MO48yS6E56WZMmsPy+jhTcIB4prIbfu4c0CggEBALgqqUKwRc4+Ybvj
|
|
||||||
rfUk+GmT/s3QUwx/u4xYAGjq7y/SgWcjG9PphC559WPWz/p2sITB7ehWs5CYTjdj
|
|
||||||
+SgWKdVY/KZThamJUTy4yAZ8lxH1gGpvvEOs+S8gmGkMt88t8ILMPWMWFW7LoEDp
|
|
||||||
PL74ANpLZn29GROnY1IhQQ3mughHhBqfZ6d2QnaDtsGYlD5TBvPSLv7VY7Jr9VR0
|
|
||||||
toeEtAjMRzc+SFwmgmTHk9BIB1KTAAQ3sbTIsJh8xW1gpo5jTEND+Mpvp10oeMVe
|
|
||||||
yxPB2Db4gt/j8MOz3QaelbrxqplcJfsCjaT49RHeQiRlE/y070iApgx8s0idaFCd
|
|
||||||
ucLXZbcCggEBANkcsdg9RYVWoeCj3UWOAll6736xN/IgDb4mqVOKVN3qVT1dbbGV
|
|
||||||
wFvHVq66NdoWQH4kAUaKWN65OyQNkQqgt/MJj8EDwZNVCeCrp2hNZS0TfCn9TDK/
|
|
||||||
aa7AojivHesLWNHIHtEPUdLIPzhbuAHvXcJ58M0upTfhpwXTJOVI5Dji0BPDrw47
|
|
||||||
Msw3rBU6n35IP4Q/HHpjXl58EDuOS4B+aGjWWwF4kFWg2MR/oqWN/JdOv2LsO1A/
|
|
||||||
HnR7ut4aa5ZvrunPXooERrf6eSsHQnLcZKX4aNTFZ/pxZbJMLYo9ZEdxJVbxqPAa
|
|
||||||
RA1HAuJTZiquV+Pb755WFfEZy0Xk19URiS0CggEAPT1e+9sdNC15z79SxvJQ4pmT
|
|
||||||
xiXat+1pq9pxp5HEOre2sSAd7CF5lu/1VQd6p0gtLZY+Aw4BXOyMtzYWgIap+u9j
|
|
||||||
ThFl9qrTFppG5KlFKKpQ8dQQ8ofO1akS8cK8nQeSdvrqEC/kGT2rmVdeevhBlfGy
|
|
||||||
BZi2ikhEQrz5jsLgIdT7sN2aLFYtmzLU9THTvlfm4ckQ7jOTxvVahb+WRe/iMCwP
|
|
||||||
Exrb83JDo31jHvAoYqUFrZkmPA+DUWFlrqb21pCzmC/0iQSuDcayRRjZkY/s5iAh
|
|
||||||
gtI6YyAsSL8hKvFVCC+VJf1QvFOpgUfsZjrIZuSc3puBWtN2dirHf7EfyxgEOg==
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
||||||
'';
|
|
||||||
"acme.test".cert = builtins.toFile "acme.test.cert" ''
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIEwDCCAqigAwIBAgICApowDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UEAwwLU25h
|
|
||||||
a2VvaWwgQ0EwIBcNMjAwODI0MDc0MjEzWhgPMjEyMDA3MzEwNzQyMTNaMBQxEjAQ
|
|
||||||
BgNVBAMMCWFjbWUudGVzdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
|
|
||||||
AN3SZeAchx0XKm2c25bMxyEuXhFt03F075ZagtZ3nRixlPXZwGG3aQ1GIb1s/8vQ
|
|
||||||
H0WdXfI2M9NY2bbecVmBtEKEFHZAnPUDz4dAMa5d/HBpYgeiGSGNKn7Vvc6y0oAj
|
|
||||||
lJ1y/+OSakqQ+ewxzEkoiZd4aDqOJHgWjETf1Cuhdw8Q/52RLIfsgQYdo7N6sZXh
|
|
||||||
MapF/CJ5oyvaRvI+6muAXuS4eIiCwR2xgDGsTO1YjQIOCoFsoHefuKgfOiRbRP3C
|
|
||||||
fq9w+tgEY1WsVOnjzi9AMEv78eZbOgxUAu/tQqRgjXpoCz83HO9LNFdEgJxe98R2
|
|
||||||
KkVoyRbbpsr8k5IkFi4NMw0DroFndwfQA7miBMdp74j8qYQLYzN2Sqy9szdWiH6s
|
|
||||||
28Sfy/E0BWtlj7D1Nvos2v5vZDHy12eFzxf0icUPuclR/q8ceTlq12dd5wjMnlaG
|
|
||||||
l0KH5hu6GbzkG7bk/a+Q0GXfVjdD9xt7MtP3TZ5TVZ/Lggb1yU0IUSrMtRREmXYH
|
|
||||||
BTbaSRBuwURvRnOotFd/Wkkc0oWciiUgUIZXNBTE5V+OORGLITyoxAv/krqvcMvy
|
|
||||||
7i4yJJKgW1YOOteyJYmy89Hw2P8q2apH0qoQlbFp62ttU8tzKbw/sJ7JE87hq7wl
|
|
||||||
U3tynFqfsJHh9Mb4a/BV1+p5+PdmAn72UiEztxRfqlrfAgMBAAGjGDAWMBQGA1Ud
|
|
||||||
EQQNMAuCCWFjbWUudGVzdDANBgkqhkiG9w0BAQsFAAOCAgEAM5WrCpBOmLrZ1QX8
|
|
||||||
l6vxVXwoI8pnqyy3cbAm3aLRPbw4gb0Ot90Pv/LoMhP0fkrNOKwH/FGRjSXyti0X
|
|
||||||
TheKrP7aEf6XL2/Xnb8rK2jYMQo6YJU9T+wBJA6Q+GBrc8SE75KfOi5NWJr8T4Ju
|
|
||||||
Etb+G05hXClrN19VFzIoz3L4kRV+xNMialcOT3xQfHtXCQUgwAWpPlwcJA/Jf60m
|
|
||||||
XsfwQwk2Ir16wq+Lc3y+mQ7d/dbG+FVrngFk4qN2B9M/Zyv4N9ZBbqeDUn3mYtJE
|
|
||||||
FeJrwHgmwH6slf1gBN3gxUKRW7Bvzxk548NdmLOyN+Y4StsqbOaYGtShUJA7f1Ng
|
|
||||||
qQqdgvxZ9MNwwMv9QVDZEnaaew3/oWOSmQGAai4hrc7gLMLJmIxzgfd5P6Dr06e4
|
|
||||||
2zwsMuI8Qh/IDqu/CfmFYvaua0FEeyAtpoID9Y/KPM7fu9bJuxjZ6kqLVFkEi9nF
|
|
||||||
/rCMchcSA8N2z/vLPabpNotO7OYH3VD7aQGTfCL82dMlp1vwZ39S3Z1TFLLh3MZ+
|
|
||||||
BYcAv8kUvCV6kIdPAXvJRSQOJUlJRV7XiI2mwugdDzMx69wQ0Zc1e4WyGfiSiVYm
|
|
||||||
ckSJ/EkxuwT/ZYLqCAKSFGMlFhad9g1Zyvd67XgfZq5p0pJTtGxtn5j8QHy6PM6m
|
|
||||||
NbjvWnP8lDU8j2l3eSG58S14iGs=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
'';
|
|
||||||
}
|
}
|
||||||
|
@ -285,7 +285,7 @@ let
|
|||||||
];
|
];
|
||||||
|
|
||||||
virtualisation.diskSize = 8 * 1024;
|
virtualisation.diskSize = 8 * 1024;
|
||||||
virtualisation.memorySize = 1024;
|
virtualisation.memorySize = 1536;
|
||||||
|
|
||||||
# Use a small /dev/vdb as the root disk for the
|
# Use a small /dev/vdb as the root disk for the
|
||||||
# installer. This ensures the target disk (/dev/vda) is
|
# installer. This ensures the target disk (/dev/vda) is
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
let
|
|
||||||
certs = import ./common/acme/server/snakeoil-certs.nix;
|
|
||||||
in
|
|
||||||
import ./make-test-python.nix {
|
import ./make-test-python.nix {
|
||||||
name = "postfix";
|
name = "postfix";
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
let
|
let
|
||||||
certs = import ./common/acme/server/snakeoil-certs.nix;
|
certs = import ./common/acme/server/snakeoil-certs.nix;
|
||||||
|
domain = certs.domain;
|
||||||
in
|
in
|
||||||
import ./make-test-python.nix {
|
import ./make-test-python.nix {
|
||||||
name = "postfix";
|
name = "postfix";
|
||||||
@ -11,8 +12,8 @@ import ./make-test-python.nix {
|
|||||||
enableSubmission = true;
|
enableSubmission = true;
|
||||||
enableSubmissions = true;
|
enableSubmissions = true;
|
||||||
sslCACert = certs.ca.cert;
|
sslCACert = certs.ca.cert;
|
||||||
sslCert = certs."acme.test".cert;
|
sslCert = certs.${domain}.cert;
|
||||||
sslKey = certs."acme.test".key;
|
sslKey = certs.${domain}.key;
|
||||||
submissionsOptions = {
|
submissionsOptions = {
|
||||||
smtpd_sasl_auth_enable = "yes";
|
smtpd_sasl_auth_enable = "yes";
|
||||||
smtpd_client_restrictions = "permit";
|
smtpd_client_restrictions = "permit";
|
||||||
@ -25,7 +26,7 @@ import ./make-test-python.nix {
|
|||||||
];
|
];
|
||||||
|
|
||||||
networking.extraHosts = ''
|
networking.extraHosts = ''
|
||||||
127.0.0.1 acme.test
|
127.0.0.1 ${domain}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
environment.systemPackages = let
|
environment.systemPackages = let
|
||||||
@ -33,7 +34,7 @@ import ./make-test-python.nix {
|
|||||||
#!${pkgs.python3.interpreter}
|
#!${pkgs.python3.interpreter}
|
||||||
import smtplib
|
import smtplib
|
||||||
|
|
||||||
with smtplib.SMTP('acme.test') as smtp:
|
with smtplib.SMTP('${domain}') as smtp:
|
||||||
smtp.sendmail('root@localhost', 'alice@localhost', 'Subject: Test\n\nTest data.')
|
smtp.sendmail('root@localhost', 'alice@localhost', 'Subject: Test\n\nTest data.')
|
||||||
smtp.quit()
|
smtp.quit()
|
||||||
'';
|
'';
|
||||||
@ -45,7 +46,7 @@ import ./make-test-python.nix {
|
|||||||
|
|
||||||
ctx = ssl.create_default_context()
|
ctx = ssl.create_default_context()
|
||||||
|
|
||||||
with smtplib.SMTP('acme.test') as smtp:
|
with smtplib.SMTP('${domain}') as smtp:
|
||||||
smtp.ehlo()
|
smtp.ehlo()
|
||||||
smtp.starttls(context=ctx)
|
smtp.starttls(context=ctx)
|
||||||
smtp.ehlo()
|
smtp.ehlo()
|
||||||
@ -60,7 +61,7 @@ import ./make-test-python.nix {
|
|||||||
|
|
||||||
ctx = ssl.create_default_context()
|
ctx = ssl.create_default_context()
|
||||||
|
|
||||||
with smtplib.SMTP_SSL(host='acme.test', context=ctx) as smtp:
|
with smtplib.SMTP_SSL(host='${domain}', context=ctx) as smtp:
|
||||||
smtp.sendmail('root@localhost', 'alice@localhost', 'Subject: Test SMTPS\n\nTest data.')
|
smtp.sendmail('root@localhost', 'alice@localhost', 'Subject: Test SMTPS\n\nTest data.')
|
||||||
smtp.quit()
|
smtp.quit()
|
||||||
'';
|
'';
|
||||||
|
78
nixos/tests/sssd-ldap.nix
Normal file
78
nixos/tests/sssd-ldap.nix
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import ./make-test-python.nix ({ pkgs, ... }:
|
||||||
|
let
|
||||||
|
dbDomain = "example.org";
|
||||||
|
dbSuffix = "dc=example,dc=org";
|
||||||
|
|
||||||
|
ldapRootUser = "admin";
|
||||||
|
ldapRootPassword = "foobar";
|
||||||
|
|
||||||
|
testUser = "alice";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "sssd-ldap";
|
||||||
|
|
||||||
|
meta = with pkgs.stdenv.lib.maintainers; {
|
||||||
|
maintainers = [ bbigras ];
|
||||||
|
};
|
||||||
|
|
||||||
|
machine = { pkgs, ... }: {
|
||||||
|
services.openldap = {
|
||||||
|
enable = true;
|
||||||
|
rootdn = "cn=${ldapRootUser},${dbSuffix}";
|
||||||
|
rootpw = ldapRootPassword;
|
||||||
|
suffix = dbSuffix;
|
||||||
|
declarativeContents = ''
|
||||||
|
dn: ${dbSuffix}
|
||||||
|
objectClass: top
|
||||||
|
objectClass: dcObject
|
||||||
|
objectClass: organization
|
||||||
|
o: ${dbDomain}
|
||||||
|
|
||||||
|
dn: ou=posix,${dbSuffix}
|
||||||
|
objectClass: top
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
|
||||||
|
dn: ou=accounts,ou=posix,${dbSuffix}
|
||||||
|
objectClass: top
|
||||||
|
objectClass: organizationalUnit
|
||||||
|
|
||||||
|
dn: uid=${testUser},ou=accounts,ou=posix,${dbSuffix}
|
||||||
|
objectClass: person
|
||||||
|
objectClass: posixAccount
|
||||||
|
# userPassword: somePasswordHash
|
||||||
|
homeDirectory: /home/${testUser}
|
||||||
|
uidNumber: 1234
|
||||||
|
gidNumber: 1234
|
||||||
|
cn: ""
|
||||||
|
sn: ""
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services.sssd = {
|
||||||
|
enable = true;
|
||||||
|
config = ''
|
||||||
|
[sssd]
|
||||||
|
config_file_version = 2
|
||||||
|
services = nss, pam, sudo
|
||||||
|
domains = ${dbDomain}
|
||||||
|
|
||||||
|
[domain/${dbDomain}]
|
||||||
|
auth_provider = ldap
|
||||||
|
id_provider = ldap
|
||||||
|
ldap_uri = ldap://127.0.0.1:389
|
||||||
|
ldap_search_base = ${dbSuffix}
|
||||||
|
ldap_default_bind_dn = cn=${ldapRootUser},${dbSuffix}
|
||||||
|
ldap_default_authtok_type = password
|
||||||
|
ldap_default_authtok = ${ldapRootPassword}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = ''
|
||||||
|
machine.start()
|
||||||
|
machine.wait_for_unit("openldap.service")
|
||||||
|
machine.wait_for_unit("sssd.service")
|
||||||
|
machine.succeed("getent passwd ${testUser}")
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
)
|
@ -4,11 +4,11 @@ cups, vivaldi-ffmpeg-codecs, libpulseaudio, at-spi2-core }:
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "exodus";
|
pname = "exodus";
|
||||||
version = "20.1.30";
|
version = "20.8.28";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://downloads.exodus.io/releases/${pname}-linux-x64-${version}.zip";
|
url = "https://downloads.exodus.io/releases/${pname}-linux-x64-${version}.zip";
|
||||||
sha256 = "0jns5zqjm0gqn18ypghbgk6gb713mh7p44ax1r8y4vcwijlp5nql";
|
sha256 = "fde9165f71f0d641f6892ddce3ec26d200e8095a383f2b4c8f924de4041d65ef";
|
||||||
};
|
};
|
||||||
|
|
||||||
sourceRoot = ".";
|
sourceRoot = ".";
|
||||||
@ -75,6 +75,6 @@ stdenv.mkDerivation rec {
|
|||||||
description = "Top-rated cryptocurrency wallet with Trezor integration and built-in Exchange";
|
description = "Top-rated cryptocurrency wallet with Trezor integration and built-in Exchange";
|
||||||
license = licenses.unfree;
|
license = licenses.unfree;
|
||||||
platforms = platforms.linux;
|
platforms = platforms.linux;
|
||||||
maintainers = [ maintainers.mmahut ];
|
maintainers = with maintainers; [ mmahut rople380 ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,18 @@
|
|||||||
|
|
||||||
buildGoModule rec {
|
buildGoModule rec {
|
||||||
pname = "pdfcpu";
|
pname = "pdfcpu";
|
||||||
version = "0.3.4";
|
version = "0.3.5";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "pdfcpu";
|
owner = "pdfcpu";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "00c4psgfh4hia144zsdhrq83bw3fqda1ancv2gkn5ymxkbpnpyrn";
|
sha256 = "0fb7l1h4dhn100y2ydq50cgj63fbr4p11x8h803rv6x3xwmviwcg";
|
||||||
};
|
};
|
||||||
|
|
||||||
vendorSha256 = "09alkpfyxapycv6zsaz7prgbr0a1jzd78n7w2mh01mg4hhb2j3k7";
|
vendorSha256 = "06xlwygqw3kzbjqlx09rs9hl4pfsmay5pj4c5hvkrj5z123ldvyw";
|
||||||
|
|
||||||
|
# No tests
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
|
|
||||||
subPackages = [ "cmd/pdfcpu" ];
|
subPackages = [ "cmd/pdfcpu" ];
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
, hyphen
|
, hyphen
|
||||||
, unrarSupport ? false
|
, unrarSupport ? false
|
||||||
, chmlib
|
, chmlib
|
||||||
, python2Packages
|
, pythonPackages
|
||||||
, libusb1
|
, libusb1
|
||||||
, libmtp
|
, libmtp
|
||||||
, xdg_utils
|
, xdg_utils
|
||||||
@ -24,17 +24,13 @@
|
|||||||
, removeReferencesTo
|
, removeReferencesTo
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
|
||||||
pypkgs = python2Packages;
|
|
||||||
|
|
||||||
in
|
|
||||||
mkDerivation rec {
|
mkDerivation rec {
|
||||||
pname = "calibre";
|
pname = "calibre";
|
||||||
version = "4.22.0";
|
version = "4.23.0";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://download.calibre-ebook.com/${version}/${pname}-${version}.tar.xz";
|
url = "https://download.calibre-ebook.com/${version}/${pname}-${version}.tar.xz";
|
||||||
sha256 = "0d0wmd3ijk8px1d662igal4lfmpyzynfzs6ms1bb9nf42mq2pxai";
|
sha256 = "sha256-Ft5RRzzw4zb5RqVyUaHk9Pu6H4V/F9j8FKoTLn61lRg=";
|
||||||
};
|
};
|
||||||
|
|
||||||
patches = [
|
patches = [
|
||||||
@ -47,7 +43,7 @@ mkDerivation rec {
|
|||||||
] ++ lib.optional (!unrarSupport) ./dont_build_unrar_plugin.patch;
|
] ++ lib.optional (!unrarSupport) ./dont_build_unrar_plugin.patch;
|
||||||
|
|
||||||
prePatch = ''
|
prePatch = ''
|
||||||
sed -i "/pyqt_sip_dir/ s:=.*:= '${pypkgs.pyqt5}/share/sip/PyQt5':" \
|
sed -i "/pyqt_sip_dir/ s:=.*:= '${pythonPackages.pyqt5}/share/sip/PyQt5':" \
|
||||||
setup/build_environment.py
|
setup/build_environment.py
|
||||||
|
|
||||||
# Remove unneeded files and libs
|
# Remove unneeded files and libs
|
||||||
@ -61,52 +57,49 @@ mkDerivation rec {
|
|||||||
|
|
||||||
nativeBuildInputs = [ pkgconfig qmake removeReferencesTo ];
|
nativeBuildInputs = [ pkgconfig qmake removeReferencesTo ];
|
||||||
|
|
||||||
CALIBRE_PY3_PORT = builtins.toString pypkgs.isPy3k;
|
CALIBRE_PY3_PORT = builtins.toString pythonPackages.isPy3k;
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
poppler_utils
|
|
||||||
libpng
|
|
||||||
imagemagick
|
|
||||||
libjpeg
|
|
||||||
fontconfig
|
|
||||||
podofo
|
|
||||||
qtbase
|
|
||||||
chmlib
|
chmlib
|
||||||
icu
|
fontconfig
|
||||||
hunspell
|
hunspell
|
||||||
hyphen
|
hyphen
|
||||||
sqlite
|
icu
|
||||||
libusb1
|
imagemagick
|
||||||
|
libjpeg
|
||||||
libmtp
|
libmtp
|
||||||
|
libpng
|
||||||
|
libusb1
|
||||||
|
podofo
|
||||||
|
poppler_utils
|
||||||
|
qtbase
|
||||||
|
sqlite
|
||||||
xdg_utils
|
xdg_utils
|
||||||
] ++ (
|
] ++ (
|
||||||
with pypkgs; [
|
with pythonPackages; [
|
||||||
apsw
|
apsw
|
||||||
cssselect
|
beautifulsoup4
|
||||||
css-parser
|
css-parser
|
||||||
|
cssselect
|
||||||
dateutil
|
dateutil
|
||||||
dnspython
|
dnspython
|
||||||
feedparser
|
feedparser
|
||||||
|
html2text
|
||||||
html5-parser
|
html5-parser
|
||||||
lxml
|
lxml
|
||||||
markdown
|
markdown
|
||||||
|
mechanize
|
||||||
|
msgpack
|
||||||
netifaces
|
netifaces
|
||||||
pillow
|
pillow
|
||||||
python
|
|
||||||
pyqt5
|
pyqt5
|
||||||
sip
|
|
||||||
regex
|
|
||||||
msgpack
|
|
||||||
beautifulsoup4
|
|
||||||
html2text
|
|
||||||
pyqtwebengine
|
pyqtwebengine
|
||||||
|
python
|
||||||
|
regex
|
||||||
|
sip
|
||||||
# the following are distributed with calibre, but we use upstream instead
|
# the following are distributed with calibre, but we use upstream instead
|
||||||
odfpy
|
odfpy
|
||||||
]
|
]
|
||||||
) ++ lib.optionals (!pypkgs.isPy3k) (
|
|
||||||
with pypkgs; [
|
|
||||||
mechanize
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
@ -121,18 +114,17 @@ mkDerivation rec {
|
|||||||
export FC_LIB_DIR=${fontconfig.lib}/lib
|
export FC_LIB_DIR=${fontconfig.lib}/lib
|
||||||
export PODOFO_INC_DIR=${podofo.dev}/include/podofo
|
export PODOFO_INC_DIR=${podofo.dev}/include/podofo
|
||||||
export PODOFO_LIB_DIR=${podofo.lib}/lib
|
export PODOFO_LIB_DIR=${podofo.lib}/lib
|
||||||
export SIP_BIN=${pypkgs.sip}/bin/sip
|
export SIP_BIN=${pythonPackages.sip}/bin/sip
|
||||||
export XDG_DATA_HOME=$out/share
|
export XDG_DATA_HOME=$out/share
|
||||||
export XDG_UTILS_INSTALL_MODE="user"
|
export XDG_UTILS_INSTALL_MODE="user"
|
||||||
|
|
||||||
${pypkgs.python.interpreter} setup.py install --root=$out \
|
${pythonPackages.python.interpreter} setup.py install --root=$out \
|
||||||
--prefix=$out \
|
--prefix=$out \
|
||||||
--libdir=$out/lib \
|
--libdir=$out/lib \
|
||||||
--staging-root=$out \
|
--staging-root=$out \
|
||||||
--staging-libdir=$out/lib \
|
--staging-libdir=$out/lib \
|
||||||
--staging-sharedir=$out/share
|
--staging-sharedir=$out/share
|
||||||
|
|
||||||
|
|
||||||
PYFILES="$out/bin/* $out/lib/calibre/calibre/web/feeds/*.py
|
PYFILES="$out/bin/* $out/lib/calibre/calibre/web/feeds/*.py
|
||||||
$out/lib/calibre/calibre/ebooks/metadata/*.py
|
$out/lib/calibre/calibre/ebooks/metadata/*.py
|
||||||
$out/lib/calibre/calibre/ebooks/rtf2xml/*.py"
|
$out/lib/calibre/calibre/ebooks/rtf2xml/*.py"
|
||||||
@ -154,7 +146,8 @@ mkDerivation rec {
|
|||||||
# 2018-11-06) was a single string like the following:
|
# 2018-11-06) was a single string like the following:
|
||||||
# /nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-podofo-0.9.6-dev/include/podofo/base/PdfVariant.h
|
# /nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-podofo-0.9.6-dev/include/podofo/base/PdfVariant.h
|
||||||
preFixup = ''
|
preFixup = ''
|
||||||
remove-references-to -t ${podofo.dev} $out/lib/calibre/calibre/plugins/podofo.so
|
remove-references-to -t ${podofo.dev} \
|
||||||
|
$out/lib/calibre/calibre/plugins${lib.optionalString pythonPackages.isPy3k "/3"}/podofo.so
|
||||||
|
|
||||||
for program in $out/bin/*; do
|
for program in $out/bin/*; do
|
||||||
wrapProgram $program \
|
wrapProgram $program \
|
||||||
|
@ -2,20 +2,20 @@
|
|||||||
|
|
||||||
mkDerivation rec {
|
mkDerivation rec {
|
||||||
pname = "cura";
|
pname = "cura";
|
||||||
version = "4.6.1";
|
version = "4.7.1";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "Ultimaker";
|
owner = "Ultimaker";
|
||||||
repo = "Cura";
|
repo = "Cura";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "0h1r9caa579d3gfpcmch54rdbkg5df64ds2v84iqsbxwjp0rmn4n";
|
sha256 = "19an168iad3cb5w8i71c0wbr79qnz5qnpxqx1j6dgh64qz6ffn2r";
|
||||||
};
|
};
|
||||||
|
|
||||||
materials = fetchFromGitHub {
|
materials = fetchFromGitHub {
|
||||||
owner = "Ultimaker";
|
owner = "Ultimaker";
|
||||||
repo = "fdm_materials";
|
repo = "fdm_materials";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "1k5c3qmixhpz3z2yi0fysxcyyf1yhcwmdlrcypkw827lhsialqp4";
|
sha256 = "1w6i0dlff8b30q987x3y0zv8847fc8ppfcr9vi982msmv284c89z";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ qtbase qtquickcontrols2 qtgraphicaleffects ];
|
buildInputs = [ qtbase qtquickcontrols2 qtgraphicaleffects ];
|
||||||
|
@ -6,13 +6,13 @@ let
|
|||||||
|
|
||||||
octoprint = stdenv.mkDerivation rec {
|
octoprint = stdenv.mkDerivation rec {
|
||||||
pname = "Cura-OctoPrintPlugin";
|
pname = "Cura-OctoPrintPlugin";
|
||||||
version = "3.5.12";
|
version = "3.5.16";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "fieldOfView";
|
owner = "fieldOfView";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "ad522c0b7ead5fbe28da686a3cc75e351274c2bc";
|
rev = "8affa8aa9796cb37129d3b7222fff03f86c936cd";
|
||||||
sha256 = "0ln11ng32bh0smfsk54mv2j3sadh0gwf031nmm95zrvbj9cr6yc0";
|
sha256 = "0l4qfcashkdmpdm8nm3klz6hmi1f0bmbpb9b1yn4mvg0fam6c5xi";
|
||||||
};
|
};
|
||||||
|
|
||||||
propagatedBuildInputs = with python3Packages; [
|
propagatedBuildInputs = with python3Packages; [
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "curaengine";
|
pname = "curaengine";
|
||||||
version = "4.6.1";
|
version = "4.7.1";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "Ultimaker";
|
owner = "Ultimaker";
|
||||||
repo = "CuraEngine";
|
repo = "CuraEngine";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "1fr151hmdg2lhk9pbpan1hb1pafj784nijr4pz646ljmjh12vfk2";
|
sha256 = "177fk6j4gn3ssi8j1qxj8p4486f7jkz328vc75agxnh7vhd4mwsm";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ cmake ];
|
nativeBuildInputs = [ cmake ];
|
||||||
|
@ -13,14 +13,14 @@
|
|||||||
|
|
||||||
buildPythonApplication rec {
|
buildPythonApplication rec {
|
||||||
pname = "hovercraft";
|
pname = "hovercraft";
|
||||||
version = "2.6";
|
version = "2.7";
|
||||||
disabled = ! isPy3k;
|
disabled = ! isPy3k;
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "regebro";
|
owner = "regebro";
|
||||||
repo = "hovercraft";
|
repo = "hovercraft";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "150sn6kvqi2s89di1akl5i0g81fasji2ipr12zq5s4dcnhw4r5wp";
|
sha256 = "0k0gjlqjz424rymcfdjpj6a71ppblfls5f8y2hd800d1as4im8az";
|
||||||
};
|
};
|
||||||
|
|
||||||
checkInputs = [ manuel ];
|
checkInputs = [ manuel ];
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
{ rustPlatform, fetchFromGitHub, lib, fzf, makeWrapper }:
|
{ fetchFromGitHub, fzf, lib, makeWrapper, rustPlatform, wget }:
|
||||||
|
|
||||||
rustPlatform.buildRustPackage rec {
|
rustPlatform.buildRustPackage rec {
|
||||||
pname = "navi";
|
pname = "navi";
|
||||||
version = "2.9.0";
|
version = "2.10.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "denisidoro";
|
owner = "denisidoro";
|
||||||
repo = "navi";
|
repo = "navi";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "16rwhpyk0zqks9z9bv2a1a8vww2m6867kg33bjbr29hawjg68jql";
|
sha256 = "1fpfc3ikb6rhb8m0dp9ybh46mnqaw361rrsbv6yrivwfm3zc4w2w";
|
||||||
};
|
};
|
||||||
|
|
||||||
cargoSha256 = "19w9gm389lj1zwhyjifhc2fzkvrvqvyc80lwxz070cnj11ir2l9m";
|
cargoSha256 = "0klizxrb92h7qfxs89m08ksdq698wx4kxsdhqhr5ld9dy3b6ks32";
|
||||||
|
|
||||||
nativeBuildInputs = [ makeWrapper ];
|
nativeBuildInputs = [ makeWrapper ];
|
||||||
|
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
wrapProgram $out/bin/navi --prefix PATH : ${lib.makeBinPath [ fzf ]}
|
wrapProgram $out/bin/navi --prefix PATH : ${lib.makeBinPath [ fzf wget ]}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
|
@ -36,8 +36,6 @@ in stdenv.mkDerivation rec {
|
|||||||
nativeBuildInputs = [ nim ];
|
nativeBuildInputs = [ nim ];
|
||||||
buildInputs = [ termbox pcre ];
|
buildInputs = [ termbox pcre ];
|
||||||
|
|
||||||
NIX_LDFLAGS = "-lpcre";
|
|
||||||
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
export HOME=$TMPDIR;
|
export HOME=$TMPDIR;
|
||||||
nim -p:${noise} -p:${nimbox} -p:${lscolors}/src c -d:release src/nimmm.nim
|
nim -p:${noise} -p:${nimbox} -p:${lscolors}/src c -d:release src/nimmm.nim
|
||||||
|
@ -24,11 +24,6 @@ let
|
|||||||
./575.patch
|
./575.patch
|
||||||
];
|
];
|
||||||
|
|
||||||
postPatch = stdenv.lib.optionalString (pname == "gammastep") ''
|
|
||||||
substituteInPlace configure.ac \
|
|
||||||
--replace "[gammastep], [2.0]" "[gammastep], [${version}]"
|
|
||||||
'';
|
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
autoconf
|
autoconf
|
||||||
automake
|
automake
|
||||||
@ -132,13 +127,13 @@ rec {
|
|||||||
|
|
||||||
gammastep = mkRedshift rec {
|
gammastep = mkRedshift rec {
|
||||||
pname = "gammastep";
|
pname = "gammastep";
|
||||||
version = "2.0.1";
|
version = "2.0.2";
|
||||||
|
|
||||||
src = fetchFromGitLab {
|
src = fetchFromGitLab {
|
||||||
owner = "chinstrap";
|
owner = "chinstrap";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "1ky4h892sg2mfbwwq5xv0vnjflsl2x3nsy5q456r1kyk1gwkj0rg";
|
sha256 = "09wqlz3yya955galhs20014qfwm2yk0lxhyqdsw8gwddvcpyprzg";
|
||||||
};
|
};
|
||||||
|
|
||||||
meta = redshift.meta // {
|
meta = redshift.meta // {
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "tippecanoe";
|
pname = "tippecanoe";
|
||||||
version = "1.35.0";
|
version = "1.36.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "mapbox";
|
owner = "mapbox";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "0v5ycc3gsqnl9pps3m45yrnb1gvw5pk6jdyr0q6516b4ac6x67m5";
|
sha256 = "0lbmhly4ivnqc6qk1k3sdqvsg6x3nfd8gnjx846bhqj4wag3f88m";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ sqlite zlib ];
|
buildInputs = [ sqlite zlib ];
|
||||||
@ -25,5 +25,6 @@ stdenv.mkDerivation rec {
|
|||||||
license = licenses.bsd2;
|
license = licenses.bsd2;
|
||||||
maintainers = with maintainers; [ sikmir ];
|
maintainers = with maintainers; [ sikmir ];
|
||||||
platforms = with platforms; linux ++ darwin;
|
platforms = with platforms; linux ++ darwin;
|
||||||
|
broken = stdenv.hostPlatform.isAarch64;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{ newScope, config, stdenv, fetchurl, makeWrapper
|
{ newScope, config, stdenv, fetchurl, makeWrapper
|
||||||
, llvmPackages_10, llvmPackages_11, ed, gnugrep, coreutils
|
, llvmPackages_10, llvmPackages_11, ed, gnugrep, coreutils, xdg_utils
|
||||||
, glib, gtk3, gnome3, gsettings-desktop-schemas, gn, fetchgit
|
, glib, gtk3, gnome3, gsettings-desktop-schemas, gn, fetchgit
|
||||||
, libva ? null
|
, libva ? null
|
||||||
, pipewire_0_2
|
, pipewire_0_2
|
||||||
@ -204,6 +204,9 @@ in stdenv.mkDerivation {
|
|||||||
|
|
||||||
export XDG_DATA_DIRS=$XDG_ICON_DIRS:$GSETTINGS_SCHEMAS_PATH\''${XDG_DATA_DIRS:+:}\$XDG_DATA_DIRS
|
export XDG_DATA_DIRS=$XDG_ICON_DIRS:$GSETTINGS_SCHEMAS_PATH\''${XDG_DATA_DIRS:+:}\$XDG_DATA_DIRS
|
||||||
|
|
||||||
|
# Mainly for xdg-open but also other xdg-* tools:
|
||||||
|
export PATH="${xdg_utils}/bin\''${PATH:+:}\$PATH"
|
||||||
|
|
||||||
.
|
.
|
||||||
w
|
w
|
||||||
EOF
|
EOF
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
buildGoModule rec {
|
buildGoModule rec {
|
||||||
pname = "helm";
|
pname = "helm";
|
||||||
version = "3.3.0";
|
version = "3.3.1";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "helm";
|
owner = "helm";
|
||||||
repo = "helm";
|
repo = "helm";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "0bp2yscrvdm46w2nxas5zs9mcvdn2yp05k0wmcjl7gh42fs6hmcs";
|
sha256 = "0y3ilvafzwizd9zqvp8jijkkd1c2yy7zyl5xfma1zv2x96p7xgqh";
|
||||||
};
|
};
|
||||||
vendorSha256 = "0lccglh5qpm5kp8xp1pn7y4cfxjpax83gyzjmnhh9h5y9zwgqp03";
|
vendorSha256 = "0f8a0psvic923rh13f5041p7hr6w8dy9qxdw3l195yky5cf3fj6w";
|
||||||
|
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
|
|
||||||
@ -28,6 +28,6 @@ buildGoModule rec {
|
|||||||
homepage = "https://github.com/kubernetes/helm";
|
homepage = "https://github.com/kubernetes/helm";
|
||||||
description = "A package manager for kubernetes";
|
description = "A package manager for kubernetes";
|
||||||
license = licenses.asl20;
|
license = licenses.asl20;
|
||||||
maintainers = with maintainers; [ rlupton20 edude03 saschagrunert Frostman ];
|
maintainers = with maintainers; [ rlupton20 edude03 saschagrunert Frostman Chili-Man ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
buildGoModule rec {
|
buildGoModule rec {
|
||||||
pname = "terragrunt";
|
pname = "terragrunt";
|
||||||
version = "0.23.33";
|
version = "0.23.40";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "gruntwork-io";
|
owner = "gruntwork-io";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "0fsyvmdg2llnzy0yzmiihnb865ccq2sn6d3i935dflppnjyp01p4";
|
sha256 = "0gd2g1nl8dgj24mzk4qymcwnp6prbi3qxj863rkpi3k32zy2iw4k";
|
||||||
};
|
};
|
||||||
|
|
||||||
vendorSha256 = "05p72l724qqf61dn0frahf4awvkkcw8cpl6nhwlacd1jw8c14fjl";
|
vendorSha256 = "0f466qn5vp74mwx9s4rcbw1x793w8hr5dcf2c12sgshya1bxs4nl";
|
||||||
|
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
|
|
||||||
|
@ -23,11 +23,11 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "liferea";
|
pname = "liferea";
|
||||||
version = "1.12.6";
|
version = "1.12.9";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://github.com/lwindolf/${pname}/releases/download/v${version}/${pname}-${version}b.tar.bz2";
|
url = "https://github.com/lwindolf/${pname}/releases/download/v${version}/${pname}-${version}.tar.bz2";
|
||||||
sha256 = "03pr1gmiv5y0i92bkhcxr8s311ll91chz19wb96jkixx32xav91d";
|
sha256 = "06ybr1wjlfir8iqjx6x0v1knd4b2hsy30qmkk4kssy6ky2ahc66q";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
@ -73,7 +73,7 @@ stdenv.mkDerivation rec {
|
|||||||
description = "A GTK-based news feed aggregator";
|
description = "A GTK-based news feed aggregator";
|
||||||
homepage = "http://lzone.de/liferea/";
|
homepage = "http://lzone.de/liferea/";
|
||||||
license = licenses.gpl2Plus;
|
license = licenses.gpl2Plus;
|
||||||
maintainers = with maintainers; [ vcunat romildo ];
|
maintainers = with maintainers; [ romildo ];
|
||||||
platforms = platforms.linux;
|
platforms = platforms.linux;
|
||||||
|
|
||||||
longDescription = ''
|
longDescription = ''
|
||||||
|
@ -26,14 +26,15 @@ in stdenv.mkDerivation rec {
|
|||||||
sha256 = "01gm9gj2x2zs4yx6wk761fi1papi7qr3gp4ln1kkn8n2f9y9h849";
|
sha256 = "01gm9gj2x2zs4yx6wk761fi1papi7qr3gp4ln1kkn8n2f9y9h849";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ nim ];
|
nativeBuildInputs = [ nim ];
|
||||||
|
buildInputs = [ htslib pcre ];
|
||||||
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
HOME=$TMPDIR
|
HOME=$TMPDIR
|
||||||
nim -p:${hts-nim}/src -p:${docopt}/src c --nilseqs:on -d:release mosdepth.nim
|
nim -p:${hts-nim}/src -p:${docopt}/src c --nilseqs:on -d:release mosdepth.nim
|
||||||
'';
|
'';
|
||||||
|
|
||||||
installPhase = "install -Dt $out/bin mosdepth";
|
installPhase = "install -Dt $out/bin mosdepth";
|
||||||
fixupPhase = "patchelf --set-rpath ${stdenv.lib.makeLibraryPath [ stdenv.cc.cc htslib pcre ]} $out/bin/mosdepth";
|
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "fast BAM/CRAM depth calculation for WGS, exome, or targeted sequencing.";
|
description = "fast BAM/CRAM depth calculation for WGS, exome, or targeted sequencing.";
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "picard-tools";
|
pname = "picard-tools";
|
||||||
version = "2.23.3";
|
version = "2.23.4";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://github.com/broadinstitute/picard/releases/download/${version}/picard.jar";
|
url = "https://github.com/broadinstitute/picard/releases/download/${version}/picard.jar";
|
||||||
sha256 = "08wgi0hijfbchr2srmndxq3h2fijvyvr8b6zv680fpcjixm5bbhf";
|
sha256 = "0xg4nbx02a2kckr6p8pqjpv5rmp95bkmglgm1bma6f77s7hkab7q";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ makeWrapper ];
|
nativeBuildInputs = [ makeWrapper ];
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "ott";
|
pname = "ott";
|
||||||
version = "0.30";
|
version = "0.31";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "ott-lang";
|
owner = "ott-lang";
|
||||||
repo = "ott";
|
repo = "ott";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "16bxfnm30z94x36vr8vs6zd6fj55vnb7aypjl6hf7clk42040brc";
|
sha256 = "0l81126i2qkz11fs5yrjdgymnqgjcs5avb7f951h61yh1s68jpnn";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ pkgconfig ];
|
nativeBuildInputs = [ pkgconfig ];
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "proverif";
|
pname = "proverif";
|
||||||
version = "2.01";
|
version = "2.02pl1";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "http://prosecco.gforge.inria.fr/personal/bblanche/proverif/proverif${version}.tar.gz";
|
url = "http://prosecco.gforge.inria.fr/personal/bblanche/proverif/proverif${version}.tar.gz";
|
||||||
sha256 = "01wp5431c77z0aaa99h8bnm5yhr6jslpqc8iyg0a7gxfqnb19gxi";
|
sha256 = "1jmzfpx0hdgfmkq0jp6i3k5av9xxgndjaj743wfy37svn0ga4jjx";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = with ocamlPackages; [ ocaml findlib lablgtk ];
|
buildInputs = with ocamlPackages; [ ocaml findlib lablgtk ];
|
||||||
|
@ -453,7 +453,7 @@ stdenv.mkDerivation {
|
|||||||
|
|
||||||
substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh
|
substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh
|
||||||
substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh
|
substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh
|
||||||
substituteAll ${../wrapper-common/utils.bash} $out/nix-support/utils.bash
|
substituteAll ${if stdenv.isDarwin then ../wrapper-common/utils.bash.darwin else ../wrapper-common/utils.bash} $out/nix-support/utils.bash
|
||||||
''
|
''
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -107,7 +107,7 @@ stdenv.mkDerivation {
|
|||||||
|
|
||||||
+ ''
|
+ ''
|
||||||
substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh
|
substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh
|
||||||
substituteAll ${../wrapper-common/utils.bash} $out/nix-support/utils.bash
|
substituteAll ${if stdenv.isDarwin then ../wrapper-common/utils.bash.darwin else ../wrapper-common/utils.bash} $out/nix-support/utils.bash
|
||||||
''
|
''
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -8,13 +8,13 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "marwaita";
|
pname = "marwaita";
|
||||||
version = "7.5.1";
|
version = "7.6.1";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "darkomarko42";
|
owner = "darkomarko42";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "0ig5wc6dkbly6yrvd13h4lyr8x0y7k3d9iv4rhg0pnjgcpna83mw";
|
sha256 = "1n7flwrngwh6gmh72j40apf8qk52162m93hsfhgxzrivkhg37zi0";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
@ -37,7 +37,7 @@ stdenv.mkDerivation rec {
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "GTK theme supporting Budgie, Pantheon, Mate and Xfce4 desktops";
|
description = "GTK theme supporting Budgie, Pantheon, Mate, Xfce4 and GNOME desktops";
|
||||||
homepage = "https://www.pling.com/p/1239855/";
|
homepage = "https://www.pling.com/p/1239855/";
|
||||||
license = licenses.cc0;
|
license = licenses.cc0;
|
||||||
platforms = platforms.unix;
|
platforms = platforms.unix;
|
||||||
|
23
pkgs/development/compilers/nim/NIM_CONFIG_DIR.patch
Normal file
23
pkgs/development/compilers/nim/NIM_CONFIG_DIR.patch
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim
|
||||||
|
index a470179bd..73cfa1a23 100644
|
||||||
|
--- a/compiler/nimconf.nim
|
||||||
|
+++ b/compiler/nimconf.nim
|
||||||
|
@@ -225,10 +225,15 @@ proc getUserConfigPath*(filename: RelativeFile): AbsoluteFile =
|
||||||
|
proc getSystemConfigPath*(conf: ConfigRef; filename: RelativeFile): AbsoluteFile =
|
||||||
|
# try standard configuration file (installation did not distribute files
|
||||||
|
# the UNIX way)
|
||||||
|
- let p = getPrefixDir(conf)
|
||||||
|
- result = p / RelativeDir"config" / filename
|
||||||
|
+ let
|
||||||
|
+ prefix = getPrefixDir(conf)
|
||||||
|
+ env = getEnv("NIM_CONFIG_PATH")
|
||||||
|
+ if env != "":
|
||||||
|
+ result = env.toAbsoluteDir / filename
|
||||||
|
+ else:
|
||||||
|
+ result = prefix / RelativeDir"config" / filename
|
||||||
|
when defined(unix):
|
||||||
|
- if not fileExists(result): result = p / RelativeDir"etc/nim" / filename
|
||||||
|
+ if not fileExists(result): result = prefix / RelativeDir"etc/nim" / filename
|
||||||
|
if not fileExists(result): result = AbsoluteDir"/etc/nim" / filename
|
||||||
|
|
||||||
|
proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef) =
|
@ -1,69 +1,255 @@
|
|||||||
# based on https://github.com/nim-lang/Nim/blob/v0.18.0/.travis.yml
|
# https://nim-lang.github.io/Nim/packaging.html
|
||||||
|
|
||||||
{ stdenv, lib, fetchurl, makeWrapper, openssl, pcre, readline,
|
{ stdenv, lib, fetchgit, fetchurl, makeWrapper, gdb, openssl, pcre, readline
|
||||||
boehmgc, sfml, sqlite }:
|
, boehmgc, sqlite, nim-unwrapped, nim-stdlib, nim }:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
let
|
||||||
pname = "nim";
|
|
||||||
version = "1.2.6";
|
version = "1.2.6";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://nim-lang.org/download/${pname}-${version}.tar.xz";
|
url = "https://nim-lang.org/download/nim-${version}.tar.xz";
|
||||||
sha256 = "0zk5qzxayqjw7kq6p92j4008g9bbyilyymhdc5xq9sln5rqym26z";
|
sha256 = "0zk5qzxayqjw7kq6p92j4008g9bbyilyymhdc5xq9sln5rqym26z";
|
||||||
};
|
};
|
||||||
|
|
||||||
enableParallelBuilding = true;
|
meta = with lib; {
|
||||||
|
|
||||||
NIX_LDFLAGS = "-lcrypto -lpcre -lreadline -lgc -lsqlite3";
|
|
||||||
|
|
||||||
# we could create a separate derivation for the "written in c" version of nim
|
|
||||||
# used for bootstrapping, but koch insists on moving the nim compiler around
|
|
||||||
# as part of building it, so it cannot be read-only
|
|
||||||
|
|
||||||
nativeBuildInputs = [
|
|
||||||
makeWrapper
|
|
||||||
];
|
|
||||||
|
|
||||||
buildInputs = [
|
|
||||||
openssl pcre readline boehmgc sfml sqlite
|
|
||||||
];
|
|
||||||
|
|
||||||
buildPhase = ''
|
|
||||||
runHook preBuild
|
|
||||||
|
|
||||||
# build.sh wants to write to $HOME/.cache
|
|
||||||
HOME=$TMPDIR
|
|
||||||
sh build.sh
|
|
||||||
./bin/nim c koch
|
|
||||||
./koch boot -d:release \
|
|
||||||
-d:useGnuReadline \
|
|
||||||
${lib.optionals (stdenv.isDarwin || stdenv.isLinux) "-d:nativeStacktrace"}
|
|
||||||
./koch tools -d:release
|
|
||||||
|
|
||||||
runHook postBuild
|
|
||||||
'';
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
runHook preInstall
|
|
||||||
|
|
||||||
install -Dt $out/bin bin/* koch
|
|
||||||
./koch install $out
|
|
||||||
mv $out/nim/bin/* $out/bin/ && rmdir $out/nim/bin
|
|
||||||
mv $out/nim/* $out/ && rmdir $out/nim
|
|
||||||
|
|
||||||
# Fortify hardening appends -O2 to gcc flags which is unwanted for unoptimized nim builds.
|
|
||||||
wrapProgram $out/bin/nim \
|
|
||||||
--run 'NIX_HARDENING_ENABLE=''${NIX_HARDENING_ENABLE/fortify/}' \
|
|
||||||
--suffix PATH : ${lib.makeBinPath [ stdenv.cc ]}
|
|
||||||
|
|
||||||
runHook postInstall
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
|
||||||
description = "Statically typed, imperative programming language";
|
description = "Statically typed, imperative programming language";
|
||||||
homepage = "https://nim-lang.org/";
|
homepage = "https://nim-lang.org/";
|
||||||
license = licenses.mit;
|
license = licenses.mit;
|
||||||
maintainers = with maintainers; [ ehmry ];
|
maintainers = with maintainers; [ ehmry ];
|
||||||
platforms = with platforms; linux ++ darwin; # arbitrary
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
parseCpu = platform:
|
||||||
|
with platform;
|
||||||
|
# Derive a Nim CPU identifier
|
||||||
|
if isAarch32 then
|
||||||
|
"arm"
|
||||||
|
else if isAarch64 then
|
||||||
|
"arm64"
|
||||||
|
else if isAlpha then
|
||||||
|
"alpha"
|
||||||
|
else if isAvr then
|
||||||
|
"avr"
|
||||||
|
else if isMips && is32bit then
|
||||||
|
"mips"
|
||||||
|
else if isMips && is64bit then
|
||||||
|
"mips64"
|
||||||
|
else if isMsp430 then
|
||||||
|
"msp430"
|
||||||
|
else if isPowerPC && is32bit then
|
||||||
|
"powerpc"
|
||||||
|
else if isPowerPC && is64bit then
|
||||||
|
"powerpc64"
|
||||||
|
else if isRiscV && is64bit then
|
||||||
|
"riscv64"
|
||||||
|
else if isSparc then
|
||||||
|
"sparc"
|
||||||
|
else if isx86_32 then
|
||||||
|
"i386"
|
||||||
|
else if isx86_64 then
|
||||||
|
"amd64"
|
||||||
|
else
|
||||||
|
abort "no Nim CPU support known for ${config}";
|
||||||
|
|
||||||
|
parseOs = platform:
|
||||||
|
with platform;
|
||||||
|
# Derive a Nim OS identifier
|
||||||
|
if isAndroid then
|
||||||
|
"Android"
|
||||||
|
else if isDarwin then
|
||||||
|
"MacOSX"
|
||||||
|
else if isFreeBSD then
|
||||||
|
"FreeBSD"
|
||||||
|
else if isGenode then
|
||||||
|
"Genode"
|
||||||
|
else if isLinux then
|
||||||
|
"Linux"
|
||||||
|
else if isNetBSD then
|
||||||
|
"NetBSD"
|
||||||
|
else if isNone then
|
||||||
|
"Standalone"
|
||||||
|
else if isOpenBSD then
|
||||||
|
"OpenBSD"
|
||||||
|
else if isWindows then
|
||||||
|
"Windows"
|
||||||
|
else if isiOS then
|
||||||
|
"iOS"
|
||||||
|
else
|
||||||
|
abort "no Nim OS support known for ${config}";
|
||||||
|
|
||||||
|
parsePlatform = p: {
|
||||||
|
cpu = parseCpu p;
|
||||||
|
os = parseOs p;
|
||||||
|
};
|
||||||
|
|
||||||
|
nimHost = parsePlatform stdenv.hostPlatform;
|
||||||
|
nimTarget = parsePlatform stdenv.targetPlatform;
|
||||||
|
|
||||||
|
wrapperInputs = rec {
|
||||||
|
|
||||||
|
bootstrap = stdenv.mkDerivation rec {
|
||||||
|
pname = "nim-bootstrap";
|
||||||
|
version = "0.20.0";
|
||||||
|
|
||||||
|
src = fetchgit {
|
||||||
|
# A Git checkout is much smaller than a GitHub tarball.
|
||||||
|
url = "https://github.com/nim-lang/csources.git";
|
||||||
|
rev = "v" + version;
|
||||||
|
sha256 = "0i6vsfy1sgapx43n226q8m0pvn159sw2mhp50zm3hhb9zfijanis";
|
||||||
|
};
|
||||||
|
|
||||||
|
enableParallelBuilding = true;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
install -Dt $out/bin bin/nim
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
unwrapped = stdenv.mkDerivation {
|
||||||
|
# https://nim-lang.github.io/Nim/packaging.html
|
||||||
|
pname = "nim-unwrapped";
|
||||||
|
inherit version src;
|
||||||
|
|
||||||
|
buildInputs = [ boehmgc openssl pcre readline sqlite ];
|
||||||
|
|
||||||
|
patches = [
|
||||||
|
./NIM_CONFIG_DIR.patch
|
||||||
|
# Override compiler configuration via an environmental variable
|
||||||
|
|
||||||
|
./nixbuild.patch
|
||||||
|
# Load libraries at runtime by absolute path
|
||||||
|
];
|
||||||
|
|
||||||
|
configurePhase = ''
|
||||||
|
runHook preConfigure
|
||||||
|
cp ${bootstrap}/bin/nim bin/
|
||||||
|
echo 'define:nixbuild' >> config/nim.cfg
|
||||||
|
runHook postConfigure
|
||||||
|
'';
|
||||||
|
|
||||||
|
kochArgs = [
|
||||||
|
"--cpu:${nimHost.cpu}"
|
||||||
|
"--os:${nimHost.os}"
|
||||||
|
"-d:release"
|
||||||
|
"-d:useGnuReadline"
|
||||||
|
] ++ lib.optional (stdenv.isDarwin || stdenv.isLinux)
|
||||||
|
"-d:nativeStacktrace";
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
local HOME=$TMPDIR
|
||||||
|
./bin/nim c koch
|
||||||
|
./koch boot $kochArgs --parallelBuild:$NIX_BUILD_CORES
|
||||||
|
./koch tools $kochArgs --parallelBuild:$NIX_BUILD_CORES
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
install -Dt $out/bin bin/*
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
inherit meta;
|
||||||
|
};
|
||||||
|
|
||||||
|
stdlib = stdenv.mkDerivation {
|
||||||
|
pname = "nim-stdlib";
|
||||||
|
inherit (nim-unwrapped) version src patches;
|
||||||
|
|
||||||
|
dontConfigure = true;
|
||||||
|
dontBuild = true;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
touch bin/nim
|
||||||
|
./install.sh $TMPDIR
|
||||||
|
cp -r $TMPDIR/nim/lib $out
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = meta // {
|
||||||
|
description = meta.description + " (standard library)";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
wrapped = let
|
||||||
|
nim = nim-unwrapped;
|
||||||
|
inherit (stdenv) targetPlatform;
|
||||||
|
in stdenv.mkDerivation {
|
||||||
|
name = "${targetPlatform.config}-nim-wrapper-${nim.version}";
|
||||||
|
inherit (nim) version;
|
||||||
|
preferLocalBuild = true;
|
||||||
|
|
||||||
|
nativeBuildInputs = [ makeWrapper ];
|
||||||
|
|
||||||
|
unpackPhase = ''
|
||||||
|
runHook preUnpack
|
||||||
|
tar xf ${nim.src} nim-$version/config/nim.cfg
|
||||||
|
cd nim-$version
|
||||||
|
runHook postUnpack
|
||||||
|
'';
|
||||||
|
|
||||||
|
dontConfigure = true;
|
||||||
|
|
||||||
|
wrapperArgs = [
|
||||||
|
"--prefix PATH : ${lib.makeBinPath [ stdenv.cc gdb ]}:${
|
||||||
|
placeholder "out"
|
||||||
|
}/bin"
|
||||||
|
"--prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [ stdenv.cc.libc openssl ]}"
|
||||||
|
"--set NIM_CONFIG_PATH ${placeholder "out"}/etc/nim"
|
||||||
|
];
|
||||||
|
|
||||||
|
buildPhase = with stdenv;
|
||||||
|
let
|
||||||
|
ccType = if cc.isGNU then
|
||||||
|
"gcc"
|
||||||
|
else if cc.isClang then
|
||||||
|
"clang"
|
||||||
|
else
|
||||||
|
abort "no Nim configuration available for ${cc.name}";
|
||||||
|
in ''
|
||||||
|
runHook preBuild
|
||||||
|
cat >> config/nim.cfg << EOF
|
||||||
|
|
||||||
|
define:nixbuild
|
||||||
|
os = ${nimTarget.os}
|
||||||
|
cpu = ${nimTarget.cpu}
|
||||||
|
cc = ${ccType}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
mkdir -p $out/bin $out/etc/nim
|
||||||
|
export cc=$CC
|
||||||
|
export cxx=$CXX
|
||||||
|
substituteAll config/nim.cfg $out/etc/nim/nim.cfg \
|
||||||
|
--replace "cc = gcc" ""
|
||||||
|
|
||||||
|
for binpath in ${nim}/bin/nim?*; do
|
||||||
|
local binname=`basename $binpath`
|
||||||
|
makeWrapper $binpath $out/bin/${targetPlatform.config}-$binname \
|
||||||
|
$wrapperArgs
|
||||||
|
ln -s $out/bin/${targetPlatform.config}-$binname $out/bin/$binname
|
||||||
|
done
|
||||||
|
|
||||||
|
makeWrapper ${nim}/bin/nim $out/bin/${targetPlatform.config}-nim \
|
||||||
|
$wrapperArgs \
|
||||||
|
--set NIX_HARDENING_ENABLE "''${NIX_HARDENING_ENABLE/fortify}" \
|
||||||
|
--add-flags --lib:${nim-stdlib}
|
||||||
|
ln -s $out/bin/${targetPlatform.config}-nim $out/bin/nim
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
# Fortify hardening appends -O2 to gcc flags which is unwanted for unoptimized nim builds.
|
||||||
|
|
||||||
|
dontInstall = true;
|
||||||
|
|
||||||
|
meta = meta // {
|
||||||
|
description = nim.meta.description
|
||||||
|
+ " (${targetPlatform.config} wrapper)";
|
||||||
|
platforms = lib.platforms.unix;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
in wrapped // wrapperInputs
|
||||||
|
51
pkgs/development/compilers/nim/nixbuild.patch
Normal file
51
pkgs/development/compilers/nim/nixbuild.patch
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
commit 164ba50fc74b980f77047080b2ae1ea099ae9b27
|
||||||
|
Author: Emery Hemingway <ehmry@posteo.net>
|
||||||
|
Date: Mon Sep 7 14:09:22 2020 +0200
|
||||||
|
|
||||||
|
Load libaries by absolute path on NixOS
|
||||||
|
|
||||||
|
If "nixbuild" is defined then choose dynamic runtime libraries by
|
||||||
|
searching $NIX_LDFLAGS at compile-time.
|
||||||
|
|
||||||
|
Fix #15194
|
||||||
|
|
||||||
|
diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim
|
||||||
|
index f31ae94dd..debed9c07 100644
|
||||||
|
--- a/lib/pure/dynlib.nim
|
||||||
|
+++ b/lib/pure/dynlib.nim
|
||||||
|
@@ -56,6 +56,9 @@
|
||||||
|
|
||||||
|
import strutils
|
||||||
|
|
||||||
|
+when defined(nixbuild):
|
||||||
|
+ import os
|
||||||
|
+
|
||||||
|
type
|
||||||
|
LibHandle* = pointer ## a handle to a dynamically loaded library
|
||||||
|
|
||||||
|
@@ -95,6 +98,25 @@ proc libCandidates*(s: string, dest: var seq[string]) =
|
||||||
|
libCandidates(prefix & middle & suffix, dest)
|
||||||
|
else:
|
||||||
|
add(dest, s)
|
||||||
|
+ when defined(nixbuild):
|
||||||
|
+ # Nix doesn't have a global library directory so
|
||||||
|
+ # load libraries using an absolute path if one
|
||||||
|
+ # can be derived from NIX_LDFLAGS.
|
||||||
|
+ #
|
||||||
|
+ # During Nix/NixOS packaging the line "define:nixbuild"
|
||||||
|
+ # should be appended to the ../../config/nim.cfg file
|
||||||
|
+ # to enable this behavior by default.
|
||||||
|
+ #
|
||||||
|
+ var libDirs = split(getEnv("LD_LIBRARY_PATH"), ':')
|
||||||
|
+ for flag in split(getEnv("NIX_LDFLAGS")):
|
||||||
|
+ if flag.startsWith("-L"):
|
||||||
|
+ libDirs.add(flag[2..flag.high])
|
||||||
|
+ for lib in dest:
|
||||||
|
+ for dir in libDirs:
|
||||||
|
+ let abs = dir / lib
|
||||||
|
+ if existsFile(abs):
|
||||||
|
+ dest = @[abs]
|
||||||
|
+ return
|
||||||
|
|
||||||
|
proc loadLibPattern*(pattern: string, globalSymbols = false): LibHandle =
|
||||||
|
## loads a library with name matching `pattern`, similar to what `dlimport`
|
@ -5,13 +5,13 @@
|
|||||||
let
|
let
|
||||||
name = "${pname}-${version}";
|
name = "${pname}-${version}";
|
||||||
pname = "guile-sdl2";
|
pname = "guile-sdl2";
|
||||||
version = "0.4.0";
|
version = "0.5.0";
|
||||||
in stdenv.mkDerivation {
|
in stdenv.mkDerivation {
|
||||||
inherit name;
|
inherit name;
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://files.dthompson.us/${pname}/${name}.tar.gz";
|
url = "https://files.dthompson.us/${pname}/${name}.tar.gz";
|
||||||
sha256 = "0zcxwgyadwpbhq6h5mv2569c3kalgra26zc186y9fqiyyzmh1v9s";
|
sha256 = "118x0cg7fzbsyrfhy5f9ab7dqp9czgia0ycgzp6sn3nlsdrcnr4m";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ libtool pkgconfig ];
|
nativeBuildInputs = [ libtool pkgconfig ];
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "catch2";
|
pname = "catch2";
|
||||||
version = "2.12.2";
|
version = "2.12.3";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "catchorg";
|
owner = "catchorg";
|
||||||
repo = "Catch2";
|
repo = "Catch2";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256="17fr2k0jhdcrmmvvb9d8igmjbyads3hkdrakvmrpgc82srm78jcc";
|
sha256="0rp30754frp88wbl17ksr40mmffw5xibq73blgx9jj42d7nl891x";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ cmake ];
|
nativeBuildInputs = [ cmake ];
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "opencl-clhpp";
|
pname = "opencl-clhpp";
|
||||||
version = "2.0.11";
|
version = "2.0.12";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "KhronosGroup";
|
owner = "KhronosGroup";
|
||||||
repo = "OpenCL-CLHPP";
|
repo = "OpenCL-CLHPP";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "0a0n0f1lb86cwfm0ndzykcn965vz1v0n9n3rfmkiwrzkdhc9iy2y";
|
sha256 = "04g3mg2cpbi048fxxkghra81bpxzqr4r3gspx5mvqipx1lzypsci";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ cmake python ];
|
nativeBuildInputs = [ cmake python ];
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{ stdenv, fetchurl, qt4, qmake4Hook, AGL }:
|
{ stdenv, fetchurl, qt4, qmake4Hook, AGL }:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
name = "qwt-6.1.4";
|
name = "qwt-6.1.5";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "mirror://sourceforge/qwt/${name}.tar.bz2";
|
url = "mirror://sourceforge/qwt/${name}.tar.bz2";
|
||||||
sha256 = "1navkcnmn0qz8kzsyqmk32d929zl72l0b580w1ica7z5559j2a8m";
|
sha256 = "0hf0mpca248xlqn7xnzkfj8drf19gdyg5syzklvq8pibxiixwxj0";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
|
@ -52,6 +52,10 @@ let param =
|
|||||||
version = "8.06.8";
|
version = "8.06.8";
|
||||||
sha256 = "0lfjc7lscq81ibqb3fcybdzs2r1i2xl7rsgi7linq46a0pcpkinw";
|
sha256 = "0lfjc7lscq81ibqb3fcybdzs2r1i2xl7rsgi7linq46a0pcpkinw";
|
||||||
};
|
};
|
||||||
|
"4.11" = mkNewParam {
|
||||||
|
version = "8.06.9";
|
||||||
|
sha256 = "1k42k3bjkf22gk39lwwzqzfhgjyhxnclslldrzpg5qy1829pbnc0";
|
||||||
|
};
|
||||||
}.${builtins.substring 0 4 ocaml.version};
|
}.${builtins.substring 0 4 ocaml.version};
|
||||||
in
|
in
|
||||||
|
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
|
|
||||||
buildPythonPackage rec {
|
buildPythonPackage rec {
|
||||||
pname = "libarcus";
|
pname = "libarcus";
|
||||||
version = "4.6.1";
|
version = "4.7.1";
|
||||||
format = "other";
|
format = "other";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "Ultimaker";
|
owner = "Ultimaker";
|
||||||
repo = "libArcus";
|
repo = "libArcus";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "1sfy8skvgw6hiihs9jmfn7a13yappqwffir98pahyg7cim7p55kr";
|
sha256 = "0wmrcvw7k34ib93shhmjzh6kpndgqr37kyr377sril5clmac0z1f";
|
||||||
};
|
};
|
||||||
|
|
||||||
disabled = pythonOlder "3.4.0";
|
disabled = pythonOlder "3.4.0";
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
buildPythonPackage rec {
|
buildPythonPackage rec {
|
||||||
pname = "libsavitar";
|
pname = "libsavitar";
|
||||||
version = "4.6.1";
|
version = "4.7.1";
|
||||||
format = "other";
|
format = "other";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "Ultimaker";
|
owner = "Ultimaker";
|
||||||
repo = "libSavitar";
|
repo = "libSavitar";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "0nk8zl5b0b36wrrkj271ck4phzxsigkjsazndscjslc9nkldmnpq";
|
sha256 = "0mzr3ynfap51bcn6kshyi2h6iny2gpavn6g3b1xcsgzzlxqgfixf";
|
||||||
};
|
};
|
||||||
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
buildPythonPackage rec {
|
buildPythonPackage rec {
|
||||||
pname = "pydub";
|
pname = "pydub";
|
||||||
version = "0.24.0";
|
version = "0.24.1";
|
||||||
# pypi version doesn't include required data files for tests
|
# pypi version doesn't include required data files for tests
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "jiaaro";
|
owner = "jiaaro";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "0cnhkk44cn3wa4fmd1rwzdx2zgrn87qg25pbcp9wsisdlpn4bj6d";
|
sha256 = "1pv4n54kkjpbjlvwh9b6a7zyq1ylg0fjmd2q4ws9nc2a6mrcivhc";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{ buildPythonPackage, fetchFromGitHub, lib, isPyPy, isPy3k, pythonOlder
|
{ buildPythonPackage, fetchFromGitHub, lib, isPyPy
|
||||||
, pycrypto, ecdsa # TODO
|
, pycrypto, ecdsa # TODO
|
||||||
, enum34, mock
|
, tox, mock, coverage, can, brotli
|
||||||
, withOptionalDeps ? true, tcpdump, ipython
|
, withOptionalDeps ? true, tcpdump, ipython
|
||||||
, withCryptography ? true, cryptography
|
, withCryptography ? true, cryptography
|
||||||
, withVoipSupport ? true, sox
|
, withVoipSupport ? true, sox
|
||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
buildPythonPackage rec {
|
buildPythonPackage rec {
|
||||||
pname = "scapy";
|
pname = "scapy";
|
||||||
version = "2.4.3";
|
version = "2.4.4";
|
||||||
|
|
||||||
disabled = isPyPy;
|
disabled = isPyPy;
|
||||||
|
|
||||||
@ -21,14 +21,11 @@ buildPythonPackage rec {
|
|||||||
owner = "secdev";
|
owner = "secdev";
|
||||||
repo = "scapy";
|
repo = "scapy";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "08ypdzp0p3gvmz3pwi0i9q5f7hz9cq8yn6gawia49ynallwnv4zy";
|
sha256 = "1wpx7gps3g8q5ykbfcd67mxwcs416zg37b53fwfzzlc1m58vhk3p";
|
||||||
};
|
};
|
||||||
|
|
||||||
# TODO: Temporary workaround
|
|
||||||
patches = [ ./fix-version.patch ];
|
|
||||||
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
sed -i "s/NIXPKGS_SCAPY_VERSION/${version}/" scapy/__init__.py
|
printf "${version}" > scapy/VERSION
|
||||||
'' + lib.optionalString withManufDb ''
|
'' + lib.optionalString withManufDb ''
|
||||||
substituteInPlace scapy/data.py --replace "/opt/wireshark" "${wireshark}"
|
substituteInPlace scapy/data.py --replace "/opt/wireshark" "${wireshark}"
|
||||||
'';
|
'';
|
||||||
@ -38,16 +35,41 @@ buildPythonPackage rec {
|
|||||||
++ lib.optional withCryptography cryptography
|
++ lib.optional withCryptography cryptography
|
||||||
++ lib.optional withVoipSupport sox
|
++ lib.optional withVoipSupport sox
|
||||||
++ lib.optional withPlottingSupport matplotlib
|
++ lib.optional withPlottingSupport matplotlib
|
||||||
++ lib.optionals withGraphicsSupport [ pyx texlive.combined.scheme-minimal graphviz imagemagick ]
|
++ lib.optionals withGraphicsSupport [ pyx texlive.combined.scheme-minimal graphviz imagemagick ];
|
||||||
++ lib.optional (isPy3k && pythonOlder "3.4") enum34
|
|
||||||
++ lib.optional doCheck mock;
|
|
||||||
|
|
||||||
# Tests fail with Python 3.6 (seems to be an upstream bug, I'll investigate)
|
# Running the tests seems too complicated:
|
||||||
doCheck = if isPy3k then false else true;
|
doCheck = false;
|
||||||
|
checkInputs = [ tox mock coverage can brotli ];
|
||||||
|
checkPhase = ''
|
||||||
|
patchShebangs .
|
||||||
|
.config/ci/test.sh
|
||||||
|
'';
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
description = "Powerful interactive network packet manipulation program";
|
description = "A Python-based network packet manipulation program and library";
|
||||||
|
longDescription = ''
|
||||||
|
Scapy is a powerful Python-based interactive packet manipulation program
|
||||||
|
and library.
|
||||||
|
|
||||||
|
It is able to forge or decode packets of a wide number of protocols, send
|
||||||
|
them on the wire, capture them, store or read them using pcap files,
|
||||||
|
match requests and replies, and much more. It is designed to allow fast
|
||||||
|
packet prototyping by using default values that work.
|
||||||
|
|
||||||
|
It can easily handle most classical tasks like scanning, tracerouting,
|
||||||
|
probing, unit tests, attacks or network discovery (it can replace hping,
|
||||||
|
85% of nmap, arpspoof, arp-sk, arping, tcpdump, wireshark, p0f, etc.). It
|
||||||
|
also performs very well at a lot of other specific tasks that most other
|
||||||
|
tools can't handle, like sending invalid frames, injecting your own
|
||||||
|
802.11 frames, combining techniques (VLAN hopping+ARP cache poisoning,
|
||||||
|
VoIP decoding on WEP protected channel, ...), etc.
|
||||||
|
|
||||||
|
Scapy supports Python 2.7 and Python 3 (3.4 to 3.8). It's intended to be
|
||||||
|
cross platform, and runs on many different platforms (Linux, OSX, *BSD,
|
||||||
|
and Windows).
|
||||||
|
'';
|
||||||
homepage = "https://scapy.net/";
|
homepage = "https://scapy.net/";
|
||||||
|
changelog = "https://github.com/secdev/scapy/releases/tag/v${version}";
|
||||||
license = licenses.gpl2;
|
license = licenses.gpl2;
|
||||||
platforms = platforms.unix;
|
platforms = platforms.unix;
|
||||||
maintainers = with maintainers; [ primeos bjornfor ];
|
maintainers = with maintainers; [ primeos bjornfor ];
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
diff --git a/scapy/__init__.py b/scapy/__init__.py
|
|
||||||
index d5ad6164..245ce2fb 100644
|
|
||||||
--- a/scapy/__init__.py
|
|
||||||
+++ b/scapy/__init__.py
|
|
||||||
@@ -90,7 +90,7 @@ def _version():
|
|
||||||
return 'unknown.version'
|
|
||||||
|
|
||||||
|
|
||||||
-VERSION = __version__ = _version()
|
|
||||||
+VERSION = __version__ = "NIXPKGS_SCAPY_VERSION"
|
|
||||||
VERSION_MAIN = re.search(r"[0-9.]+", VERSION).group()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
@ -2,7 +2,7 @@
|
|||||||
, pyqt5, numpy, scipy, shapely, libarcus, doxygen, gettext, pythonOlder }:
|
, pyqt5, numpy, scipy, shapely, libarcus, doxygen, gettext, pythonOlder }:
|
||||||
|
|
||||||
buildPythonPackage rec {
|
buildPythonPackage rec {
|
||||||
version = "4.6.1";
|
version = "4.7.1";
|
||||||
pname = "uranium";
|
pname = "uranium";
|
||||||
format = "other";
|
format = "other";
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ buildPythonPackage rec {
|
|||||||
owner = "Ultimaker";
|
owner = "Ultimaker";
|
||||||
repo = "Uranium";
|
repo = "Uranium";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "07pksjbgxs1ks2i6pgxkwfg9c56pcql7f9p89dnwaf2rcn7yhx6r";
|
sha256 = "1h5d3scy3cnbyhh0pbavflpqklhn2lbp7hl193rc5gx8yzr3mqbh";
|
||||||
};
|
};
|
||||||
|
|
||||||
disabled = pythonOlder "3.5.0";
|
disabled = pythonOlder "3.5.0";
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
buildGoModule rec {
|
buildGoModule rec {
|
||||||
pname = "bazel-kazel";
|
pname = "bazel-kazel";
|
||||||
version = "0.0.12";
|
version = "0.1.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "kubernetes";
|
owner = "kubernetes";
|
||||||
repo = "repo-infra";
|
repo = "repo-infra";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "1mnyp116q54xy7flml4cdcsbczhyyqnpyn2pnqrzy49aahbhpn5z";
|
sha256 = "121asn0h2vfgqnjk72wqjcfq0w15k15abjdm39i8hv455kzrc2hs";
|
||||||
};
|
};
|
||||||
|
|
||||||
vendorSha256 = "1pzkjh4n9ai8yqi98bkdhicjdr2l8j3fckl5n90c2gdcwqyxvgkf";
|
vendorSha256 = "1pzkjh4n9ai8yqi98bkdhicjdr2l8j3fckl5n90c2gdcwqyxvgkf";
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{ stdenv
|
{ stdenv
|
||||||
, buildGoModule
|
, buildGoModule
|
||||||
, fetchFromGitHub
|
, fetchFromGitHub
|
||||||
|
, go-md2man
|
||||||
, installShellFiles
|
, installShellFiles
|
||||||
, pkg-config
|
, pkg-config
|
||||||
, gpgme
|
, gpgme
|
||||||
@ -13,13 +14,13 @@
|
|||||||
|
|
||||||
buildGoModule rec {
|
buildGoModule rec {
|
||||||
pname = "buildah";
|
pname = "buildah";
|
||||||
version = "1.15.2";
|
version = "1.16.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "containers";
|
owner = "containers";
|
||||||
repo = "buildah";
|
repo = "buildah";
|
||||||
rev = "v${version}";
|
rev = "V${version}";
|
||||||
sha256 = "13kqcdrdzkbg6h5za6hhkzdx4nbrg5yl97ydj2hfcakl00q4y0dp";
|
sha256 = "0z9fblxm3pk2jqw7h36clmj8k4k39n6ab536lyh0rp6p7hz5a988";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = [ "out" "man" ];
|
outputs = [ "out" "man" ];
|
||||||
@ -28,7 +29,7 @@ buildGoModule rec {
|
|||||||
|
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
|
|
||||||
nativeBuildInputs = [ installShellFiles pkg-config ];
|
nativeBuildInputs = [ go-md2man installShellFiles pkg-config ];
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
btrfs-progs
|
btrfs-progs
|
||||||
@ -41,12 +42,12 @@ buildGoModule rec {
|
|||||||
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
patchShebangs .
|
patchShebangs .
|
||||||
make GIT_COMMIT="unknown"
|
make bin/buildah GIT_COMMIT="unknown"
|
||||||
make -C docs
|
make -C docs GOMD2MAN="${go-md2man}/bin/go-md2man"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
install -Dm755 buildah $out/bin/buildah
|
install -Dm755 bin/buildah $out/bin/buildah
|
||||||
installShellCompletion --bash contrib/completions/bash/buildah
|
installShellCompletion --bash contrib/completions/bash/buildah
|
||||||
make -C docs install PREFIX="$man"
|
make -C docs install PREFIX="$man"
|
||||||
'';
|
'';
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
{ stdenv, buildGoPackage, fetchFromGitHub }:
|
{ stdenv, buildGoModule, fetchFromGitHub }:
|
||||||
|
|
||||||
buildGoPackage rec {
|
buildGoModule rec {
|
||||||
pname = "scc";
|
pname = "scc";
|
||||||
version = "2.12.0";
|
version = "2.13.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "boyter";
|
owner = "boyter";
|
||||||
repo = "scc";
|
repo = "scc";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "0hbcq5qn97kr9d4q9m2p1mj3ijn8zmwycrs5bgf1kfiwr09wg2yh";
|
sha256 = "16p5g20n5jsbisbgikk9xny94xx6c0dxf19saa686ghh31jr2hh3";
|
||||||
};
|
};
|
||||||
|
|
||||||
goPackagePath = "github.com/boyter/scc";
|
vendorSha256 = null;
|
||||||
|
|
||||||
# scc has a scripts/ sub-package that's for testing.
|
# scc has a scripts/ sub-package that's for testing.
|
||||||
subPackages = [ "./" ];
|
excludedPackages = [ "scripts" ];
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
homepage = "https://github.com/boyter/scc";
|
homepage = "https://github.com/boyter/scc";
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
buildGoPackage rec {
|
buildGoPackage rec {
|
||||||
pname = "terraform-ls";
|
pname = "terraform-ls";
|
||||||
version = "0.6.1";
|
version = "0.7.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "hashicorp";
|
owner = "hashicorp";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "0yhpxb9dkwi6rlabr0sd5rk15q0bin6yhww171jrzlnfl036l0sl";
|
sha256 = "1afdd1zs242nh1cync5ip1fbah34wc3gbsx3hwwiisc8yziwiq18";
|
||||||
};
|
};
|
||||||
|
|
||||||
goPackagePath = "github.com/hashicorp/terraform-ls";
|
goPackagePath = "github.com/hashicorp/terraform-ls";
|
||||||
|
@ -10,7 +10,7 @@ stdenv.mkDerivation rec {
|
|||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://github.com/ocaml/dune/releases/download/${version}/dune-${version}.tbz";
|
url = "https://github.com/ocaml/dune/releases/download/${version}/dune-${version}.tbz";
|
||||||
sha256 = "0lnfmc06yhbdiv6mmp0aksnnvzz4aw4zabrdg89p5msyzir3qrvn";
|
sha256 = "0pcjf209gynjwipnpplaqyvyivnawqiwhvqnivhkybisicpqyln3";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ ocaml findlib ];
|
buildInputs = [ ocaml findlib ];
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
perlPackages.buildPerlPackage rec {
|
perlPackages.buildPerlPackage rec {
|
||||||
pname = "pgformatter";
|
pname = "pgformatter";
|
||||||
version = "4.3";
|
version = "4.4";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "darold";
|
owner = "darold";
|
||||||
repo = "pgFormatter";
|
repo = "pgFormatter";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "0n8ydj01nmnkd8glzjb0yrsyax1pmdfvaxb5xj4pkb2mf6zm94qy";
|
sha256 = "1sqjw6q005lws7qhkd26jqyb1xqmpcklzw5hk8paxxi8mzyjn0jp";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = [ "out" ];
|
outputs = [ "out" ];
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
buildGoModule rec {
|
buildGoModule rec {
|
||||||
pname = "vultr-cli";
|
pname = "vultr-cli";
|
||||||
version = "0.3.2";
|
version = "0.4.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "vultr";
|
owner = "vultr";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "1gqc4w5j9x7vxvxah6hmqd5i1lxyybpml7yfzzcbngwgwm3y5ym0";
|
sha256 = "0gp1v62iqh3hk46cc5sh8a1nw5nf98m969fdhgxdppwr5dhj9isp";
|
||||||
};
|
};
|
||||||
|
|
||||||
vendorSha256 = null;
|
vendorSha256 = null;
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "eventstat";
|
pname = "eventstat";
|
||||||
version = "0.04.09";
|
version = "0.04.10";
|
||||||
src = fetchzip {
|
src = fetchzip {
|
||||||
url = "https://kernel.ubuntu.com/~cking/tarballs/eventstat/eventstat-${version}.tar.gz";
|
url = "https://kernel.ubuntu.com/~cking/tarballs/eventstat/eventstat-${version}.tar.gz";
|
||||||
sha256 = "1b3m58mak62ym2amnmk62c2d6fypk30fw6jsmirh1qz7dwix4bl5";
|
sha256 = "0rmg49m56qxji7gwci03pkk4f4hnaq1n2x1348dqkaf5zs5nhi6b";
|
||||||
};
|
};
|
||||||
buildInputs = [ ncurses ];
|
buildInputs = [ ncurses ];
|
||||||
installFlags = [ "DESTDIR=$(out)" ];
|
installFlags = [ "DESTDIR=$(out)" ];
|
||||||
|
@ -244,6 +244,8 @@ let
|
|||||||
DRM_AMDGPU_SI = whenAtLeast "4.9" yes;
|
DRM_AMDGPU_SI = whenAtLeast "4.9" yes;
|
||||||
# (stable) amdgpu support for bonaire and newer chipsets
|
# (stable) amdgpu support for bonaire and newer chipsets
|
||||||
DRM_AMDGPU_CIK = whenAtLeast "4.9" yes;
|
DRM_AMDGPU_CIK = whenAtLeast "4.9" yes;
|
||||||
|
# Allow device firmware updates
|
||||||
|
DRM_DP_AUX_CHARDEV = whenAtLeast "4.6" yes;
|
||||||
} // optionalAttrs (stdenv.hostPlatform.system == "x86_64-linux") {
|
} // optionalAttrs (stdenv.hostPlatform.system == "x86_64-linux") {
|
||||||
# Intel GVT-g graphics virtualization supports 64-bit only
|
# Intel GVT-g graphics virtualization supports 64-bit only
|
||||||
DRM_I915_GVT = whenAtLeast "4.16" yes;
|
DRM_I915_GVT = whenAtLeast "4.16" yes;
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
{ stdenv, fetchurl, withoutInitTools ? false }:
|
{ stdenv, fetchurl, withoutInitTools ? false }:
|
||||||
|
|
||||||
let version = "2.96"; in
|
let version = "2.97"; in
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = (if withoutInitTools then "sysvtools" else "sysvinit") + "-" + version;
|
name = (if withoutInitTools then "sysvtools" else "sysvinit") + "-" + version;
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "mirror://savannah/sysvinit/sysvinit-${version}.tar.xz";
|
url = "mirror://savannah/sysvinit/sysvinit-${version}.tar.xz";
|
||||||
sha256 = "11xmcamvjmrw874zp0vc37hrqc4hz02i0iy8n4xa4dd25avjcbia";
|
sha256 = "042iyayyh3j28vfbypzn822b73r3nfmyn79f9mixigqrfn2rcn9d";
|
||||||
};
|
};
|
||||||
|
|
||||||
prePatch = ''
|
prePatch = ''
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "atlassian-jira";
|
pname = "atlassian-jira";
|
||||||
version = "8.10.0";
|
version = "8.12.0";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://product-downloads.atlassian.com/software/jira/downloads/atlassian-jira-software-${version}.tar.gz";
|
url = "https://product-downloads.atlassian.com/software/jira/downloads/atlassian-jira-software-${version}.tar.gz";
|
||||||
sha256 = "1l0kxh4cwqyciylbccd4vfmsvq9cr5sfd0v2gbs3lz41av79mlwa";
|
sha256 = "149yqj60b35mbvjz7jyh5a3ayh61kvwrz452s0zyb1q3pirj10xq";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
{ stdenv, lib, fetchFromGitHub, makeWrapper, php }: with lib; stdenv.mkDerivation rec {
|
{ stdenv, lib, fetchFromGitHub, makeWrapper, php }: with lib; stdenv.mkDerivation rec {
|
||||||
pname = "icingaweb2";
|
pname = "icingaweb2";
|
||||||
version = "2.8.0";
|
version = "2.8.1";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "Icinga";
|
owner = "Icinga";
|
||||||
repo = "icingaweb2";
|
repo = "icingaweb2";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "18q3d15w7d46g4vyq4iph5c1bbxcl8ikcdc8djrfi30wx36ziybs";
|
sha256 = "1hmw681a2qv578npr389szkxpbhcfqzq9c1wzkbjjm3avnvi37mf";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ makeWrapper ];
|
nativeBuildInputs = [ makeWrapper ];
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
buildGoModule rec {
|
buildGoModule rec {
|
||||||
pname = "timescale-prometheus";
|
pname = "timescale-prometheus";
|
||||||
version = "0.1.0-beta.2";
|
version = "0.1.0-beta.4";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "timescale";
|
owner = "timescale";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "${version}";
|
rev = "${version}";
|
||||||
sha256 = "1rrr0qb27hh3kcmmxapr1j39dhfxf02vihpjf4b7zpwdf1mpvrbc";
|
sha256 = "1q9zjxxjxa5kkhlsh69bvgns3kzf23z84jjzg294qb7y7xypym5q";
|
||||||
};
|
};
|
||||||
|
|
||||||
vendorSha256 = "sha256:0y5rq2y48kf2z1z3a8ags6rqzfvjs54klk2679fk8x0yjamj5x04";
|
vendorSha256 = "sha256:0y5rq2y48kf2z1z3a8ags6rqzfvjs54klk2679fk8x0yjamj5x04";
|
||||||
|
@ -3,7 +3,7 @@ let
|
|||||||
package = (import ./node.nix { inherit pkgs system; }).package;
|
package = (import ./node.nix { inherit pkgs system; }).package;
|
||||||
in
|
in
|
||||||
package.override rec {
|
package.override rec {
|
||||||
version = "1.14.3";
|
version = "1.14.4";
|
||||||
reconstructLock = true;
|
reconstructLock = true;
|
||||||
|
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
@ -20,7 +20,7 @@ package.override rec {
|
|||||||
owner = "Koenkk";
|
owner = "Koenkk";
|
||||||
repo = "zigbee2mqtt";
|
repo = "zigbee2mqtt";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "164ddb8i4r6rjahjic09sd24xbms4d6b6bnwx0d9fh8sn3ib4v06";
|
sha256 = "1gyl4f7wh7796w4789pi0ix5y30677784miwylr8wrfqgb1hmddq";
|
||||||
};
|
};
|
||||||
|
|
||||||
passthru.tests.zigbee2mqtt = nixosTests.zigbee2mqtt;
|
passthru.tests.zigbee2mqtt = nixosTests.zigbee2mqtt;
|
||||||
|
1392
pkgs/servers/zigbee2mqtt/node-packages.nix
generated
1392
pkgs/servers/zigbee2mqtt/node-packages.nix
generated
File diff suppressed because it is too large
Load Diff
@ -8,12 +8,12 @@ let
|
|||||||
py = python3.override {
|
py = python3.override {
|
||||||
packageOverrides = self: super: {
|
packageOverrides = self: super: {
|
||||||
botocore = super.botocore.overridePythonAttrs (oldAttrs: rec {
|
botocore = super.botocore.overridePythonAttrs (oldAttrs: rec {
|
||||||
version = "2.0.0dev40";
|
version = "2.0.0dev50";
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "boto";
|
owner = "boto";
|
||||||
repo = "botocore";
|
repo = "botocore";
|
||||||
rev = "6b3f96c5e985597053850f0c2761d503d4c18bfe";
|
rev = "e3dceaf9052cc8e221ea757207d5ba37054af2b8";
|
||||||
sha256 = "1ffx86m3b592kj331800qbcz5f532z8kzf1wmd04i4bfiqvqn4h8";
|
sha256 = "0fcf78il4z6gr4gg0jy2h5045ifkslsgldnk6zyvzcl5gykp8i2f";
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
prompt_toolkit = super.prompt_toolkit.overridePythonAttrs (oldAttrs: rec {
|
prompt_toolkit = super.prompt_toolkit.overridePythonAttrs (oldAttrs: rec {
|
||||||
@ -29,13 +29,13 @@ let
|
|||||||
in
|
in
|
||||||
with py.pkgs; buildPythonApplication rec {
|
with py.pkgs; buildPythonApplication rec {
|
||||||
pname = "awscli2";
|
pname = "awscli2";
|
||||||
version = "2.0.36"; # N.B: if you change this, change botocore to a matching version too
|
version = "2.0.46"; # N.B: if you change this, change botocore to a matching version too
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "aws";
|
owner = "aws";
|
||||||
repo = "aws-cli";
|
repo = "aws-cli";
|
||||||
rev = version;
|
rev = version;
|
||||||
hash = "sha256:05c9lss7jg7bwaij1nxwg50grah68zamcixy8jiw3hpc1vdighql";
|
hash = "sha256:10bq4m7hsmj1m7nwr3jgpfvm8bx091vl2hig574r1bjmsi32vy58";
|
||||||
};
|
};
|
||||||
|
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
}:
|
}:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
version = "1.13.1";
|
version = "1.13.2";
|
||||||
pname = "wimlib";
|
pname = "wimlib";
|
||||||
|
|
||||||
nativeBuildInputs = [ pkgconfig makeWrapper ];
|
nativeBuildInputs = [ pkgconfig makeWrapper ];
|
||||||
@ -16,7 +16,7 @@ stdenv.mkDerivation rec {
|
|||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://wimlib.net/downloads/${pname}-${version}.tar.gz";
|
url = "https://wimlib.net/downloads/${pname}-${version}.tar.gz";
|
||||||
sha256 = "0pxgrpr3dr81rcf2jh71aiiq3v4anc5sj1nld18f2vhvbijbrx27";
|
sha256 = "0id9ym3hzij4kpdrk0sz3ijxp5r0z1md5jch83pml9hdy1zbx5bj";
|
||||||
};
|
};
|
||||||
|
|
||||||
preBuild = ''
|
preBuild = ''
|
||||||
|
@ -2,13 +2,18 @@
|
|||||||
, ocamlPackages
|
, ocamlPackages
|
||||||
, libao, portaudio, alsaLib, libpulseaudio, libjack2
|
, libao, portaudio, alsaLib, libpulseaudio, libjack2
|
||||||
, libsamplerate, libmad, taglib, lame, libogg
|
, libsamplerate, libmad, taglib, lame, libogg
|
||||||
, libvorbis, speex, libtheora, libopus, fdk_aac
|
, libvorbis, speex, libtheora, libopus
|
||||||
, faad2, flac, ladspaH, ffmpeg, frei0r, dssi
|
, faad2, flac, ladspaH, ffmpeg, frei0r, dssi
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
pname = "liquidsoap";
|
pname = "liquidsoap";
|
||||||
version = "1.3.4";
|
version = "1.4.2";
|
||||||
|
|
||||||
|
ocaml-ffmpeg = fetchurl {
|
||||||
|
url = "https://github.com/savonet/ocaml-ffmpeg/releases/download/v0.4.2/ocaml-ffmpeg-0.4.2.tar.gz";
|
||||||
|
sha256 = "1lx5s1avds9fsh77828ifn71r2g89rxakhs8pp995a675phm9viw";
|
||||||
|
};
|
||||||
|
|
||||||
packageFilters = map (p: "-e '/ocaml-${p}/d'" )
|
packageFilters = map (p: "-e '/ocaml-${p}/d'" )
|
||||||
[ "gstreamer" "shine" "aacplus" "schroedinger"
|
[ "gstreamer" "shine" "aacplus" "schroedinger"
|
||||||
@ -19,10 +24,17 @@ stdenv.mkDerivation {
|
|||||||
name = "${pname}-full-${version}";
|
name = "${pname}-full-${version}";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://github.com/savonet/${pname}/releases/download/${version}/${pname}-${version}-full.tar.bz2";
|
url = "https://github.com/savonet/${pname}/releases/download/v${version}/${pname}-${version}-full.tar.gz";
|
||||||
sha256 = "11l1h42sljfxcdhddc8klya4bk99j7a1pndwnzvscb04pvmfmlk0";
|
sha256 = "0wkwnzj1a0vizv7sr1blwk5gzm2qi0n02ndijnq1i50cwrgxs1a4";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Use ocaml-srt and ocaml-fdkaac from nixpkgs
|
||||||
|
# Use ocaml-ffmpeg at 0.4.2 for compatibility with ffmpeg 4.3
|
||||||
|
prePatch = ''
|
||||||
|
rm -rf ocaml-srt*/ ocaml-fdkaac*/ ocaml-ffmpeg*/
|
||||||
|
tar xzf ${ocaml-ffmpeg}
|
||||||
|
'';
|
||||||
|
|
||||||
preConfigure = /* we prefer system-wide libs */ ''
|
preConfigure = /* we prefer system-wide libs */ ''
|
||||||
sed -i "s|gsed|sed|" Makefile
|
sed -i "s|gsed|sed|" Makefile
|
||||||
make bootstrap
|
make bootstrap
|
||||||
@ -42,10 +54,12 @@ stdenv.mkDerivation {
|
|||||||
[ which ocamlPackages.ocaml ocamlPackages.findlib
|
[ which ocamlPackages.ocaml ocamlPackages.findlib
|
||||||
libao portaudio alsaLib libpulseaudio libjack2
|
libao portaudio alsaLib libpulseaudio libjack2
|
||||||
libsamplerate libmad taglib lame libogg
|
libsamplerate libmad taglib lame libogg
|
||||||
libvorbis speex libtheora libopus fdk_aac
|
libvorbis speex libtheora libopus
|
||||||
faad2 flac ladspaH ffmpeg frei0r dssi
|
faad2 flac ladspaH ffmpeg frei0r dssi
|
||||||
ocamlPackages.xmlm ocamlPackages.ocaml_pcre
|
ocamlPackages.xmlm ocamlPackages.ocaml_pcre
|
||||||
ocamlPackages.camomile
|
ocamlPackages.camomile
|
||||||
|
ocamlPackages.fdkaac
|
||||||
|
ocamlPackages.srt ocamlPackages.sedlex_2 ocamlPackages.menhir
|
||||||
];
|
];
|
||||||
|
|
||||||
hardeningDisable = [ "format" "fortify" ];
|
hardeningDisable = [ "format" "fortify" ];
|
||||||
|
@ -57,6 +57,6 @@ buildRustPackage rec {
|
|||||||
'';
|
'';
|
||||||
homepage = "https://the.exa.website";
|
homepage = "https://the.exa.website";
|
||||||
license = licenses.mit;
|
license = licenses.mit;
|
||||||
maintainers = with maintainers; [ ehegnes lilyball globin zowoq ];
|
maintainers = with maintainers; [ ehegnes lilyball globin ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "fx_cast_bridge";
|
pname = "fx_cast_bridge";
|
||||||
version = "0.0.6";
|
version = "0.0.7";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchurl {
|
||||||
url = "https://github.com/hensm/fx_cast/releases/download/v${version}/${pname}-${version}-x64.deb";
|
url = "https://github.com/hensm/fx_cast/releases/download/v${version}/${pname}-${version}-x64.deb";
|
||||||
sha256 = "1mjpwd27b0cpigz4cc2mdl97d78rj5ikn2bqfdic50lqjciaqi1b";
|
sha256 = "0kd58vzsq1qzl7qsh1qv25ylxvr5y37li03gjb48x4vhd85slzz5";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ dpkg ];
|
nativeBuildInputs = [ dpkg ];
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "lesspipe";
|
pname = "lesspipe";
|
||||||
version = "1.84";
|
version = "1.85";
|
||||||
|
|
||||||
buildInputs = [ perl ];
|
buildInputs = [ perl ];
|
||||||
preConfigure = "patchShebangs .";
|
preConfigure = "patchShebangs .";
|
||||||
@ -11,7 +11,7 @@ stdenv.mkDerivation rec {
|
|||||||
owner = "wofr06";
|
owner = "wofr06";
|
||||||
repo = "lesspipe";
|
repo = "lesspipe";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "124ffhzrikr88ab14rk6753n8adxijpmg7q3zx7nmqc52wpkfd8q";
|
sha256 = "1v1jdkdq1phc93gdr6mjlk98gipxrkkq4bj8kks0kfdvjgdwkdaa";
|
||||||
};
|
};
|
||||||
|
|
||||||
patches = [
|
patches = [
|
||||||
|
@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
rustPlatform.buildRustPackage rec {
|
rustPlatform.buildRustPackage rec {
|
||||||
pname = "topgrade";
|
pname = "topgrade";
|
||||||
version = "5.5.0";
|
version = "5.7.0";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "r-darwish";
|
owner = "r-darwish";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "1adx029cq30g0qnrvdq2di8bpadzdxrpbsqchxfsda8zg6cprh1j";
|
sha256 = "0nxqi2rykfxhvn8jzprklsc47iilxp1pmm2f17ikfyf5dgi69whb";
|
||||||
};
|
};
|
||||||
|
|
||||||
cargoSha256 = "0jpjn6sb8bkwnq7np487hb8bkm6rv84mihmqwy3ymgdzlqcng6sk";
|
cargoSha256 = "05afmz2n006331hc8yi2mq9kj574xi1iq6gr983jj75ix7n40rgg";
|
||||||
|
|
||||||
buildInputs = lib.optional stdenv.isDarwin Foundation;
|
buildInputs = lib.optional stdenv.isDarwin Foundation;
|
||||||
|
|
||||||
|
@ -1,50 +1,41 @@
|
|||||||
{ stdenv, fetchurl, libpcap, tcl }:
|
{ stdenv, fetchFromGitHub, libpcap, withTcl ? true, tcl }:
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "hping";
|
pname = "hping";
|
||||||
version = "20051105";
|
version = "2014-12-26";
|
||||||
|
|
||||||
src = fetchurl {
|
src = fetchFromGitHub {
|
||||||
url = "http://www.hping.org/hping3-${version}.tar.gz";
|
owner = "antirez";
|
||||||
sha256 = "1s5f9xd1msx05ibhwaw37jmc7l9fahcxxslqz8a83p0i5ak739pm";
|
repo = pname;
|
||||||
|
rev = "3547c7691742c6eaa31f8402e0ccbb81387c1b99"; # there are no tags/releases
|
||||||
|
sha256 = "0y0n1ybij3yg9lfgzcwfmjz1sjg913zcqrv391xx83dm0j80sdpb";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ libpcap tcl ];
|
buildInputs = [ libpcap ] ++ stdenv.lib.optional withTcl tcl;
|
||||||
|
|
||||||
configurePhase = ''
|
postPatch = ''
|
||||||
MANPATH="$out/share/man" ./configure
|
substituteInPlace Makefile.in --replace "gcc" "$CC"
|
||||||
sed -i -r -e 's|/usr(/s?bin)|'"$out"'\1|g' Makefile
|
substituteInPlace version.c --replace "RELEASE_DATE" "\"$version\""
|
||||||
'';
|
'' + stdenv.lib.optionalString stdenv.isLinux ''
|
||||||
|
sed -i -e 's|#include <net/bpf.h>|#include <pcap/bpf.h>|' \
|
||||||
TCLSH = "${tcl}/bin/tclsh";
|
|
||||||
|
|
||||||
prePatch = ''
|
|
||||||
sed -i -e '/#if.*defined(__i386__)/a \
|
|
||||||
|| defined(__x86_64__) \\
|
|
||||||
' bytesex.h
|
|
||||||
|
|
||||||
sed -i -e 's|#include.*net/bpf.h|#include <pcap/bpf.h>|' \
|
|
||||||
libpcap_stuff.c script.c
|
libpcap_stuff.c script.c
|
||||||
|
|
||||||
sed -i -r -e 's|"(/usr/(local/)?)?bin/"|"${tcl}/bin"|g' \
|
|
||||||
-e 's!/usr/(local/)?(lib|include)!${tcl}/\2!g' \
|
|
||||||
configure
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
preInstall = ''
|
configureFlags = [ (if withTcl then "TCLSH=${tcl}/bin/tclsh" else "--no-tcl") ];
|
||||||
mkdir -vp "$out/sbin" "$out/share/man/man8"
|
|
||||||
'';
|
|
||||||
|
|
||||||
postInstall = ''
|
installPhase = ''
|
||||||
ln -vs hping3.8.gz "$out/share/man/man8/hping.8.gz"
|
install -Dm755 hping3 -t $out/sbin
|
||||||
ln -vs hping3.8.gz "$out/share/man/man8/hping2.8.gz"
|
ln -s $out/sbin/hping3 $out/sbin/hping
|
||||||
|
ln -s $out/sbin/hping3 $out/sbin/hping2
|
||||||
|
install -Dm644 docs/hping3.8 -t $out/share/man/man8
|
||||||
|
ln -s hping3.8.gz $out/share/man/man8/hping.8.gz
|
||||||
|
ln -s hping3.8.gz $out/share/man/man8/hping2.8.gz
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = with stdenv.lib; {
|
meta = with stdenv.lib; {
|
||||||
description = "A command-line oriented TCP/IP packet assembler/analyzer";
|
description = "A command-line oriented TCP/IP packet assembler/analyzer";
|
||||||
homepage = "http://www.hping.org/";
|
homepage = "http://www.hping.org/";
|
||||||
license = licenses.gpl2;
|
license = licenses.gpl2Only;
|
||||||
platforms = platforms.all;
|
platforms = platforms.unix;
|
||||||
broken = stdenv.isDarwin;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "keepalived";
|
pname = "keepalived";
|
||||||
version = "2.0.20";
|
version = "2.1.3";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "acassen";
|
owner = "acassen";
|
||||||
repo = "keepalived";
|
repo = "keepalived";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "0ijzw56hbac24dhrgjd0hjgf45072imyzq3mcgsirdl3xqjc6x12";
|
sha256 = "1zdfvicpll7a5iw6p12pmdcg8y30mr0j5miycn0nhjp8yzi9hdc5";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
|
34
pkgs/tools/security/minica/default.nix
Normal file
34
pkgs/tools/security/minica/default.nix
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{ lib, buildGoPackage, fetchFromGitHub }:
|
||||||
|
|
||||||
|
buildGoPackage rec {
|
||||||
|
pname = "minica";
|
||||||
|
version = "1.0.2";
|
||||||
|
|
||||||
|
goPackagePath = "github.com/jsha/minica";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "jsha";
|
||||||
|
repo = "minica";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "18518wp3dcjhf3mdkg5iwxqr3326n6jwcnqhyibphnb2a58ap7ny";
|
||||||
|
};
|
||||||
|
|
||||||
|
buildFlagsArray = ''
|
||||||
|
-ldflags=
|
||||||
|
-X main.BuildVersion=${version}
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "A simple tool for generating self signed certificates.";
|
||||||
|
longDescription = ''
|
||||||
|
Minica is a simple CA intended for use in situations where the CA
|
||||||
|
operator also operates each host where a certificate will be used. It
|
||||||
|
automatically generates both a key and a certificate when asked to
|
||||||
|
produce a certificate.
|
||||||
|
'';
|
||||||
|
homepage = "https://github.com/jsha/minica/";
|
||||||
|
license = licenses.mit;
|
||||||
|
maintainers = with maintainers; [ m1cr0man ];
|
||||||
|
platforms = platforms.linux ++ platforms.darwin;
|
||||||
|
};
|
||||||
|
}
|
@ -3,13 +3,13 @@
|
|||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "miller";
|
pname = "miller";
|
||||||
|
|
||||||
version = "5.9.0";
|
version = "5.9.1";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "johnkerl";
|
owner = "johnkerl";
|
||||||
repo = "miller";
|
repo = "miller";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "14fi6jlqb980qjcpb90fk85cglskq9b9i2k0216bhpvjmagywgp7";
|
sha256 = "1i9bcpfjnl2yjnfmf0ar1l62zwq01ph0yylz0dby8k2l7cvq5ci6";
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = [ autoreconfHook flex libtool ];
|
nativeBuildInputs = [ autoreconfHook flex libtool ];
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "ugrep";
|
pname = "ugrep";
|
||||||
version = "2.5.3";
|
version = "2.5.5";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "Genivia";
|
owner = "Genivia";
|
||||||
repo = pname;
|
repo = pname;
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "16ly1dz8wxnjk6kc88dl2x0ijmzw5v87fhai9fnardwfmycn7ivc";
|
sha256 = "0ba9h0m9c28rllym1djij3b97k4rj06nsgajmbxg5mpxfzplgxy2";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ boost bzip2 lz4 pcre2 xz zlib ];
|
buildInputs = [ boost bzip2 lz4 pcre2 xz zlib ];
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
buildGoModule rec {
|
buildGoModule rec {
|
||||||
pname = "vale";
|
pname = "vale";
|
||||||
version = "2.3.3";
|
version = "2.3.4";
|
||||||
|
|
||||||
subPackages = [ "." ];
|
subPackages = [ "." ];
|
||||||
outputs = [ "out" "data" ];
|
outputs = [ "out" "data" ];
|
||||||
@ -11,7 +11,7 @@ buildGoModule rec {
|
|||||||
owner = "errata-ai";
|
owner = "errata-ai";
|
||||||
repo = "vale";
|
repo = "vale";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
sha256 = "13b565l87nm3gpxxhw1bpjx7yqcgf5124k3wh7r149z38xyqc3wk";
|
sha256 = "0vk7kk2a2891vm46lss8q2893n2zdirlicac2f3xfkrbb5lhkicd";
|
||||||
};
|
};
|
||||||
|
|
||||||
vendorSha256 = null;
|
vendorSha256 = null;
|
||||||
|
24
pkgs/tools/text/vgrep/default.nix
Normal file
24
pkgs/tools/text/vgrep/default.nix
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{ lib, buildGoModule, fetchFromGitHub }:
|
||||||
|
|
||||||
|
buildGoModule rec {
|
||||||
|
pname = "vgrep";
|
||||||
|
version = "2.4.0";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "vrothberg";
|
||||||
|
repo = pname;
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "109j04my2xib8m52a0337996a27nvfgzackpg20zs3nzn66dmvb7";
|
||||||
|
};
|
||||||
|
|
||||||
|
vendorSha256 = null;
|
||||||
|
|
||||||
|
buildFlagsArray = [ "-ldflags=-s -w -X main.version=${version}" ];
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "User-friendly pager for grep/git-grep/ripgrep";
|
||||||
|
homepage = "https://github.com/vrothberg/vgrep";
|
||||||
|
license = licenses.gpl3Only;
|
||||||
|
maintainers = with maintainers; [ zowoq ];
|
||||||
|
};
|
||||||
|
}
|
@ -121,7 +121,9 @@ in
|
|||||||
autoPatchelfHook = makeSetupHook { name = "auto-patchelf-hook"; }
|
autoPatchelfHook = makeSetupHook { name = "auto-patchelf-hook"; }
|
||||||
../build-support/setup-hooks/auto-patchelf.sh;
|
../build-support/setup-hooks/auto-patchelf.sh;
|
||||||
|
|
||||||
appimageTools = callPackage ../build-support/appimage { };
|
appimageTools = callPackage ../build-support/appimage {
|
||||||
|
buildFHSUserEnv = buildFHSUserEnvBubblewrap;
|
||||||
|
};
|
||||||
|
|
||||||
appindicator-sharp = callPackage ../development/libraries/appindicator-sharp { };
|
appindicator-sharp = callPackage ../development/libraries/appindicator-sharp { };
|
||||||
|
|
||||||
@ -4855,7 +4857,6 @@ in
|
|||||||
|
|
||||||
liquidsoap = callPackage ../tools/audio/liquidsoap/full.nix {
|
liquidsoap = callPackage ../tools/audio/liquidsoap/full.nix {
|
||||||
ffmpeg = ffmpeg-full;
|
ffmpeg = ffmpeg-full;
|
||||||
ocamlPackages = ocaml-ng.ocamlPackages_4_07;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
lksctp-tools = callPackage ../os-specific/linux/lksctp-tools { };
|
lksctp-tools = callPackage ../os-specific/linux/lksctp-tools { };
|
||||||
@ -4959,6 +4960,8 @@ in
|
|||||||
|
|
||||||
minergate-cli = callPackage ../applications/misc/minergate-cli { };
|
minergate-cli = callPackage ../applications/misc/minergate-cli { };
|
||||||
|
|
||||||
|
minica = callPackage ../tools/security/minica { };
|
||||||
|
|
||||||
minidlna = callPackage ../tools/networking/minidlna { };
|
minidlna = callPackage ../tools/networking/minidlna { };
|
||||||
|
|
||||||
minisign = callPackage ../tools/security/minisign { };
|
minisign = callPackage ../tools/security/minisign { };
|
||||||
@ -7634,6 +7637,8 @@ in
|
|||||||
|
|
||||||
verilog = callPackage ../applications/science/electronics/verilog {};
|
verilog = callPackage ../applications/science/electronics/verilog {};
|
||||||
|
|
||||||
|
vgrep = callPackage ../tools/text/vgrep { };
|
||||||
|
|
||||||
vhd2vl = callPackage ../applications/science/electronics/vhd2vl { };
|
vhd2vl = callPackage ../applications/science/electronics/vhd2vl { };
|
||||||
|
|
||||||
video2midi = callPackage ../tools/audio/video2midi {
|
video2midi = callPackage ../tools/audio/video2midi {
|
||||||
@ -9440,6 +9445,8 @@ in
|
|||||||
mozart2-binary = callPackage ../development/compilers/mozart/binary.nix { };
|
mozart2-binary = callPackage ../development/compilers/mozart/binary.nix { };
|
||||||
|
|
||||||
nim = callPackage ../development/compilers/nim { };
|
nim = callPackage ../development/compilers/nim { };
|
||||||
|
nim-unwrapped = nim.unwrapped;
|
||||||
|
nim-stdlib = nim.stdlib;
|
||||||
nrpl = callPackage ../development/tools/nrpl { };
|
nrpl = callPackage ../development/tools/nrpl { };
|
||||||
|
|
||||||
neko = callPackage ../development/compilers/neko { };
|
neko = callPackage ../development/compilers/neko { };
|
||||||
@ -19698,7 +19705,11 @@ in
|
|||||||
|
|
||||||
calculix = callPackage ../applications/science/math/calculix {};
|
calculix = callPackage ../applications/science/math/calculix {};
|
||||||
|
|
||||||
calibre = libsForQt5.callPackage ../applications/misc/calibre { };
|
calibre-py2 = libsForQt5.callPackage ../applications/misc/calibre { pythonPackages = python2Packages; };
|
||||||
|
|
||||||
|
calibre-py3 = libsForQt5.callPackage ../applications/misc/calibre { pythonPackages = python3Packages; };
|
||||||
|
|
||||||
|
calibre = calibre-py3;
|
||||||
|
|
||||||
calligra = libsForQt5.callPackage ../applications/office/calligra {
|
calligra = libsForQt5.callPackage ../applications/office/calligra {
|
||||||
inherit (kdeApplications) akonadi-calendar akonadi-contacts;
|
inherit (kdeApplications) akonadi-calendar akonadi-contacts;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user