11 Commits

Author SHA1 Message Date
d85e4b1593 fix: caddy denylist and jellyfin prometheus 2023-07-16 21:04:07 +00:00
6ea99eca5d enable caddy prometheus metrics 2023-07-16 20:13:41 +00:00
60e779085e add victoriametrics to tempest 2023-07-16 10:43:55 -04:00
6abcdfa3bd switch flame to victoriametrics 2023-07-16 14:43:14 +00:00
0f0a64b5c4 add victoriametrics 2023-07-16 13:50:58 +00:00
edb4ec77ca set caddy prometheus port dynamically 2023-07-16 03:34:03 +00:00
3cc264a857 fix: register gitea runner 2023-07-16 03:33:35 +00:00
76a7480a1d working prometheus setup with processes 2023-07-16 01:04:52 +00:00
9d4bf082c7 fix: prometheus remote write 2023-07-14 02:52:23 +00:00
e86b2f184f fix: cloudflare tunnel on tempest
requires openssh, but removing public key
2023-07-12 23:33:35 -04:00
d14054ab17 update to nextcloud 27 2023-07-13 03:22:45 +00:00
21 changed files with 409 additions and 171 deletions

View File

@ -110,20 +110,10 @@
}; };
outputs = { self, nixpkgs, ... }@inputs: outputs = { nixpkgs, ... }@inputs:
let let
# Common overlays to always use
overlays = [
inputs.nur.overlay
inputs.nix2vim.overlay
(import ./overlays/neovim-plugins.nix inputs)
(import ./overlays/calibre-web.nix)
(import ./overlays/disko.nix inputs)
(import ./overlays/tree-sitter.nix inputs)
];
# Global configuration for my systems # Global configuration for my systems
globals = let baseName = "masu.rs"; globals = let baseName = "masu.rs";
in rec { in rec {
@ -135,7 +125,6 @@
mail.imapHost = "imap.purelymail.com"; mail.imapHost = "imap.purelymail.com";
mail.smtpHost = "smtp.purelymail.com"; mail.smtpHost = "smtp.purelymail.com";
dotfilesRepo = "git@github.com:nmasur/dotfiles"; dotfilesRepo = "git@github.com:nmasur/dotfiles";
nixpkgs.overlays = overlays;
hostnames = { hostnames = {
git = "git.${baseName}"; git = "git.${baseName}";
metrics = "metrics.${baseName}"; metrics = "metrics.${baseName}";
@ -148,6 +137,16 @@
}; };
}; };
# Common overlays to always use
overlays = [
inputs.nur.overlay
inputs.nix2vim.overlay
(import ./overlays/neovim-plugins.nix inputs)
(import ./overlays/calibre-web.nix)
(import ./overlays/disko.nix inputs)
(import ./overlays/tree-sitter.nix inputs)
];
# System types to support. # System types to support.
supportedSystems = supportedSystems =
[ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ];
@ -157,26 +156,20 @@
in rec { in rec {
nixosModules = {
globals = { config }: { config = globals; };
common = import ./modules/common;
nixos = import ./modules/nixos;
darwin = import ./modules/darwin;
};
# Contains my full system builds, including home-manager # Contains my full system builds, including home-manager
# nixos-rebuild switch --flake .#tempest # nixos-rebuild switch --flake .#tempest
nixosConfigurations = { nixosConfigurations = {
tempest = import ./hosts/tempest { inherit self; }; tempest = import ./hosts/tempest { inherit inputs globals overlays; };
hydra = import ./hosts/hydra { inherit self; }; hydra = import ./hosts/hydra { inherit inputs globals overlays; };
flame = import ./hosts/flame { inherit self; }; flame = import ./hosts/flame { inherit inputs globals overlays; };
swan = import ./hosts/swan { inherit self; }; swan = import ./hosts/swan { inherit inputs globals overlays; };
}; };
# Contains my full Mac system builds, including home-manager # Contains my full Mac system builds, including home-manager
# darwin-rebuild switch --flake .#lookingglass # darwin-rebuild switch --flake .#lookingglass
darwinConfigurations = { darwinConfigurations = {
lookingglass = import ./hosts/lookingglass { inherit self; }; lookingglass =
import ./hosts/lookingglass { inherit inputs globals overlays; };
}; };
# For quickly applying home-manager settings with: # For quickly applying home-manager settings with:
@ -192,8 +185,10 @@
diskoConfigurations = { root = import ./disks/root.nix; }; diskoConfigurations = { root = import ./disks/root.nix; };
packages = let packages = let
aws = system: import ./hosts/aws { inherit self system; }; aws = system:
staff = system: import ./hosts/staff { inherit self system; }; import ./hosts/aws { inherit inputs globals overlays system; };
staff = system:
import ./hosts/staff { inherit inputs globals overlays system; };
neovim = system: neovim = system:
let pkgs = import nixpkgs { inherit system overlays; }; let pkgs = import nixpkgs { inherit system overlays; };
in import ./modules/common/neovim/package { in import ./modules/common/neovim/package {

View File

@ -1,14 +1,17 @@
{ self, system, ... }: { inputs, system, globals, overlays, ... }:
self.inputs.nixos-generators.nixosGenerate { inputs.nixos-generators.nixosGenerate {
inherit system; inherit system;
format = "amazon"; format = "amazon";
modules = [ modules = [
self.inputs.home-manager.nixosModules.home-manager inputs.home-manager.nixosModules.home-manager
self.nixosModules.globals
self.nixosModules.common
self.nixosModules.nixos
{ {
nixpkgs.overlays = overlays;
user = globals.user;
fullName = globals.fullName;
dotfilesRepo = globals.dotfilesRepo;
gitName = globals.gitName;
gitEmail = globals.gitEmail;
networking.hostName = "sheep"; networking.hostName = "sheep";
gui.enable = false; gui.enable = false;
theme.colors = (import ../../colorscheme/gruvbox).dark; theme.colors = (import ../../colorscheme/gruvbox).dark;
@ -18,6 +21,9 @@ self.inputs.nixos-generators.nixosGenerate {
# AWS settings require this # AWS settings require this
permitRootLogin = "prohibit-password"; permitRootLogin = "prohibit-password";
} }
../../modules/common
../../modules/nixos
../../modules/nixos/services/sshd.nix
] ++ [ ] ++ [
# Required to fix diskSize errors during build # Required to fix diskSize errors during build
({ ... }: { amazonImage.sizeMB = 16 * 1024; }) ({ ... }: { amazonImage.sizeMB = 16 * 1024; })

View File

@ -4,23 +4,24 @@
# How to install: # How to install:
# https://blog.korfuri.fr/posts/2022/08/nixos-on-an-oracle-free-tier-ampere-machine/ # https://blog.korfuri.fr/posts/2022/08/nixos-on-an-oracle-free-tier-ampere-machine/
{ self, ... }: { inputs, globals, overlays, ... }:
self.inputs.nixpkgs.lib.nixosSystem { inputs.nixpkgs.lib.nixosSystem {
system = "aarch64-linux"; system = "aarch64-linux";
specialArgs = { }; specialArgs = { };
modules = [ modules = [
self.inputs.home-manager.nixosModules.home-manager globals
self.nixosModules.globals inputs.home-manager.nixosModules.home-manager
self.nixosModules.common ../../modules/common
self.nixosModules.nixos ../../modules/nixos
{ {
nixpkgs.overlays = overlays;
# Hardware # Hardware
server = true; server = true;
networking.hostName = "flame"; networking.hostName = "flame";
imports = imports = [ (inputs.nixpkgs + "/nixos/modules/profiles/qemu-guest.nix") ];
[ (self.inputs.nixpkgs + "/nixos/modules/profiles/qemu-guest.nix") ];
boot.initrd.availableKernelModules = [ "xhci_pci" "virtio_pci" "usbhid" ]; boot.initrd.availableKernelModules = [ "xhci_pci" "virtio_pci" "usbhid" ];
fileSystems."/" = { fileSystems."/" = {
@ -48,7 +49,8 @@ self.inputs.nixpkgs.lib.nixosSystem {
services.caddy.enable = true; services.caddy.enable = true;
services.grafana.enable = true; services.grafana.enable = true;
services.prometheus.enable = true; services.openssh.enable = true;
services.victoriametrics.enable = true;
services.gitea.enable = true; services.gitea.enable = true;
services.vaultwarden.enable = true; services.vaultwarden.enable = true;
services.minecraft-server.enable = true; # Setup Minecraft server services.minecraft-server.enable = true; # Setup Minecraft server
@ -70,6 +72,9 @@ self.inputs.nixpkgs.lib.nixosSystem {
accessKeyId = "0026b0e73b2e2c80000000005"; accessKeyId = "0026b0e73b2e2c80000000005";
}; };
# # Grant access to Jellyfin directories from Nextcloud
# users.users.nextcloud.extraGroups = [ "jellyfin" ];
# # Wireguard config for Transmission # # Wireguard config for Transmission
# wireguard.enable = true; # wireguard.enable = true;
# networking.wireguard.interfaces.wg0 = { # networking.wireguard.interfaces.wg0 = {

View File

@ -1,20 +1,21 @@
# The Hydra # The Hydra
# System configuration for WSL # System configuration for WSL
{ self, ... }: { inputs, globals, overlays, ... }:
self.inputs.nixpkgs.lib.nixosSystem { inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = { }; specialArgs = { };
modules = [ modules = [
self.inputs.wsl.nixosModules.wsl ../../modules/common
self.inputs.home-manager.nixosModules.home-manager ../../modules/nixos
self.nixosModules.globals ../../modules/wsl
self.nixosModules.common globals
self.nixosModules.nixos inputs.wsl.nixosModules.wsl
self.nixosModules.wsl inputs.home-manager.nixosModules.home-manager
{ {
networking.hostName = "hydra"; networking.hostName = "hydra";
nixpkgs.overlays = overlays;
identityFile = "/home/${globals.user}/.ssh/id_ed25519"; identityFile = "/home/${globals.user}/.ssh/id_ed25519";
gui.enable = false; gui.enable = false;
theme = { theme = {

View File

@ -1,46 +1,46 @@
# The Looking Glass # The Looking Glass
# System configuration for my work Macbook # System configuration for my work Macbook
{ self, ... }: { inputs, globals, overlays, ... }:
self.inputs.darwin.lib.darwinSystem { inputs.darwin.lib.darwinSystem {
system = "x86_64-darwin"; system = "x86_64-darwin";
specialArgs = { }; specialArgs = { };
modules = [ modules = [
self.inputs.home-manager.darwinModules.home-manager ../../modules/common
self.nixosModules.common ../../modules/darwin
self.nixosModules.darwin (globals // rec {
({ config, lib, ... }: { user = "Noah.Masur";
config = rec { gitName = "Noah-Masur_1701";
user = lib.mkForce "Noah.Masur"; gitEmail = "${user}@take2games.com";
gitName = lib.mkForce "Noah-Masur_1701";
gitEmail = lib.mkForce "${user}@take2games.com";
nixpkgs.overlays = [ self.inputs.firefox-darwin.overlay ];
networking.hostName = "lookingglass";
identityFile = "/Users/${user}/.ssh/id_ed25519";
gui.enable = true;
theme = {
colors = (import ../../colorscheme/gruvbox-dark).dark;
dark = true;
};
mail.user = globals.user;
charm.enable = true;
neovim.enable = true;
mail.enable = true;
mail.aerc.enable = true;
mail.himalaya.enable = false;
kitty.enable = true;
discord.enable = true;
firefox.enable = true;
dotfiles.enable = true;
nixlang.enable = true;
terraform.enable = true;
python.enable = true;
lua.enable = true;
kubernetes.enable = true;
_1password.enable = true;
slack.enable = true;
};
}) })
inputs.home-manager.darwinModules.home-manager
{
nixpkgs.overlays = [ inputs.firefox-darwin.overlay ] ++ overlays;
networking.hostName = "lookingglass";
identityFile = "/Users/Noah.Masur/.ssh/id_ed25519";
gui.enable = true;
theme = {
colors = (import ../../colorscheme/gruvbox-dark).dark;
dark = true;
};
mail.user = globals.user;
charm.enable = true;
neovim.enable = true;
mail.enable = true;
mail.aerc.enable = true;
mail.himalaya.enable = false;
kitty.enable = true;
discord.enable = true;
firefox.enable = true;
dotfiles.enable = true;
nixlang.enable = true;
terraform.enable = true;
python.enable = true;
lua.enable = true;
kubernetes.enable = true;
_1password.enable = true;
slack.enable = true;
}
]; ];
} }

View File

@ -1,32 +1,31 @@
# The Staff # The Staff
# ISO configuration for my USB drive # ISO configuration for my USB drive
{ self, system, ... }: { inputs, system, overlays, ... }:
self.inputs.nixos-generators.nixosGenerate { inputs.nixos-generators.nixosGenerate {
inherit system; inherit system;
format = "install-iso"; format = "install-iso";
modules = [ modules = [{
self.nixosModules.global nixpkgs.overlays = overlays;
self.nixosModules.common networking.hostName = "staff";
self.nixosModules.nixos users.extraUsers.root.openssh.authorizedKeys.keys = [
({ config, pkgs, ... }: { "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+AbmjGEwITk5CK9y7+Rg27Fokgj9QEjgc9wST6MA3s"
networking.hostName = "staff"; ];
users.extraUsers.root.openssh.authorizedKeys.keys = [ services.openssh = {
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+AbmjGEwITk5CK9y7+Rg27Fokgj9QEjgc9wST6MA3s" enable = true;
]; ports = [ 22 ];
services.openssh = { allowSFTP = true;
enable = true; settings = {
ports = [ 22 ]; GatewayPorts = "no";
allowSFTP = true; X11Forwarding = false;
settings = { PasswordAuthentication = false;
GatewayPorts = "no"; PermitRootLogin = "yes";
X11Forwarding = false;
PasswordAuthentication = false;
PermitRootLogin = "yes";
};
}; };
environment.systemPackages = with pkgs; [ };
environment.systemPackages =
let pkgs = import inputs.nixpkgs { inherit system overlays; };
in with pkgs; [
git git
vim vim
wget wget
@ -36,10 +35,9 @@ self.inputs.nixos-generators.nixosGenerate {
colors = (import ../../colorscheme/gruvbox).dark; colors = (import ../../colorscheme/gruvbox).dark;
}) })
]; ];
nix.extraOptions = '' nix.extraOptions = ''
experimental-features = nix-command flakes experimental-features = nix-command flakes
warn-dirty = false warn-dirty = false
''; '';
}) }];
];
} }

View File

@ -1,17 +1,17 @@
# The Swan # The Swan
# System configuration for my home NAS server # System configuration for my home NAS server
{ self, ... }: { inputs, globals, overlays, ... }:
self.inputs.nixpkgs.lib.nixosSystem { inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = { }; specialArgs = { };
modules = [ modules = [
self.inputs.home-manager.nixosModules.home-manager globals
self.inputs.disko.nixosModules.disko inputs.home-manager.nixosModules.home-manager
self.nixosModules.globals inputs.disko.nixosModules.disko
self.nixosModules.common ../../modules/common
self.nixosModules.nixos ../../modules/nixos
{ {
# Hardware # Hardware
server = true; server = true;
@ -46,6 +46,7 @@ self.inputs.nixpkgs.lib.nixosSystem {
gui.enable = false; gui.enable = false;
theme = { colors = (import ../../colorscheme/gruvbox).dark; }; theme = { colors = (import ../../colorscheme/gruvbox).dark; };
nixpkgs.overlays = overlays;
neovim.enable = true; neovim.enable = true;
cloudflare.enable = true; cloudflare.enable = true;
dotfiles.enable = true; dotfiles.enable = true;
@ -55,7 +56,9 @@ self.inputs.nixpkgs.lib.nixosSystem {
services.jellyfin.enable = true; services.jellyfin.enable = true;
services.nextcloud.enable = true; services.nextcloud.enable = true;
services.calibre-web.enable = true; services.calibre-web.enable = true;
services.prometheus.enable = true; services.openssh.enable = true;
services.prometheus.enable = false;
services.vmagent.enable = true;
services.samba.enable = true; services.samba.enable = true;
cloudflareTunnel = { cloudflareTunnel = {

View File

@ -1,16 +1,18 @@
# The Tempest # The Tempest
# System configuration for my desktop # System configuration for my desktop
{ self, ... }: { inputs, globals, overlays, ... }:
self.inputs.nixpkgs.lib.nixosSystem { inputs.nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
modules = [ modules = [
self.inputs.home-manager.nixosModules.home-manager globals
self.nixosModules.globals inputs.home-manager.nixosModules.home-manager
self.nixosModules.common ../../modules/common
self.nixosModules.nixos ../../modules/nixos
{ {
nixpkgs.overlays = overlays;
# Hardware # Hardware
physical = true; physical = true;
networking.hostName = "tempest"; networking.hostName = "tempest";
@ -51,7 +53,7 @@ self.inputs.nixpkgs.lib.nixosSystem {
# Must be prepared ahead # Must be prepared ahead
identityFile = "/home/${globals.user}/.ssh/id_ed25519"; identityFile = "/home/${globals.user}/.ssh/id_ed25519";
passwordHash = self.inputs.nixpkgs.lib.fileContents ../../password.sha512; passwordHash = inputs.nixpkgs.lib.fileContents ../../password.sha512;
# Theming # Theming
gui.enable = true; gui.enable = true;
@ -59,8 +61,8 @@ self.inputs.nixpkgs.lib.nixosSystem {
colors = (import ../../colorscheme/gruvbox-dark).dark; colors = (import ../../colorscheme/gruvbox-dark).dark;
dark = true; dark = true;
}; };
wallpaper = "${self.inputs.wallpapers}/gruvbox/road.jpg"; wallpaper = "${inputs.wallpapers}/gruvbox/road.jpg";
gtk.theme.name = self.inputs.nixpkgs.lib.mkDefault "Adwaita-dark"; gtk.theme.name = inputs.nixpkgs.lib.mkDefault "Adwaita-dark";
# Programs and services # Programs and services
charm.enable = true; charm.enable = true;
@ -89,7 +91,9 @@ self.inputs.nixpkgs.lib.nixosSystem {
leagueoflegends.enable = true; leagueoflegends.enable = true;
ryujinx.enable = true; ryujinx.enable = true;
}; };
services.vmagent.enable = true;
services.openssh.enable = true; # Required for Cloudflare tunnel
cloudflareTunnel = { cloudflareTunnel = {
enable = true; enable = true;
id = "ac133a82-31fb-480c-942a-cdbcd4c58173"; id = "ac133a82-31fb-480c-942a-cdbcd4c58173";

View File

@ -10,6 +10,13 @@
config.boot.zfs.package.latestCompatibleLinuxPackages; config.boot.zfs.package.latestCompatibleLinuxPackages;
boot.kernelParams = [ "nohibernate" ]; boot.kernelParams = [ "nohibernate" ];
boot.supportedFilesystems = [ "zfs" ]; boot.supportedFilesystems = [ "zfs" ];
services.prometheus.exporters.zfs.enable =
config.prometheus.exporters.enable;
prometheus.scrapeTargets = [
"127.0.0.1:${
builtins.toString config.services.prometheus.exporters.zfs.port
}"
];
}; };

View File

@ -30,6 +30,7 @@
errors.routes = config.caddy.blocks; errors.routes = config.caddy.blocks;
# logs = { }; # Uncomment to collect access logs # logs = { }; # Uncomment to collect access logs
}; };
apps.http.servers.metrics = { }; # Enables Prometheus metrics
apps.tls.automation.policies = config.caddy.tlsPolicies; apps.tls.automation.policies = config.caddy.tlsPolicies;
logging.logs.main = { logging.logs.main = {
encoder = { format = "console"; }; encoder = { format = "console"; };
@ -47,6 +48,8 @@
networking.firewall.allowedTCPPorts = [ 80 443 ]; networking.firewall.allowedTCPPorts = [ 80 443 ];
networking.firewall.allowedUDPPorts = [ 443 ]; networking.firewall.allowedUDPPorts = [ 443 ];
prometheus.scrapeTargets = [ "127.0.0.1:2019" ];
}; };
} }

View File

@ -41,11 +41,11 @@ in {
config = lib.mkIf config.cloudflare.enable { config = lib.mkIf config.cloudflare.enable {
# Forces Caddy to error if coming from a non-Cloudflare IP # Forces Caddy to error if coming from a non-Cloudflare IP
caddy.blocks = [{ caddy.routes = [{
match = [{ not = [{ remote_ip.ranges = cloudflareIpRanges; }]; }]; match = [{ not = [{ remote_ip.ranges = cloudflareIpRanges; }]; }];
handle = [{ handle = [{
handler = "static_response"; handler = "static_response";
abort = true; status_code = "403";
}]; }];
}]; }];

View File

@ -24,6 +24,7 @@
./sshd.nix ./sshd.nix
./transmission.nix ./transmission.nix
./vaultwarden.nix ./vaultwarden.nix
./victoriametrics.nix
./wireguard.nix ./wireguard.nix
]; ];

View File

@ -10,9 +10,9 @@
enable = true; enable = true;
labels = [ labels = [
# Provide a Debian base with NodeJS for actions # Provide a Debian base with NodeJS for actions
"debian-latest:docker://node:18-bullseye" # "debian-latest:docker://node:18-bullseye"
# Fake the Ubuntu name, because Node provides no Ubuntu builds # Fake the Ubuntu name, because Node provides no Ubuntu builds
"ubuntu-latest:docker://node:18-bullseye" # "ubuntu-latest:docker://node:18-bullseye"
# Provide native execution on the host using below packages # Provide native execution on the host using below packages
"native:host" "native:host"
]; ];
@ -31,6 +31,23 @@
tokenFile = config.secrets.giteaRunnerToken.dest; tokenFile = config.secrets.giteaRunnerToken.dest;
}; };
secrets.giteaRunnerToken = {
source = ../../../private/gitea-runner-token.age; # TOKEN=xyz
dest = "${config.secretsDirectory}/gitea-runner-token";
};
systemd.services.giteaRunnerToken-secret = {
requiredBy = [
"gitea-runner-${
config.services.gitea-actions-runner.instances.${config.networking.hostName}.name
}.service"
];
before = [
"gitea-runner-${
config.services.gitea-actions-runner.instances.${config.networking.hostName}.name
}.service"
];
};
}; };
} }

View File

@ -13,7 +13,12 @@
match = [{ host = [ config.hostnames.metrics ]; }]; match = [{ host = [ config.hostnames.metrics ]; }];
handle = [{ handle = [{
handler = "reverse_proxy"; handler = "reverse_proxy";
upstreams = [{ dial = "localhost:3000"; }]; upstreams = [{
dial = "localhost:${
builtins.toString
config.services.grafana.settings.server.http_port
}";
}];
}]; }];
}]; }];

View File

@ -5,13 +5,25 @@
services.jellyfin.group = "media"; services.jellyfin.group = "media";
users.users.jellyfin = { isSystemUser = true; }; users.users.jellyfin = { isSystemUser = true; };
caddy.routes = [{ caddy.routes = [
match = [{ host = [ config.hostnames.stream ]; }]; {
handle = [{ match = [{
handler = "reverse_proxy"; host = [ config.hostnames.stream ];
upstreams = [{ dial = "localhost:8096"; }]; path = [ "/metrics*" ];
}]; }];
}]; handle = [{
handler = "static_response";
status_code = "403";
}];
}
{
match = [{ host = [ config.hostnames.stream ]; }];
handle = [{
handler = "reverse_proxy";
upstreams = [{ dial = "localhost:8096"; }];
}];
}
];
# Create videos directory, allow anyone in Jellyfin group to manage it # Create videos directory, allow anyone in Jellyfin group to manage it
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
@ -35,6 +47,9 @@
users.users.jellyfin.extraGroups = users.users.jellyfin.extraGroups =
[ "render" "video" ]; # Access to /dev/dri [ "render" "video" ]; # Access to /dev/dri
# Requires MetricsEnable is true in /var/lib/jellyfin/config/system.xml
prometheus.scrapeTargets = [ "127.0.0.1:8096" ];
}; };
} }

View File

@ -1,9 +1,15 @@
{ config, pkgs, lib, ... }: { { config, pkgs, lib, ... }:
let
port = 8080;
in {
config = lib.mkIf config.services.nextcloud.enable { config = lib.mkIf config.services.nextcloud.enable {
services.nextcloud = { services.nextcloud = {
package = pkgs.nextcloud26; # Required to specify package = pkgs.nextcloud27; # Required to specify
datadir = "/data/nextcloud"; datadir = "/data/nextcloud";
https = true; https = true;
hostName = "localhost"; hostName = "localhost";
@ -11,13 +17,14 @@
config = { config = {
adminpassFile = config.secrets.nextcloud.dest; adminpassFile = config.secrets.nextcloud.dest;
extraTrustedDomains = [ config.hostnames.content ]; extraTrustedDomains = [ config.hostnames.content ];
trustedProxies = [ "127.0.0.1" ];
}; };
}; };
# Don't let Nginx use main ports (using Caddy instead) # Don't let Nginx use main ports (using Caddy instead)
services.nginx.virtualHosts."localhost".listen = [{ services.nginx.virtualHosts."localhost".listen = [{
addr = "127.0.0.1"; addr = "127.0.0.1";
port = 8080; port = port;
}]; }];
# Point Caddy to Nginx # Point Caddy to Nginx
@ -25,7 +32,7 @@
match = [{ host = [ config.hostnames.content ]; }]; match = [{ host = [ config.hostnames.content ]; }];
handle = [{ handle = [{
handler = "reverse_proxy"; handler = "reverse_proxy";
upstreams = [{ dial = "localhost:8080"; }]; upstreams = [{ dial = "localhost:${builtins.toString port}"; }];
}]; }];
}]; }];
@ -74,6 +81,23 @@
requires = [ "phpfpm-nextcloud.service" ]; requires = [ "phpfpm-nextcloud.service" ];
}; };
# Log metrics to prometheus
services.prometheus.exporters.nextcloud = {
enable = config.prometheus.exporters.enable;
username = config.services.nextcloud.config.adminuser;
url = "http://localhost:${builtins.toString port}";
passwordFile = config.services.nextcloud.config.adminpassFile;
};
prometheus.scrapeTargets = [
"127.0.0.1:${
builtins.toString config.services.prometheus.exporters.nextcloud.port
}"
];
# Allows nextcloud-exporter to read passwordFile
users.users.nextcloud-exporter.extraGroups =
lib.mkIf config.services.prometheus.exporters.nextcloud.enable
[ "nextcloud" ];
}; };
} }

View File

@ -1,18 +1,58 @@
{ config, pkgs, lib, ... }: { { config, pkgs, lib, ... }: {
options.prometheus = {
exporters.enable = lib.mkEnableOption "Enable Prometheus exporters";
scrapeTargets = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "Prometheus scrape targets";
default = [ ];
};
};
config = let config = let
# If hosting Grafana, host local Prometheus and listen for inbound jobs. If # If hosting Grafana, host local Prometheus and listen for inbound jobs. If
# not hosting Grafana, send remote Prometheus writes to primary host. # not hosting Grafana, send remote Prometheus writes to primary host.
isServer = config.services.grafana.enable; isServer = config.services.grafana.enable;
in lib.mkIf config.services.prometheus.enable { in {
# Turn on exporters if any Prometheus scraper is running
prometheus.exporters.enable = builtins.any (x: x) [
config.services.prometheus.enable
config.services.victoriametrics.enable
config.services.vmagent.enable
];
prometheus.scrapeTargets = [
"127.0.0.1:${
builtins.toString config.services.prometheus.exporters.node.port
}"
"127.0.0.1:${
builtins.toString config.services.prometheus.exporters.systemd.port
}"
"127.0.0.1:${
builtins.toString config.services.prometheus.exporters.process.port
}"
];
services.prometheus = { services.prometheus = {
exporters.node.enable = true; exporters.node.enable = config.prometheus.exporters.enable;
exporters.node.enabledCollectors = [ ];
exporters.node.disabledCollectors = [ "cpufreq" ];
exporters.systemd.enable = config.prometheus.exporters.enable;
exporters.process.enable = config.prometheus.exporters.enable;
exporters.process.settings.process_names = [
# Remove nix store path from process name
{
name = "{{.Matches.Wrapped}} {{ .Matches.Args }}";
cmdline = [ "^/nix/store[^ ]*/(?P<Wrapped>[^ /]*) (?P<Args>.*)" ];
}
];
extraFlags = lib.mkIf isServer [ "--web.enable-remote-write-receiver" ];
scrapeConfigs = [{ scrapeConfigs = [{
job_name = "local"; job_name = config.networking.hostName;
static_configs = [{ targets = [ "127.0.0.1:9100" ]; }]; static_configs = [{ targets = config.scrapeTargets; }];
}]; }];
webExternalUrl = webExternalUrl =
lib.mkIf isServer "https://${config.hostnames.prometheus}"; lib.mkIf isServer "https://${config.hostnames.prometheus}";
@ -28,7 +68,7 @@
}); });
remoteWrite = lib.mkIf (!isServer) [{ remoteWrite = lib.mkIf (!isServer) [{
name = config.networking.hostName; name = config.networking.hostName;
url = "https://${config.hostnames.prometheus}"; url = "https://${config.hostnames.prometheus}/api/v1/write";
basic_auth = { basic_auth = {
# Uses password hashed with bcrypt above # Uses password hashed with bcrypt above
username = "prometheus"; username = "prometheus";
@ -38,23 +78,26 @@
}; };
# Create credentials file for remote Prometheus push # Create credentials file for remote Prometheus push
secrets.prometheus = lib.mkIf (!isServer) { secrets.prometheus =
source = ../../../private/prometheus.age; lib.mkIf (config.services.prometheus.enable && !isServer) {
dest = "${config.secretsDirectory}/prometheus"; source = ../../../private/prometheus.age;
owner = "prometheus"; dest = "${config.secretsDirectory}/prometheus";
group = "prometheus"; owner = "prometheus";
permissions = "0440"; group = "prometheus";
}; permissions = "0440";
systemd.services.prometheus-secret = lib.mkIf (!isServer) { };
requiredBy = [ "prometheus.service" ]; systemd.services.prometheus-secret =
before = [ "prometheus.service" ]; lib.mkIf (config.services.prometheus.enable && !isServer) {
}; requiredBy = [ "prometheus.service" ];
before = [ "prometheus.service" ];
};
caddy.routes = lib.mkIf isServer [{ caddy.routes = lib.mkIf (config.services.prometheus.enable && isServer) [{
match = [{ host = [ config.hostnames.prometheus ]; }]; match = [{ host = [ config.hostnames.prometheus ]; }];
handle = [{ handle = [{
handler = "reverse_proxy"; handler = "reverse_proxy";
upstreams = [{ dial = "localhost:9090"; }]; upstreams =
[{ dial = "localhost:${config.services.prometheus.port}"; }];
}]; }];
}]; }];

View File

@ -39,6 +39,11 @@
type = lib.types.str; type = lib.types.str;
description = "Permissions expressed as octal."; description = "Permissions expressed as octal.";
}; };
prefix = lib.mkOption {
default = "";
type = lib.types.str;
description = "Prefix for secret value (for environment files).";
};
}; };
}); });
description = "Set of secrets to decrypt to disk."; description = "Set of secrets to decrypt to disk.";
@ -65,10 +70,10 @@
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "oneshot"; serviceConfig.Type = "oneshot";
script = '' script = ''
${pkgs.age}/bin/age --decrypt \ echo "${attrs.prefix}$(
--identity ${config.identityFile} \ ${pkgs.age}/bin/age --decrypt \
--output ${attrs.dest} \ --identity ${config.identityFile} ${attrs.source}
${attrs.source} )" > ${attrs.dest}
chown '${attrs.owner}':'${attrs.group}' '${attrs.dest}' chown '${attrs.owner}':'${attrs.group}' '${attrs.dest}'
chmod '${attrs.permissions}' '${attrs.dest}' chmod '${attrs.permissions}' '${attrs.dest}'

View File

@ -13,9 +13,8 @@
}; };
}; };
config = lib.mkIf (config.publicKey != null) { config = lib.mkIf config.services.openssh.enable {
services.openssh = { services.openssh = {
enable = true;
ports = [ 22 ]; ports = [ 22 ];
allowSFTP = true; allowSFTP = true;
settings = { settings = {
@ -27,7 +26,7 @@
}; };
users.users.${config.user}.openssh.authorizedKeys.keys = users.users.${config.user}.openssh.authorizedKeys.keys =
[ config.publicKey ]; lib.mkIf (config.publicKey != null) [ config.publicKey ];
# Implement a simple fail2ban service for sshd # Implement a simple fail2ban service for sshd
services.sshguard.enable = true; services.sshguard.enable = true;

View File

@ -0,0 +1,95 @@
{ config, pkgs, lib, ... }:
let
username = "prometheus";
prometheusConfig = (pkgs.formats.yaml { }).generate "prometheus.yml" {
scrape_configs = [{
job_name = config.networking.hostName;
stream_parse = true;
static_configs = [{ targets = config.prometheus.scrapeTargets; }];
}];
};
authConfig = (pkgs.formats.yaml { }).generate "auth.yml" {
users = [{
username = username;
password = "%{PASSWORD}";
url_prefix =
"http://localhost${config.services.victoriametrics.listenAddress}";
}];
};
authPort = "8427";
in {
config = {
services.victoriametrics.extraOptions =
[ "-promscrape.config=${prometheusConfig}" ];
systemd.services.vmauth = lib.mkIf config.services.victoriametrics.enable {
description = "VictoriaMetrics basic auth proxy";
after = [ "network.target" ];
startLimitBurst = 5;
serviceConfig = {
Restart = "on-failure";
RestartSec = 1;
DynamicUser = true;
EnvironmentFile = config.secrets.vmauth.dest;
ExecStart = ''
${pkgs.victoriametrics}/bin/vmauth \
-auth.config=${authConfig} \
-httpListenAddr=:${authPort}'';
};
wantedBy = [ "multi-user.target" ];
};
secrets.vmauth = lib.mkIf config.services.victoriametrics.enable {
source = ../../../private/prometheus.age;
dest = "${config.secretsDirectory}/vmauth";
prefix = "PASSWORD=";
};
systemd.services.vmauth-secret =
lib.mkIf config.services.victoriametrics.enable {
requiredBy = [ "vmauth.service" ];
before = [ "vmauth.service" ];
};
caddy.routes = lib.mkIf config.services.victoriametrics.enable [{
match = [{ host = [ config.hostnames.prometheus ]; }];
handle = [{
handler = "reverse_proxy";
upstreams = [{ dial = "localhost:${authPort}"; }];
}];
}];
# VMAgent
services.vmagent.prometheusConfig = prometheusConfig; # Overwritten below
systemd.services.vmagent.serviceConfig =
lib.mkIf config.services.vmagent.enable {
ExecStart = lib.mkForce ''
${pkgs.victoriametrics}/bin/vmagent \
-promscrape.config=${prometheusConfig} \
-remoteWrite.url="https://${config.hostnames.prometheus}/api/v1/write" \
-remoteWrite.basicAuth.username=${username} \
-remoteWrite.basicAuth.passwordFile=${config.secrets.vmagent.dest}'';
};
secrets.vmagent = lib.mkIf config.services.vmagent.enable {
source = ../../../private/prometheus.age;
dest = "${config.secretsDirectory}/vmagent";
owner = "vmagent";
group = "vmagent";
};
systemd.services.vmagent-secret = lib.mkIf config.services.vmagent.enable {
requiredBy = [ "vmagent.service" ];
before = [ "vmagent.service" ];
};
};
}

View File

@ -0,0 +1,12 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IE1nSGFPdyBoOVF1
NmZocHpQQnRJcWpWUHh2bU93NkdnZWNzSlFiaHdTd24rcHpsczFRCmJaSzNkNGs1
UDJCN2dYUVE3UTE1OU5RUWljQlN4dmxuUnpOMFYxQTdUaVEKLT4gc3NoLWVkMjU1
MTkgWXlTVU1RIE5HdGd6aTlKM0lFUlYzT1VhS05nZ2ZxTndVZHBNQlJxYlovdXkx
ei96d2cKdzlUYVFFaEIzaS9LZmY3MzM1RmNnR0xjOEpHK1kxM0FMTWRQSlVnczVF
dwotPiBzc2gtZWQyNTUxOSBuanZYNUEgQ1lhMGQvUy9OWkRBR3BZV1pFNmNtb2pq
Y2VEUzhRWGVWUkZJY1l4RGtWdwphdFZtM0ZLZURvYVZQYjV4bWVPdWJxa3RmWmVh
SHl0T0pQWmxnVlFPR2drCi0tLSBnd2lwS3dqUk5Jelg0b3RxbFdEcnJ6ZkkvZTVN
UllBeUUyOXBxVDBKMG5BCkGo9kj9sMVhbnXVM35lGScAb8r5LH9vf5jOdhLC/Wj2
+uA0ONIh7F2GELzf5Cw1KZJ8aHTURM2r41vZvfAQN1RwrmYOiUzlyMrvTDe78cY=
-----END AGE ENCRYPTED FILE-----