@ -2,6 +2,7 @@
let
cfg = config . services . geoipupdate ;
inherit ( builtins ) isAttrs isString isInt isList typeOf hashString ;
in
{
imports = [
@ -27,11 +28,30 @@ in
} ;
settings = lib . mkOption {
example = lib . literalExpression ''
{
AccountID = 200001 ;
DatabaseDirectory = " / v a r / l i b / G e o I P " ;
LicenseKey = { _secret = " / r u n / k e y s / m a x m i n d _ l i c e n s e _ k e y " ; } ;
Proxy = " 1 0 . 0 . 0 . 1 0 : 8 8 8 8 " ;
ProxyUserPassword = { _secret = " / r u n / k e y s / p r o x y _ p a s s " ; } ;
}
'' ;
description = ''
<productname> geoipupdate < /productname > configuration
options . See
< link xlink:href= " h t t p s : / / g i t h u b . c o m / m a x m i n d / g e o i p u p d a t e / b l o b / m a i n / d o c / G e o I P . c o n f . m d " / >
for a full list of available options .
Settings containing secret data should be set to an
attribute set containing the attribute
<literal> _secret < /literal > - a string pointing to a file
containing the value the option should be set to . See the
example to get a better picture of this : in the resulting
<filename> GeoIP . conf < /filename > file , the
<literal> ProxyUserPassword < /literal > key will be set to the
contents of the
<filename> /run/keys/proxy_pass < /filename > file .
'' ;
type = lib . types . submodule {
freeformType =
@ -65,11 +85,18 @@ in
} ;
LicenseKey = lib . mkOption {
type = lib . types . path ;
type = with lib . types ; either path ( attrsOf path ) ;
description = ''
A file containing the <productname> MaxMind < /productname >
license key .
A file containing the
<productname> MaxMind < /productname > license key .
Always handled as a secret whether the value is
wrapped in a <literal> { _secret = . . . ; } < /literal >
attrset or not ( refer to < xref
linkend = " o p t - s e r v i c e s . g e o i p u p d a t e . s e t t i n g s " / > for
details ) .
'' ;
apply = x : if isAttrs x then x else { _secret = x ; } ;
} ;
DatabaseDirectory = lib . mkOption {
@ -118,22 +145,30 @@ in
" n e t w o r k - o n l i n e . t a r g e t "
" n s s - l o o k u p . t a r g e t "
] ;
path = [ pkgs . replace-secret ] ;
wants = [ " n e t w o r k - o n l i n e . t a r g e t " ] ;
startAt = cfg . interval ;
serviceConfig = {
ExecStartPre =
let
isSecret = v : isAttrs v && v ? _secret && isString v . _secret ;
geoipupdateKeyValue = lib . generators . toKeyValue {
mkKeyValue = lib . flip lib . generators . mkKeyValueDefault " " rec {
mkValueString = v : with builtins ;
mkValueString = v :
if isInt v then toString v
else if isString v then v
else if true == v then " 1 "
else if false == v then " 0 "
else if isList v then lib . concatMapStringsSep " " mkValueString v
else if isSecret v then hashString " s h a 2 5 6 " v . _secret
else throw " u n s u p p o r t e d t y p e ${ typeOf v } : ${ ( lib . generators . toPretty { } ) v } " ;
} ;
} ;
secretPaths = lib . catAttrs " _ s e c r e t " ( lib . collect isSecret cfg . settings ) ;
mkSecretReplacement = file : ''
replace-secret $ { lib . escapeShellArgs [ ( hashString " s h a 2 5 6 " file ) file " / r u n / g e o i p u p d a t e / G e o I P . c o n f " ] }
'' ;
secretReplacements = lib . concatMapStrings mkSecretReplacement secretPaths ;
geoipupdateConf = pkgs . writeText " g e o i p u p d a t e . c o n f " ( geoipupdateKeyValue cfg . settings ) ;
@ -144,9 +179,7 @@ in
chown geoip " ${ cfg . settings . DatabaseDirectory } "
cp $ { geoipupdateConf } /run/geoipupdate/GeoIP.conf
$ { pkgs . replace-secret } /bin/replace-secret ' $ { cfg . settings . LicenseKey } ' \
' $ { cfg . settings . LicenseKey } ' \
/run/geoipupdate/GeoIP.conf
$ { secretReplacements }
'' ;
in
" + ${ pkgs . writeShellScript " s t a r t - p r e - f u l l - p r i v i l e g e s " script } " ;