Apply nixfmt

This commit is contained in:
Tim Van Baak 2024-09-21 12:51:24 -07:00
parent 75c13a21dc
commit a5754e7023
5 changed files with 257 additions and 203 deletions

View File

@ -1,10 +1,9 @@
(import (import (
( let
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball { fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash; sha256 = lock.nodes.flake-compat.locked.narHash;
} }
) ) { src = ./.; }).defaultNix
{ src = ./.; }
).defaultNix

View File

@ -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"; from = "host";
host.port = 5234; host.port = 5234;
guest.port = 8080; guest.port = 8080;
}]; }
];
# Mount the demo content for both users # Mount the demo content for both users
nixos-shell.mounts = { nixos-shell.mounts = {

View File

@ -13,28 +13,47 @@
nixos-shell.inputs.nixpkgs.follows = "nixpkgs"; nixos-shell.inputs.nixpkgs.follows = "nixpkgs";
}; };
outputs = { self, nixpkgs, flake-compat, nixos-shell }: outputs =
{
self,
nixpkgs,
flake-compat,
nixos-shell,
}:
let let
inherit (nixpkgs.lib) makeOverridable nixosSystem; inherit (nixpkgs.lib) makeOverridable nixosSystem;
system = "x86_64-linux"; system = "x86_64-linux";
in { in
{
formatter.${system} = nixpkgs.legacyPackages.${system}.nixfmt-rfc-style; formatter.${system} = nixpkgs.legacyPackages.${system}.nixfmt-rfc-style;
packages.${system} = let packages.${system} =
pkgs = (import nixpkgs { let
pkgs = (
import nixpkgs {
inherit system; inherit system;
overlays = [ self.overlays.default ]; overlays = [ self.overlays.default ];
}); }
in { );
in
{
default = self.packages.${system}.intake; default = self.packages.${system}.intake;
inherit (pkgs) intake; inherit (pkgs) intake;
}; };
devShells.${system} = { devShells.${system} = {
default = let default =
let
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
pythonEnv = pkgs.python3.withPackages (pypkgs: with pypkgs; [ flask black pytest ]); pythonEnv = pkgs.python3.withPackages (
in pkgs.mkShell { pypkgs: with pypkgs; [
flask
black
pytest
]
);
in
pkgs.mkShell {
packages = [ packages = [
pythonEnv pythonEnv
pkgs.nixos-shell pkgs.nixos-shell
@ -50,14 +69,23 @@
overlays.default = final: prev: { overlays.default = final: prev: {
intake = final.python3Packages.buildPythonPackage { intake = final.python3Packages.buildPythonPackage {
name = "intake"; name = "intake";
src = builtins.path { path = ./.; name = "intake"; }; src = builtins.path {
path = ./.;
name = "intake";
};
format = "pyproject"; format = "pyproject";
propagatedBuildInputs = with final.python3Packages; [ flask setuptools ]; propagatedBuildInputs = with final.python3Packages; [
flask
setuptools
];
}; };
}; };
templates.source = { templates.source = {
path = builtins.path { path = ./template; name = "source"; }; path = builtins.path {
path = ./template;
name = "source";
};
description = "A basic intake source config"; description = "A basic intake source config";
}; };

View File

@ -1,54 +1,71 @@
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 (
types.submodule {
options = { options = {
enable = mkEnableOption "intake, a personal feed aggregator."; 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.";
}; };
}; };
}); }
);
}; };
}; };
}; };
@ -62,8 +79,10 @@ in {
# Assign each user an internal port for their personal intake instance # Assign each user an internal port for their personal intake instance
enabledUsers = filterAttrs (userName: userCfg: userCfg.enable) intakeCfg.users; enabledUsers = filterAttrs (userName: userCfg: userCfg.enable) intakeCfg.users;
enabledUserNames = mapAttrsToList (userName: userCfg: userName) enabledUsers; enabledUserNames = mapAttrsToList (userName: userCfg: userName) enabledUsers;
userPortList = imap1 (i: userName: { ${userName} = i + intakeCfg.internalPortStart; }) enabledUserNames; userPortList = imap1 (i: userName: {
userPort = foldl (acc: val: acc // val) {} userPortList; ${userName} = i + intakeCfg.internalPortStart;
}) enabledUserNames;
userPort = foldl (acc: val: acc // val) { } userPortList;
# To avoid polluting PATH with httpd programs, define an htpasswd wrapper # To avoid polluting PATH with httpd programs, define an htpasswd wrapper
htpasswdWrapper = pkgs.writeShellScriptBin "htpasswd" '' htpasswdWrapper = pkgs.writeShellScriptBin "htpasswd" ''
@ -73,12 +92,13 @@ in {
# File locations # File locations
intakeDir = "/etc/intake"; intakeDir = "/etc/intake";
intakePwd = "${intakeDir}/htpasswd"; intakePwd = "${intakeDir}/htpasswd";
in { in
{
# Apply the overlay so intake is included in pkgs. # Apply the overlay so intake is included in pkgs.
nixpkgs.overlays = [ flake.overlays.default ]; nixpkgs.overlays = [ flake.overlays.default ];
# Define a user group for access to the htpasswd file. nginx needs to be able to read it. # 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" ]); users.groups.intake.members = mkIf (enabledUsers != { }) (enabledUserNames ++ [ "nginx" ]);
# Define an activation script that ensures that the htpasswd file exists. # Define an activation script that ensures that the htpasswd file exists.
system.activationScripts.etc-intake = '' system.activationScripts.etc-intake = ''
@ -98,12 +118,13 @@ in {
users.users = users.users =
let let
addPackagesToUser = userName: { addPackagesToUser = userName: {
${userName}.packages = ${userName}.packages = [
[ htpasswdWrapper intake ] htpasswdWrapper
++ intakeCfg.extraPackages intake
++ intakeCfg.users.${userName}.extraPackages; ] ++ intakeCfg.extraPackages ++ intakeCfg.users.${userName}.extraPackages;
}; };
in mkMerge (map addPackagesToUser enabledUserNames); in
mkMerge (map addPackagesToUser enabledUserNames);
# Enable cron # Enable cron
services.cron.enable = true; services.cron.enable = true;
@ -111,7 +132,9 @@ in {
# Define a user service for each configured user # Define a user service for each configured user
systemd.services = systemd.services =
let let
runScript = userName: pkgs.writeShellScript "intake-run.sh" '' runScript =
userName:
pkgs.writeShellScript "intake-run.sh" ''
# Add the setuid wrapper directory so `crontab` is accessible # Add the setuid wrapper directory so `crontab` is accessible
export PATH="${config.security.wrapperDir}:$PATH" export PATH="${config.security.wrapperDir}:$PATH"
${pythonEnv}/bin/intake run -d /home/${userName}/.local/share/intake --port ${toString userPort.${userName}} ${pythonEnv}/bin/intake run -d /home/${userName}/.local/share/intake --port ${toString userPort.${userName}}
@ -131,22 +154,25 @@ in {
enable = userCfg.enable; enable = userCfg.enable;
}; };
}; };
in mkMerge (mapAttrsToList userServiceConfig intakeCfg.users); in
mkMerge (mapAttrsToList userServiceConfig intakeCfg.users);
# Define an nginx reverse proxy to request auth # Define an nginx reverse proxy to request auth
services.nginx = mkIf (enabledUsers != {}) { services.nginx = mkIf (enabledUsers != { }) {
enable = true; enable = true;
virtualHosts."intake" = mkIf (enabledUsers != {}) { virtualHosts."intake" = mkIf (enabledUsers != { }) {
listen = [ intakeCfg.listen ]; listen = [ intakeCfg.listen ];
locations."/" = { locations."/" = {
proxyPass = "http://127.0.0.1:$target_port"; proxyPass = "http://127.0.0.1:$target_port";
basicAuthFile = intakePwd; basicAuthFile = intakePwd;
}; };
extraConfig = foldl (acc: val: acc + val) "" (mapAttrsToList (userName: port: '' extraConfig = foldl (acc: val: acc + val) "" (
mapAttrsToList (userName: port: ''
if ($remote_user = "${userName}") { if ($remote_user = "${userName}") {
set $target_port ${toString port}; set $target_port ${toString port};
} }
'') userPort); '') userPort
);
}; };
}; };
}; };

View File

@ -1,10 +1,9 @@
(import (import (
( let
let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball { fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash; sha256 = lock.nodes.flake-compat.locked.narHash;
} }
) ) { src = ./.; }).shellNix
{ src = ./.; }
).shellNix