mirror of
https://github.com/vale981/phoebe
synced 2025-03-04 09:21:40 -05:00
Automatically depending on NixOps key services, new Rails sourcedFile option
* Services that need password files will automatically depend on the appropriate NixOps key service as necessary. * New `sourcedFile` option for Rails applications to load a Bash script just before starting the Rails service. Useful for setting secret environment variables.
This commit is contained in:
parent
accdc1bf54
commit
193b82189e
7 changed files with 124 additions and 33 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/result
|
24
default.nix
24
default.nix
|
@ -1,7 +1,21 @@
|
|||
{ config, lib, pkgs, ...}:
|
||||
{ pkgs ? import <nixpkgs> { }
|
||||
, ...
|
||||
}:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./modules
|
||||
];
|
||||
pkgs.stdenvNoCC.mkDerivation rec {
|
||||
name = "phoebe-${version}";
|
||||
version = "0.1";
|
||||
src = ./.;
|
||||
|
||||
phases =
|
||||
[ "unpackPhase"
|
||||
"installPhase"
|
||||
"fixupPhase"
|
||||
];
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp -rp bin modules lib $out/
|
||||
chmod 0555 $out/bin/*
|
||||
'';
|
||||
}
|
||||
|
|
43
lib/keys.nix
Normal file
43
lib/keys.nix
Normal file
|
@ -0,0 +1,43 @@
|
|||
# Functions for working with NixOps keys.
|
||||
{ lib }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
# Where NixOps stores keys:
|
||||
keyDirectory = "/run/keys/";
|
||||
|
||||
# Generate a service name:
|
||||
mkServiceName = path:
|
||||
replaceStrings ["/"] ["-"]
|
||||
(removePrefix keyDirectory path + "-key.service");
|
||||
|
||||
funcs = rec {
|
||||
|
||||
/* Test to see if a file path is a NixOps managed key.
|
||||
|
||||
Example:
|
||||
isKeyFile "/run/keys/foo"
|
||||
=> true
|
||||
isKeyFile "/etc/passwd"
|
||||
=> false
|
||||
*/
|
||||
isKeyFile = path:
|
||||
if path == null
|
||||
then false
|
||||
else hasPrefix keyDirectory path;
|
||||
|
||||
/* Returns an array containing a systemd service name that can be
|
||||
used to add a 'wants' or 'after' entry for a NixOps key.
|
||||
|
||||
Example:
|
||||
keyService "/run/keys/foo"
|
||||
=> ["foo.service"]
|
||||
keyService "/etc/passwd"
|
||||
=> []
|
||||
*/
|
||||
keyService = path: optional (isKeyFile path) (mkServiceName path);
|
||||
|
||||
};
|
||||
|
||||
in funcs
|
|
@ -1,8 +1,26 @@
|
|||
{ config, lib, pkgs, ...}:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
libFiles = [
|
||||
../lib/keys.nix
|
||||
];
|
||||
|
||||
loadLib = path: import path { inherit lib; };
|
||||
libs = foldr (a: b: recursiveUpdate (loadLib a) b) {} libFiles;
|
||||
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
./security
|
||||
./services
|
||||
];
|
||||
|
||||
options.phoebe.lib = mkOption {
|
||||
type = types.attrs;
|
||||
default = libs;
|
||||
internal = true;
|
||||
readOnly = true;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,9 +6,10 @@ with lib;
|
|||
|
||||
let
|
||||
cfg = config.phoebe.services.postgresql;
|
||||
plib = config.phoebe.lib;
|
||||
superuser = config.services.postgresql.superUser;
|
||||
create-user = import ./create-user.nix { inherit config lib pkgs; };
|
||||
afterservices = concatMap (a: a.afterServices) (attrValues cfg.accounts);
|
||||
afterservices = concatMap (a: plib.keyService a.passwordFile) (attrValues cfg.accounts);
|
||||
|
||||
# Per-account options:
|
||||
account = { name, ... }: {
|
||||
|
@ -30,18 +31,10 @@ let
|
|||
A file containing the password of this database user.
|
||||
You'll want to use something like NixOps to get the password
|
||||
file onto the target machine.
|
||||
'';
|
||||
};
|
||||
|
||||
afterServices = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
example = [ "dbpassword.service" ];
|
||||
description = ''
|
||||
A list of services that need to run before this user account
|
||||
can be created. This is really useful if you are using
|
||||
NixOps to deploy the password file and want to wait for the
|
||||
key to appear in /run/keys.
|
||||
If the file looks like it's a NixOps key then the account
|
||||
creation script will automatically wait for the appropriate
|
||||
key service to start.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ let
|
|||
##############################################################################
|
||||
# Save some typing.
|
||||
cfg = config.phoebe.services.rails;
|
||||
plib = config.phoebe.lib;
|
||||
scripts = import ./scripts.nix { inherit lib pkgs; };
|
||||
options = import ./options.nix { inherit config lib pkgs; };
|
||||
|
||||
|
@ -70,10 +71,17 @@ let
|
|||
} // app.environment;
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
wants = optional (app.database.passwordService != null) app.database.passwordService;
|
||||
after = [ "network.target" ] ++
|
||||
|
||||
wants =
|
||||
plib.keyService app.database.passwordFile ++
|
||||
plib.keyService app.sourcedFile;
|
||||
|
||||
after =
|
||||
[ "network.target" ] ++
|
||||
optional localpg "postgresql.service" ++
|
||||
optional (app.database.passwordService != null) app.database.passwordService;
|
||||
optional localpg "pg-accounts.service" ++
|
||||
plib.keyService app.database.passwordFile ++
|
||||
plib.keyService app.sourcedFile;
|
||||
|
||||
preStart = ''
|
||||
# Prepare the config directory:
|
||||
|
@ -88,6 +96,11 @@ let
|
|||
mkdir -p ${app.home}/home
|
||||
ln -nfs ${app.package}/share/${app.name} ${app.home}/home/${app.name}
|
||||
|
||||
# Copy the sourcedFile if necessary:
|
||||
${optionalString (app.sourcedFile != null) ''
|
||||
cp ${app.sourcedFile} ${app.home}/state/sourcedFile.sh
|
||||
''}
|
||||
|
||||
# Fix permissions:
|
||||
chown -R rails-${app.name}:rails-${app.name} ${app.home}
|
||||
chmod go+rx $(dirname "${app.home}")
|
||||
|
@ -101,6 +114,11 @@ let
|
|||
-s ${app.home}/state
|
||||
'';
|
||||
|
||||
script = ''
|
||||
${optionalString (app.sourcedFile != null) ". ${app.home}/state/sourcedFile.sh"}
|
||||
${app.package.rubyEnv}/bin/puma -e ${app.railsEnv} -p ${toString app.port}
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
WorkingDirectory = "${app.package}/share/${app.name}";
|
||||
Restart = "on-failure";
|
||||
|
@ -110,7 +128,6 @@ let
|
|||
User = "rails-${app.name}";
|
||||
Group = "rails-${app.name}";
|
||||
UMask = "0077";
|
||||
ExecStart = "${app.package.rubyEnv}/bin/puma -e ${app.railsEnv} -p ${toString app.port}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -31,18 +31,6 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
passwordService = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "db-password.service";
|
||||
description = ''
|
||||
A service to wait on before starting the Rails application.
|
||||
This service should provide the password file for the
|
||||
passwordFile option. Useful when deploying passwords with
|
||||
NixOps.
|
||||
'';
|
||||
};
|
||||
|
||||
migrate = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
|
@ -112,6 +100,23 @@ let
|
|||
default = { };
|
||||
description = "Environment variables.";
|
||||
};
|
||||
|
||||
sourcedFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
example = "/run/keys/env.sh";
|
||||
description = ''
|
||||
Bash file to source immediately before running any service
|
||||
command.
|
||||
|
||||
If the file is store under /run/keys the service will wait
|
||||
for the file to become available.
|
||||
|
||||
This option can be used to set environment variables more
|
||||
securely than using the environment option. However, you
|
||||
should really use the Rails secrets system.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
|
Loading…
Add table
Reference in a new issue