added stuff
This commit is contained in:
parent
6d31f5b5a1
commit
7d4f626b7d
907 changed files with 70990 additions and 0 deletions
7
nyx/modules/core/roles/graphical/default.nix
Normal file
7
nyx/modules/core/roles/graphical/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./system
|
||||
];
|
||||
|
||||
system.nixos.tags = ["graphical"];
|
||||
}
|
8
nyx/modules/core/roles/graphical/system/default.nix
Normal file
8
nyx/modules/core/roles/graphical/system/default.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
imports = [
|
||||
./security
|
||||
./services
|
||||
|
||||
./environment.nix
|
||||
];
|
||||
}
|
6
nyx/modules/core/roles/graphical/system/environment.nix
Normal file
6
nyx/modules/core/roles/graphical/system/environment.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
environment.variables = {
|
||||
# open links with the default browser
|
||||
BROWSER = "firefox";
|
||||
};
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./polkit.nix
|
||||
];
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
# enable polkit for privilege escalation
|
||||
security.polkit.enable = true;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./login
|
||||
|
||||
./xserver.nix
|
||||
];
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
imports = [
|
||||
./greetd.nix
|
||||
./logind.nix
|
||||
./pam.nix
|
||||
./session.nix
|
||||
];
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkIf;
|
||||
inherit (lib.strings) concatStringsSep;
|
||||
inherit (lib.meta) getExe;
|
||||
|
||||
env = config.modules.usrEnv;
|
||||
sys = config.modules.system;
|
||||
|
||||
# make desktop session paths available to greetd
|
||||
sessionData = config.services.xserver.displayManager.sessionData.desktops;
|
||||
sessionPaths = concatStringsSep ":" [
|
||||
"${sessionData}/share/xsessions"
|
||||
"${sessionData}/share/wayland-sessions"
|
||||
];
|
||||
|
||||
initialSession = {
|
||||
user = "${sys.mainUser}";
|
||||
command = "${env.desktop}";
|
||||
};
|
||||
|
||||
defaultSession = {
|
||||
user = "greeter";
|
||||
command = concatStringsSep " " [
|
||||
(getExe pkgs.greetd.tuigreet)
|
||||
"--time"
|
||||
"--remember"
|
||||
"--remember-user-session"
|
||||
"--asterisks"
|
||||
"--sessions '${sessionPaths}'"
|
||||
];
|
||||
};
|
||||
in {
|
||||
services.greetd = {
|
||||
enable = true;
|
||||
vt = 2;
|
||||
restart = !sys.autoLogin;
|
||||
|
||||
# <https://man.sr.ht/~kennylevinsen/greetd/>
|
||||
settings = {
|
||||
# default session is what will be used if no session is selected
|
||||
# in this case it'll be a TUI greeter
|
||||
default_session = defaultSession;
|
||||
|
||||
# initial session
|
||||
initial_session = mkIf sys.autoLogin initialSession;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
# despite being under logind, this has nothing to do with login
|
||||
# it's about power management
|
||||
services.logind = {
|
||||
lidSwitch = "suspend-then-hibernate";
|
||||
lidSwitchExternalPower = "lock";
|
||||
extraConfig = ''
|
||||
HandlePowerKey=suspend-then-hibernate
|
||||
HibernateDelaySec=3600
|
||||
'';
|
||||
};
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
# unlock GPG keyring on login
|
||||
security.pam.services = let
|
||||
gnupg = {
|
||||
enable = true;
|
||||
noAutostart = true;
|
||||
storeOnly = true;
|
||||
};
|
||||
in {
|
||||
login = {
|
||||
enableGnomeKeyring = true;
|
||||
inherit gnupg;
|
||||
};
|
||||
|
||||
greetd = {
|
||||
enableGnomeKeyring = true;
|
||||
inherit gnupg;
|
||||
};
|
||||
|
||||
tuigreet = {
|
||||
enableGnomeKeyring = true;
|
||||
inherit gnupg;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkIf;
|
||||
|
||||
env = config.modules.usrEnv;
|
||||
in {
|
||||
# adding dessktop items to the environment is generally handled by the programs' respective
|
||||
# nixos modules, however, to unify the desktop interface I prefer handling them manually
|
||||
# and ignoring the nixos modules entirely.
|
||||
services.xserver.displayManager = {
|
||||
startx.enable = true;
|
||||
session = [
|
||||
(mkIf env.desktops.i3.enable {
|
||||
name = "i3wm";
|
||||
manage = "desktop";
|
||||
start = ''
|
||||
${pkgs.xorg.xinit}/bin/startx ${pkgs.i3-rounded}/bin/i3 -- vt2 &
|
||||
waitPID=$!
|
||||
'';
|
||||
})
|
||||
];
|
||||
};
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
config = {
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
displayManager.gdm.enable = false;
|
||||
displayManager.lightdm.enable = false;
|
||||
};
|
||||
};
|
||||
}
|
7
nyx/modules/core/roles/headless/default.nix
Normal file
7
nyx/modules/core/roles/headless/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./system
|
||||
];
|
||||
|
||||
system.nixos.tags = ["headless"];
|
||||
}
|
9
nyx/modules/core/roles/headless/system/default.nix
Normal file
9
nyx/modules/core/roles/headless/system/default.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
imports = [
|
||||
./environment.nix
|
||||
./systemd.nix
|
||||
./documentation.nix
|
||||
./fonts.nix
|
||||
./xdg.nix
|
||||
];
|
||||
}
|
17
nyx/modules/core/roles/headless/system/documentation.nix
Normal file
17
nyx/modules/core/roles/headless/system/documentation.nix
Normal file
|
@ -0,0 +1,17 @@
|
|||
{lib, ...}: let
|
||||
inherit (lib) mkForce mapAttrs;
|
||||
in {
|
||||
documentation = mapAttrs (_: mkForce) {
|
||||
enable = false;
|
||||
dev.enable = false;
|
||||
doc.enable = false;
|
||||
info.enable = false;
|
||||
nixos.enable = false;
|
||||
man = {
|
||||
enable = false;
|
||||
generateCaches = false;
|
||||
man-db.enable = false;
|
||||
mandoc.enable = false;
|
||||
};
|
||||
};
|
||||
}
|
45
nyx/modules/core/roles/headless/system/environment.nix
Normal file
45
nyx/modules/core/roles/headless/system/environment.nix
Normal file
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
self,
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
environment = {
|
||||
# normally we wouldn't need any Xlibs on a headless server but for whatever reason
|
||||
# this affects whether or not some programs can build - such as pipewire
|
||||
# noXlibs = true;
|
||||
|
||||
# print the URL instead on servers
|
||||
variables.BROWSER = "echo";
|
||||
|
||||
interactiveShellInit = let
|
||||
exec = package: program: "${package}/bin/${program}";
|
||||
util = exec pkgs.coreutils;
|
||||
uptime = exec pkgs.procps "uptime";
|
||||
grep = exec pkgs.gnugrep "grep";
|
||||
countUsers = ''${util "who"} -q | ${util "head"} -n1 | ${util "tr"} ' ' \\n | ${util "uniq"} | ${util "wc"} -l'';
|
||||
countSessions = ''${util "who"} -q | ${util "head"} -n1 | ${util "wc"} -w'';
|
||||
in ''
|
||||
(
|
||||
|
||||
# Get the common color codes from lib
|
||||
${toString lib.common.shellColors}
|
||||
|
||||
# Color accent to use in any primary text
|
||||
CA=$PURPLE
|
||||
CAB=$BPURPLE
|
||||
|
||||
echo
|
||||
echo -e " █ ''${BWHITE}Welcome back''${CO}"
|
||||
echo " █"
|
||||
echo -e " █ ''${BWHITE}Hostname......:''${CAB} ${config.networking.hostName}''${CO}"
|
||||
echo -e " █ ''${BWHITE}OS Version....:''${CO} NixOS ''${CAB}${config.system.nixos.version}''${CO}"
|
||||
echo -e " █ ''${BWHITE}Configuration.:''${CO} ''${CAB}${self.rev or "\${BRED}(✘)\${CO}\${BWHITE} Dirty"}''${CO}"
|
||||
echo -e " █ ''${BWHITE}Uptime........:''${CO} $(${uptime} -p | ${util "cut"} -d ' ' -f2- | GREP_COLORS='mt=01;35' ${grep} --color=always '[0-9]*')"
|
||||
echo -e " █ ''${BWHITE}SSH Logins....:''${CO} There are currently ''${CAB}$(${countUsers})''${CO} users logged in on ''${CAB}$(${countSessions})''${CO} sessions"
|
||||
echo
|
||||
)
|
||||
'';
|
||||
};
|
||||
}
|
5
nyx/modules/core/roles/headless/system/fonts.nix
Normal file
5
nyx/modules/core/roles/headless/system/fonts.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{lib, ...}: {
|
||||
# we don't need fontconfig on a server
|
||||
# since there are no fonts to be configured outside the console
|
||||
fonts.fontconfig.enable = lib.mkDefault false;
|
||||
}
|
5
nyx/modules/core/roles/headless/system/services.nix
Normal file
5
nyx/modules/core/roles/headless/system/services.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
# a headless system shoudld not mount any removable media
|
||||
# without explicit user action
|
||||
services.udisks2.enable = false;
|
||||
}
|
29
nyx/modules/core/roles/headless/system/systemd.nix
Normal file
29
nyx/modules/core/roles/headless/system/systemd.nix
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
# https://github.com/numtide/srvos/blob/main/nixos/server/default.nix
|
||||
systemd = {
|
||||
# given that our systems are headless, emergency mode is useless.
|
||||
# we prefer the system to attempt to continue booting so
|
||||
# that we can hopefully still access it remotely.
|
||||
enableEmergencyMode = false;
|
||||
|
||||
# For more detail, see:
|
||||
# https://0pointer.de/blog/projects/watchdog.html
|
||||
watchdog = {
|
||||
# systemd will send a signal to the hardware watchdog at half
|
||||
# the interval defined here, so every 10s.
|
||||
# If the hardware watchdog does not get a signal for 20s,
|
||||
# it will forcefully reboot the system.
|
||||
runtimeTime = "20s";
|
||||
# Forcefully reboot if the final stage of the reboot
|
||||
# hangs without progress for more than 30s.
|
||||
# For more info, see:
|
||||
# https://utcc.utoronto.ca/~cks/space/blog/linux/SystemdShutdownWatchdog
|
||||
rebootTime = "30s";
|
||||
};
|
||||
|
||||
sleep.extraConfig = ''
|
||||
AllowSuspend=no
|
||||
AllowHibernation=no
|
||||
'';
|
||||
};
|
||||
}
|
11
nyx/modules/core/roles/headless/system/xdg.nix
Normal file
11
nyx/modules/core/roles/headless/system/xdg.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
{lib, ...}: let
|
||||
inherit (lib) mkForce mapAttrs;
|
||||
in {
|
||||
xdg = mapAttrs (_: mkForce) {
|
||||
sounds.enable = false;
|
||||
mime.enable = false;
|
||||
menus.enable = false;
|
||||
icons.enable = false;
|
||||
autostart.enable = false;
|
||||
};
|
||||
}
|
8
nyx/modules/core/roles/iso/default.nix
Normal file
8
nyx/modules/core/roles/iso/default.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
imports = [
|
||||
./image
|
||||
./system
|
||||
];
|
||||
|
||||
system.nixos.tags = ["iso-image"];
|
||||
}
|
71
nyx/modules/core/roles/iso/image/default.nix
Normal file
71
nyx/modules/core/roles/iso/image/default.nix
Normal file
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
modulesPath,
|
||||
self,
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkImageMediaOverride;
|
||||
in {
|
||||
imports = [
|
||||
"${modulesPath}/installer/cd-dvd/iso-image.nix"
|
||||
|
||||
# make sure our installer can detect and interact with all hardware that is supported in Nixpkgs
|
||||
# this loads basically every hardware related kernel module
|
||||
"${modulesPath}/profiles/all-hardware.nix"
|
||||
];
|
||||
|
||||
# the ISO image must be completely immutable in the sense that we do not
|
||||
# want the user to be able modify the ISO image after booting into it
|
||||
# the below option will disable rebuild switches (i.e nixos-rebuild switch)
|
||||
system.switch.enable = false;
|
||||
|
||||
isoImage = let
|
||||
# hostname will be set as a "top-level" attribute in hosts.nix, per-host.
|
||||
# therefore we can use the networking.hostName to get the hostname of the live
|
||||
# system without defining it explicitly in the system-agnostic ISO role module
|
||||
hostname = config.networking.hostName or "nixos";
|
||||
|
||||
# if the system is built from a git repository, we want to include the git revision
|
||||
# in the ISO name. if the tree is dirty, we use the term "dirty" to make it explicit
|
||||
rev = self.shortRev or "dirty";
|
||||
|
||||
# the format of the iso will always be uniform:
|
||||
# $hostname-$release-$rev-$arch
|
||||
# therefore we can set it once to avoid repetition later on
|
||||
name = "${hostname}-${config.system.nixos.release}-${rev}-${pkgs.stdenv.hostPlatform.uname.processor}";
|
||||
in {
|
||||
# this will cause the resulting .iso file to be named as follows:
|
||||
# $hostname-$release-$rev-$arch.iso
|
||||
isoName = mkImageMediaOverride "${name}.iso";
|
||||
# this will cause the label or volume ID of the generated ISO image to be as follows:
|
||||
# $hostname-$release-$rev-$arch
|
||||
# volumeID is used is used by stage 1 of the boot process, so it must be distintctive
|
||||
volumeID = mkImageMediaOverride "${name}";
|
||||
|
||||
# maximum compression, in exchange for build speed
|
||||
squashfsCompression = "zstd -Xcompression-level 10"; # default uses gzip
|
||||
|
||||
# ISO image should be an EFI-bootable volume
|
||||
makeEfiBootable = true;
|
||||
|
||||
# ISO image should be bootable from USB
|
||||
# FIXME: the module decription is as follows:
|
||||
# "Whether the ISO image should be bootable from CD as well as USB."
|
||||
# is this supposed to make the ISO image bootable from *CD* instead of USB?
|
||||
makeUsbBootable = true;
|
||||
|
||||
# my module system already contains an option to add memtest86+
|
||||
# to the boot menu at will but in case our system is unbootable
|
||||
# lets include memtest86+ in the ISO image
|
||||
# so that we may test the memory of the system
|
||||
# exclusively from the ISO image
|
||||
contents = [
|
||||
{
|
||||
source = pkgs.memtest86plus + "/memtest.bin";
|
||||
target = "boot/memtest.bin";
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
37
nyx/modules/core/roles/iso/system/boot.nix
Normal file
37
nyx/modules/core/roles/iso/system/boot.nix
Normal file
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkForce;
|
||||
in {
|
||||
boot = {
|
||||
# use the latest Linux kernel
|
||||
kernelPackages = pkgs.linuxPackages_latest;
|
||||
|
||||
# talk to me kernel
|
||||
kernelParams = lib.mkAfter ["noquiet"];
|
||||
|
||||
# no need for systemd in the initrd stage on an installation media
|
||||
# being put in to recovery mode, or having systemd in stage one is
|
||||
# entirely pointless
|
||||
initrd.systemd = {
|
||||
enable = lib.mkImageMediaOverride false;
|
||||
emergencyAccess = lib.mkImageMediaOverride true;
|
||||
};
|
||||
|
||||
# Needed for https://github.com/NixOS/nixpkgs/issues/58959
|
||||
# tl;dr: ZFS is problematic and we don't want it
|
||||
supportedFilesystems = mkForce [
|
||||
"btrfs"
|
||||
"vfat"
|
||||
"f2fs"
|
||||
"xfs"
|
||||
"ntfs"
|
||||
"cifs"
|
||||
];
|
||||
|
||||
# disable software RAID
|
||||
swraid.enable = mkForce false;
|
||||
};
|
||||
}
|
13
nyx/modules/core/roles/iso/system/default.nix
Normal file
13
nyx/modules/core/roles/iso/system/default.nix
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
imports = [
|
||||
./misc
|
||||
./services
|
||||
|
||||
./boot.nix
|
||||
./environment.nix
|
||||
./hardware.nix
|
||||
./networking.nix
|
||||
./nix.nix
|
||||
./users.nix
|
||||
];
|
||||
}
|
46
nyx/modules/core/roles/iso/system/environment.nix
Normal file
46
nyx/modules/core/roles/iso/system/environment.nix
Normal file
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
inputs,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkForce;
|
||||
in {
|
||||
environment = {
|
||||
# our installer is a minimal, TUI-only environment. I don't find any
|
||||
# good reason to keep X11 libs around while we will not be depending
|
||||
# on any GUI frameworks.
|
||||
noXlibs = true;
|
||||
|
||||
# 24.04 has brought in a stub-ld that will throw a warning if you try to run a
|
||||
# dynamically linked binary. This is an installer, so we probably won't try to run
|
||||
# dynamically linked binaries on this system. Besides, it's annoying.
|
||||
stub-ld.enable = mkForce false;
|
||||
|
||||
# NixOS bundles a few packages by default
|
||||
# it's not too large of a list, but I don't need it and I prefer
|
||||
# my system containing only the packages I've declared.
|
||||
defaultPackages = mkForce [];
|
||||
|
||||
# packages I might want on an installer environment
|
||||
systemPackages = with pkgs; [
|
||||
gitMinimal
|
||||
curl
|
||||
wget
|
||||
pciutils
|
||||
lshw
|
||||
rsync
|
||||
nixos-install-tools
|
||||
];
|
||||
|
||||
etc = {
|
||||
# link a copy of our nixpkgs input as the nixpkgs channel
|
||||
"nix/flake-channels/nixpkgs".source = inputs.nixpkgs;
|
||||
|
||||
# fix an annoying warning
|
||||
"mdadm.conf".text = ''
|
||||
MAILADDR root
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
6
nyx/modules/core/roles/iso/system/hardware.nix
Normal file
6
nyx/modules/core/roles/iso/system/hardware.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
# provide all hardware drivers, including proprietary ones
|
||||
hardware = {
|
||||
enableRedistributableFirmware = true;
|
||||
};
|
||||
}
|
10
nyx/modules/core/roles/iso/system/misc/console.nix
Normal file
10
nyx/modules/core/roles/iso/system/misc/console.nix
Normal file
|
@ -0,0 +1,10 @@
|
|||
{pkgs, ...}: {
|
||||
# console locale
|
||||
console = let
|
||||
variant = "u24n";
|
||||
in {
|
||||
# hidpi terminal font
|
||||
font = "${pkgs.terminus_font}/share/consolefonts/ter-${variant}.psf.gz";
|
||||
keyMap = "trq";
|
||||
};
|
||||
}
|
6
nyx/modules/core/roles/iso/system/misc/default.nix
Normal file
6
nyx/modules/core/roles/iso/system/misc/default.nix
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./console.nix
|
||||
./sound.nix
|
||||
];
|
||||
}
|
4
nyx/modules/core/roles/iso/system/misc/sound.nix
Normal file
4
nyx/modules/core/roles/iso/system/misc/sound.nix
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
# disable sound related programs
|
||||
sound.enable = false;
|
||||
}
|
20
nyx/modules/core/roles/iso/system/networking.nix
Normal file
20
nyx/modules/core/roles/iso/system/networking.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkForce;
|
||||
in {
|
||||
networking.networkmanager = {
|
||||
enable = true;
|
||||
plugins = mkForce [];
|
||||
};
|
||||
|
||||
networking.wireless.enable = mkForce false;
|
||||
|
||||
# Enable SSH in the boot process.
|
||||
systemd.services.sshd.wantedBy = mkForce ["multi-user.target"];
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHRDg2lu1rXKP4OfyghP17ZVL2csnyJEJcy9Km3LQm4r notashelf@enyo"
|
||||
];
|
||||
}
|
12
nyx/modules/core/roles/iso/system/nix.nix
Normal file
12
nyx/modules/core/roles/iso/system/nix.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
nix = {
|
||||
settings = {
|
||||
experimental-features = ["nix-command" "flakes" "repl-flake"];
|
||||
log-lines = 30;
|
||||
warn-dirty = false;
|
||||
http-connections = 50;
|
||||
accept-flake-config = true;
|
||||
auto-optimise-store = true;
|
||||
};
|
||||
};
|
||||
}
|
11
nyx/modules/core/roles/iso/system/security.nix
Normal file
11
nyx/modules/core/roles/iso/system/security.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
# attempt to fix "too many open files"
|
||||
security.pam.loginLimits = [
|
||||
{
|
||||
domain = "*";
|
||||
item = "nofile";
|
||||
type = "-";
|
||||
value = "65536";
|
||||
}
|
||||
];
|
||||
}
|
5
nyx/modules/core/roles/iso/system/services/default.nix
Normal file
5
nyx/modules/core/roles/iso/system/services/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./openssh.nix
|
||||
];
|
||||
}
|
88
nyx/modules/core/roles/iso/system/services/openssh.nix
Normal file
88
nyx/modules/core/roles/iso/system/services/openssh.nix
Normal file
|
@ -0,0 +1,88 @@
|
|||
{
|
||||
# Hardened SSH configuration
|
||||
services.openssh = {
|
||||
extraConfig = ''
|
||||
AllowTcpForwarding no
|
||||
HostKeyAlgorithms ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com
|
||||
PermitTunnel no
|
||||
'';
|
||||
settings = {
|
||||
Ciphers = [
|
||||
"aes256-gcm@openssh.com"
|
||||
"aes256-ctr,aes192-ctr"
|
||||
"aes128-ctr"
|
||||
"aes128-gcm@openssh.com"
|
||||
"chacha20-poly1305@openssh.com"
|
||||
];
|
||||
KbdInteractiveAuthentication = false;
|
||||
KexAlgorithms = [
|
||||
"curve25519-sha256"
|
||||
"curve25519-sha256@libssh.org"
|
||||
"diffie-hellman-group16-sha512"
|
||||
"diffie-hellman-group18-sha512"
|
||||
"sntrup761x25519-sha512@openssh.com"
|
||||
];
|
||||
Macs = [
|
||||
"hmac-sha2-512-etm@openssh.com"
|
||||
"hmac-sha2-256-etm@openssh.com"
|
||||
"umac-128-etm@openssh.com"
|
||||
];
|
||||
X11Forwarding = false;
|
||||
};
|
||||
};
|
||||
|
||||
# Client side SSH configuration
|
||||
programs.ssh = {
|
||||
ciphers = [
|
||||
"aes256-gcm@openssh.com"
|
||||
"aes256-ctr,aes192-ctr"
|
||||
"aes128-ctr"
|
||||
"aes128-gcm@openssh.com"
|
||||
"chacha20-poly1305@openssh.com"
|
||||
];
|
||||
|
||||
hostKeyAlgorithms = [
|
||||
"ssh-ed25519"
|
||||
"ssh-ed25519-cert-v01@openssh.com"
|
||||
"sk-ssh-ed25519@openssh.com"
|
||||
"sk-ssh-ed25519-cert-v01@openssh.com"
|
||||
"rsa-sha2-512"
|
||||
"rsa-sha2-512-cert-v01@openssh.com"
|
||||
"rsa-sha2-256"
|
||||
"rsa-sha2-256-cert-v01@openssh.com"
|
||||
];
|
||||
|
||||
kexAlgorithms = [
|
||||
"curve25519-sha256"
|
||||
"curve25519-sha256@libssh.org"
|
||||
"diffie-hellman-group16-sha512"
|
||||
"diffie-hellman-group18-sha512"
|
||||
"sntrup761x25519-sha512@openssh.com"
|
||||
];
|
||||
|
||||
knownHosts = {
|
||||
github-rsa = {
|
||||
hostNames = ["github.com"];
|
||||
publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=";
|
||||
};
|
||||
github-ed25519 = {
|
||||
hostNames = ["github.com"];
|
||||
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl";
|
||||
};
|
||||
gitlab-rsa = {
|
||||
hostNames = ["gitlab.com"];
|
||||
publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9";
|
||||
};
|
||||
gitlab-ed25519 = {
|
||||
hostNames = ["gitlab.com"];
|
||||
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf";
|
||||
};
|
||||
};
|
||||
|
||||
macs = [
|
||||
"hmac-sha2-512-etm@openssh.com"
|
||||
"hmac-sha2-256-etm@openssh.com"
|
||||
"umac-128-etm@openssh.com"
|
||||
];
|
||||
};
|
||||
}
|
11
nyx/modules/core/roles/iso/system/users.nix
Normal file
11
nyx/modules/core/roles/iso/system/users.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
users.extraUsers.root.password = "";
|
||||
|
||||
users.users.nixos = {
|
||||
uid = 1000;
|
||||
password = "nixos";
|
||||
description = "default";
|
||||
isNormalUser = true;
|
||||
extraGroups = ["wheel"];
|
||||
};
|
||||
}
|
7
nyx/modules/core/roles/laptop/default.nix
Normal file
7
nyx/modules/core/roles/laptop/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./system
|
||||
];
|
||||
|
||||
system.nixos.tags = ["laptop"];
|
||||
}
|
7
nyx/modules/core/roles/laptop/system/default.nix
Normal file
7
nyx/modules/core/roles/laptop/system/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./power
|
||||
|
||||
./touchpad.nix
|
||||
];
|
||||
}
|
75
nyx/modules/core/roles/laptop/system/power/default.nix
Normal file
75
nyx/modules/core/roles/laptop/system/power/default.nix
Normal file
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf mkDefault;
|
||||
|
||||
dev = config.modules.device;
|
||||
acceptedTypes = ["laptop" "hybrid"];
|
||||
in {
|
||||
imports = [./monitor.nix];
|
||||
|
||||
config = mkIf (builtins.elem dev.type acceptedTypes) {
|
||||
hardware.acpilight.enable = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
acpi
|
||||
powertop
|
||||
];
|
||||
|
||||
services = {
|
||||
# handle ACPI events
|
||||
acpid.enable = true;
|
||||
|
||||
# allows changing system behavior based upon user-selected power profiles
|
||||
power-profiles-daemon.enable = true;
|
||||
|
||||
# temperature target on battery
|
||||
undervolt = {
|
||||
tempBat = 65; # deg C
|
||||
package = pkgs.undervolt;
|
||||
};
|
||||
|
||||
# superior power management
|
||||
auto-cpufreq = {
|
||||
enable = true;
|
||||
settings = let
|
||||
MHz = x: x * 1000;
|
||||
in {
|
||||
battery = {
|
||||
governor = "powersave";
|
||||
scaling_min_freq = mkDefault (MHz 1200);
|
||||
scaling_max_freq = mkDefault (MHz 1800);
|
||||
turbo = "never";
|
||||
};
|
||||
|
||||
charger = {
|
||||
governor = "performance";
|
||||
scaling_min_freq = mkDefault (MHz 1800);
|
||||
scaling_max_freq = mkDefault (MHz 3800);
|
||||
turbo = "auto";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# DBus service that provides power management support to applications.
|
||||
upower = {
|
||||
enable = true;
|
||||
percentageLow = 15;
|
||||
percentageCritical = 5;
|
||||
percentageAction = 3;
|
||||
criticalPowerAction = "Hibernate";
|
||||
};
|
||||
};
|
||||
|
||||
boot = {
|
||||
kernelModules = ["acpi_call"];
|
||||
extraModulePackages = with config.boot.kernelPackages; [
|
||||
acpi_call
|
||||
cpupower
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
40
nyx/modules/core/roles/laptop/system/power/monitor.nix
Normal file
40
nyx/modules/core/roles/laptop/system/power/monitor.nix
Normal file
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
inputs',
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (builtins) readFile;
|
||||
inherit (lib.modules) mkForce;
|
||||
inherit (lib.strings) makeBinPath;
|
||||
|
||||
dependencies = with pkgs;
|
||||
[
|
||||
coreutils
|
||||
power-profiles-daemon
|
||||
inotify-tools
|
||||
jaq
|
||||
]
|
||||
++ [
|
||||
inputs'.hyprland.packages.hyprland
|
||||
];
|
||||
in {
|
||||
config = {
|
||||
# Power state monitor. Switches Power profiles based on charging state.
|
||||
# Plugged in - performance
|
||||
# Unplugged - power-saver
|
||||
systemd.services."power-monitor" = {
|
||||
description = "Power Monitoring Service";
|
||||
environment.PATH = mkForce "/run/wrappers/bin:${makeBinPath dependencies}";
|
||||
script = readFile ./scripts/power_monitor.sh;
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
Restart = "on-failure";
|
||||
};
|
||||
|
||||
wants = ["power-profiles-daemon.service"];
|
||||
wantedBy = ["default.target"];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
BAT=$(echo /sys/class/power_supply/BAT*)
|
||||
BAT_STATUS="$BAT/status"
|
||||
BAT_CAP="$BAT/capacity"
|
||||
AC_PROFILE="performance"
|
||||
BAT_PROFILE="balanced"
|
||||
|
||||
# low and critical battery levels
|
||||
LOW_BAT_PERCENT=25
|
||||
CRIT_BAT_PERCENT=5
|
||||
|
||||
# how long to wait before suspending
|
||||
SUSPEND_WAIT=60s
|
||||
|
||||
# define the wait & suspend function
|
||||
wait_and_suspend() {
|
||||
sleep "$SUSPEND_WAIT"
|
||||
|
||||
# check if we're still discharging
|
||||
if [[ $(cat "$BAT_STATUS") == "Discharging" ]]; then
|
||||
systemctl suspend
|
||||
fi
|
||||
}
|
||||
|
||||
# wait a while if needed
|
||||
[[ -z $STARTUP_WAIT ]] || sleep "$STARTUP_WAIT"
|
||||
|
||||
# start the monitor loop
|
||||
prev=0
|
||||
while true; do
|
||||
# read the current state
|
||||
if [[ $(cat "$BAT_STATUS") == "Discharging" ]]; then
|
||||
profile=$BAT_PROFILE
|
||||
else
|
||||
profile=$AC_PROFILE
|
||||
fi
|
||||
|
||||
# set the new profile
|
||||
if [[ $prev != "$profile" ]]; then
|
||||
echo -en "Setting power profile to ${profile}\n"
|
||||
powerprofilesctl set $profile
|
||||
fi
|
||||
prev=$profile
|
||||
|
||||
if [[ $(cat "$BAT_CAP") -le $LOW_BAT_PERCENT && $BAT_STATUS == "Discharging" ]]; then
|
||||
notify-send --urgency=critical --hint=int:transient:1 --icon=battery_empty "Battery Low" \
|
||||
"Consider plugging in."
|
||||
|
||||
for i in $(hyprctl instances -j | jaq ".[].instance" -r); do
|
||||
hyprctl -i "$i" --batch 'keyword decoration:blur:enabled false; keyword animations:enabled false'
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ $(cat "$BAT_CAP") -le $CRIT_BAT_PERCENT && $BAT_STATUS == "Discharging" ]]; then
|
||||
notify-send --urgency=critical --hint=int:transient:1 --icon=battery_empty "Battery Critically Low" \
|
||||
"Computer will suspend in 60 seconds."
|
||||
wait_and_suspend &
|
||||
fi
|
||||
|
||||
if [[ $(cat "$BAT_CAP") -gt $LOW_BAT_PERCENT && $BAT_STATUS == "Charging" ]]; then
|
||||
for i in $(hyprctl instances -j | jaq ".[].instance" -r); do
|
||||
hyprctl -i "$i" --batch 'keyword decoration:blur:enabled true; keyword animations:enabled true'
|
||||
done
|
||||
fi
|
||||
|
||||
# wait for the next power change event
|
||||
inotifywait -qq "$BAT_STATUS" "$BAT_CAP"
|
||||
done
|
133
nyx/modules/core/roles/laptop/system/power/tlp.nix
Normal file
133
nyx/modules/core/roles/laptop/system/power/tlp.nix
Normal file
|
@ -0,0 +1,133 @@
|
|||
let
|
||||
MHz = x: x * 1000;
|
||||
in {
|
||||
config = {
|
||||
services = {
|
||||
tlp = {
|
||||
enable = false;
|
||||
settings = {
|
||||
TLP_ENABLE = 1;
|
||||
TLP_DEFAULT_MODE = "BAT";
|
||||
|
||||
# Timeout (in seconds) for the audio power saving mode (supports Intel HDA, AC97).
|
||||
# A value of 1 is recommended for Linux desktop environments with PulseAudio,
|
||||
# systems without PulseAudio may require 10. The value 0 disables power save.
|
||||
SOUND_POWER_SAVE_ON_AC = 10;
|
||||
SOUND_POWER_SAVE_ON_BAT = 10;
|
||||
|
||||
# SOUND_POWER_SAVE_CONTROLLER = "Y";
|
||||
|
||||
START_CHARGE_THRESH_BAT0 = 80;
|
||||
STOP_CHARGE_THRESH_BAT0 = 95;
|
||||
|
||||
RESTORE_THRESHOLDS_ON_BAT = 1;
|
||||
|
||||
# battery care drivers
|
||||
# NATACPI_ENABLE = 1;
|
||||
# TPACPI_ENABLE = 1;
|
||||
# TPSMAPI_ENABLE = 1;
|
||||
|
||||
# DISK_DEVICES = "nvme0n1 mmcblk0";
|
||||
|
||||
# DISK_APM_LEVEL_ON_AC = "254 254";
|
||||
# DISK_APM_LEVEL_ON_BAT = "128 128";
|
||||
|
||||
# DISK_IDLE_SECS_ON_AC=0;
|
||||
DISK_IDLE_SECS_ON_BAT = 5;
|
||||
|
||||
# Timeout (in seconds) for writing unsaved data in file system buffers to disk.
|
||||
# MAX_LOST_WORK_SECS_ON_AC = 15;
|
||||
# MAX_LOST_WORK_SECS_ON_BAT = 60;
|
||||
|
||||
# RADEON_DPM_PERF_LEVEL_ON_AC = "auto";
|
||||
RADEON_DPM_PERF_LEVEL_ON_BAT = "low";
|
||||
|
||||
# RADEON_DPM_STATE_ON_AC = "performance";
|
||||
# RADEON_DPM_STATE_ON_BAT = "battery";
|
||||
|
||||
RADEON_POWER_PROFILE_ON_AC = "high";
|
||||
RADEON_POWER_PROFILE_ON_BAT = "low";
|
||||
|
||||
# NMI_WATCHDOG = 0;
|
||||
|
||||
# Sets Wi-Fi power saving mode. Adapter support depends on kernel and driver.
|
||||
# WIFI_PWR_ON_AC = "off";
|
||||
# WIFI_PWR_ON_BAT = "on";
|
||||
|
||||
# WOL_DISABLE = "Y";
|
||||
|
||||
# Select the platform profile to control system operating characteristics
|
||||
# around power/performance levels, thermal and fan speed.
|
||||
# PLATFORM_PROFILE_ON_AC = "performance";
|
||||
# PLATFORM_PROFILE_ON_BAT = "low-power";
|
||||
|
||||
# <https://www.kernel.org/doc/html/latest/admin-guide/pm/cpufreq.html>
|
||||
CPU_SCALING_GOVERNOR_ON_AC = "schedutil";
|
||||
CPU_SCALING_GOVERNOR_ON_BAT = "powersave";
|
||||
|
||||
CPU_SCALING_MIN_FREQ_ON_AC = MHz 1400;
|
||||
CPU_SCALING_MAX_FREQ_ON_AC = MHz 1700;
|
||||
CPU_SCALING_MIN_FREQ_ON_BAT = MHz 1400;
|
||||
CPU_SCALING_MAX_FREQ_ON_BAT = MHz 1600;
|
||||
|
||||
CPU_BOOST_ON_AC = 1;
|
||||
CPU_BOOST_ON_BAT = 0;
|
||||
|
||||
# SCHED_POWERSAVE_ON_AC = 0;
|
||||
# SCHED_POWERSAVE_ON_BAT = 1;
|
||||
|
||||
# Restores radio device state (builtin Bluetooth, Wi-Fi, WWAN) from previous shutdown on boot.
|
||||
# RESTORE_DEVICE_STATE_ON_STARTUP = 0;
|
||||
|
||||
DEVICES_TO_DISABLE_ON_STARTUP = "bluetooth wwan";
|
||||
DEVICES_TO_ENABLE_ON_STARTUP = "wifi";
|
||||
|
||||
# DEVICES_TO_DISABLE_ON_SHUTDOWN = "bluetooth wifi wwan";
|
||||
# DEVICES_TO_ENABLE_ON_SHUTDOWN = "bluetooth wifi wwan";
|
||||
|
||||
# has precedence
|
||||
DEVICES_TO_ENABLE_ON_AC = "";
|
||||
DEVICES_TO_DISABLE_ON_BAT = "";
|
||||
|
||||
DEVICES_TO_DISABLE_ON_BAT_NOT_IN_USE = "bluetooth wwan";
|
||||
|
||||
DEVICES_TO_DISABLE_ON_LAN_CONNECT = "wwan";
|
||||
DEVICES_TO_DISABLE_ON_WIFI_CONNECT = "";
|
||||
DEVICES_TO_DISABLE_ON_WWAN_CONNECT = "wifi";
|
||||
|
||||
DEVICES_TO_ENABLE_ON_LAN_DISCONNECT = "wifi";
|
||||
DEVICES_TO_ENABLE_ON_WIFI_DISCONNECT = "";
|
||||
DEVICES_TO_ENABLE_ON_WWAN_DISCONNECT = "";
|
||||
|
||||
DEVICES_TO_ENABLE_ON_DOCK = "wifi bluetooth";
|
||||
# DEVICES_TO_DISABLE_ON_DOCK = "";
|
||||
|
||||
DEVICES_TO_ENABLE_ON_UNDOCK = "";
|
||||
DEVICES_TO_DISABLE_ON_UNDOCK = "bluetooth";
|
||||
|
||||
# RUNTIME_PM_ON_AC = "on";
|
||||
# RUNTIME_PM_ON_BAT = "auto";
|
||||
|
||||
# RUNTIME_PM_DENYLIST = "11:22.3 44:55.6";
|
||||
RUNTIME_PM_DRIVER_DENYLIST = "mei_me nouveau radeon psmouse";
|
||||
|
||||
# RUNTIME_PM_ENABLE="11:22.3";
|
||||
# RUNTIME_PM_DISABLE="44:55.6";
|
||||
|
||||
# PCIE_ASPM_ON_AC = "default";
|
||||
PCIE_ASPM_ON_BAT = "powersupersave";
|
||||
|
||||
# USB_AUTOSUSPEND = 1;
|
||||
# USB_DENYLIST = "1111:2222 3333:4444";
|
||||
# USB_EXCLUDE_AUDIO = 1;
|
||||
# USB_EXCLUDE_BTUSB = 1;
|
||||
# USB_EXCLUDE_PHONE = 1;
|
||||
# USB_EXCLUDE_PRINTER = 1;
|
||||
# USB_EXCLUDE_WWAN = 0;
|
||||
# USB_ALLOWLIST="5555:6666 7777:8888";
|
||||
# USB_AUTOSUSPEND_DISABLE_ON_SHUTDOWN = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
27
nyx/modules/core/roles/laptop/system/touchpad.nix
Normal file
27
nyx/modules/core/roles/laptop/system/touchpad.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
config = {
|
||||
services = {
|
||||
# Input settings for libinput
|
||||
xserver.libinput = {
|
||||
# enable libinput
|
||||
enable = true;
|
||||
|
||||
# disable mouse acceleration
|
||||
mouse = {
|
||||
accelProfile = "flat";
|
||||
accelSpeed = "0";
|
||||
middleEmulation = false;
|
||||
};
|
||||
|
||||
# touchpad settings
|
||||
touchpad = {
|
||||
naturalScrolling = true;
|
||||
tapping = true;
|
||||
clickMethod = "clickfinger";
|
||||
horizontalScrolling = false;
|
||||
disableWhileTyping = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
7
nyx/modules/core/roles/microvm/default.nix
Normal file
7
nyx/modules/core/roles/microvm/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./system
|
||||
];
|
||||
|
||||
system.nixos.tags = ["microvm"];
|
||||
}
|
7
nyx/modules/core/roles/microvm/system/default.nix
Normal file
7
nyx/modules/core/roles/microvm/system/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./nix
|
||||
./os
|
||||
./securiy
|
||||
];
|
||||
}
|
12
nyx/modules/core/roles/microvm/system/nix/default.nix
Normal file
12
nyx/modules/core/roles/microvm/system/nix/default.nix
Normal file
|
@ -0,0 +1,12 @@
|
|||
{pkgs, ...}: {
|
||||
nix = {
|
||||
settings.trusted-users = ["admin"];
|
||||
package = pkgs.nixUnstable;
|
||||
keep-outputs = true;
|
||||
keep-derivations = true;
|
||||
extra-experimental-features = [
|
||||
"nix-command"
|
||||
"flakes"
|
||||
];
|
||||
};
|
||||
}
|
9
nyx/modules/core/roles/microvm/system/os/default.nix
Normal file
9
nyx/modules/core/roles/microvm/system/os/default.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
imports = [
|
||||
./programs
|
||||
./users
|
||||
|
||||
./environment.nix
|
||||
./networking.nix
|
||||
];
|
||||
}
|
31
nyx/modules/core/roles/microvm/system/os/environment.nix
Normal file
31
nyx/modules/core/roles/microvm/system/os/environment.nix
Normal file
|
@ -0,0 +1,31 @@
|
|||
{pkgs, ...}: {
|
||||
time.timeZone = "UTC";
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
|
||||
console = {
|
||||
font = "ter-v32n";
|
||||
packages = [pkgs.terminus-font];
|
||||
};
|
||||
|
||||
environment = {
|
||||
shells = with pkgs; [bash zsh];
|
||||
systemPackages = with pkgs; [
|
||||
vim
|
||||
git
|
||||
killall
|
||||
bind.dnsutils
|
||||
tcpdump
|
||||
nmap
|
||||
usbutils
|
||||
wget
|
||||
tmux
|
||||
direnv
|
||||
nix-direnv
|
||||
sops
|
||||
rage
|
||||
ssh-to-age
|
||||
pwgen
|
||||
w3m
|
||||
];
|
||||
};
|
||||
}
|
17
nyx/modules/core/roles/microvm/system/os/networking.nix
Normal file
17
nyx/modules/core/roles/microvm/system/os/networking.nix
Normal file
|
@ -0,0 +1,17 @@
|
|||
{lib, ...}: {
|
||||
systemd.network.enable = true;
|
||||
|
||||
# Enable the OpenSSH daemon.
|
||||
services.openssh.enable = true;
|
||||
|
||||
networking = {
|
||||
useDHCP = false;
|
||||
networkmanager.enable = false;
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowPing = lib.mkForce false;
|
||||
allowedTCPPorts = lib.mkForce [];
|
||||
allowedUDPPorts = lib.mkForce [];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
imports = [
|
||||
./git.nix
|
||||
./neovim.nix
|
||||
./tmux.nix
|
||||
./zsh.nix
|
||||
];
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{programs.git.enable = true;}
|
23
nyx/modules/core/roles/microvm/system/os/programs/neovim.nix
Normal file
23
nyx/modules/core/roles/microvm/system/os/programs/neovim.nix
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
programs.neovim = {
|
||||
enable = true;
|
||||
viAlias = true;
|
||||
vimAlias = true;
|
||||
|
||||
configure.customRC = ''
|
||||
syntax enable
|
||||
|
||||
set noexpandtab
|
||||
set shiftwidth=2
|
||||
set tabstop=2
|
||||
|
||||
set cindent
|
||||
set smartindent
|
||||
set autoindent
|
||||
set foldmethod=syntax
|
||||
nmap <F2> zA
|
||||
nmap <F3> zR
|
||||
nmap <F4> zM
|
||||
'';
|
||||
};
|
||||
}
|
20
nyx/modules/core/roles/microvm/system/os/programs/tmux.nix
Normal file
20
nyx/modules/core/roles/microvm/system/os/programs/tmux.nix
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
programs.tmux = {
|
||||
enable = true;
|
||||
baseIndex = 1;
|
||||
clock24 = true;
|
||||
historyLimit = 10000;
|
||||
terminal = "tmux-256color";
|
||||
extraConfig = ''
|
||||
unbind C-b
|
||||
set-option -g prefix C-a
|
||||
bind-key C-a last-window
|
||||
set-option -g set-titles on
|
||||
set-option -g set-titles-string '#H:#S.#I.#P #W #T'
|
||||
setw -g monitor-activity on
|
||||
set-option -g status-justify left
|
||||
set-option -g status-bg yellow
|
||||
set-option -g status-fg black
|
||||
'';
|
||||
};
|
||||
}
|
11
nyx/modules/core/roles/microvm/system/os/programs/zsh.nix
Normal file
11
nyx/modules/core/roles/microvm/system/os/programs/zsh.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
environment.pathsToLink = ["/share/zsh"];
|
||||
programs.zsh = {
|
||||
enable = true;
|
||||
enableCompletion = true;
|
||||
autosuggestions = {
|
||||
enable = true;
|
||||
async = true;
|
||||
};
|
||||
};
|
||||
}
|
7
nyx/modules/core/roles/microvm/system/os/users/admin.nix
Normal file
7
nyx/modules/core/roles/microvm/system/os/users/admin.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
users.users.admin = {
|
||||
isNormalUser = true;
|
||||
extraGroups = ["wheel"];
|
||||
openssh.authorizedKeys.keys = [];
|
||||
};
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./admin.nix
|
||||
];
|
||||
}
|
13
nyx/modules/core/roles/microvm/system/security/default.nix
Normal file
13
nyx/modules/core/roles/microvm/system/security/default.nix
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
security.sudo.extraRules = [
|
||||
{
|
||||
users = ["admin"];
|
||||
commands = [
|
||||
{
|
||||
command = "ALL";
|
||||
options = ["SETENV" "NOPASSWD"];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
7
nyx/modules/core/roles/server/default.nix
Normal file
7
nyx/modules/core/roles/server/default.nix
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
imports = [
|
||||
./system
|
||||
];
|
||||
|
||||
system.nixos.tags = ["server"];
|
||||
}
|
5
nyx/modules/core/roles/server/system/default.nix
Normal file
5
nyx/modules/core/roles/server/system/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./services
|
||||
];
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
{
|
||||
inputs,
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services.bincache.atticd;
|
||||
|
||||
domain = "cache" + config.networking.domain;
|
||||
inherit (cfg.settings) host port;
|
||||
in {
|
||||
imports = [inputs.atticd.nixosModules.atticd];
|
||||
config = mkIf cfg.enable {
|
||||
environment.systemPackages = [pkgs.attic-client];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [port];
|
||||
|
||||
users = {
|
||||
groups.atticd = {};
|
||||
users."atticd" = {
|
||||
isSystemUser = true;
|
||||
group = "atticd";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.atticd = {
|
||||
serviceConfig.DynamicUser = lib.mkForce false;
|
||||
};
|
||||
|
||||
services = {
|
||||
atticd = {
|
||||
enable = true;
|
||||
credentialsFile = config.age.secrets.attic-env.path;
|
||||
user = "atticd";
|
||||
group = "atticd";
|
||||
|
||||
settings = {
|
||||
listen = "${host}:${toString port}"; # this listens ONLY locally
|
||||
database.url = "postgresql:///atticd?host=/run/postgresql";
|
||||
|
||||
allowed-hosts = ["${domain}"];
|
||||
api-endpoint = "https://${domain}/";
|
||||
require-proof-of-possession = false;
|
||||
|
||||
/*
|
||||
storage = {
|
||||
type = "s3";
|
||||
region = "helios";
|
||||
bucket = "attic-cache";
|
||||
endpoint = "https://s3.notashelf.dev";
|
||||
};
|
||||
*/
|
||||
|
||||
chunking = let
|
||||
KB = x: x * 1024;
|
||||
in {
|
||||
nar-size-threshold = KB 64;
|
||||
min-size = KB 16;
|
||||
avg-size = KB 64;
|
||||
max-size = KB 256;
|
||||
};
|
||||
|
||||
garbage-collection = {
|
||||
interval = "24 hours";
|
||||
default-retention-period = "6 weeks";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nginx.virtualHosts."${domain}" = {
|
||||
extraConfig = ''
|
||||
client_max_body_size 0;
|
||||
|
||||
proxy_read_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
'';
|
||||
|
||||
locations."/" = {
|
||||
recommendedProxySettings = true;
|
||||
proxyPass = "http://${host}:${toString port}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./atticd.nix
|
||||
./harmonia.nix
|
||||
];
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services.bincache.harmonia;
|
||||
|
||||
inherit (cfg.settings) port host;
|
||||
in {
|
||||
config = mkIf cfg.enable {
|
||||
users = {
|
||||
groups.harmonia = {};
|
||||
users.harmonia = {
|
||||
isSystemUser = true;
|
||||
createHome = true;
|
||||
group = "harmonia";
|
||||
home = "/srv/storage/harmonia";
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
harmonia = {
|
||||
enable = true;
|
||||
# NOTE: generated via
|
||||
# $ nix-store --generate-binary-cache-key cache.domain.tld-1 /var/lib/secrets/harmonia.secret /var/lib/secrets/harmonia.pub
|
||||
signKeyPath = config.age.secrets.harmonia-privateKey.path;
|
||||
settings = {
|
||||
# default ip:hostname to bind to
|
||||
bind = "${host}:${toString port}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nix.settings.allowed-users = ["harmonia"];
|
||||
|
||||
services.nginx = {
|
||||
virtualHosts."cache.notashelf.dev" =
|
||||
{
|
||||
locations."/".extraConfig = ''
|
||||
proxy_pass http://127.0.0.1:${toString port};
|
||||
proxy_set_header Host $host;
|
||||
proxy_redirect http:// https://;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
|
||||
zstd on;
|
||||
zstd_types application/x-nix-archive;
|
||||
'';
|
||||
|
||||
quic = true;
|
||||
}
|
||||
// lib.sslTemplate;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
imports = [
|
||||
./mongodb.nix
|
||||
./postgresql.nix
|
||||
./mysql.nix
|
||||
./redis.nix
|
||||
./garage.nix
|
||||
];
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
config = mkIf cfg.database.garage.enable {
|
||||
networking.firewall.allowedTCPPorts = [3900 3901 3903];
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.garage
|
||||
];
|
||||
|
||||
systemd = let
|
||||
sc = config.systemd.services.garage.serviceConfig;
|
||||
gc = config.services.garage.settings;
|
||||
in {
|
||||
tmpfiles.rules = [
|
||||
"d /srv/storage/garage 0755 ${sc.User} ${sc.Group}"
|
||||
"d '${gc.data_dir}' 0700 ${sc.User} ${sc.Group} - -"
|
||||
"d '${gc.metadata_dir}' 0700 ${sc.User} ${sc.Group} - -"
|
||||
];
|
||||
|
||||
services.garage = {
|
||||
# this lets custom data directory work by having a real user own the service process
|
||||
# the user and its group need to be created in the users section
|
||||
serviceConfig = {
|
||||
User = "garage";
|
||||
Group = "garage";
|
||||
ReadWritePaths = [gc.data_dir gc.metadata_dir];
|
||||
RequiresMountsFor = [gc.data_dir];
|
||||
DynamicUser = false;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = true;
|
||||
};
|
||||
|
||||
environment = {
|
||||
RUST_LOG = "debug";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
users = {
|
||||
groups.garage = {};
|
||||
|
||||
users.garage = {
|
||||
isSystemUser = true;
|
||||
createHome = false;
|
||||
group = "garage";
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
garage = {
|
||||
enable = true;
|
||||
package = pkgs.garage;
|
||||
|
||||
environmentFile = config.age.secrets.garage-env.path;
|
||||
|
||||
settings = {
|
||||
metadata_dir = "/srv/storage/garage/meta";
|
||||
data_dir = "/srv/storage/garage/data";
|
||||
metadata_fsync = false; # synchronous mode for the database engine
|
||||
|
||||
db_engine = "lmdb";
|
||||
replication_mode = "none";
|
||||
compression_level = -1;
|
||||
|
||||
# For inter-node comms
|
||||
rpc_bind_addr = "[::]:3901";
|
||||
rpc_secret_file = config.age.secrets.garage-env.path;
|
||||
# rpc_public_addr = "127.0.0.1:3901";
|
||||
|
||||
# Standard S3 api endpoint
|
||||
s3_api = {
|
||||
s3_region = "helios";
|
||||
api_bind_addr = "[::]:3900";
|
||||
};
|
||||
|
||||
# Static file serve endpoint
|
||||
/*
|
||||
s3_web = {
|
||||
bind_addr = "[::1]:3902";
|
||||
root_domain = "s3.notashelf.dev";
|
||||
index = "index.html";
|
||||
};
|
||||
|
||||
"k2v_api" = {
|
||||
"api_bind_addr" = "[::1]:3904";
|
||||
};
|
||||
*/
|
||||
|
||||
# Admin api endpoint
|
||||
admin = {
|
||||
api_bind_addr = "[::]:3903";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nginx.virtualHosts."s3.notashelf.dev" =
|
||||
{
|
||||
locations."/".proxyPass = "http://127.0.0.1:3900";
|
||||
extraConfig = ''
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $host;
|
||||
# Disable buffering to a temporary file.
|
||||
proxy_max_temp_file_size 0;
|
||||
'';
|
||||
}
|
||||
// lib.sslTemplate;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
config = mkIf cfg.database.mongodb.enable {
|
||||
services.mongodb = {
|
||||
enable = true;
|
||||
package = pkgs.mongodb;
|
||||
enableAuth = true;
|
||||
initialRootPassword = config.age.secrets.mongodb-secret.path;
|
||||
#bind_ip = "0.0.0.0";
|
||||
extraConfig = ''
|
||||
operationProfiling.mode: all
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
config = mkIf cfg.database.mysql.enable {
|
||||
services.mysql = {
|
||||
enable = true;
|
||||
package = pkgs.mariadb;
|
||||
|
||||
# databases and users
|
||||
ensureDatabases = ["mkm"];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "mkm";
|
||||
ensurePermissions = {
|
||||
"mkm.*" = "ALL PRIVILEGES";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
config = mkIf cfg.database.postgresql.enable {
|
||||
services.postgresql = {
|
||||
enable = true;
|
||||
package = pkgs.postgresql_15;
|
||||
dataDir = "/srv/storage/postgresql/${config.services.postgresql.package.psqlSchema}";
|
||||
|
||||
ensureDatabases = [
|
||||
"nextcloud"
|
||||
"forgejo"
|
||||
"grafana"
|
||||
"vaultwarden"
|
||||
"roundcube"
|
||||
"headscale"
|
||||
"atticd"
|
||||
];
|
||||
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "postgres";
|
||||
ensureClauses = {
|
||||
superuser = true;
|
||||
login = true; # not implied by superuser
|
||||
createrole = true;
|
||||
createdb = true;
|
||||
replication = true;
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "forgejo";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
{
|
||||
name = "grafana";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
{
|
||||
name = "vaultwarden";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
{
|
||||
name = "nextcloud";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
{
|
||||
name = "roundcube";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
{
|
||||
name = "headscale";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
{
|
||||
name = "atticd";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
|
||||
checkConfig = true;
|
||||
enableTCPIP = false;
|
||||
|
||||
# http://pgconfigurator.cybertec.at/;
|
||||
# https://git.darmstadt.ccc.de/maralorn/nixos-config/-/blob/master/nixos/roles/matrix-synapse/postgres-tuning.nix
|
||||
settings = {
|
||||
# Connectivity;
|
||||
max_connections = 100;
|
||||
superuser_reserved_connections = 3;
|
||||
|
||||
# Memory Settings;
|
||||
shared_buffers = "1024 MB";
|
||||
work_mem = "32 MB";
|
||||
maintenance_work_mem = "320 MB";
|
||||
huge_pages = "off";
|
||||
effective_cache_size = "2 GB";
|
||||
effective_io_concurrency = 100; # concurrent IO only really activated if OS supports posix_fadvise function;
|
||||
random_page_cost = 1.25; # speed of random disk access relative to sequential access (1.0);
|
||||
# Monitoring;
|
||||
shared_preload_libraries = "pg_stat_statements,auto_explain"; # per statement resource usage stats & log explain statements for slow queries
|
||||
track_io_timing = "on"; # measure exact block IO times;
|
||||
track_functions = "pl"; # track execution times of pl-language procedures if any;
|
||||
# Replication;
|
||||
wal_level = "replica"; # consider using at least "replica";
|
||||
max_wal_senders = 0;
|
||||
synchronous_commit = "on";
|
||||
|
||||
# Checkpointing: ;
|
||||
checkpoint_timeout = "15 min";
|
||||
checkpoint_completion_target = 0.9;
|
||||
max_wal_size = "1024 MB";
|
||||
min_wal_size = "512 MB";
|
||||
|
||||
# WAL writing;
|
||||
wal_compression = "on";
|
||||
wal_buffers = -1; # auto-tuned by Postgres till maximum of segment size (16MB by default);
|
||||
wal_writer_delay = "200ms";
|
||||
wal_writer_flush_after = "1MB";
|
||||
|
||||
# Background writer;
|
||||
bgwriter_delay = "200ms";
|
||||
bgwriter_lru_maxpages = 100;
|
||||
bgwriter_lru_multiplier = 2.0;
|
||||
bgwriter_flush_after = 0;
|
||||
|
||||
# Parallel queries: ;
|
||||
max_worker_processes = 6;
|
||||
max_parallel_workers_per_gather = 3;
|
||||
max_parallel_maintenance_workers = 3;
|
||||
max_parallel_workers = 6;
|
||||
parallel_leader_participation = "on";
|
||||
|
||||
# Advanced features ;
|
||||
enable_partitionwise_join = "on";
|
||||
enable_partitionwise_aggregate = "on";
|
||||
jit = "on";
|
||||
|
||||
jit_above_cost = 100000;
|
||||
jit_inline_above_cost = 150000;
|
||||
jit_optimize_above_cost = 500000;
|
||||
|
||||
# log slow queries
|
||||
log_min_duration_statement = 100;
|
||||
"auto_explain.log_min_duration" = 100;
|
||||
|
||||
# logging configuration
|
||||
log_connections = true;
|
||||
log_statement = "all";
|
||||
logging_collector = true;
|
||||
log_disconnections = true;
|
||||
log_destination = lib.mkForce "syslog";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
config = mkIf cfg.database.redis.enable {
|
||||
services.redis = {
|
||||
vmOverCommit = true;
|
||||
servers = mkIf cfg.nextcloud.enable {
|
||||
nextcloud = {
|
||||
enable = true;
|
||||
user = "nextcloud";
|
||||
port = 0;
|
||||
};
|
||||
|
||||
searxng = mkIf cfg.searxng.enable {
|
||||
enable = true;
|
||||
user = "searx";
|
||||
port = 6370;
|
||||
databases = 16;
|
||||
logLevel = "debug";
|
||||
requirePass = "searxng";
|
||||
};
|
||||
|
||||
forgejo = mkIf cfg.forgejo.enable {
|
||||
enable = true;
|
||||
user = "forgejo";
|
||||
port = 6371;
|
||||
databases = 16;
|
||||
logLevel = "debug";
|
||||
requirePass = "forgejo";
|
||||
};
|
||||
|
||||
mastodon = mkIf cfg.social.mastodon.enable {
|
||||
enable = true;
|
||||
user = "mastodon";
|
||||
port = 6372;
|
||||
databases = 16;
|
||||
logLevel = "debug";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
27
nyx/modules/core/roles/server/system/services/default.nix
Normal file
27
nyx/modules/core/roles/server/system/services/default.nix
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
imports = [
|
||||
# essentials
|
||||
./databases # mysql, postgreqsl, redis and more
|
||||
./nginx # base nginx webserver configuration
|
||||
|
||||
# other services
|
||||
./bincache # atticd and harmonia
|
||||
./monitoring # prometheus, grafana, loki and uptime-kuma
|
||||
./networking # wireguard and headscale
|
||||
./social # mastodon and matrix
|
||||
./forgejo.nix # lightweight git service, fork of gitea
|
||||
./forgejo-runner.nix # self-hosted runner for forgejo
|
||||
./nextcloud.nix # cloud storage (not a backup solution)
|
||||
./vaultwarden.nix # bitwarden compatible password manager
|
||||
./mailserver.nix # nixos-mailserver setup
|
||||
./jellyfin.nix # media server
|
||||
./tor.nix # tor relay
|
||||
./searxng.nix # searx search engine
|
||||
./reposilite.nix # self-hosted maven repository
|
||||
./elasticsearch.nix # elasticsearch
|
||||
./kanidm.nix # kanidm identity management
|
||||
|
||||
# misc
|
||||
./mkm.nix # holy fuck
|
||||
];
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
config = mkIf cfg.elasticsearch.enable {
|
||||
services.elasticsearch = {
|
||||
enable = true;
|
||||
single_node = true;
|
||||
cluster_name = "elasticsearch-${config.networking.hostName}";
|
||||
|
||||
extraConf = ''
|
||||
xpack.security.enabled: false
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.modules.system.services;
|
||||
|
||||
# construct each runner using the mkRunner function
|
||||
# you can pass additional configuration options in the instance submodule
|
||||
# it'll be merged to the below configuration
|
||||
mkRunner = {
|
||||
name,
|
||||
settings,
|
||||
}:
|
||||
{
|
||||
enable = true;
|
||||
inherit name;
|
||||
|
||||
url = "https://git.notashelf.dev";
|
||||
|
||||
# NOTE: changing (i.e adding or removing) labels causes your old registration token to expire
|
||||
# make sure your labels are final before deploying
|
||||
labels = [
|
||||
"debian-latest:docker://node:18-bullseye"
|
||||
"ubuntu-latest:docker://node:18-bullseye"
|
||||
"act:docker://ghcr.io/catthehacker/ubuntu:act-latest"
|
||||
#"native:host"
|
||||
];
|
||||
}
|
||||
// settings;
|
||||
in {
|
||||
config = mkIf cfg.forgejo.enable {
|
||||
users = {
|
||||
groups.gitea-runner = {};
|
||||
users.gitea-runner = {
|
||||
isSystemUser = true;
|
||||
createHome = true;
|
||||
home = "/var/lib/gitea-runner";
|
||||
group = "gitea-runner";
|
||||
extraGroups = ["docker"];
|
||||
};
|
||||
};
|
||||
|
||||
services.gitea-actions-runner = {
|
||||
package = pkgs.forgejo-actions-runner;
|
||||
instances = {
|
||||
"runner-01" = mkRunner {
|
||||
name = "runner-01";
|
||||
settings = {
|
||||
tokenFile = config.age.secrets.forgejo-runner-token.path;
|
||||
settings = {
|
||||
capacity = 4;
|
||||
container.network = "host";
|
||||
cache.enabled = true;
|
||||
};
|
||||
|
||||
# packages that'll be made available to the host
|
||||
# when the runner is configured with a host execution label.
|
||||
hostPackages = with pkgs; [
|
||||
bash
|
||||
curl
|
||||
coreutils
|
||||
wget
|
||||
gitMinimal
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
134
nyx/modules/core/roles/server/system/services/forgejo.nix
Normal file
134
nyx/modules/core/roles/server/system/services/forgejo.nix
Normal file
|
@ -0,0 +1,134 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
cfg = config.modules.system.services;
|
||||
domain = "git.notashelf.dev";
|
||||
|
||||
inherit (cfg.forgejo.settings) port;
|
||||
in {
|
||||
config = mkIf cfg.forgejo.enable {
|
||||
modules.system.services = {
|
||||
nginx.enable = true;
|
||||
database = {
|
||||
redis.enable = true;
|
||||
postgresql.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
# make sure the service is reachable from outside
|
||||
config.services.forgejo.settings.server.HTTP_PORT
|
||||
config.services.forgejo.settings.server.SSH_PORT
|
||||
];
|
||||
|
||||
users = {
|
||||
users.git = {
|
||||
isSystemUser = true;
|
||||
createHome = false;
|
||||
group = "git";
|
||||
};
|
||||
|
||||
groups.git = {};
|
||||
};
|
||||
|
||||
services = {
|
||||
forgejo = {
|
||||
enable = true;
|
||||
package = pkgs.forgejo;
|
||||
stateDir = "/srv/storage/forgejo/data";
|
||||
|
||||
mailerPasswordFile = config.age.secrets.mailserver-forgejo-secret.path;
|
||||
lfs.enable = true;
|
||||
|
||||
settings = {
|
||||
default.APP_NAME = "The Secret Shelf";
|
||||
|
||||
actions = {
|
||||
ENABLED = true;
|
||||
DEFAULT_ACTIONS_URL = "https://git.notashelf.dev";
|
||||
};
|
||||
|
||||
other = {
|
||||
SHOW_FOOTER_VERSION = false;
|
||||
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false;
|
||||
};
|
||||
|
||||
session = {
|
||||
COOKIE_SECURE = true;
|
||||
SAME_SITE = "strict";
|
||||
};
|
||||
|
||||
server = {
|
||||
PROTOCOL = "http+unix";
|
||||
HTTP_PORT = port;
|
||||
ROOT_URL = "https://${domain}";
|
||||
DOMAIN = "${domain}";
|
||||
DISABLE_ROUTER_LOG = true;
|
||||
SSH_CREATE_AUTHORIZED_KEYS_FILE = true;
|
||||
LANDING_PAGE = "/explore";
|
||||
|
||||
START_SSH_SERVER = true;
|
||||
SSH_PORT = 2222;
|
||||
SSH_LISTEN_PORT = 2222;
|
||||
};
|
||||
|
||||
database = {
|
||||
DB_TYPE = lib.mkForce "postgres";
|
||||
HOST = "/run/postgresql";
|
||||
NAME = "forgejo";
|
||||
USER = "forgejo";
|
||||
PASSWD = "forgejo";
|
||||
};
|
||||
|
||||
cache = {
|
||||
ENABLED = true;
|
||||
ADAPTER = "redis";
|
||||
HOST = "redis://:forgejo@localhost:6371";
|
||||
};
|
||||
|
||||
mailer = mkIf config.modules.system.services.mailserver.enable {
|
||||
ENABLED = true;
|
||||
PROTOCOL = "smtps";
|
||||
SMTP_ADDR = "mail.notashelf.dev";
|
||||
USER = "git@notashelf.dev";
|
||||
};
|
||||
|
||||
ui.DEFAULT_THEME = "arc-green";
|
||||
attachment.ALLOWED_TYPES = "*/*";
|
||||
service.DISABLE_REGISTRATION = true;
|
||||
packages.ENABLED = false;
|
||||
repository.PREFERRED_LICENSES = "MIT,GPL-3.0,GPL-2.0,LGPL-3.0,LGPL-2.1";
|
||||
log.LEVEL = "Debug";
|
||||
"repository.upload" = {
|
||||
FILE_MAX_SIZE = 100;
|
||||
MAX_FILES = 10;
|
||||
};
|
||||
};
|
||||
|
||||
# backup
|
||||
dump = {
|
||||
enable = true;
|
||||
backupDir = "/srv/storage/forgejo/dump";
|
||||
interval = "06:00";
|
||||
type = "tar.zst";
|
||||
};
|
||||
};
|
||||
|
||||
nginx.virtualHosts."git.notashelf.dev" =
|
||||
{
|
||||
locations."/" = {
|
||||
recommendedProxySettings = true;
|
||||
proxyPass = "http://unix:/run/forgejo/forgejo.sock";
|
||||
};
|
||||
|
||||
quic = true;
|
||||
}
|
||||
// lib.sslTemplate;
|
||||
};
|
||||
};
|
||||
}
|
38
nyx/modules/core/roles/server/system/services/jellyfin.nix
Normal file
38
nyx/modules/core/roles/server/system/services/jellyfin.nix
Normal file
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
config = mkIf cfg.jellyfin.enable {
|
||||
modules.system.services = {
|
||||
nginx.enable = true;
|
||||
};
|
||||
|
||||
services = {
|
||||
jellyfin = {
|
||||
enable = true;
|
||||
group = "jellyfin";
|
||||
user = "jellyfin";
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
nginx.virtualHosts. "fin.notashelf.dev" =
|
||||
{
|
||||
locations."/" = {
|
||||
# TODO: the port is not customizable in the upstream service, PR nixpkgs
|
||||
proxyPass = "http://127.0.0.1:${cfg.jellyfin.settings.port}/";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = "proxy_pass_header Authorization;";
|
||||
};
|
||||
|
||||
quic = true;
|
||||
}
|
||||
// lib.sslTemplate;
|
||||
};
|
||||
};
|
||||
}
|
47
nyx/modules/core/roles/server/system/services/kanidm.nix
Normal file
47
nyx/modules/core/roles/server/system/services/kanidm.nix
Normal file
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
domain = "idm.notashelf.dev";
|
||||
certDir = config.security.acme.certs.${domain}.directory;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
|
||||
inherit (cfg.kanidm.settings) host port;
|
||||
in {
|
||||
config = mkIf cfg.kanidm.enable {
|
||||
services.kanidm = {
|
||||
enableServer = true;
|
||||
serverSettings = {
|
||||
inherit domain;
|
||||
origin = "https://${domain}";
|
||||
bindaddress = "${host}:${toString port}";
|
||||
trust_x_forward_for = true;
|
||||
#tls_chain = "${certDir}/fullchain.pem";
|
||||
#tls_key = "${certDir}/key.pem";
|
||||
online_backup = {
|
||||
path = "/srv/storage/kanidm/backups";
|
||||
schedule = "0 0 * * *"; # Every day at midnight.
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.kanidm = {
|
||||
after = ["acme-selfsigned-internal.${domain}.target"];
|
||||
serviceConfig = {
|
||||
SupplementaryGroups = [config.security.acme.certs.${domain}.group];
|
||||
BindReadOnlyPaths = [certDir];
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts.${domain} = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations."/".proxyPass = "https://${host}:${toString port}";
|
||||
};
|
||||
};
|
||||
}
|
193
nyx/modules/core/roles/server/system/services/mailserver.nix
Normal file
193
nyx/modules/core/roles/server/system/services/mailserver.nix
Normal file
|
@ -0,0 +1,193 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
inherit (config.age) secrets;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
imports = [
|
||||
inputs.simple-nixos-mailserver.nixosModule
|
||||
];
|
||||
|
||||
config = mkIf cfg.mailserver.enable {
|
||||
# required for roundcube
|
||||
networking.firewall.allowedTCPPorts = [80 443];
|
||||
|
||||
mailserver = {
|
||||
enable = true;
|
||||
mailDirectory = "/srv/storage/mail/vmail";
|
||||
dkimKeyDirectory = "/srv/storage/mail/dkim";
|
||||
sieveDirectory = "/srv/storage/mail/sieve";
|
||||
openFirewall = true;
|
||||
enableImap = true;
|
||||
enableImapSsl = true;
|
||||
enablePop3 = false;
|
||||
enablePop3Ssl = false;
|
||||
enableSubmission = false;
|
||||
enableSubmissionSsl = true;
|
||||
hierarchySeparator = "/";
|
||||
localDnsResolver = false;
|
||||
fqdn = "mail.notashelf.dev";
|
||||
certificateScheme = "acme-nginx";
|
||||
domains = ["notashelf.dev"];
|
||||
loginAccounts = {
|
||||
"raf@notashelf.dev" = {
|
||||
hashedPasswordFile = secrets.mailserver-secret.path;
|
||||
aliases = [
|
||||
"me"
|
||||
"raf"
|
||||
"me@notashelf.dev"
|
||||
"admin"
|
||||
"admin@notashelf.dev"
|
||||
"root"
|
||||
"root@notashelf.dev"
|
||||
"postmaster"
|
||||
"postmaster@notashelf.dev"
|
||||
];
|
||||
};
|
||||
|
||||
"noreply@notashelf.dev" = {
|
||||
aliases = ["noreply"];
|
||||
hashedPasswordFile = secrets.mailserver-noreply-secret.path;
|
||||
sendOnly = true;
|
||||
sendOnlyRejectMessage = "";
|
||||
};
|
||||
|
||||
"git@notashelf.dev" = mkIf cfg.forgejo.enable {
|
||||
aliases = ["git" "forgejo"];
|
||||
hashedPasswordFile = secrets.mailserver-forgejo-secret.path;
|
||||
sendOnly = true;
|
||||
sendOnlyRejectMessage = "";
|
||||
};
|
||||
|
||||
"vaultwarden@notashelf.dev" = mkIf cfg.vaultwarden.enable {
|
||||
aliases = ["vaultwarden" "vault"];
|
||||
hashedPasswordFile = secrets.mailserver-vaultwarden-secret.path;
|
||||
sendOnly = true;
|
||||
sendOnlyRejectMessage = "";
|
||||
};
|
||||
|
||||
"matrix@notashelf.dev" = mkIf cfg.social.matrix.enable {
|
||||
aliases = ["matrix"];
|
||||
hashedPasswordFile = secrets.mailserver-matrix-secret.path;
|
||||
sendOnly = true;
|
||||
sendOnlyRejectMessage = "";
|
||||
};
|
||||
|
||||
"cloud@notashelf.dev" = mkIf cfg.nextcloud.enable {
|
||||
aliases = ["cloud" "nextcloud"];
|
||||
hashedPasswordFile = secrets.mailserver-cloud-secret.path;
|
||||
sendOnly = true;
|
||||
sendOnlyRejectMessage = "";
|
||||
};
|
||||
};
|
||||
|
||||
mailboxes = {
|
||||
Archive = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Archive";
|
||||
};
|
||||
Drafts = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Drafts";
|
||||
};
|
||||
Sent = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Sent";
|
||||
};
|
||||
Junk = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Junk";
|
||||
};
|
||||
Trash = {
|
||||
auto = "subscribe";
|
||||
specialUse = "Trash";
|
||||
};
|
||||
};
|
||||
|
||||
fullTextSearch = {
|
||||
enable = true;
|
||||
# index new email as they arrive
|
||||
autoIndex = true;
|
||||
# this only applies to plain text attachments, binary attachments are never indexed
|
||||
indexAttachments = true;
|
||||
enforced = "body";
|
||||
};
|
||||
|
||||
vmailUserName = "vmail";
|
||||
vmailGroupName = "vmail";
|
||||
|
||||
useFsLayout = true;
|
||||
};
|
||||
|
||||
services = {
|
||||
roundcube = {
|
||||
enable = true;
|
||||
database.username = "roundcube";
|
||||
maxAttachmentSize = 50;
|
||||
dicts = with pkgs.aspellDicts; [en tr de];
|
||||
# this is the url of the vhost, not necessarily the same as the fqdn of
|
||||
# the mailserver
|
||||
hostName = "webmail.notashelf.dev";
|
||||
extraConfig = ''
|
||||
$config['imap_host'] = array(
|
||||
'tls://mail.notashelf.dev' => "NotAShelf's Mail Server",
|
||||
'ssl://imap.gmail.com:993' => 'Google Mail',
|
||||
);
|
||||
$config['username_domain'] = array(
|
||||
'mail.notashelf.dev' => 'notashelf.dev',
|
||||
'mail.gmail.com' => 'gmail.com',
|
||||
);
|
||||
$config['x_frame_options'] = false;
|
||||
# starttls needed for authentication, so the fqdn required to match
|
||||
# the certificate
|
||||
$config['smtp_host'] = "tls://${config.mailserver.fqdn}";
|
||||
$config['smtp_user'] = "%u";
|
||||
$config['smtp_pass'] = "%p";
|
||||
$config['plugins'] = [ "carddav" ];
|
||||
'';
|
||||
};
|
||||
|
||||
postfix = {
|
||||
dnsBlacklists = [
|
||||
"all.s5h.net"
|
||||
"b.barracudacentral.org"
|
||||
"bl.spamcop.net"
|
||||
"blacklist.woody.ch"
|
||||
];
|
||||
dnsBlacklistOverrides = ''
|
||||
notashelf.dev OK
|
||||
mail.notashelf.dev OK
|
||||
127.0.0.0/8 OK
|
||||
192.168.0.0/16 OK
|
||||
'';
|
||||
headerChecks = [
|
||||
{
|
||||
action = "IGNORE";
|
||||
pattern = "/^User-Agent.*Roundcube Webmail/";
|
||||
}
|
||||
];
|
||||
|
||||
config = {
|
||||
smtp_helo_name = config.mailserver.fqdn;
|
||||
};
|
||||
};
|
||||
|
||||
phpfpm.pools.roundcube.settings = {
|
||||
"listen.owner" = config.services.nginx.user;
|
||||
"listen.group" = config.services.nginx.group;
|
||||
};
|
||||
|
||||
nginx.virtualHosts = {
|
||||
"mail.notashelf.dev" = {quic = true;} // lib.sslTemplate;
|
||||
"webmail.notashelf.dev" = {quic = true;} // lib.sslTemplate;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
92
nyx/modules/core/roles/server/system/services/miniflux.nix
Normal file
92
nyx/modules/core/roles/server/system/services/miniflux.nix
Normal file
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf getExe';
|
||||
|
||||
dev = config.modules.device;
|
||||
cfg = config.modules.system.services;
|
||||
acceptedTypes = ["server" "hybrid"];
|
||||
in {
|
||||
config = mkIf ((builtins.elem dev.type acceptedTypes) && cfg.miniflux.enable) {
|
||||
# https://github.com/Gerg-L/nixos/blob/master/hosts/gerg-desktop/services/miniflux.nix
|
||||
# miniflux setup courtesy of the funny frog man (he's bald)
|
||||
|
||||
systemd.services = {
|
||||
miniflux = {
|
||||
description = "Miniflux service";
|
||||
wantedBy = ["multi-user.target"];
|
||||
requires = ["miniflux-dbsetup.service"];
|
||||
after = ["network.target" "postgresql.service" "miniflux-dbsetup.service"];
|
||||
script = getExe' pkgs.miniflux "miniflux";
|
||||
|
||||
serviceConfig = {
|
||||
User = "miniflux";
|
||||
RuntimeDirectory = "miniflux";
|
||||
RuntimeDirectoryMode = "0770";
|
||||
EnvironmentFile = config.age.secrets.miniflux-env.path;
|
||||
|
||||
# Hardening
|
||||
CapabilityBoundingSet = [""];
|
||||
DeviceAllow = [""];
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
PrivateDevices = true;
|
||||
PrivateUsers = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
RestrictAddressFamilies = ["AF_INET" "AF_INET6" "AF_UNIX"];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = ["@system-service" "~@privileged"];
|
||||
UMask = "0077";
|
||||
};
|
||||
|
||||
environment = {
|
||||
BASE_URL = "https://flux.notashelf.dev";
|
||||
LISTEN_ADDR = "/run/miniflux/miniflux.sock";
|
||||
DATABASE_URL = "user=miniflux host=/run/postgresql dbname=miniflux";
|
||||
RUN_MIGRATIONS = "1";
|
||||
CREATE_ADMIN = "1";
|
||||
};
|
||||
};
|
||||
miniflux-dbsetup = {
|
||||
description = "Miniflux database setup";
|
||||
requires = ["postgresql.service"];
|
||||
after = ["network.target" "postgresql.service"];
|
||||
script = ''
|
||||
${lib.getExe' config.services.postgresql.package "psql"} "miniflux" -c "CREATE EXTENSION IF NOT EXISTS hstore"
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = config.services.postgresql.superUser;
|
||||
};
|
||||
};
|
||||
};
|
||||
users = {
|
||||
groups.miniflux = {
|
||||
gid = 377;
|
||||
};
|
||||
users = {
|
||||
miniflux = {
|
||||
group = "miniflux";
|
||||
extraGroups = ["postgres"];
|
||||
isSystemUser = true;
|
||||
uid = 377;
|
||||
};
|
||||
${config.services.nginx.user}.extraGroups = ["miniflux"];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
31
nyx/modules/core/roles/server/system/services/mkm.nix
Normal file
31
nyx/modules/core/roles/server/system/services/mkm.nix
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
inputs',
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
cfg = config.modules.system.services;
|
||||
in {
|
||||
config = mkIf cfg.mkm.enable {
|
||||
virtualisation.oci-containers = {
|
||||
backend = "podman";
|
||||
containers = {
|
||||
"mkm-web" = mkIf (config.networking.hostName == "helios") {
|
||||
autoStart = true;
|
||||
environmentFiles = [
|
||||
config.age.secrets.mkm-web.path
|
||||
];
|
||||
ports = [
|
||||
"3005:3005"
|
||||
"3306:3306"
|
||||
];
|
||||
extraOptions = ["--network=host"];
|
||||
|
||||
image = "mkm-web";
|
||||
imageFile = inputs'.mkm.packages.dockerImage;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
imports = [
|
||||
./grafana
|
||||
./prometheus.nix
|
||||
./loki.nix
|
||||
./uptime-kuma.nix
|
||||
];
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
loadDashboard = file:
|
||||
lib.pipe file [
|
||||
lib.importJSON
|
||||
({dashboard, ...}: rec {
|
||||
name = "provision-dashboard-${dashboard.uid}.json";
|
||||
path = builtins.toFile name (builtins.toJSON dashboard);
|
||||
})
|
||||
];
|
||||
|
||||
dashboardsDir =
|
||||
pkgs.linkFarm
|
||||
"grafana-provisioning-dashboards"
|
||||
(map loadDashboard (lib.filesystem.listFilesRecursive ./objects/dashboards));
|
||||
in {
|
||||
services.grafana.provision.dashboards.settings = {
|
||||
providers = lib.singleton {
|
||||
options.path = dashboardsDir;
|
||||
allowUiUpdates = true;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
# imports = [./dashboards.nix];
|
||||
config = mkIf cfg.monitoring.grafana.enable {
|
||||
networking.firewall.allowedTCPPorts = [config.services.grafana.settings.server.http_port];
|
||||
|
||||
modules.system.services.database = {
|
||||
postgresql.enable = true;
|
||||
};
|
||||
|
||||
services = {
|
||||
grafana = {
|
||||
enable = true;
|
||||
settings = {
|
||||
server = {
|
||||
http_addr = "0.0.0.0";
|
||||
http_port = 3000;
|
||||
|
||||
root_url = "https://dash.notashelf.dev";
|
||||
domain = "dash.notashelf.dev";
|
||||
enforce_domain = true;
|
||||
};
|
||||
|
||||
database = {
|
||||
type = "postgres";
|
||||
host = "/run/postgresql";
|
||||
name = "grafana";
|
||||
user = "grafana";
|
||||
ssl_mode = "disable";
|
||||
};
|
||||
|
||||
security = {
|
||||
cookie_secure = true;
|
||||
disable_gravatar = true;
|
||||
};
|
||||
|
||||
analytics = {
|
||||
reporting_enabled = false;
|
||||
check_for_updates = false;
|
||||
};
|
||||
|
||||
"auth.anonymous".enabled = false;
|
||||
"auth.basic".enabled = false;
|
||||
|
||||
users = {
|
||||
allow_signup = false;
|
||||
};
|
||||
};
|
||||
|
||||
provision = {
|
||||
enable = true;
|
||||
datasources.settings = {
|
||||
datasources = [
|
||||
(mkIf sys.services.monitoring.prometheus.enable {
|
||||
name = "Prometheus";
|
||||
type = "prometheus";
|
||||
access = "proxy";
|
||||
orgId = 1;
|
||||
uid = "Y4SSG429DWCGDQ3R";
|
||||
url = "http://127.0.0.1:${toString config.services.prometheus.port}";
|
||||
isDefault = true;
|
||||
version = 1;
|
||||
editable = true;
|
||||
jsonData = {
|
||||
graphiteVersion = "1.1";
|
||||
tlsAuth = false;
|
||||
tlsAuthWithCACert = false;
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf sys.services.monitoring.loki.enable {
|
||||
name = "Loki";
|
||||
type = "loki";
|
||||
access = "proxy";
|
||||
url = "http://127.0.0.1:${toString config.services.loki.configuration.server.http_listen_port}";
|
||||
})
|
||||
|
||||
(mkIf sys.services.database.postgresql.enable {
|
||||
name = "PostgreSQL";
|
||||
type = "postgres";
|
||||
access = "proxy";
|
||||
url = "http://127.0.0.1:9103";
|
||||
})
|
||||
];
|
||||
|
||||
# typos go here
|
||||
deleteDatasources = [
|
||||
{
|
||||
name = "postgres";
|
||||
orgId = 0;
|
||||
}
|
||||
{
|
||||
name = "redis";
|
||||
orgId = 0;
|
||||
}
|
||||
{
|
||||
name = "Endlessh-go";
|
||||
orgId = 0;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nginx.virtualHosts."dash.notashelf.dev" =
|
||||
{
|
||||
locations."/" = {
|
||||
proxyPass = with config.services.grafana.settings.server; "http://${toString http_addr}:${toString http_port}/";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
|
||||
quic = true;
|
||||
}
|
||||
// {
|
||||
addSSL = true;
|
||||
enableACME = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,95 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = config.services.loki;
|
||||
in {
|
||||
config = mkIf sys.services.monitoring.loki.enable {
|
||||
# https://gist.github.com/rickhull/895b0cb38fdd537c1078a858cf15d63e
|
||||
services.loki = {
|
||||
enable = true;
|
||||
dataDir = "/srv/storage/loki";
|
||||
extraFlags = ["--config.expand-env=true"];
|
||||
|
||||
configuration = {
|
||||
auth_enabled = false;
|
||||
|
||||
server = {
|
||||
http_listen_port = 3030;
|
||||
log_level = "warn";
|
||||
};
|
||||
|
||||
ingester = {
|
||||
lifecycler = {
|
||||
address = "127.0.0.1";
|
||||
ring = {
|
||||
kvstore = {
|
||||
store = "inmemory";
|
||||
};
|
||||
replication_factor = 1;
|
||||
};
|
||||
};
|
||||
chunk_idle_period = "1h";
|
||||
max_chunk_age = "1h";
|
||||
chunk_target_size = 999999;
|
||||
chunk_retain_period = "30s";
|
||||
max_transfer_retries = 0;
|
||||
};
|
||||
|
||||
schema_config.configs = [
|
||||
{
|
||||
from = "2022-05-14";
|
||||
store = "boltdb";
|
||||
object_store = "filesystem";
|
||||
schema = "v11";
|
||||
index = {
|
||||
prefix = "index_";
|
||||
period = "168h";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
storage_config = {
|
||||
boltdb.directory = "${cfg.dataDir}/boltdb-index";
|
||||
filesystem.directory = "${cfg.dataDir}/storage-chunks";
|
||||
|
||||
boltdb_shipper = {
|
||||
active_index_directory = "/srv/storage/loki/boltdb-shipper-active";
|
||||
cache_location = "/srv/storage/loki/boltdb-shipper-cache";
|
||||
cache_ttl = "24h";
|
||||
shared_store = "filesystem";
|
||||
};
|
||||
};
|
||||
|
||||
limits_config = {
|
||||
reject_old_samples = true;
|
||||
reject_old_samples_max_age = "168h";
|
||||
};
|
||||
|
||||
chunk_store_config = {
|
||||
max_look_back_period = "0s";
|
||||
};
|
||||
|
||||
table_manager = {
|
||||
retention_deletes_enabled = false;
|
||||
retention_period = "0s";
|
||||
};
|
||||
|
||||
compactor = {
|
||||
shared_store = "filesystem";
|
||||
working_directory = "${cfg.dataDir}/compactor-work";
|
||||
compactor_ring = {
|
||||
kvstore = {
|
||||
store = "inmemory";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
# user, group, dataDir, extraFlags, (configFile)
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
config = mkIf cfg.monitoring.prometheus.enable {
|
||||
services = {
|
||||
# Prometheus exporter for Grafana
|
||||
prometheus = {
|
||||
enable = true;
|
||||
port = 9100;
|
||||
|
||||
# relatively frequent scraping intervals
|
||||
globalConfig = {
|
||||
scrape_interval = "10s";
|
||||
scrape_timeout = "2s";
|
||||
};
|
||||
|
||||
# enabled exporters
|
||||
exporters = {
|
||||
node = {
|
||||
enable = true;
|
||||
port = 9101;
|
||||
enabledCollectors = ["systemd" "processes"];
|
||||
};
|
||||
|
||||
redis = {
|
||||
enable = true;
|
||||
port = 9102;
|
||||
user = "redis";
|
||||
};
|
||||
|
||||
postgres = {
|
||||
enable = true;
|
||||
port = 9103;
|
||||
user = "postgres";
|
||||
};
|
||||
|
||||
nginx = {
|
||||
enable = false;
|
||||
port = 9104;
|
||||
};
|
||||
|
||||
smartctl = {
|
||||
inherit (config.services.smartd) enable;
|
||||
openFirewall = config.services.smartd.enable;
|
||||
# Defaults:
|
||||
user = "smartctl-exporter";
|
||||
group = "disk";
|
||||
port = 9110;
|
||||
};
|
||||
};
|
||||
|
||||
scrapeConfigs = [
|
||||
# internal scrape jobs
|
||||
{
|
||||
job_name = "prometheus";
|
||||
scrape_interval = "30s";
|
||||
static_configs = [{targets = ["localhost:9100"];}];
|
||||
}
|
||||
{
|
||||
job_name = "node";
|
||||
scrape_interval = "30s";
|
||||
static_configs = [{targets = ["localhost:9101"];}];
|
||||
}
|
||||
{
|
||||
job_name = "redis";
|
||||
scrape_interval = "30s";
|
||||
static_configs = [{targets = ["localhost:9102"];}];
|
||||
}
|
||||
{
|
||||
job_name = "postgres";
|
||||
scrape_interval = "30s";
|
||||
static_configs = [{targets = ["localhost:9103"];}];
|
||||
}
|
||||
{
|
||||
job_name = "nginx";
|
||||
scrape_interval = "30s";
|
||||
static_configs = [{targets = ["localhost:9104"];}];
|
||||
}
|
||||
{
|
||||
job_name = "endlessh-go";
|
||||
scrape_interval = "30s";
|
||||
static_configs = [{targets = ["localhost:9105"];}];
|
||||
}
|
||||
|
||||
# TODO: exterenal scrape jobs - over tailscale/wireguard mesh
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
domain = "up.notashelf.dev";
|
||||
in {
|
||||
users = {
|
||||
users.uptime-kuma = {
|
||||
isSystemUser = true;
|
||||
group = "uptime-kuma";
|
||||
};
|
||||
groups.uptime-kuma = {};
|
||||
};
|
||||
|
||||
systemd.services.uptime-kuma = {
|
||||
serviceConfig = {
|
||||
DynamicUser = lib.mkForce false;
|
||||
User = "uptime-kuma";
|
||||
Group = "uptime-kuma";
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
uptime-kuma = {
|
||||
enable = true;
|
||||
settings = {
|
||||
PORT = "4000";
|
||||
};
|
||||
};
|
||||
|
||||
nginx.virtualHosts."${domain}" =
|
||||
{
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString config.services.uptime-kuma.settings.PORT}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
}
|
||||
// lib.sslTemplate;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./wireguard
|
||||
./headscale.nix
|
||||
];
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
{
|
||||
inputs',
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
config = mkIf cfg.networking.headscale.enable {
|
||||
environment.systemPackages = [config.services.headscale.package];
|
||||
networking.firewall.allowedUDPPorts = [8086]; # DERP
|
||||
|
||||
services = {
|
||||
headscale = {
|
||||
enable = true;
|
||||
address = "127.0.0.1";
|
||||
port = 8085;
|
||||
|
||||
settings = {
|
||||
grpc_listen_addr = "127.0.0.1:50443";
|
||||
grpc_allow_insecure = false;
|
||||
|
||||
server_url = "https://hs.notashelf.dev";
|
||||
tls_cert_path = null;
|
||||
tls_key_path = null;
|
||||
|
||||
# default headscale prefix
|
||||
ip_prefixes = [
|
||||
"100.64.0.0/10"
|
||||
"fd7a:115c:a1e0::/48"
|
||||
];
|
||||
|
||||
dns_config = {
|
||||
override_local_dns = true;
|
||||
magic_dns = true;
|
||||
base_domain = "notashelf.dev";
|
||||
domains = [];
|
||||
nameservers = [
|
||||
"9.9.9.9" # no cloudflare, nice
|
||||
];
|
||||
|
||||
/*
|
||||
extra_records = [
|
||||
{
|
||||
name = "idm.notashelf.dev";
|
||||
type = "A";
|
||||
value = "100.64.0.1"; # NOTE: this should be the address of the "host" node - which is the server
|
||||
}
|
||||
];
|
||||
*/
|
||||
};
|
||||
|
||||
acl_policy_path = pkgs.writeText "headscale-acl" (builtins.toJSON {
|
||||
acls = [
|
||||
{
|
||||
# Allow client --> server traffic
|
||||
# but not the other way around.
|
||||
# Servers face the internet, clients
|
||||
# do so far less.
|
||||
action = "accept";
|
||||
proto = "tcp";
|
||||
src = ["tag:client"];
|
||||
dst = ["tag:server:*"];
|
||||
}
|
||||
];
|
||||
|
||||
# Allow all users to SSH into their own devices in check mode.
|
||||
ssh = [
|
||||
{
|
||||
action = "check";
|
||||
src = ["autogroup:member"];
|
||||
dst = ["autogroup:self"];
|
||||
users = ["autogroup:nonroot" "root"];
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
derp = {
|
||||
server = {
|
||||
enabled = true;
|
||||
region_id = 900;
|
||||
region_code = "headscale";
|
||||
region_name = "Headscale Embedded DERP";
|
||||
stun_listen_addr = "0.0.0.0:8344";
|
||||
};
|
||||
|
||||
urls = [];
|
||||
paths = [];
|
||||
|
||||
auto_update_enabled = false;
|
||||
update_frequency = "24h";
|
||||
};
|
||||
|
||||
disable_check_updates = true;
|
||||
ephemeral_node_inactivity_timeout = "30m";
|
||||
node_update_check_interval = "10s";
|
||||
|
||||
/*
|
||||
db_type = "postgres";
|
||||
db_host = "/run/postgresql";
|
||||
db_name = "headscale";
|
||||
db_user = "headscale";
|
||||
db_port = 5432; # not ignored for some reason
|
||||
*/
|
||||
|
||||
metrics_listen_addr = "127.0.0.1:8087";
|
||||
|
||||
log = {
|
||||
format = "text";
|
||||
level = "info";
|
||||
};
|
||||
|
||||
# TODO: logtail
|
||||
logtail = {
|
||||
enabled = false;
|
||||
};
|
||||
|
||||
randomize_client_port = false;
|
||||
};
|
||||
};
|
||||
|
||||
nginx.virtualHosts."hs.notashelf.dev" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://localhost:${toString config.services.headscale.port}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
|
||||
# see <https://github.com/gurucomputing/headscale-ui/blob/master/SECURITY.md> before
|
||||
# possibly using the web frontend
|
||||
"/web" = {
|
||||
root = "${inputs'.nyxpkgs.packages.headscale-ui}/share";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
# TODO: consider enabling postgresql storage
|
||||
# postgresql is normally pretty neat, but unless you expect your setup to receive
|
||||
# very frequent logins, sqlite (default) storage may be more performant
|
||||
# headscale.requires = ["postgresql.service"];
|
||||
|
||||
create-headscale-user = {
|
||||
description = "Create a headscale user and preauth keys for this server";
|
||||
|
||||
wantedBy = ["multi-user.target"];
|
||||
after = ["headscale.service"];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "headscale";
|
||||
};
|
||||
|
||||
path = [pkgs.headscale];
|
||||
script = ''
|
||||
if ! headscale users list | grep notashelf; then
|
||||
headscale users create notashelf
|
||||
headscale --user notashelf preauthkeys create --reusable --expiration 100y > /var/lib/headscale/preauth.key
|
||||
fi
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
imports = [
|
||||
./server.nix
|
||||
];
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
|
||||
dev = config.modules.device;
|
||||
acceptedTypes = ["server" "hybrid"];
|
||||
in {
|
||||
config = mkIf ((builtins.elem dev.type acceptedTypes) && cfg.networking.wireguard.enable) {
|
||||
networking = {
|
||||
nat = {
|
||||
enable = true;
|
||||
externalInterface = "ens3";
|
||||
internalInterfaces = ["wg0"];
|
||||
};
|
||||
|
||||
firewall = {
|
||||
allowedUDPPorts = [51820];
|
||||
trustedInterfaces = ["wg0"];
|
||||
};
|
||||
};
|
||||
|
||||
boot.kernelModules = [
|
||||
"wireguard"
|
||||
];
|
||||
|
||||
# Wireguard Server Peer Setup
|
||||
networking.wireguard = {
|
||||
enable = true;
|
||||
interfaces = {
|
||||
wg0 = {
|
||||
# General settings
|
||||
privateKeyFile = config.age.secrets.wg-server.path;
|
||||
listenPort = 51820;
|
||||
|
||||
# IPs
|
||||
ips = [
|
||||
"10.255.255.10/24" # v4 general
|
||||
"10.255.255.254/24" # v4 adtl
|
||||
"fe80::10/64" # v6 link local
|
||||
"2a01:4f9:c010:2cf9:f::10/80" #v6 general
|
||||
"2a01:4f9:c010:2cf9:f::ffff/80" #v6 adtl
|
||||
];
|
||||
|
||||
# Peers
|
||||
peers = [
|
||||
# enyo
|
||||
{
|
||||
allowedIPs = [
|
||||
"10.255.255.11/32"
|
||||
"fe80::11/128"
|
||||
"2a01:4f9:c010:2cf9:f::11/128"
|
||||
];
|
||||
publicKey = "u5Riuu4NEWEH06qATdnrPO+LacZTspoghqMnoWQ+uEQ=";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
networking = {
|
||||
firewall.allowedUDPPorts = [51820 51821];
|
||||
|
||||
nat.internalInterfaces = ["wg0"];
|
||||
|
||||
wireguard.interfaces = {
|
||||
wg0 = {
|
||||
ips = ["10.0.0.1/24"];
|
||||
listenPort = 51820;
|
||||
privateKeyFile = config.age.secrets.wireguard.path;
|
||||
peers = [
|
||||
{
|
||||
# enyo
|
||||
publicKey = "vv190fxSVr+u7Zv0ujPcwE4aYs0QcbObHwzWGwUNSUA=";
|
||||
allowedIPs = ["10.0.0.2/32"];
|
||||
}
|
||||
/*
|
||||
{
|
||||
# test
|
||||
publicKey = "";
|
||||
allowedIPs = ["10.0.0.3/32"];
|
||||
}
|
||||
*/
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
167
nyx/modules/core/roles/server/system/services/nextcloud.nix
Normal file
167
nyx/modules/core/roles/server/system/services/nextcloud.nix
Normal file
|
@ -0,0 +1,167 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
domain = "cloud.notashelf.dev";
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
config = mkIf cfg.nextcloud.enable {
|
||||
modules.system.services = {
|
||||
nginx.enable = true;
|
||||
database = {
|
||||
redis.enable = true;
|
||||
postgresql.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
nextcloud = {
|
||||
enable = true;
|
||||
package = pkgs.nextcloud28;
|
||||
|
||||
nginx.recommendedHttpHeaders = true;
|
||||
https = true;
|
||||
hostName = domain;
|
||||
|
||||
home = "/srv/storage/nextcloud";
|
||||
maxUploadSize = "4G";
|
||||
enableImagemagick = true;
|
||||
|
||||
extraApps = let
|
||||
inherit (config.services.nextcloud.package.packages) apps;
|
||||
in {
|
||||
# wtf is this formatting
|
||||
inherit (apps) mail polls onlyoffice contacts calendar tasks bookmarks deck forms cookbook impersonate groupfolders;
|
||||
};
|
||||
|
||||
autoUpdateApps = {
|
||||
enable = true;
|
||||
startAt = "03:00";
|
||||
};
|
||||
|
||||
caching = {
|
||||
apcu = true;
|
||||
memcached = true;
|
||||
redis = true;
|
||||
};
|
||||
|
||||
config = {
|
||||
# admin user settings
|
||||
# only effective during setup
|
||||
adminuser = "notashelf";
|
||||
adminpassFile = config.age.secrets.nextcloud-secret.path;
|
||||
|
||||
# database
|
||||
dbtype = "pgsql";
|
||||
dbhost = "/run/postgresql";
|
||||
dbname = "nextcloud";
|
||||
dbuser = "nextcloud";
|
||||
};
|
||||
|
||||
settings = {
|
||||
"memories.exiftool" = "${lib.getExe pkgs.exiftool}";
|
||||
"memories.vod.ffmpeg" = "${pkgs.ffmpeg-headless}/bin/ffmpeg";
|
||||
"memories.vod.ffprobe" = "${pkgs.ffmpeg-headless}/bin/ffprobe";
|
||||
|
||||
# be very specific about the preview providers
|
||||
enabledPreviewProviders = [
|
||||
"OC\\Preview\\BMP"
|
||||
"OC\\Preview\\GIF"
|
||||
"OC\\Preview\\JPEG"
|
||||
"OC\\Preview\\Krita"
|
||||
"OC\\Preview\\MarkDown"
|
||||
"OC\\Preview\\MP3"
|
||||
"OC\\Preview\\OpenDocument"
|
||||
"OC\\Preview\\PNG"
|
||||
"OC\\Preview\\TXT"
|
||||
"OC\\Preview\\XBitmap"
|
||||
"OC\\Preview\\HEIC"
|
||||
];
|
||||
|
||||
# run maintenance jobs at low-load hours
|
||||
# i.e. 01:00am UTC and 05:00am UTC
|
||||
maintenance_window_start = 1;
|
||||
|
||||
# force https
|
||||
overwriteprotocol = "https";
|
||||
trusted_domains = ["https://${toString domain}"];
|
||||
trusted_proxies = ["https://${toString domain}"];
|
||||
|
||||
redis = {
|
||||
host = "/run/redis-default/redis.sock";
|
||||
dbindex = 0;
|
||||
timeout = 3;
|
||||
};
|
||||
|
||||
# other stuff
|
||||
default_phone_region = "TR";
|
||||
lost_password_link = "disabled";
|
||||
};
|
||||
|
||||
phpOptions = {
|
||||
"opcache.enable" = "1";
|
||||
"opcache.enable_cli" = "1";
|
||||
"opcache.jit" = "1255";
|
||||
"opcache.jit_buffer_size" = "256M";
|
||||
"opcache.validate_timestamps" = "0";
|
||||
"opcache.save_comments" = "1";
|
||||
|
||||
# fix the opcache "buffer is almost full" error in admin overview
|
||||
"opcache.interned_strings_buffer" = "16";
|
||||
# try to resolve delays in displaying content or incomplete page rendering
|
||||
"output_buffering" = "off";
|
||||
|
||||
"pm" = "dynamic";
|
||||
"pm.max_children" = "50";
|
||||
"pm.start_servers" = "15";
|
||||
"pm.min_spare_servers" = "15";
|
||||
"pm.max_spare_servers" = "25";
|
||||
"pm.max_requests" = "500";
|
||||
};
|
||||
|
||||
phpExtraExtensions = ext: [ext.redis];
|
||||
};
|
||||
|
||||
nginx.virtualHosts."cloud.notashelf.dev" =
|
||||
{
|
||||
quic = true;
|
||||
http3 = true;
|
||||
}
|
||||
// lib.sslTemplate;
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
phpfpm-nextcloud.aliases = ["nextcloud.service"];
|
||||
"nextcloud-setup" = {
|
||||
requires = ["postgresql.service"];
|
||||
after = ["postgresql.service"];
|
||||
serviceConfig = {
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
"nextcloud-preview" = {
|
||||
description = "Generate previews for all images that haven't been rendered";
|
||||
startAt = "01:00:00";
|
||||
requires = ["nextcloud.service"];
|
||||
after = ["nextcloud.service"];
|
||||
path = [config.services.nextcloud.occ];
|
||||
script = "nextcloud-occ preview:generate";
|
||||
|
||||
serviceConfig = {
|
||||
Restart = "on-failure";
|
||||
RestartSec = "10s";
|
||||
};
|
||||
};
|
||||
*/
|
||||
};
|
||||
};
|
||||
}
|
168
nyx/modules/core/roles/server/system/services/nginx/default.nix
Normal file
168
nyx/modules/core/roles/server/system/services/nginx/default.nix
Normal file
|
@ -0,0 +1,168 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib.modules) mkIf mkDefault;
|
||||
inherit (lib.strings) fileContents;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
|
||||
inherit (config.networking) domain;
|
||||
in {
|
||||
config = mkIf cfg.nginx.enable {
|
||||
security = {
|
||||
acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = "me@notashelf.dev";
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
nginx = {
|
||||
enable = true;
|
||||
package = pkgs.nginxQuic.override {withKTLS = true;};
|
||||
|
||||
# makes /nginx_status endpoint available t o localhost
|
||||
statusPage = true;
|
||||
|
||||
recommendedTlsSettings = true;
|
||||
recommendedBrotliSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedZstdSettings = true;
|
||||
|
||||
clientMaxBodySize = mkDefault "512m";
|
||||
serverNamesHashBucketSize = 1024;
|
||||
appendHttpConfig = ''
|
||||
# set the maximum size of the headers hash tables to 1024 bytes
|
||||
# this applies to the total size of all headers in a client request
|
||||
# or a server response.
|
||||
proxy_headers_hash_max_size 1024;
|
||||
|
||||
# set the bucket size for the headers hash tables to 256 bytes
|
||||
# bucket size determines how many entries can be stored in
|
||||
# each hash table bucket
|
||||
proxy_headers_hash_bucket_size 256;
|
||||
'';
|
||||
|
||||
# lets be more picky on our ciphers and protocols
|
||||
sslCiphers = "EECDH+aRSA+AESGCM:EDH+aRSA:EECDH+aRSA:+AES256:+AES128:+SHA1:!CAMELLIA:!SEED:!3DES:!DES:!RC4:!eNULL";
|
||||
sslProtocols = "TLSv1.3 TLSv1.2";
|
||||
|
||||
commonHttpConfig = ''
|
||||
# map the scheme (HTTP or HTTPS) to the HSTS header for HTTPS
|
||||
# the header includes max-age, includeSubdomains and preload
|
||||
map $scheme $hsts_header {
|
||||
https "max-age=31536000; includeSubdomains; preload";
|
||||
}
|
||||
|
||||
# add the Referrer-Policy header with a value of "no-referrer"
|
||||
# which instructs the browser not to send the 'Referer' header in
|
||||
# subsequent requests
|
||||
add_header "Referrer-Policy" "no-referrer";
|
||||
|
||||
# adds the Strict-Transport-Security header with a value derived from the mapped HSTS header
|
||||
# which instructs the browser to always use HTTPS instead of HTTP
|
||||
add_header Strict-Transport-Security $hsts_header;
|
||||
|
||||
# sets the path for cookies to "/", and adds attributes "secure", "HttpOnly", and "SameSite=strict"
|
||||
# "secure": ensures that the cookie is only sent over HTTPS
|
||||
# "HttpOnly": prevents the cookie from being accessed by JavaScript
|
||||
# "SameSite=strict": restricts the cookie to be sent only in requests originating from the same site
|
||||
proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
|
||||
|
||||
# define a new map that anonymizes the remote address
|
||||
# by replacing the last octet of IPv4 addresses with 0
|
||||
map $remote_addr $remote_addr_anon {
|
||||
~(?P<ip>\d+\.\d+\.\d+)\. $ip.0;
|
||||
~(?P<ip>[^:]+:[^:]+): $ip::;
|
||||
default 0.0.0.0;
|
||||
}
|
||||
|
||||
# define a new log format that anonymizes the remote address
|
||||
# and adds the remote user name, the time, the request line,
|
||||
log_format combined_anon '$remote_addr_anon - $remote_user [$time_local] '
|
||||
'"$request" $status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent"';
|
||||
|
||||
# write the access log to a file with the combined_anon format
|
||||
# and a buffer size of 32k, flushing every 5 minutes
|
||||
access_log /var/log/nginx/access.log combined_anon buffer=32k flush=5m;
|
||||
|
||||
# define a new log format that anonymizes the remote address
|
||||
# and adds remote user name, local time, the request line and http3
|
||||
# this is important for debugging quic enabled requests
|
||||
log_format quic '$remote_addr_anon - $remote_user [$time_local] '
|
||||
'"$request" $status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent" "$http3"';
|
||||
|
||||
# write the access log to a file with the quic format
|
||||
access_log /var/log/nginx/quic-access.log quic;
|
||||
|
||||
# error log should log only "warn" level and above
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
'';
|
||||
|
||||
virtualHosts = {
|
||||
"${domain}" = {
|
||||
default = true;
|
||||
serverAliases = ["www.${domain}"];
|
||||
|
||||
locations = let
|
||||
commonConfig = ''
|
||||
try_files $uri $uri/ =404;
|
||||
|
||||
default_type text/plain;
|
||||
charset utf-8;
|
||||
'';
|
||||
|
||||
# takes a path to a file and returns a
|
||||
# configuration for a location that serves that file
|
||||
mkStaticPage = {
|
||||
name,
|
||||
root,
|
||||
header ? "",
|
||||
footer ? "",
|
||||
}: let
|
||||
builtIndex = pkgs.writeTextDir "${name}" ''
|
||||
${header}
|
||||
${fileContents root}
|
||||
${footer}
|
||||
'';
|
||||
in {
|
||||
index = name;
|
||||
root = builtIndex.outPath;
|
||||
extraConfig = commonConfig;
|
||||
};
|
||||
in {
|
||||
# root location
|
||||
"/" = mkStaticPage {
|
||||
root = ./static/root.txt;
|
||||
name = "root.txt";
|
||||
header = builtins.readFile ./static/header.txt;
|
||||
footer = "> served by ${pkgs.nginx.outPath}";
|
||||
};
|
||||
|
||||
# /gpg endpoint for my gpg key
|
||||
"/gpg" = mkStaticPage {
|
||||
name = "gpg.txt";
|
||||
root = ./static/gpg.txt;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
logrotate.settings.nginx = {
|
||||
enable = true;
|
||||
minsize = "50M";
|
||||
rotate = "4"; # 4 files of 50mb each
|
||||
compress = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
=QQXP
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
|
@ -0,0 +1,5 @@
|
|||
_ _ _ __
|
||||
_ __ ___ | |_ __ _ ___| |__ ___| |/ _|
|
||||
| '_ \ / _ \| __/ _` / __| '_ \ / _ \ | |_
|
||||
| | | | (_) | || (_| \__ \ | | | __/ | _|
|
||||
|_| |_|\___/ \__\__,_|___/_| |_|\___|_|_|.dev
|
|
@ -0,0 +1,90 @@
|
|||
Howdy!
|
||||
|
||||
I'm raf, more commonly known as NotAShelf on most online spaces. This
|
||||
is my personal webpage, which is actually pure plaintext due to my utmosts
|
||||
disdain for modern web technologies.
|
||||
|
||||
Frequently Asked Questions
|
||||
|
||||
***
|
||||
|
||||
Q: What do you do for a living?
|
||||
|
||||
A: I am a professional sailmaker. I design, manufacture and sell sails. I also
|
||||
work as a part-time Political Science instructor for the time being. Sometimes
|
||||
I do digital art, other times I do sailing as a sport.
|
||||
|
||||
***
|
||||
|
||||
Q: Did you study Computer Science? Why do you know programming?
|
||||
|
||||
A: No, I graduated as an International Relations major. I've been teaching
|
||||
myself programming and Linux system administration since 2018. I mostly enjoy
|
||||
open-source software, and my primary stack (as of now) is mostly backend
|
||||
development in Go. Programming is something I enjoy as a tool to help me get
|
||||
from point A to point B, which is why I am interested in learning new
|
||||
technologies as much as I can.
|
||||
|
||||
***
|
||||
|
||||
Q: How are the International Relations?
|
||||
|
||||
A: They're good, thanks for asking.
|
||||
|
||||
***
|
||||
|
||||
Q: What programming languages do you know?
|
||||
|
||||
A: I mostly work with JavaScript, Typescript, Go, C and Nix. I also have some
|
||||
experience with Rust, C++ and Python. There are other languages I've used, but
|
||||
don't really consider noteworthy. I hate PHP. PHP probably hates me back. Good.
|
||||
|
||||
***
|
||||
|
||||
Q: What do you do now?
|
||||
|
||||
A: I am currently working on my PhD in Political Science where I conduct
|
||||
research on the impact of digital technologies on political participation and
|
||||
executive functions as well as the effects of open-source software. on said
|
||||
fields. I would love to go into further detail but I also would like to avoid
|
||||
doxxing myself. Just know that I get the prefix of "Doctor" when I'm done.
|
||||
|
||||
I frequently work with Nix and NixOS, embedded programming and Linux systems
|
||||
in general. I also do some web development in my free time.
|
||||
|
||||
***
|
||||
|
||||
If you want to contact me for any reason, you may just shoot me an email
|
||||
@ raf [at] notashelf [dot] dev. In case you were unable to reach me
|
||||
via email (e.g. your smtp server uses an outdated cipher, or my domain is
|
||||
blacklisted by your provider), you may contact me via Matrix or Mastodon using
|
||||
the links below. I am also on Discord, going by the same handle as my github
|
||||
username. My public gpg key is available at https://notashelf.dev/gpg which
|
||||
is also in plaintext. If you're a bot, you're probably having a field day.
|
||||
|
||||
On that note, please stop scraping my website. I **do not** have anything
|
||||
of your interest.
|
||||
|
||||
***
|
||||
|
||||
List of stuff you might find interesting if you came here and are a human:
|
||||
|
||||
- E-mail | raf [at] notashelf [dot] dev
|
||||
- Matrix | https://matrix.to/#/@raf:notashelf.dev
|
||||
- Mastodon | https://social.notashelf.dev/
|
||||
- Github | https://github.com/notashelf
|
||||
- https://github.com/schizofox/schizofox
|
||||
- https://github.com/hyprland-community/hyprkeys
|
||||
- https://github.com/notashelf/catApi
|
||||
- https://github.com/notashelf/neovim-flake
|
||||
|
||||
|
||||
If you have found a vulnerability on this server, I'd be very grateful if you
|
||||
told me about it. Contact me through any of the ways above.
|
||||
|
||||
***
|
||||
|
||||
I can't have a footer but this is a good place to put a shoutout to the
|
||||
awesome motherfuckingwebsite.com.
|
||||
|
||||
***
|
46
nyx/modules/core/roles/server/system/services/reposilite.nix
Normal file
46
nyx/modules/core/roles/server/system/services/reposilite.nix
Normal file
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
inputs',
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf sslTemplate;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
|
||||
inherit (cfg.reposilite.settings) port;
|
||||
in {
|
||||
config = mkIf sys.services.reposilite.enable {
|
||||
modules.system.services = {
|
||||
nginx.enable = true;
|
||||
};
|
||||
|
||||
services.reposilite = {
|
||||
enable = true;
|
||||
package = inputs'.nyxpkgs.packages.reposilite-bin;
|
||||
dataDir = "/srv/storage/reposilite";
|
||||
|
||||
openFirewall = true;
|
||||
|
||||
user = "reposilite";
|
||||
group = "reposilite";
|
||||
|
||||
settings = {
|
||||
inherit port;
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts = {
|
||||
"repo.notashelf.dev" =
|
||||
{
|
||||
locations."/".proxyPass = "http://127.0.0.1:${toString port}";
|
||||
extraConfig = ''
|
||||
access_log /var/log/nginx/reposilite-access.log;
|
||||
error_log /var/log/nginx/reposilite-error.log;
|
||||
'';
|
||||
}
|
||||
// sslTemplate;
|
||||
};
|
||||
};
|
||||
}
|
146
nyx/modules/core/roles/server/system/services/searxng.nix
Normal file
146
nyx/modules/core/roles/server/system/services/searxng.nix
Normal file
|
@ -0,0 +1,146 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
|
||||
inherit (cfg.searxng.settings) host port;
|
||||
in {
|
||||
config = mkIf cfg.searxng.enable {
|
||||
networking.firewall.allowedTCPPorts = [port];
|
||||
|
||||
modules.system.services = {
|
||||
nginx.enable = true;
|
||||
database.redis.enable = true;
|
||||
};
|
||||
|
||||
users = {
|
||||
users.searx = {
|
||||
isSystemUser = true;
|
||||
createHome = false;
|
||||
group = lib.mkForce "searx-redis";
|
||||
};
|
||||
|
||||
groups.searx-redis = {};
|
||||
};
|
||||
|
||||
services = {
|
||||
searx = {
|
||||
enable = true;
|
||||
package = pkgs.searxng;
|
||||
environmentFile = config.age.secrets.searx-secretkey.path;
|
||||
settings = {
|
||||
use_default_settings = true;
|
||||
|
||||
general = {
|
||||
instance_name = "NotASearx";
|
||||
privacypolicy_url = false;
|
||||
donation_url = "https://ko-fi.com/notashelf";
|
||||
contact_url = "mailto:raf@notashelf.dev";
|
||||
enable_metrics = true;
|
||||
debug = false;
|
||||
};
|
||||
|
||||
search = {
|
||||
safe_search = 0; # 0 = None, 1 = Moderate, 2 = Strict
|
||||
formats = ["html" "json" "rss"];
|
||||
autocomplete = "google"; # "dbpedia", "duckduckgo", "google", "startpage", "swisscows", "qwant", "wikipedia" - leave blank to turn it off by default
|
||||
default_lang = "en";
|
||||
};
|
||||
|
||||
server = {
|
||||
inherit port;
|
||||
method = "GET";
|
||||
secret_key = "@SEARX_SECRET_KEY@"; # set in the environment file
|
||||
limiter = false;
|
||||
image_proxy = false; # no thanks, lol
|
||||
default_http_headers = {
|
||||
X-Content-Type-Options = "nosniff";
|
||||
X-XSS-Protection = "1; mode=block";
|
||||
X-Download-Options = "noopen";
|
||||
X-Robots-Tag = "noindex, nofollow";
|
||||
Referrer-Policy = "no-referrer";
|
||||
};
|
||||
};
|
||||
|
||||
ui = {
|
||||
query_in_title = true;
|
||||
theme_args.simple_style = "dark"; # auto, dark, light
|
||||
results_on_new_tab = false;
|
||||
};
|
||||
|
||||
redis = {
|
||||
url = "unix://searxng:localhost@/run/redis-searxng?db=0";
|
||||
#url = "unix:///run/redis-searxng/redis.sock?db=0";
|
||||
#url = "redis://searxng@localhost:6370/0";
|
||||
};
|
||||
|
||||
outgoing = {
|
||||
request_timeout = 15.0;
|
||||
max_request_timeout = 30.0;
|
||||
};
|
||||
|
||||
engines = [
|
||||
{
|
||||
name = "wikipedia";
|
||||
engine = "wikipedia";
|
||||
shortcut = "w";
|
||||
base_url = "https://wikipedia.org/";
|
||||
}
|
||||
{
|
||||
name = "duckduckgo";
|
||||
engine = "duckduckgo";
|
||||
shortcut = "ddg";
|
||||
}
|
||||
{
|
||||
name = "google";
|
||||
engine = "google";
|
||||
shortcut = "g";
|
||||
use_mobile_ui = false;
|
||||
}
|
||||
{
|
||||
name = "archwiki";
|
||||
engine = "archlinux";
|
||||
shortcut = "aw";
|
||||
}
|
||||
{
|
||||
name = "github";
|
||||
engine = "github";
|
||||
categories = "it";
|
||||
shortcut = "gh";
|
||||
}
|
||||
{
|
||||
name = "nixpkgs";
|
||||
shortcut = "nx";
|
||||
engine = "elasticsearch";
|
||||
categories = "dev,nix";
|
||||
base_url = "https://nixos-search-5886075189.us-east-1.bonsaisearch.net:443";
|
||||
index = "latest-31-nixos-unstable";
|
||||
query_type = "match";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
nginx.virtualHosts."search.notashelf.dev" =
|
||||
{
|
||||
locations."/".proxyPass = "http://${host}:${toString port}";
|
||||
extraConfig = ''
|
||||
access_log /dev/null;
|
||||
error_log /dev/null;
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
'';
|
||||
|
||||
quic = true;
|
||||
}
|
||||
// lib.sslTemplate;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
imports = [
|
||||
./matrix.nix # matrix communication server
|
||||
./mastodon.nix # decentralized social
|
||||
];
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
{
|
||||
inputs',
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services.social;
|
||||
in {
|
||||
config = mkIf cfg.mastodon.enable {
|
||||
modules.system.services = {
|
||||
elasticsearch.enable = true;
|
||||
database = {
|
||||
postgresql.enable = true;
|
||||
redis.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
mastodon = {
|
||||
enable = true;
|
||||
package = inputs'.nyxpkgs.packages.mastodon-bird-ui;
|
||||
|
||||
user = "mastodon";
|
||||
|
||||
configureNginx = false;
|
||||
trustedProxy = "127.0.0.1";
|
||||
localDomain = "social.notashelf.dev";
|
||||
streamingProcesses = 2;
|
||||
|
||||
webPort = 55001;
|
||||
sidekiqPort = 55002;
|
||||
enableUnixSocket = true;
|
||||
sidekiqThreads = 12;
|
||||
|
||||
elasticsearch.host = "127.0.0.1";
|
||||
|
||||
redis = {
|
||||
createLocally = false;
|
||||
host = "localhost";
|
||||
port = 6372;
|
||||
};
|
||||
|
||||
database = {
|
||||
createLocally = true;
|
||||
host = "/run/postgresql";
|
||||
name = "mastodon";
|
||||
user = "mastodon";
|
||||
};
|
||||
|
||||
# configure smtp
|
||||
smtp = {
|
||||
authenticate = true;
|
||||
createLocally = false;
|
||||
fromAddress = "noreply@notashelf.dev";
|
||||
user = "noreply";
|
||||
host = "mail.notashelf.dev";
|
||||
passwordFile = config.age.secrets.mailserver-noreply-secret.path;
|
||||
};
|
||||
|
||||
# extra config
|
||||
extraConfig = {
|
||||
SINGLE_USER_MODE = "true";
|
||||
WEB_DOMAIN = "social.notashelf.dev";
|
||||
AUTHORIZED_FETCH = "true";
|
||||
};
|
||||
};
|
||||
|
||||
# this does what configureNginx option under the mastodon service is supposed to
|
||||
# to be able to fine-grain the service, we move it to its own configuration block
|
||||
# and also, I don't trust nixpkgs maintainers to properly maintain a service - so this is a safety net
|
||||
# in case they break another thing without proper documentation
|
||||
# /rant
|
||||
nginx = {
|
||||
virtualHosts."social.notashelf.dev" =
|
||||
{
|
||||
root = "${config.services.mastodon.package}/public/";
|
||||
quic = true;
|
||||
|
||||
locations = {
|
||||
"/" = {
|
||||
tryFiles = "$uri @proxy";
|
||||
};
|
||||
|
||||
"/system/".alias = "/var/lib/mastodon/public-system/";
|
||||
|
||||
"@proxy" = {
|
||||
proxyPass = "http://unix:/run/mastodon-web/web.socket";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
|
||||
"/api/v1/streaming/" = {
|
||||
proxyPass = "http://unix:/run/mastodon-streaming/streaming.socket";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
// lib.sslTemplate;
|
||||
};
|
||||
};
|
||||
|
||||
users.groups.mastodon.members = [config.services.nginx.user];
|
||||
};
|
||||
}
|
201
nyx/modules/core/roles/server/system/services/social/matrix.nix
Normal file
201
nyx/modules/core/roles/server/system/services/social/matrix.nix
Normal file
|
@ -0,0 +1,201 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services.social;
|
||||
|
||||
inherit (cfg.matrix.settings) port;
|
||||
bindAddress = "::1";
|
||||
serverConfig."m.server" = "${config.services.matrix-synapse.settings.server_name}:443";
|
||||
clientConfig = {
|
||||
"m.homeserver".base_url = "https://${config.networking.domain}";
|
||||
"m.identity_server" = {};
|
||||
};
|
||||
|
||||
mkWellKnown = data: ''
|
||||
add_header Content-Type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
add_header 'Referrer-Policy' 'origin-when-cross-origin';
|
||||
add_header X-Frame-Options DENY;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
return 200 '${builtins.toJSON data}';
|
||||
'';
|
||||
in {
|
||||
config = mkIf cfg.matrix.enable {
|
||||
networking.firewall.allowedTCPPorts = [port];
|
||||
|
||||
modules.system.services.database = {
|
||||
postgresql.enable = true;
|
||||
};
|
||||
|
||||
services = {
|
||||
postgresql = {
|
||||
initialScript = pkgs.writeText "synapse-init.sql" ''
|
||||
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
|
||||
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
|
||||
TEMPLATE template0
|
||||
LC_COLLATE = "C"
|
||||
LC_CTYPE = "C";
|
||||
'';
|
||||
};
|
||||
|
||||
nginx.virtualHosts = {
|
||||
"notashelf.dev" =
|
||||
{
|
||||
serverAliases = ["matrix.notashelf.dev"];
|
||||
locations = {
|
||||
"= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig;
|
||||
"= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig;
|
||||
"/_matrix".proxyPass = "http://[${bindAddress}]:${toString port}";
|
||||
"/_synapse/client".proxyPass = "http://[${bindAddress}]:${toString port}";
|
||||
};
|
||||
|
||||
quic = true;
|
||||
http3 = true;
|
||||
}
|
||||
// lib.sslTemplate;
|
||||
};
|
||||
|
||||
matrix-synapse = {
|
||||
enable = true;
|
||||
|
||||
extraConfigFiles = [config.age.secrets.matrix-secret.path];
|
||||
settings = {
|
||||
server_name = "notashelf.dev";
|
||||
public_baseurl = "https://notashelf.dev";
|
||||
|
||||
withJemalloc = true;
|
||||
enable_registration = true;
|
||||
registration_requires_token = true;
|
||||
|
||||
bcrypt_rounds = 14;
|
||||
|
||||
# Don't report anonymized usage statistics
|
||||
report_stats = false;
|
||||
|
||||
# db
|
||||
database = {
|
||||
name = "psycopg2";
|
||||
args = {
|
||||
host = "/run/postgresql";
|
||||
user = "matrix-synapse";
|
||||
database = "matrix-synapse";
|
||||
cp_min = 5;
|
||||
cp_max = 10;
|
||||
};
|
||||
};
|
||||
|
||||
# media
|
||||
media_retention.remote_media_lifetime = "30d";
|
||||
max_upload_size = "100M";
|
||||
url_preview_enabled = true;
|
||||
url_preview_ip_range_blacklist = [
|
||||
"127.0.0.0/8"
|
||||
"10.0.0.0/8"
|
||||
"172.16.0.0/12"
|
||||
"192.168.0.0/16"
|
||||
"100.64.0.0/10"
|
||||
"192.0.0.0/24"
|
||||
"169.254.0.0/16"
|
||||
"192.88.99.0/24"
|
||||
"198.18.0.0/15"
|
||||
"192.0.2.0/24"
|
||||
"198.51.100.0/24"
|
||||
"203.0.113.0/24"
|
||||
"224.0.0.0/4"
|
||||
"::1/128"
|
||||
"fe80::/10"
|
||||
"fc00::/7"
|
||||
"2001:db8::/32"
|
||||
"ff00::/8"
|
||||
"fec0::/10"
|
||||
];
|
||||
|
||||
thumbnail_sizes = [
|
||||
{
|
||||
width = 32;
|
||||
height = 32;
|
||||
method = "crop";
|
||||
}
|
||||
{
|
||||
width = 96;
|
||||
height = 96;
|
||||
method = "crop";
|
||||
}
|
||||
{
|
||||
width = 320;
|
||||
height = 240;
|
||||
method = "scale";
|
||||
}
|
||||
{
|
||||
width = 640;
|
||||
height = 480;
|
||||
method = "scale";
|
||||
}
|
||||
{
|
||||
width = 800;
|
||||
height = 600;
|
||||
method = "scale";
|
||||
}
|
||||
];
|
||||
|
||||
# listener configuration
|
||||
listeners = [
|
||||
{
|
||||
inherit port;
|
||||
bind_addresses = ["${bindAddress}"];
|
||||
resources = [
|
||||
{
|
||||
names = ["client" "federation"];
|
||||
compress = true;
|
||||
}
|
||||
];
|
||||
tls = false;
|
||||
type = "http";
|
||||
x_forwarded = true;
|
||||
}
|
||||
];
|
||||
|
||||
experimental_features = {
|
||||
msc3202_device_masquerading = true;
|
||||
msc3202_transaction_extensions = true;
|
||||
msc2409_to_device_messages_enabled = true;
|
||||
};
|
||||
|
||||
logConfig = ''
|
||||
version: 1
|
||||
|
||||
# In systemd's journal, loglevel is implicitly stored, so let's omit it
|
||||
# from the message text.
|
||||
formatters:
|
||||
journal_fmt:
|
||||
format: '%(name)s: [%(request)s] %(message)s'
|
||||
|
||||
filters:
|
||||
context:
|
||||
(): synapse.util.logcontext.LoggingContextFilter
|
||||
request: ""
|
||||
|
||||
handlers:
|
||||
journal:
|
||||
class: systemd.journal.JournalHandler
|
||||
formatter: journal_fmt
|
||||
filters: [context]
|
||||
SYSLOG_IDENTIFIER: synapse
|
||||
|
||||
root:
|
||||
level: WARNING
|
||||
handlers: [journal]
|
||||
|
||||
disable_existing_loggers: False
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
35
nyx/modules/core/roles/server/system/services/tor.nix
Normal file
35
nyx/modules/core/roles/server/system/services/tor.nix
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit (lib) mkIf;
|
||||
|
||||
sys = config.modules.system;
|
||||
cfg = sys.services;
|
||||
in {
|
||||
config = mkIf cfg.tor.enable {
|
||||
services = {
|
||||
tor = {
|
||||
settings = {
|
||||
AutomapHostsOnResolve = true;
|
||||
AutomapHostsSuffixes = [".exit" ".onion"];
|
||||
EnforceDistinctSubnets = true;
|
||||
ExitNodes = "{de}";
|
||||
EntryNodes = "{de}";
|
||||
NewCircuitPeriod = 120;
|
||||
DNSPort = 9053;
|
||||
BandWidthRate = "15 MBytes";
|
||||
};
|
||||
|
||||
relay.onionServices = {
|
||||
# hide ssh from script kiddies
|
||||
ssh = {
|
||||
version = 3;
|
||||
map = [{port = builtins.elemAt config.services.openssh.ports 0;}];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue