Merge pull request #291554 from jnsgruk/homepage-config

nixos/homepage-dashboard: support structured config

Changed files
+248 -22
nixos
doc
manual
release-notes
modules
services
tests
pkgs
servers
homepage-dashboard
+2
nixos/doc/manual/release-notes/rl-2405.section.md
···
- `paperless`' `services.paperless.extraConfig` setting has been removed and converted to the freeform type and option named `services.paperless.settings`.
+
- `services.homepage-dashboard` now takes it's configuration using native Nix expressions, rather than dumping templated configurations into `/var/lib/homepage-dashboard` where they were previously managed manually. There are now new options which allow the configuration of bookmarks, services, widgets and custom CSS/JS natively in Nix.
+
- The legacy and long deprecated systemd target `network-interfaces.target` has been removed. Use `network.target` instead.
- `services.frp.settings` now generates the frp configuration file in TOML format as [recommended by upstream](https://github.com/fatedier/frp#configuration-files), instead of the legacy INI format. This has also introduced other changes in the configuration file structure and options.
+206 -18
nixos/modules/services/misc/homepage-dashboard.nix
···
let
cfg = config.services.homepage-dashboard;
+
# Define the settings format used for this program
+
settingsFormat = pkgs.formats.yaml { };
in
{
options = {
···
default = 8082;
description = lib.mdDoc "Port for Homepage to bind to.";
};
+
+
environmentFile = lib.mkOption {
+
type = lib.types.str;
+
description = ''
+
The path to an environment file that contains environment variables to pass
+
to the homepage-dashboard service, for the purpose of passing secrets to
+
the service.
+
+
See the upstream documentation:
+
+
https://gethomepage.dev/latest/installation/docker/#using-environment-secrets
+
'';
+
default = "";
+
};
+
+
customCSS = lib.mkOption {
+
type = lib.types.lines;
+
description = lib.mdDoc ''
+
Custom CSS for styling Homepage.
+
+
See https://gethomepage.dev/latest/configs/custom-css-js/.
+
'';
+
default = "";
+
};
+
+
customJS = lib.mkOption {
+
type = lib.types.lines;
+
description = lib.mdDoc ''
+
Custom Javascript for Homepage.
+
+
See https://gethomepage.dev/latest/configs/custom-css-js/.
+
'';
+
default = "";
+
};
+
+
bookmarks = lib.mkOption {
+
inherit (settingsFormat) type;
+
description = lib.mdDoc ''
+
Homepage bookmarks configuration.
+
+
See https://gethomepage.dev/latest/configs/bookmarks/.
+
'';
+
# Defaults: https://github.com/gethomepage/homepage/blob/main/src/skeleton/bookmarks.yaml
+
example = [
+
{
+
Developer = [
+
{ Github = [{ abbr = "GH"; href = "https://github.com/"; }]; }
+
];
+
}
+
{
+
Entertainment = [
+
{ YouTube = [{ abbr = "YT"; href = "https://youtube.com/"; }]; }
+
];
+
}
+
];
+
default = [ ];
+
};
+
+
services = lib.mkOption {
+
inherit (settingsFormat) type;
+
description = lib.mdDoc ''
+
Homepage services configuration.
+
+
See https://gethomepage.dev/latest/configs/services/.
+
'';
+
# Defaults: https://github.com/gethomepage/homepage/blob/main/src/skeleton/services.yaml
+
example = [
+
{
+
"My First Group" = [
+
{
+
"My First Service" = {
+
href = "http://localhost/";
+
description = "Homepage is awesome";
+
};
+
}
+
];
+
}
+
{
+
"My Second Group" = [
+
{
+
"My Second Service" = {
+
href = "http://localhost/";
+
description = "Homepage is the best";
+
};
+
}
+
];
+
}
+
];
+
default = [ ];
+
};
+
+
widgets = lib.mkOption {
+
inherit (settingsFormat) type;
+
description = lib.mdDoc ''
+
Homepage widgets configuration.
+
+
See https://gethomepage.dev/latest/configs/service-widgets/.
+
'';
+
# Defaults: https://github.com/gethomepage/homepage/blob/main/src/skeleton/widgets.yaml
+
example = [
+
{
+
resources = {
+
cpu = true;
+
memory = true;
+
disk = "/";
+
};
+
}
+
{
+
search = {
+
provider = "duckduckgo";
+
target = "_blank";
+
};
+
}
+
];
+
default = [ ];
+
};
+
+
kubernetes = lib.mkOption {
+
inherit (settingsFormat) type;
+
description = lib.mdDoc ''
+
Homepage kubernetes configuration.
+
+
See https://gethomepage.dev/latest/configs/kubernetes/.
+
'';
+
default = { };
+
};
+
+
docker = lib.mkOption {
+
inherit (settingsFormat) type;
+
description = lib.mdDoc ''
+
Homepage docker configuration.
+
+
See https://gethomepage.dev/latest/configs/docker/.
+
'';
+
default = { };
+
};
+
+
settings = lib.mkOption {
+
inherit (settingsFormat) type;
+
description = lib.mdDoc ''
+
Homepage settings.
+
+
See https://gethomepage.dev/latest/configs/settings/.
+
'';
+
# Defaults: https://github.com/gethomepage/homepage/blob/main/src/skeleton/settings.yaml
+
default = { };
+
};
};
};
-
config = lib.mkIf cfg.enable {
-
systemd.services.homepage-dashboard = {
-
description = "Homepage Dashboard";
-
after = [ "network.target" ];
-
wantedBy = [ "multi-user.target" ];
+
config =
+
let
+
# If homepage-dashboard is enabled, but none of the configuration values have been updated,
+
# then default to "unmanaged" configuration which is manually updated in
+
# var/lib/homepage-dashboard. This is to maintain backwards compatibility, and should be
+
# deprecated in a future release.
+
managedConfig = !(
+
cfg.bookmarks == [ ] &&
+
cfg.customCSS == "" &&
+
cfg.customJS == "" &&
+
cfg.docker == { } &&
+
cfg.kubernetes == { } &&
+
cfg.services == [ ] &&
+
cfg.settings == { } &&
+
cfg.widgets == [ ]
+
);
+
+
configDir = if managedConfig then "/etc/homepage-dashboard" else "/var/lib/homepage-dashboard";
-
environment = {
-
HOMEPAGE_CONFIG_DIR = "/var/lib/homepage-dashboard";
-
PORT = "${toString cfg.listenPort}";
+
msg = "using unmanaged configuration for homepage-dashboard is deprecated and will be removed"
+
+ " in 24.05. please see the NixOS documentation for `services.homepage-dashboard' and add"
+
+ " your bookmarks, services, widgets, and other configuration using the options provided.";
+
in
+
lib.mkIf cfg.enable {
+
warnings = lib.optional (!managedConfig) msg;
+
+
environment.etc = lib.mkIf managedConfig {
+
"homepage-dashboard/custom.css".text = cfg.customCSS;
+
"homepage-dashboard/custom.js".text = cfg.customJS;
+
+
"homepage-dashboard/bookmarks.yaml".source = settingsFormat.generate "bookmarks.yaml" cfg.bookmarks;
+
"homepage-dashboard/docker.yaml".source = settingsFormat.generate "docker.yaml" cfg.docker;
+
"homepage-dashboard/kubernetes.yaml".source = settingsFormat.generate "kubernetes.yaml" cfg.kubernetes;
+
"homepage-dashboard/services.yaml".source = settingsFormat.generate "services.yaml" cfg.services;
+
"homepage-dashboard/settings.yaml".source = settingsFormat.generate "settings.yaml" cfg.settings;
+
"homepage-dashboard/widgets.yaml".source = settingsFormat.generate "widgets.yaml" cfg.widgets;
};
-
serviceConfig = {
-
Type = "simple";
-
DynamicUser = true;
-
StateDirectory = "homepage-dashboard";
-
ExecStart = "${lib.getExe cfg.package}";
-
Restart = "on-failure";
+
systemd.services.homepage-dashboard = {
+
description = "Homepage Dashboard";
+
after = [ "network.target" ];
+
wantedBy = [ "multi-user.target" ];
+
+
environment = {
+
HOMEPAGE_CONFIG_DIR = configDir;
+
PORT = toString cfg.listenPort;
+
LOG_TARGETS = lib.mkIf managedConfig "stdout";
+
};
+
+
serviceConfig = {
+
Type = "simple";
+
DynamicUser = true;
+
EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
+
StateDirectory = lib.mkIf (!managedConfig) "homepage-dashboard";
+
ExecStart = lib.getExe cfg.package;
+
Restart = "on-failure";
+
};
};
-
};
-
networking.firewall = lib.mkIf cfg.openFirewall {
-
allowedTCPPorts = [ cfg.listenPort ];
+
networking.firewall = lib.mkIf cfg.openFirewall {
+
allowedTCPPorts = [ cfg.listenPort ];
+
};
};
-
};
}
+26 -4
nixos/tests/homepage-dashboard.nix
···
name = "homepage-dashboard";
meta.maintainers = with lib.maintainers; [ jnsgruk ];
-
nodes.machine = { pkgs, ... }: {
+
nodes.unmanaged_conf = { pkgs, ... }: {
services.homepage-dashboard.enable = true;
};
+
nodes.managed_conf = { pkgs, ... }: {
+
services.homepage-dashboard = {
+
enable = true;
+
settings.title = "custom";
+
};
+
};
+
testScript = ''
-
machine.wait_for_unit("homepage-dashboard.service")
-
machine.wait_for_open_port(8082)
-
machine.succeed("curl --fail http://localhost:8082/")
+
# Ensure the services are started on unmanaged machine
+
unmanaged_conf.wait_for_unit("homepage-dashboard.service")
+
unmanaged_conf.wait_for_open_port(8082)
+
unmanaged_conf.succeed("curl --fail http://localhost:8082/")
+
+
# Ensure that /etc/homepage-dashboard doesn't exist, and boilerplate
+
# configs are copied into place.
+
unmanaged_conf.fail("test -d /etc/homepage-dashboard")
+
unmanaged_conf.succeed("test -f /var/lib/private/homepage-dashboard/settings.yaml")
+
+
# Ensure the services are started on managed machine
+
managed_conf.wait_for_unit("homepage-dashboard.service")
+
managed_conf.wait_for_open_port(8082)
+
managed_conf.succeed("curl --fail http://localhost:8082/")
+
+
# Ensure /etc/homepage-dashboard is created and unmanaged conf location isn't.
+
managed_conf.succeed("test -d /etc/homepage-dashboard")
+
managed_conf.fail("test -f /var/lib/private/homepage-dashboard/settings.yaml")
'';
})
+14
pkgs/servers/homepage-dashboard/default.nix
···
npmDepsHash = "sha256-u15lDdXnV3xlXAC9WQQKLIeV/AgtRM1sFNsacw3j6kU=";
+
# This project is primarily designed to be consumed through Docker.
+
# By default it logs to stdout, and also to a directory. This makes
+
# little sense here where all the logs will be collated in the
+
# systemd journal anyway, so the patch removes the file logging.
+
# This patch has been suggested upstream, but the contribution won't
+
# be accepted until it gets at least 10 upvotes, per their policy:
+
# https://github.com/gethomepage/homepage/discussions/3067
+
patches = [
+
(fetchpatch {
+
url = "https://github.com/gethomepage/homepage/commit/3be28a2c8b68f2404e4083e7f32eebbccdc4d293.patch";
+
hash = "sha256-5fUOXiHBZ4gdPeOHe1NIaBLaHJTDImsRjSwtueQOEXY=";
+
})
+
];
+
preBuild = ''
mkdir -p config
'';