Hello,
I’m currently trying to create a multi-site web server in NixOS where the goal is to create different “site modules” for different types of sites. The code below works in terms of that the user is created for each site based on the submodule options but the laravel-module isn’t being used.
Is it possible to extend the submodule based on the moduleName option so that the site module (e.g. laravel) can add options and global config while having access to the site-specific config? If it isn’t possible by using the submodule system, is it possible in another way where site modules such as laravel.nix has access to services.ts1997.sites.<name>s config while being able to extend the options and set global services config?
# sites.nix
{ config, lib, ... }:
let
sites = config.services.ts1997.sites;
siteModules = {
laravel = ./modules/laravel.nix;
};
in
{
options.services.ts1997.sites = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ config, name, ... }:
{
imports = [ ./site-options.nix ];
options = {
moduleName = lib.mkOption {
type = lib.types.enum (lib.attrNames siteModules);
description = "The site module to use for ${name}.";
};
};
}
)
);
default = { };
description = "NixOS Site Configurations";
};
config = lib.mkIf (sites != { }) {
users = {
users = lib.mkMerge (
lib.mapAttrsToList (name: siteCfg: {
${siteCfg.user} = {
isSystemUser = true;
createHome = true;
home = siteCfg.workingDir;
group = siteCfg.user;
};
}) sites
);
groups = lib.mkMerge (
lib.mapAttrsToList (name: siteCfg: {
${siteCfg.user} = {
members = [
siteCfg.user
];
};
}) sites
);
};
};
}
# site-options.nix
{
config,
lib,
name,
...
}:
{
options = {
domain = lib.mkOption {
type = lib.types.str;
description = "The domain name for ${name}.";
};
workingDir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${name}";
description = "The working directory for the site ${name}.";
};
webRoot = lib.mkOption {
type = lib.types.str;
default = "${config.workingDir}/public";
description = "The web root directory for the site ${name}.";
};
user = lib.mkOption {
type = lib.types.str;
default = name;
description = "The user that owns the site files for ${name}.";
};
};
}
# laravel.nix
{
config,
lib,
name,
...
}:
{
options = {
scheduler.enable = lib.mkEnableOption "Enable the Laravel scheduler for ${name}";
};
config = {
services.ts1997.virtualHosts.${name} = {
serverName = config.domain;
user = config.user;
locations."/" = {
extraConfig = ''
default_type text/html;
return 200 "<h1>Welcome to ${name}!</h1>";
'';
};
};
};
}