Apply nixfmt
This commit is contained in:
parent
75c13a21dc
commit
a5754e7023
19
default.nix
19
default.nix
|
@ -1,10 +1,9 @@
|
||||||
(import
|
(import (
|
||||||
(
|
let
|
||||||
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
|
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
|
||||||
fetchTarball {
|
in
|
||||||
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
fetchTarball {
|
||||||
sha256 = lock.nodes.flake-compat.locked.narHash;
|
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
||||||
}
|
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||||
)
|
}
|
||||||
{ src = ./.; }
|
) { src = ./.; }).defaultNix
|
||||||
).defaultNix
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
users.users.bob = {
|
users.users.bob = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
password = "beta";
|
password = "beta";
|
||||||
uid = 1001;
|
uid = 1001;
|
||||||
packages = [ pkgs.intake ];
|
packages = [ pkgs.intake ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,11 +26,13 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
# Expose the vm's intake revproxy at host port 5234
|
# Expose the vm's intake revproxy at host port 5234
|
||||||
virtualisation.forwardPorts = [{
|
virtualisation.forwardPorts = [
|
||||||
from = "host";
|
{
|
||||||
host.port = 5234;
|
from = "host";
|
||||||
guest.port = 8080;
|
host.port = 5234;
|
||||||
}];
|
guest.port = 8080;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
# Mount the demo content for both users
|
# Mount the demo content for both users
|
||||||
nixos-shell.mounts = {
|
nixos-shell.mounts = {
|
||||||
|
@ -48,19 +50,19 @@
|
||||||
# Create an activation script that copies and chowns the demo content
|
# Create an activation script that copies and chowns the demo content
|
||||||
# chmod 777 because the users may not exist when the activation script runs
|
# chmod 777 because the users may not exist when the activation script runs
|
||||||
system.activationScripts =
|
system.activationScripts =
|
||||||
let
|
let
|
||||||
userSetup = name: uid: ''
|
userSetup = name: uid: ''
|
||||||
${pkgs.coreutils}/bin/mkdir -p /home/${name}/.local/share/intake
|
${pkgs.coreutils}/bin/mkdir -p /home/${name}/.local/share/intake
|
||||||
${pkgs.coreutils}/bin/cp -r /mnt/${name}/* /home/${name}/.local/share/intake/
|
${pkgs.coreutils}/bin/cp -r /mnt/${name}/* /home/${name}/.local/share/intake/
|
||||||
${pkgs.coreutils}/bin/chown -R ${uid} /home/${name}
|
${pkgs.coreutils}/bin/chown -R ${uid} /home/${name}
|
||||||
${pkgs.findutils}/bin/find /home/${name} -type d -exec ${pkgs.coreutils}/bin/chmod 755 {} \;
|
${pkgs.findutils}/bin/find /home/${name} -type d -exec ${pkgs.coreutils}/bin/chmod 755 {} \;
|
||||||
${pkgs.findutils}/bin/find /home/${name} -type f -exec ${pkgs.coreutils}/bin/chmod 644 {} \;
|
${pkgs.findutils}/bin/find /home/${name} -type f -exec ${pkgs.coreutils}/bin/chmod 644 {} \;
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
aliceSetup = userSetup "alice" "1000";
|
aliceSetup = userSetup "alice" "1000";
|
||||||
bobSetup = userSetup "bob" "1001";
|
bobSetup = userSetup "bob" "1001";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Put the demo sources on the global PATH
|
# Put the demo sources on the global PATH
|
||||||
environment.variables.PATH = "/mnt/sources";
|
environment.variables.PATH = "/mnt/sources";
|
||||||
|
|
136
flake.nix
136
flake.nix
|
@ -13,63 +13,91 @@
|
||||||
nixos-shell.inputs.nixpkgs.follows = "nixpkgs";
|
nixos-shell.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, flake-compat, nixos-shell }:
|
outputs =
|
||||||
let
|
{
|
||||||
inherit (nixpkgs.lib) makeOverridable nixosSystem;
|
self,
|
||||||
system = "x86_64-linux";
|
nixpkgs,
|
||||||
in {
|
flake-compat,
|
||||||
formatter.${system} = nixpkgs.legacyPackages.${system}.nixfmt-rfc-style;
|
nixos-shell,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (nixpkgs.lib) makeOverridable nixosSystem;
|
||||||
|
system = "x86_64-linux";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
formatter.${system} = nixpkgs.legacyPackages.${system}.nixfmt-rfc-style;
|
||||||
|
|
||||||
packages.${system} = let
|
packages.${system} =
|
||||||
pkgs = (import nixpkgs {
|
let
|
||||||
|
pkgs = (
|
||||||
|
import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
overlays = [ self.overlays.default ];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
default = self.packages.${system}.intake;
|
||||||
|
inherit (pkgs) intake;
|
||||||
|
};
|
||||||
|
|
||||||
|
devShells.${system} = {
|
||||||
|
default =
|
||||||
|
let
|
||||||
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
|
pythonEnv = pkgs.python3.withPackages (
|
||||||
|
pypkgs: with pypkgs; [
|
||||||
|
flask
|
||||||
|
black
|
||||||
|
pytest
|
||||||
|
]
|
||||||
|
);
|
||||||
|
in
|
||||||
|
pkgs.mkShell {
|
||||||
|
packages = [
|
||||||
|
pythonEnv
|
||||||
|
pkgs.nixos-shell
|
||||||
|
# We only take this dependency for htpasswd, which is a little unfortunate
|
||||||
|
pkgs.apacheHttpd
|
||||||
|
];
|
||||||
|
shellHook = ''
|
||||||
|
PS1="(develop) $PS1"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
overlays.default = final: prev: {
|
||||||
|
intake = final.python3Packages.buildPythonPackage {
|
||||||
|
name = "intake";
|
||||||
|
src = builtins.path {
|
||||||
|
path = ./.;
|
||||||
|
name = "intake";
|
||||||
|
};
|
||||||
|
format = "pyproject";
|
||||||
|
propagatedBuildInputs = with final.python3Packages; [
|
||||||
|
flask
|
||||||
|
setuptools
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
templates.source = {
|
||||||
|
path = builtins.path {
|
||||||
|
path = ./template;
|
||||||
|
name = "source";
|
||||||
|
};
|
||||||
|
description = "A basic intake source config";
|
||||||
|
};
|
||||||
|
|
||||||
|
nixosModules.default = import ./module.nix self;
|
||||||
|
|
||||||
|
nixosConfigurations."demo" = makeOverridable nixosSystem {
|
||||||
inherit system;
|
inherit system;
|
||||||
overlays = [ self.overlays.default ];
|
modules = [
|
||||||
});
|
nixos-shell.nixosModules.nixos-shell
|
||||||
in {
|
self.nixosModules.default
|
||||||
default = self.packages.${system}.intake;
|
./demo
|
||||||
inherit (pkgs) intake;
|
|
||||||
};
|
|
||||||
|
|
||||||
devShells.${system} = {
|
|
||||||
default = let
|
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
|
||||||
pythonEnv = pkgs.python3.withPackages (pypkgs: with pypkgs; [ flask black pytest ]);
|
|
||||||
in pkgs.mkShell {
|
|
||||||
packages = [
|
|
||||||
pythonEnv
|
|
||||||
pkgs.nixos-shell
|
|
||||||
# We only take this dependency for htpasswd, which is a little unfortunate
|
|
||||||
pkgs.apacheHttpd
|
|
||||||
];
|
];
|
||||||
shellHook = ''
|
|
||||||
PS1="(develop) $PS1"
|
|
||||||
'';
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
overlays.default = final: prev: {
|
|
||||||
intake = final.python3Packages.buildPythonPackage {
|
|
||||||
name = "intake";
|
|
||||||
src = builtins.path { path = ./.; name = "intake"; };
|
|
||||||
format = "pyproject";
|
|
||||||
propagatedBuildInputs = with final.python3Packages; [ flask setuptools ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
templates.source = {
|
|
||||||
path = builtins.path { path = ./template; name = "source"; };
|
|
||||||
description = "A basic intake source config";
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosModules.default = import ./module.nix self;
|
|
||||||
|
|
||||||
nixosConfigurations."demo" = makeOverridable nixosSystem {
|
|
||||||
inherit system;
|
|
||||||
modules = [
|
|
||||||
nixos-shell.nixosModules.nixos-shell
|
|
||||||
self.nixosModules.default
|
|
||||||
./demo
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
244
module.nix
244
module.nix
|
@ -1,153 +1,179 @@
|
||||||
flake: { config, lib, pkgs, ... }:
|
flake:
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
inherit (lib) filterAttrs foldl imap1 mapAttrsToList mkEnableOption mkIf mkMerge mkOption mkPackageOption types;
|
inherit (lib)
|
||||||
|
filterAttrs
|
||||||
|
foldl
|
||||||
|
imap1
|
||||||
|
mapAttrsToList
|
||||||
|
mkEnableOption
|
||||||
|
mkIf
|
||||||
|
mkMerge
|
||||||
|
mkOption
|
||||||
|
mkPackageOption
|
||||||
|
types
|
||||||
|
;
|
||||||
intakeCfg = config.services.intake;
|
intakeCfg = config.services.intake;
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
options = {
|
options = {
|
||||||
services.intake = {
|
services.intake = {
|
||||||
listen.addr = mkOption {
|
listen.addr = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "0.0.0.0";
|
default = "0.0.0.0";
|
||||||
description = "The listen address for the entry point to intake services. This endpoint will redirect to a "
|
description = "The listen address for the entry point to intake services. This endpoint will redirect to a local port based on the request's HTTP Basic Auth credentials.";
|
||||||
"local port based on the request's HTTP Basic Auth credentials.";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
listen.port = mkOption {
|
listen.port = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 80;
|
default = 80;
|
||||||
description = "The listen port for the entry point to intake services. This endpoint will redirect to a local "
|
description = "The listen port for the entry point to intake services. This endpoint will redirect to a local port based on the request's HTTP Basic Auth credentials.";
|
||||||
"port based on the request's HTTP Basic Auth credentials.";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
package = mkPackageOption pkgs "intake" {};
|
package = mkPackageOption pkgs "intake" { };
|
||||||
|
|
||||||
internalPortStart = mkOption {
|
internalPortStart = mkOption {
|
||||||
type = types.port;
|
type = types.port;
|
||||||
default = 24130;
|
default = 24130;
|
||||||
description = "The first port to use for internal service endpoints. A number of ports will be continguously "
|
description = "The first port to use for internal service endpoints. A number of ports will be continguously allocated equal to the number of users with enabled intake services.";
|
||||||
"allocated equal to the number of users with enabled intake services.";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extraPackages = mkOption {
|
extraPackages = mkOption {
|
||||||
type = types.listOf types.package;
|
type = types.listOf types.package;
|
||||||
default = [];
|
default = [ ];
|
||||||
description = "Extra packages available to all enabled users and their intake services.";
|
description = "Extra packages available to all enabled users and their intake services.";
|
||||||
};
|
};
|
||||||
|
|
||||||
users = mkOption {
|
users = mkOption {
|
||||||
description = "User intake service definitions.";
|
description = "User intake service definitions.";
|
||||||
default = {};
|
default = { };
|
||||||
type = types.attrsOf (types.submodule {
|
type = types.attrsOf (
|
||||||
options = {
|
types.submodule {
|
||||||
enable = mkEnableOption "intake, a personal feed aggregator.";
|
options = {
|
||||||
|
enable = mkEnableOption "intake, a personal feed aggregator.";
|
||||||
|
|
||||||
extraPackages = mkOption {
|
extraPackages = mkOption {
|
||||||
type = types.listOf types.package;
|
type = types.listOf types.package;
|
||||||
default = [];
|
default = [ ];
|
||||||
description = "Extra packages available to this user and their intake service.";
|
description = "Extra packages available to this user and their intake service.";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
});
|
);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config =
|
config =
|
||||||
let
|
|
||||||
# Define the intake package and a python environment to run it from
|
|
||||||
intake = intakeCfg.package;
|
|
||||||
pythonEnv = pkgs.python3.withPackages (pypkgs: [ intake ]);
|
|
||||||
|
|
||||||
# Assign each user an internal port for their personal intake instance
|
|
||||||
enabledUsers = filterAttrs (userName: userCfg: userCfg.enable) intakeCfg.users;
|
|
||||||
enabledUserNames = mapAttrsToList (userName: userCfg: userName) enabledUsers;
|
|
||||||
userPortList = imap1 (i: userName: { ${userName} = i + intakeCfg.internalPortStart; }) enabledUserNames;
|
|
||||||
userPort = foldl (acc: val: acc // val) {} userPortList;
|
|
||||||
|
|
||||||
# To avoid polluting PATH with httpd programs, define an htpasswd wrapper
|
|
||||||
htpasswdWrapper = pkgs.writeShellScriptBin "htpasswd" ''
|
|
||||||
${pkgs.apacheHttpd}/bin/htpasswd $@
|
|
||||||
'';
|
|
||||||
|
|
||||||
# File locations
|
|
||||||
intakeDir = "/etc/intake";
|
|
||||||
intakePwd = "${intakeDir}/htpasswd";
|
|
||||||
in {
|
|
||||||
# Apply the overlay so intake is included in pkgs.
|
|
||||||
nixpkgs.overlays = [ flake.overlays.default ];
|
|
||||||
|
|
||||||
# Define a user group for access to the htpasswd file. nginx needs to be able to read it.
|
|
||||||
users.groups.intake.members = mkIf (enabledUsers != {}) (enabledUserNames ++ [ "nginx" ]);
|
|
||||||
|
|
||||||
# Define an activation script that ensures that the htpasswd file exists.
|
|
||||||
system.activationScripts.etc-intake = ''
|
|
||||||
if [ ! -e ${intakeDir} ]; then
|
|
||||||
${pkgs.coreutils}/bin/mkdir -p ${intakeDir};
|
|
||||||
fi
|
|
||||||
${pkgs.coreutils}/bin/chown root:root ${intakeDir}
|
|
||||||
${pkgs.coreutils}/bin/chmod 755 ${intakeDir}
|
|
||||||
if [ ! -e ${intakePwd} ]; then
|
|
||||||
${pkgs.coreutils}/bin/touch ${intakePwd}
|
|
||||||
fi
|
|
||||||
${pkgs.coreutils}/bin/chown root:intake ${intakePwd}
|
|
||||||
${pkgs.coreutils}/bin/chmod 660 ${intakePwd}
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Give every intake user the htpasswd wrapper, the shared packages, and the user-specific packages.
|
|
||||||
users.users =
|
|
||||||
let
|
let
|
||||||
addPackagesToUser = userName: {
|
# Define the intake package and a python environment to run it from
|
||||||
${userName}.packages =
|
intake = intakeCfg.package;
|
||||||
[ htpasswdWrapper intake ]
|
pythonEnv = pkgs.python3.withPackages (pypkgs: [ intake ]);
|
||||||
++ intakeCfg.extraPackages
|
|
||||||
++ intakeCfg.users.${userName}.extraPackages;
|
|
||||||
};
|
|
||||||
in mkMerge (map addPackagesToUser enabledUserNames);
|
|
||||||
|
|
||||||
# Enable cron
|
# Assign each user an internal port for their personal intake instance
|
||||||
services.cron.enable = true;
|
enabledUsers = filterAttrs (userName: userCfg: userCfg.enable) intakeCfg.users;
|
||||||
|
enabledUserNames = mapAttrsToList (userName: userCfg: userName) enabledUsers;
|
||||||
|
userPortList = imap1 (i: userName: {
|
||||||
|
${userName} = i + intakeCfg.internalPortStart;
|
||||||
|
}) enabledUserNames;
|
||||||
|
userPort = foldl (acc: val: acc // val) { } userPortList;
|
||||||
|
|
||||||
# Define a user service for each configured user
|
# To avoid polluting PATH with httpd programs, define an htpasswd wrapper
|
||||||
systemd.services =
|
htpasswdWrapper = pkgs.writeShellScriptBin "htpasswd" ''
|
||||||
let
|
${pkgs.apacheHttpd}/bin/htpasswd $@
|
||||||
runScript = userName: pkgs.writeShellScript "intake-run.sh" ''
|
|
||||||
# Add the setuid wrapper directory so `crontab` is accessible
|
|
||||||
export PATH="${config.security.wrapperDir}:$PATH"
|
|
||||||
${pythonEnv}/bin/intake run -d /home/${userName}/.local/share/intake --port ${toString userPort.${userName}}
|
|
||||||
'';
|
'';
|
||||||
# systemd service definition for a single user, given `services.intake.users.userName` = `userCfg`
|
|
||||||
userServiceConfig = userName: userCfg: {
|
|
||||||
"intake@${userName}" = {
|
|
||||||
description = "Intake service for user ${userName}";
|
|
||||||
script = "${runScript userName}";
|
|
||||||
path = intakeCfg.extraPackages ++ userCfg.extraPackages;
|
|
||||||
serviceConfig = {
|
|
||||||
User = userName;
|
|
||||||
Type = "simple";
|
|
||||||
};
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
after = [ "network.target" ];
|
|
||||||
enable = userCfg.enable;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in mkMerge (mapAttrsToList userServiceConfig intakeCfg.users);
|
|
||||||
|
|
||||||
# Define an nginx reverse proxy to request auth
|
# File locations
|
||||||
services.nginx = mkIf (enabledUsers != {}) {
|
intakeDir = "/etc/intake";
|
||||||
enable = true;
|
intakePwd = "${intakeDir}/htpasswd";
|
||||||
virtualHosts."intake" = mkIf (enabledUsers != {}) {
|
in
|
||||||
listen = [ intakeCfg.listen ];
|
{
|
||||||
locations."/" = {
|
# Apply the overlay so intake is included in pkgs.
|
||||||
proxyPass = "http://127.0.0.1:$target_port";
|
nixpkgs.overlays = [ flake.overlays.default ];
|
||||||
basicAuthFile = intakePwd;
|
|
||||||
|
# Define a user group for access to the htpasswd file. nginx needs to be able to read it.
|
||||||
|
users.groups.intake.members = mkIf (enabledUsers != { }) (enabledUserNames ++ [ "nginx" ]);
|
||||||
|
|
||||||
|
# Define an activation script that ensures that the htpasswd file exists.
|
||||||
|
system.activationScripts.etc-intake = ''
|
||||||
|
if [ ! -e ${intakeDir} ]; then
|
||||||
|
${pkgs.coreutils}/bin/mkdir -p ${intakeDir};
|
||||||
|
fi
|
||||||
|
${pkgs.coreutils}/bin/chown root:root ${intakeDir}
|
||||||
|
${pkgs.coreutils}/bin/chmod 755 ${intakeDir}
|
||||||
|
if [ ! -e ${intakePwd} ]; then
|
||||||
|
${pkgs.coreutils}/bin/touch ${intakePwd}
|
||||||
|
fi
|
||||||
|
${pkgs.coreutils}/bin/chown root:intake ${intakePwd}
|
||||||
|
${pkgs.coreutils}/bin/chmod 660 ${intakePwd}
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Give every intake user the htpasswd wrapper, the shared packages, and the user-specific packages.
|
||||||
|
users.users =
|
||||||
|
let
|
||||||
|
addPackagesToUser = userName: {
|
||||||
|
${userName}.packages = [
|
||||||
|
htpasswdWrapper
|
||||||
|
intake
|
||||||
|
] ++ intakeCfg.extraPackages ++ intakeCfg.users.${userName}.extraPackages;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
mkMerge (map addPackagesToUser enabledUserNames);
|
||||||
|
|
||||||
|
# Enable cron
|
||||||
|
services.cron.enable = true;
|
||||||
|
|
||||||
|
# Define a user service for each configured user
|
||||||
|
systemd.services =
|
||||||
|
let
|
||||||
|
runScript =
|
||||||
|
userName:
|
||||||
|
pkgs.writeShellScript "intake-run.sh" ''
|
||||||
|
# Add the setuid wrapper directory so `crontab` is accessible
|
||||||
|
export PATH="${config.security.wrapperDir}:$PATH"
|
||||||
|
${pythonEnv}/bin/intake run -d /home/${userName}/.local/share/intake --port ${toString userPort.${userName}}
|
||||||
|
'';
|
||||||
|
# systemd service definition for a single user, given `services.intake.users.userName` = `userCfg`
|
||||||
|
userServiceConfig = userName: userCfg: {
|
||||||
|
"intake@${userName}" = {
|
||||||
|
description = "Intake service for user ${userName}";
|
||||||
|
script = "${runScript userName}";
|
||||||
|
path = intakeCfg.extraPackages ++ userCfg.extraPackages;
|
||||||
|
serviceConfig = {
|
||||||
|
User = userName;
|
||||||
|
Type = "simple";
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
enable = userCfg.enable;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
mkMerge (mapAttrsToList userServiceConfig intakeCfg.users);
|
||||||
|
|
||||||
|
# Define an nginx reverse proxy to request auth
|
||||||
|
services.nginx = mkIf (enabledUsers != { }) {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts."intake" = mkIf (enabledUsers != { }) {
|
||||||
|
listen = [ intakeCfg.listen ];
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://127.0.0.1:$target_port";
|
||||||
|
basicAuthFile = intakePwd;
|
||||||
|
};
|
||||||
|
extraConfig = foldl (acc: val: acc + val) "" (
|
||||||
|
mapAttrsToList (userName: port: ''
|
||||||
|
if ($remote_user = "${userName}") {
|
||||||
|
set $target_port ${toString port};
|
||||||
|
}
|
||||||
|
'') userPort
|
||||||
|
);
|
||||||
};
|
};
|
||||||
extraConfig = foldl (acc: val: acc + val) "" (mapAttrsToList (userName: port: ''
|
|
||||||
if ($remote_user = "${userName}") {
|
|
||||||
set $target_port ${toString port};
|
|
||||||
}
|
|
||||||
'') userPort);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
19
shell.nix
19
shell.nix
|
@ -1,10 +1,9 @@
|
||||||
(import
|
(import (
|
||||||
(
|
let
|
||||||
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in
|
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
|
||||||
fetchTarball {
|
in
|
||||||
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
fetchTarball {
|
||||||
sha256 = lock.nodes.flake-compat.locked.narHash;
|
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
|
||||||
}
|
sha256 = lock.nodes.flake-compat.locked.narHash;
|
||||||
)
|
}
|
||||||
{ src = ./.; }
|
) { src = ./.; }).shellNix
|
||||||
).shellNix
|
|
||||||
|
|
Loading…
Reference in New Issue