mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-26 19:16:47 +03:00
pumpio service: don't keep secrets in nix store
Added extra config options to allow reading passwords from file rather than the world-readable nix store. The full config.json file is created at service startup. Relevant to #18881
This commit is contained in:
parent
f1a1490135
commit
f488b1811b
2 changed files with 149 additions and 70 deletions
23
nixos/modules/services/web-apps/pump.io-configure.js
Normal file
23
nixos/modules/services/web-apps/pump.io-configure.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var opts = JSON.parse(fs.readFileSync("/dev/stdin").toString());
|
||||||
|
var config = opts.config;
|
||||||
|
|
||||||
|
var readSecret = function(filename) {
|
||||||
|
return fs.readFileSync(filename).toString().trim();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (opts.secretFile) {
|
||||||
|
config.secret = readSecret(opts.secretFile);
|
||||||
|
}
|
||||||
|
if (opts.dbPasswordFile) {
|
||||||
|
config.params.dbpass = readSecret(opts.dbPasswordFile);
|
||||||
|
}
|
||||||
|
if (opts.smtpPasswordFile) {
|
||||||
|
config.smtppass = readSecret(opts.smtpPasswordFile);
|
||||||
|
}
|
||||||
|
if (opts.spamClientSecretFile) {
|
||||||
|
config.spamclientsecret = readSecret(opts.opts.spamClientSecretFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(opts.outputFile, JSON.stringify(config));
|
|
@ -5,27 +5,31 @@ with lib;
|
||||||
let
|
let
|
||||||
cfg = config.services.pumpio;
|
cfg = config.services.pumpio;
|
||||||
dataDir = "/var/lib/pump.io";
|
dataDir = "/var/lib/pump.io";
|
||||||
|
runDir = "/run/pump.io";
|
||||||
user = "pumpio";
|
user = "pumpio";
|
||||||
|
|
||||||
|
optionalSet = condition: value: if condition then value else {};
|
||||||
|
|
||||||
|
configScript = ./pump.io-configure.js;
|
||||||
configOptions = {
|
configOptions = {
|
||||||
driver = if cfg.driver == "disk" then null else cfg.driver;
|
outputFile = "${runDir}/config.json";
|
||||||
params = ({ } //
|
config =
|
||||||
(if cfg.driver == "disk" then {
|
(optionalSet (cfg.driver != "disk") {
|
||||||
dir = dataDir;
|
driver = cfg.driver;
|
||||||
} else { }) //
|
}) //
|
||||||
(if cfg.driver == "mongodb" || cfg.driver == "redis" then {
|
{
|
||||||
|
params = (optionalSet (cfg.driver == "disk") { dir = dataDir; }) //
|
||||||
|
(optionalSet (cfg.driver == "mongodb" || cfg.driver == "redis") {
|
||||||
host = cfg.dbHost;
|
host = cfg.dbHost;
|
||||||
port = cfg.dbPort;
|
port = cfg.dbPort;
|
||||||
dbname = cfg.dbName;
|
dbname = cfg.dbName;
|
||||||
dbuser = cfg.dbUser;
|
dbuser = cfg.dbUser;
|
||||||
dbpass = cfg.dbPassword;
|
dbpass = cfg.dbPassword;
|
||||||
} else { }) //
|
}) //
|
||||||
(if cfg.driver == "memcached" then {
|
(optionalSet (cfg.driver == "memcached") {
|
||||||
host = cfg.dbHost;
|
host = cfg.dbHost;
|
||||||
port = cfg.dbPort;
|
port = cfg.dbPort;
|
||||||
} else { }) //
|
}) // cfg.driverParams;
|
||||||
cfg.driverParams);
|
|
||||||
|
|
||||||
secret = cfg.secret;
|
secret = cfg.secret;
|
||||||
|
|
||||||
address = cfg.address;
|
address = cfg.address;
|
||||||
|
@ -62,15 +66,13 @@ let
|
||||||
debugClient = false;
|
debugClient = false;
|
||||||
firehose = cfg.firehose;
|
firehose = cfg.firehose;
|
||||||
disableRegistration = cfg.disableRegistration;
|
disableRegistration = cfg.disableRegistration;
|
||||||
|
|
||||||
|
inherit (cfg) secretFile dbPasswordFile smtpPasswordFile spamClientSecretFile;
|
||||||
} //
|
} //
|
||||||
(if cfg.port < 1024 then {
|
(optionalSet (cfg.port < 1024) {
|
||||||
serverUser = user; # have pump.io listen then drop privileges
|
serverUser = user; # have pump.io listen then drop privileges
|
||||||
} else { }) //
|
}) // cfg.extraConfig;
|
||||||
cfg.extraConfig;
|
}; in {
|
||||||
|
|
||||||
in
|
|
||||||
|
|
||||||
{
|
|
||||||
options = {
|
options = {
|
||||||
|
|
||||||
services.pumpio = {
|
services.pumpio = {
|
||||||
|
@ -78,7 +80,8 @@ in
|
||||||
enable = mkEnableOption "Pump.io social streams server";
|
enable = mkEnableOption "Pump.io social streams server";
|
||||||
|
|
||||||
secret = mkOption {
|
secret = mkOption {
|
||||||
type = types.str;
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
example = "my dog has fleas";
|
example = "my dog has fleas";
|
||||||
description = ''
|
description = ''
|
||||||
A session-generating secret, server-wide password. Warning:
|
A session-generating secret, server-wide password. Warning:
|
||||||
|
@ -86,6 +89,16 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
secretFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
example = "/run/keys/pump.io-secret";
|
||||||
|
description = ''
|
||||||
|
A file containing the session-generating secret,
|
||||||
|
server-wide password.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
site = mkOption {
|
site = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
example = "Awesome Sauce";
|
example = "Awesome Sauce";
|
||||||
|
@ -126,7 +139,7 @@ in
|
||||||
|
|
||||||
hostname = mkOption {
|
hostname = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = "localhost";
|
||||||
description = ''
|
description = ''
|
||||||
The hostname of the server, used for generating
|
The hostname of the server, used for generating
|
||||||
URLs. Defaults to "localhost" which doesn't do much for you.
|
URLs. Defaults to "localhost" which doesn't do much for you.
|
||||||
|
@ -263,6 +276,15 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dbPasswordFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
example = "/run/keys/pump.io-dbpassword";
|
||||||
|
description = ''
|
||||||
|
A file containing the password corresponding to dbUser.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
smtpHost = mkOption {
|
smtpHost = mkOption {
|
||||||
type = types.nullOr types.str;
|
type = types.nullOr types.str;
|
||||||
default = null;
|
default = null;
|
||||||
|
@ -301,6 +323,17 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
smtpPasswordFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
example = "/run/keys/pump.io-smtppassword";
|
||||||
|
description = ''
|
||||||
|
A file containing the password used to connect to SMTP
|
||||||
|
server. Might not be necessary for some servers.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
smtpUseSSL = mkOption {
|
smtpUseSSL = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
|
@ -342,32 +375,55 @@ in
|
||||||
stored in cleartext in the Nix store!
|
stored in cleartext in the Nix store!
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
spamClientSecretFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
example = "/run/keys/pump.io-spamclientsecret";
|
||||||
|
description = ''
|
||||||
|
A file containing the OAuth key for the spam server.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
warnings = let warn = k: optional (cfg.${k} != null)
|
||||||
|
"config.services.pumpio.${k} is insecure. Use ${k}File instead.";
|
||||||
|
in concatMap warn [ "secret" "dbPassword" "smtpPassword" "spamClientSecret" ];
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{ assertion = !(isNull cfg.secret && isNull cfg.secretFile);
|
||||||
|
message = "pump.io needs a secretFile configured";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
systemd.services."pump.io" =
|
systemd.services."pump.io" =
|
||||||
{ description = "pump.io social network stream server";
|
{ description = "Pump.io - stream server that does most of what people really want from a social network";
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
||||||
preStart = ''
|
preStart = ''
|
||||||
mkdir -p ${dataDir}/uploads
|
mkdir -p ${dataDir}/uploads
|
||||||
chown pumpio:pumpio ${dataDir}/uploads
|
mkdir -p ${runDir}
|
||||||
chmod 770 ${dataDir}/uploads
|
chown pumpio:pumpio ${dataDir}/uploads ${runDir}
|
||||||
|
chmod 770 ${dataDir}/uploads ${runDir}
|
||||||
|
|
||||||
|
${pkgs.nodejs}/bin/node ${configScript} <<EOF
|
||||||
|
${builtins.toJSON configOptions}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chgrp pumpio ${configOptions.outputFile}
|
||||||
|
chmod 640 ${configOptions.outputFile}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
serviceConfig.ExecStart = "${pkgs.pumpio}/bin/pump -c /etc/pump.io.json";
|
serviceConfig = {
|
||||||
|
ExecStart = "${pkgs.pumpio}/bin/pump -c ${configOptions.outputFile}";
|
||||||
PermissionsStartOnly = true;
|
PermissionsStartOnly = true;
|
||||||
serviceConfig.User = if cfg.port < 1024 then "root" else user;
|
User = if cfg.port < 1024 then "root" else user;
|
||||||
serviceConfig.Group = user;
|
Group = user;
|
||||||
};
|
};
|
||||||
|
environment = { NODE_ENV = "production"; };
|
||||||
environment.etc."pump.io.json" = {
|
|
||||||
mode = "0440";
|
|
||||||
gid = config.ids.gids.pumpio;
|
|
||||||
text = builtins.toJSON configOptions;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
users.extraGroups.pumpio.gid = config.ids.gids.pumpio;
|
users.extraGroups.pumpio.gid = config.ids.gids.pumpio;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue