feat: your spotify modules
This commit is contained in:
parent
dfc62da346
commit
6fe5d90427
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
.pre-commit-config.yaml
|
||||
.direnv
|
||||
result
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
{config, ...}: {
|
||||
imports = [./your_spotify_m.nix];
|
||||
age.secrets.spotify = {
|
||||
owner = config.services.your_spotify.user;
|
||||
group = config.services.your_spotify.group;
|
||||
inherit (config.services.your_spotify) user group;
|
||||
rekeyFile = ../../secrets/your_spotify.age;
|
||||
};
|
||||
services.your_spotify = {
|
||||
enable = true;
|
||||
config = {
|
||||
clientEndpoint = "https://spotify.${config.secrets.secrets.global.domains.web}";
|
||||
apiEndpoint = "https://api.spotify.${config.secrets.secrets.global.domains.web}";
|
||||
};
|
||||
environmentFile = config.age.secrets.spotify.path;
|
||||
};
|
||||
environment.persistence."/persist".directories = [
|
||||
{
|
||||
inherit (config.services.mongodb) user;
|
||||
directory = config.services.mongodb.dbpath;
|
||||
user = config.services.mongodb.user;
|
||||
}
|
||||
];
|
||||
}
|
||||
|
|
|
@ -9,52 +9,21 @@
|
|||
boolToString
|
||||
concatMapAttrs
|
||||
concatStrings
|
||||
elem
|
||||
foldl'
|
||||
head
|
||||
isBool
|
||||
isList
|
||||
lowerChars
|
||||
mapAttrsToList
|
||||
mdDoc
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
optional
|
||||
optionalAttrs
|
||||
optionalString
|
||||
stringLength
|
||||
substring
|
||||
toUpper
|
||||
types
|
||||
;
|
||||
cfg = config.services.your_spotify;
|
||||
|
||||
# Convert name from camel case (e.g. disable2FARemember) to upper case snake case (e.g. DISABLE_2FA_REMEMBER).
|
||||
nameToEnvVar = name: let
|
||||
parts = builtins.split "([A-Z0-9]+)" name;
|
||||
partsToEnvVar = parts:
|
||||
foldl' (key: x: let
|
||||
last = stringLength key - 1;
|
||||
in
|
||||
if isList x
|
||||
then key + optionalString (key != "" && substring last 1 key != "_") "_" + head x
|
||||
else if key != "" && elem (substring 0 1 x) lowerChars
|
||||
then # to handle e.g. [ "disable" [ "2FAR" ] "emember" ]
|
||||
substring 0 last key + optionalString (substring (last - 1) 1 key != "_") "_" + substring last 1 key + toUpper x
|
||||
else key + toUpper x) ""
|
||||
parts;
|
||||
in
|
||||
if builtins.match "[A-Z0-9_]+" name != null
|
||||
then name
|
||||
else partsToEnvVar parts;
|
||||
|
||||
# Due to the different naming schemes allowed for config keys,
|
||||
# we can only check for values consistently after converting them to their corresponding environment variable name.
|
||||
configEnv = concatMapAttrs (name: value:
|
||||
optionalAttrs (value != null) {
|
||||
${nameToEnvVar name} =
|
||||
name =
|
||||
if isBool value
|
||||
then boolToString value
|
||||
else toString value;
|
||||
|
@ -64,30 +33,25 @@
|
|||
configFile = pkgs.writeText "your_spotify.env" (concatStrings (mapAttrsToList (name: value: "${name}=${value}\n") configEnv));
|
||||
in {
|
||||
options.services.your_spotify = let
|
||||
inherit (types) nullOr int str bool package;
|
||||
inherit (types) nullOr port str bool package;
|
||||
in {
|
||||
enable = mkEnableOption (lib.mdDoc "your_spotify");
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "your_spotify";
|
||||
description = lib.mdDoc "User account under which your_spotify runs.";
|
||||
};
|
||||
enable = mkEnableOption "your_spotify";
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "your_spotify";
|
||||
description = lib.mdDoc "Group account under which your_spotify runs.";
|
||||
};
|
||||
enableLocalDB = mkEnableOption "a local mongodb instance";
|
||||
enableNginxVirtualHost = mkEnableOption "a ngnix virtual Host for your client";
|
||||
|
||||
package = mkPackageOption pkgs "your_spotify" {};
|
||||
|
||||
clientPackage = mkOption {
|
||||
type = package;
|
||||
default = cfg.package.client.override {apiEndpoint = cfg.config.apiEndpoint;};
|
||||
description = lib.mdDoc "Client package to use.";
|
||||
default = cfg.package.client.override {inherit (cfg.config) apiEndpoint;};
|
||||
description = "Client package to use.";
|
||||
};
|
||||
|
||||
config = {
|
||||
settings = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = types.attrOf types.str;
|
||||
options = {
|
||||
clientEndpoint = mkOption {
|
||||
type = str;
|
||||
description = "The endpoint of your web application";
|
||||
|
@ -95,12 +59,17 @@ in {
|
|||
};
|
||||
apiEndpoint = mkOption {
|
||||
type = str;
|
||||
description = "The endpoint of your server";
|
||||
description = ''
|
||||
The endpoint of your server
|
||||
This api has to be reachable from the device you use the website from not from the server.
|
||||
This means that for example you may need two nginx virtual hosts if you want to expose this on the
|
||||
internet.
|
||||
'';
|
||||
default = "http://localhost:8080";
|
||||
};
|
||||
spotifyPublic = mkOption {
|
||||
type = nullOr str;
|
||||
description = mdDoc ''
|
||||
description = ''
|
||||
The public key of your Spotify application
|
||||
[Creating the Spotify Application](https://github.com/Yooooomi/your_spotify#creating-the-spotify-application)
|
||||
'';
|
||||
|
@ -108,7 +77,7 @@ in {
|
|||
};
|
||||
spotifySecret = mkOption {
|
||||
type = nullOr str;
|
||||
description = mdDoc ''
|
||||
description = ''
|
||||
The secret key of your Spotify application
|
||||
[Creating the Spotify Application](https://github.com/Yooooomi/your_spotify#creating-the-spotify-application)
|
||||
Note that you may want to set this using the `environmentFile` config option to prevent
|
||||
|
@ -118,14 +87,14 @@ in {
|
|||
};
|
||||
cors = mkOption {
|
||||
type = nullOr str;
|
||||
description = mdDoc ''
|
||||
description = ''
|
||||
List of comma-separated origin allowed, or nothing to allow any origin
|
||||
'';
|
||||
default = null;
|
||||
};
|
||||
maxImportCacheSize = mkOption {
|
||||
type = str;
|
||||
description = mdDoc ''
|
||||
description = ''
|
||||
The maximum element in the cache when importing data from an outside source,
|
||||
more cache means less requests to Spotify, resulting in faster imports
|
||||
'';
|
||||
|
@ -133,43 +102,45 @@ in {
|
|||
};
|
||||
mongoEndpoint = mkOption {
|
||||
type = str;
|
||||
description = mdDoc ''
|
||||
description = ''
|
||||
The endpoint of the Mongo database.
|
||||
'';
|
||||
default = "mongodb://localhost:27017/your_spotify";
|
||||
};
|
||||
port = mkOption {
|
||||
type = int;
|
||||
description = "The port of the server";
|
||||
type = port;
|
||||
description = "The port of the api server";
|
||||
default = 8080;
|
||||
};
|
||||
timezone = mkOption {
|
||||
type = str;
|
||||
description = mdDoc ''
|
||||
description = ''
|
||||
The timezone of your stats, only affects read requests since data is saved with UTC time
|
||||
'';
|
||||
default = "Europe/Paris";
|
||||
};
|
||||
logLevel = mkOption {
|
||||
type = str;
|
||||
description = mdDoc ''
|
||||
description = ''
|
||||
The log level, debug is useful if you encouter any bugs
|
||||
'';
|
||||
default = "info";
|
||||
};
|
||||
cookieValidityMs = mkOption {
|
||||
type = str;
|
||||
description = mdDoc ''
|
||||
description = ''
|
||||
Validity time of the authentication cookie
|
||||
'';
|
||||
default = "1h";
|
||||
};
|
||||
mongoNoAdminRights = mkOption {
|
||||
type = bool;
|
||||
description = mdDoc ''
|
||||
description = ''
|
||||
Do not ask for admin right on the Mongo database
|
||||
'';
|
||||
default = true;
|
||||
default = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -177,7 +148,7 @@ in {
|
|||
type = with types; nullOr path;
|
||||
default = null;
|
||||
example = "/var/lib/your_spotify.env";
|
||||
description = lib.mdDoc ''
|
||||
description = ''
|
||||
Additional environment file as defined in {manpage}`systemd.exec(5)`.
|
||||
|
||||
Secrets like {env}`SPOTIFY_SECRET`
|
||||
|
@ -190,24 +161,19 @@ in {
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
users.users.${cfg.user} = {
|
||||
inherit (cfg) group;
|
||||
isSystemUser = true;
|
||||
};
|
||||
users.groups.${cfg.group} = {};
|
||||
|
||||
systemd.services.your_spotify = {
|
||||
after = ["network.target"];
|
||||
serviceConfig = {
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
User = "your_spotify";
|
||||
Group = "your_spotify";
|
||||
DynamicUser = true;
|
||||
EnvironmentFile = [configFile] ++ optional (cfg.environmentFile != null) cfg.environmentFile;
|
||||
ExecStartPre = "${pkgs.your_spotify}/bin/your_spotify_migrate";
|
||||
ExecStart = "${pkgs.your_spotify}/bin/your_spotify_server";
|
||||
LimitNOFILE = "1048576";
|
||||
PrivateTmp = "true";
|
||||
PrivateDevices = "true";
|
||||
ProtectHome = "true";
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectHome = true;
|
||||
ProtectSystem = "strict";
|
||||
StateDirectory = "your_spotify";
|
||||
StateDirectoryMode = "0700";
|
||||
|
@ -215,6 +181,15 @@ in {
|
|||
};
|
||||
wantedBy = ["multi-user.target"];
|
||||
};
|
||||
services.mongodb.enable = true;
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts.${cfg.clientEndpoint}.root = cfg.clientPackage;
|
||||
};
|
||||
services.mongodb = mkIf cfg.enableLocalDB {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
# nginx gaten
|
||||
# systemd hardening(e.g. esphome)
|
||||
|
||||
|
|
Loading…
Reference in a new issue