mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-09 19:13:26 +03:00
nixos/glance: allow specifying secret settings
This commit is contained in:
parent
5e5402ecbc
commit
27d160b60b
2 changed files with 99 additions and 14 deletions
|
@ -8,15 +8,27 @@ let
|
||||||
cfg = config.services.glance;
|
cfg = config.services.glance;
|
||||||
|
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
mkEnableOption
|
catAttrs
|
||||||
mkPackageOption
|
concatMapStrings
|
||||||
mkOption
|
|
||||||
mkIf
|
|
||||||
getExe
|
getExe
|
||||||
|
mkEnableOption
|
||||||
|
mkIf
|
||||||
|
mkOption
|
||||||
|
mkPackageOption
|
||||||
types
|
types
|
||||||
;
|
;
|
||||||
|
|
||||||
|
inherit (builtins)
|
||||||
|
concatLists
|
||||||
|
isAttrs
|
||||||
|
isList
|
||||||
|
attrNames
|
||||||
|
getAttr
|
||||||
|
;
|
||||||
|
|
||||||
settingsFormat = pkgs.formats.yaml { };
|
settingsFormat = pkgs.formats.yaml { };
|
||||||
|
settingsFile = settingsFormat.generate "glance.yaml" cfg.settings;
|
||||||
|
mergedSettingsFile = "/run/glance/glance.yaml";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.services.glance = {
|
options.services.glance = {
|
||||||
|
@ -69,7 +81,9 @@ in
|
||||||
{ type = "calendar"; }
|
{ type = "calendar"; }
|
||||||
{
|
{
|
||||||
type = "weather";
|
type = "weather";
|
||||||
location = "Nivelles, Belgium";
|
location = {
|
||||||
|
_secret = "/var/lib/secrets/glance/location";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -84,6 +98,13 @@ in
|
||||||
Configuration written to a yaml file that is read by glance. See
|
Configuration written to a yaml file that is read by glance. See
|
||||||
<https://github.com/glanceapp/glance/blob/main/docs/configuration.md>
|
<https://github.com/glanceapp/glance/blob/main/docs/configuration.md>
|
||||||
for more.
|
for more.
|
||||||
|
|
||||||
|
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 in `services.glance.settings.pages` at the weather widget
|
||||||
|
with a location secret to get a better picture of this.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -102,13 +123,41 @@ in
|
||||||
description = "Glance feed dashboard server";
|
description = "Glance feed dashboard server";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
|
path = [ pkgs.replace-secret ];
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart =
|
ExecStartPre =
|
||||||
let
|
let
|
||||||
glance-yaml = settingsFormat.generate "glance.yaml" cfg.settings;
|
findSecrets =
|
||||||
|
data:
|
||||||
|
if isAttrs data then
|
||||||
|
if data ? _secret then
|
||||||
|
[ data ]
|
||||||
|
else
|
||||||
|
concatLists (map (attr: findSecrets (getAttr attr data)) (attrNames data))
|
||||||
|
else if isList data then
|
||||||
|
concatLists (map findSecrets data)
|
||||||
|
else
|
||||||
|
[ ];
|
||||||
|
secretPaths = catAttrs "_secret" (findSecrets cfg.settings);
|
||||||
|
mkSecretReplacement = secretPath: ''
|
||||||
|
replace-secret ${
|
||||||
|
lib.escapeShellArgs [
|
||||||
|
"_secret: ${secretPath}"
|
||||||
|
secretPath
|
||||||
|
mergedSettingsFile
|
||||||
|
]
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
secretReplacements = concatMapStrings mkSecretReplacement secretPaths;
|
||||||
in
|
in
|
||||||
"${getExe cfg.package} --config ${glance-yaml}";
|
# Use "+" to run as root because the secrets may not be accessible to glance
|
||||||
|
"+"
|
||||||
|
+ pkgs.writeShellScript "glance-start-pre" ''
|
||||||
|
install -m 600 -o $USER ${settingsFile} ${mergedSettingsFile}
|
||||||
|
${secretReplacements}
|
||||||
|
'';
|
||||||
|
ExecStart = "${getExe cfg.package} --config ${mergedSettingsFile}";
|
||||||
WorkingDirectory = "/var/lib/glance";
|
WorkingDirectory = "/var/lib/glance";
|
||||||
StateDirectory = "glance";
|
StateDirectory = "glance";
|
||||||
RuntimeDirectory = "glance";
|
RuntimeDirectory = "glance";
|
||||||
|
|
|
@ -5,19 +5,47 @@
|
||||||
|
|
||||||
nodes = {
|
nodes = {
|
||||||
machine_default =
|
machine_default =
|
||||||
{ pkgs, ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
services.glance = {
|
services.glance = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
machine_custom_port =
|
machine_configured =
|
||||||
{ pkgs, ... }:
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
# Do not use this in production. This will make the secret world-readable
|
||||||
|
# in the Nix store
|
||||||
|
secrets.glance-location.path = builtins.toString (
|
||||||
|
pkgs.writeText "location-secret" "Nivelles, Belgium"
|
||||||
|
);
|
||||||
|
in
|
||||||
{
|
{
|
||||||
services.glance = {
|
services.glance = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings.server.port = 5678;
|
settings = {
|
||||||
|
server.port = 5678;
|
||||||
|
pages = [
|
||||||
|
{
|
||||||
|
name = "Home";
|
||||||
|
columns = [
|
||||||
|
{
|
||||||
|
size = "full";
|
||||||
|
widgets = [
|
||||||
|
{ type = "calendar"; }
|
||||||
|
{
|
||||||
|
type = "weather";
|
||||||
|
location = {
|
||||||
|
_secret = secrets.glance-location.path;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -25,23 +53,31 @@
|
||||||
extraPythonPackages =
|
extraPythonPackages =
|
||||||
p: with p; [
|
p: with p; [
|
||||||
beautifulsoup4
|
beautifulsoup4
|
||||||
|
pyyaml
|
||||||
|
types-pyyaml
|
||||||
types-beautifulsoup4
|
types-beautifulsoup4
|
||||||
];
|
];
|
||||||
|
|
||||||
testScript = ''
|
testScript = ''
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
import yaml
|
||||||
|
|
||||||
machine_default.start()
|
machine_default.start()
|
||||||
machine_default.wait_for_unit("glance.service")
|
machine_default.wait_for_unit("glance.service")
|
||||||
machine_default.wait_for_open_port(8080)
|
machine_default.wait_for_open_port(8080)
|
||||||
|
|
||||||
machine_custom_port.start()
|
machine_configured.start()
|
||||||
machine_custom_port.wait_for_unit("glance.service")
|
machine_configured.wait_for_unit("glance.service")
|
||||||
machine_custom_port.wait_for_open_port(5678)
|
machine_configured.wait_for_open_port(5678)
|
||||||
|
|
||||||
soup = BeautifulSoup(machine_default.succeed("curl http://localhost:8080"))
|
soup = BeautifulSoup(machine_default.succeed("curl http://localhost:8080"))
|
||||||
expected_version = "v${config.nodes.machine_default.services.glance.package.version}"
|
expected_version = "v${config.nodes.machine_default.services.glance.package.version}"
|
||||||
assert any(a.text == expected_version for a in soup.select(".footer a"))
|
assert any(a.text == expected_version for a in soup.select(".footer a"))
|
||||||
|
|
||||||
|
yaml_contents = machine_configured.succeed("cat /run/glance/glance.yaml")
|
||||||
|
yaml_parsed = yaml.load(yaml_contents, Loader=yaml.FullLoader)
|
||||||
|
location = yaml_parsed["pages"][0]["columns"][0]["widgets"][1]["location"]
|
||||||
|
assert location == "Nivelles, Belgium"
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta.maintainers = [ lib.maintainers.drupol ];
|
meta.maintainers = [ lib.maintainers.drupol ];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue