Compare commits

...

6 commits

16 changed files with 264 additions and 60 deletions

View file

@ -6,6 +6,8 @@ let
in in
{ {
x86_64-linux = lib.mergeAttrsList [ x86_64-linux = lib.mergeAttrsList [
flake-inputs.self.nixosConfigurations.hetzner-1.config.serviceTests
{ {
nix = checkLib.mkLint { nix = checkLib.mkLint {
name = "nix-lints"; name = "nix-lints";

View file

@ -1,5 +1,5 @@
{ {
config, lib,
modulesPath, modulesPath,
flake-inputs, flake-inputs,
... ...
@ -9,25 +9,11 @@
flake-inputs.disko.nixosModules.disko flake-inputs.disko.nixosModules.disko
flake-inputs.sops-nix.nixosModules.sops flake-inputs.sops-nix.nixosModules.sops
flake-inputs.tlaternet-webserver.nixosModules.default flake-inputs.tlaternet-webserver.nixosModules.default
"${modulesPath}/profiles/minimal.nix" "${modulesPath}/profiles/minimal.nix"
(import ../modules)
./services/backups.nix ../modules
./services/battery-manager.nix
./services/conduit
./services/crowdsec.nix
./services/foundryvtt.nix
./services/gitea.nix
./services/immich.nix
./services/metrics
./services/minecraft.nix
./services/nextcloud.nix
./services/webserver.nix
./services/wireguard.nix
# ./services/starbound.nix -- Not currently used
./services/postgres.nix
./nginx ./nginx
./services
]; ];
nix = { nix = {
@ -39,49 +25,9 @@
settings.trusted-users = [ "@wheel" ]; settings.trusted-users = [ "@wheel" ];
}; };
# Optimization for minecraft servers, see:
# https://bugs.mojang.com/browse/MC-183518
boot.kernelParams = [
"highres=off"
"nohz=off"
];
networking = { networking = {
usePredictableInterfaceNames = false; usePredictableInterfaceNames = false;
useDHCP = false; useDHCP = false;
firewall = {
allowedTCPPorts = [
# http
80
443
# ssh
2222
# matrix
8448
# starbound
21025
config.services.coturn.listening-port
config.services.coturn.tls-listening-port
config.services.coturn.alt-listening-port
config.services.coturn.alt-tls-listening-port
];
allowedUDPPorts = [
config.services.coturn.listening-port
config.services.coturn.tls-listening-port
config.services.coturn.alt-listening-port
config.services.coturn.alt-tls-listening-port
];
allowedUDPPortRanges = [
{
from = config.services.coturn.min-port;
to = config.services.coturn.max-port;
}
];
};
}; };
systemd.network.enable = true; systemd.network.enable = true;
@ -124,7 +70,7 @@
sops.defaultSopsFile = ../keys/production.yaml; sops.defaultSopsFile = ../keys/production.yaml;
# Remove some unneeded packages # Remove some unneeded packages
environment.defaultPackages = [ ]; environment.defaultPackages = lib.mkForce [ ];
system.stateVersion = "20.09"; system.stateVersion = "20.09";
} }

View file

@ -1,4 +1,10 @@
{ config, lib, ... }: {
flake-inputs,
pkgs,
config,
lib,
...
}:
let let
hostNames = lib.attrNames config.services.nginx.virtualHosts; hostNames = lib.attrNames config.services.nginx.virtualHosts;
logPath = name: "/var/log/nginx/${name}/access.log"; logPath = name: "/var/log/nginx/${name}/access.log";
@ -80,5 +86,55 @@ in
}; };
}; };
}; };
serviceTests =
let
testHostConfig =
{ config, ... }:
{
imports = [
./.
../../modules/serviceTests/mocks.nix
];
networking.firewall.allowedTCPPorts = [ 80 ];
services.nginx = {
domain = "testHost";
virtualHosts."${config.services.nginx.domain}".locations."/".return = "200 ok";
};
};
in
{
nginxMetricsWork = pkgs.testers.runNixOSTest {
name = "nginx-metrics-work";
node.specialArgs = { inherit flake-inputs; };
nodes = {
testHost = testHostConfig;
client =
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.curl ];
};
};
testScript = ''
import time
start_all()
testHost.wait_for_unit("nginx.service")
client.succeed("curl --max-time 10 http://testHost")
# Wait a bit for the prometheus exporter to scrape our logs
time.sleep(5)
res = testHost.succeed("curl localhost:${builtins.toString config.services.prometheus.exporters.nginxlog.port}/metrics")
assert 'nginxlog_http_response_count_total{method="GET",status="200",vhost="testHost"} 1' in res, res
'';
};
};
}; };
} }

View file

@ -1,4 +1,5 @@
{ {
flake-inputs,
pkgs, pkgs,
config, config,
lib, lib,
@ -69,5 +70,72 @@
"porkbun/api-key".owner = "acme"; "porkbun/api-key".owner = "acme";
"porkbun/secret-api-key".owner = "acme"; "porkbun/secret-api-key".owner = "acme";
}; };
serviceTests =
let
testHostConfig =
{ config, ... }:
{
imports = [
./.
../../modules/serviceTests/mocks.nix
];
networking.firewall.allowedTCPPorts = [
80
443
];
security.acme.certs."tlater.net".extraDomainNames = [ config.services.nginx.domain ];
services.nginx = {
domain = "testHost";
virtualHosts."${config.services.nginx.domain}" = {
useACMEHost = "tlater.net";
forceSSL = true;
enableHSTS = true;
locations."/".return = "200 ok";
};
};
};
in
{
hstsIsSet = pkgs.testers.runNixOSTest {
name = "hsts-is-set";
node.specialArgs = { inherit flake-inputs; };
nodes = {
testHost = testHostConfig;
client =
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.curl ];
};
};
testScript = ''
start_all()
testHost.wait_for_unit("nginx.service")
testHost.copy_from_vm("/var/lib/acme/tlater.net/", "certs")
client.copy_from_host(f"{testHost.out_dir}/certs", "/certs")
client.succeed("curl --max-time 10 http://testHost")
res = client.succeed(" ".join([
"curl",
"--show-error",
"--silent",
"--dump-header -",
"--cacert /certs/tlater.net/fullchain.pem",
"https://testHost",
"-o /dev/null"
]))
assert "strict-transport-security: max-age=15552000; includeSubDomains" in res
'';
};
};
}; };
} }

View file

@ -17,6 +17,36 @@ in
./matrix-hookshot.nix ./matrix-hookshot.nix
]; ];
networking.firewall = {
allowedTCPPorts = [
# These are for "normal" clients
80
443
# Federation happens on 8448
8448
config.services.coturn.listening-port
config.services.coturn.tls-listening-port
config.services.coturn.alt-listening-port
config.services.coturn.alt-tls-listening-port
];
allowedUDPPorts = [
config.services.coturn.listening-port
config.services.coturn.tls-listening-port
config.services.coturn.alt-listening-port
config.services.coturn.alt-tls-listening-port
];
allowedUDPPortRanges = [
{
from = config.services.coturn.min-port;
to = config.services.coturn.max-port;
}
];
};
services = { services = {
matrix-conduit = { matrix-conduit = {
enable = true; enable = true;

View file

@ -0,0 +1,18 @@
{
imports = [
./backups.nix
./battery-manager.nix
./conduit
./crowdsec.nix
./foundryvtt.nix
./gitea.nix
./immich.nix
./metrics
./minecraft.nix
./nextcloud.nix
./postgres.nix
# ./starbound.nix -- Not currently used
./webserver.nix
./wireguard.nix
];
}

View file

@ -11,6 +11,11 @@ in
{ {
imports = [ flake-inputs.foundryvtt.nixosModules.foundryvtt ]; imports = [ flake-inputs.foundryvtt.nixosModules.foundryvtt ];
networking.firewall.allowedTCPPorts = [
80
443
];
services = { services = {
foundryvtt = { foundryvtt = {
enable = true; enable = true;

View file

@ -8,6 +8,11 @@ let
domain = "gitea.${config.services.nginx.domain}"; domain = "gitea.${config.services.nginx.domain}";
in in
{ {
networking.firewall.allowedTCPPorts = [
80
443
];
services = { services = {
forgejo = { forgejo = {
enable = true; enable = true;

View file

@ -8,6 +8,11 @@ let
hostName = "immich.${config.services.nginx.domain}"; hostName = "immich.${config.services.nginx.domain}";
in in
{ {
networking.firewall.allowedTCPPorts = [
80
443
];
services = { services = {
immich = { immich = {
enable = true; enable = true;

View file

@ -3,6 +3,11 @@ let
domain = "metrics.${config.services.nginx.domain}"; domain = "metrics.${config.services.nginx.domain}";
in in
{ {
networking.firewall.allowedTCPPorts = [
80
443
];
services.grafana = { services.grafana = {
enable = true; enable = true;
settings = { settings = {

View file

@ -9,6 +9,11 @@ let
hostName = "nextcloud.${config.services.nginx.domain}"; hostName = "nextcloud.${config.services.nginx.domain}";
in in
{ {
networking.firewall.allowedTCPPorts = [
80
443
];
services = { services = {
nextcloud = { nextcloud = {
inherit hostName; inherit hostName;

View file

@ -8,6 +8,8 @@ let
inherit (lib) concatStringsSep; inherit (lib) concatStringsSep;
in in
{ {
networking.firewall.allowedTCPPorts = [ 21025 ];
# Sadly, steam-run requires some X libs # Sadly, steam-run requires some X libs
environment.noXlibs = false; environment.noXlibs = false;

View file

@ -3,6 +3,11 @@ let
inherit (config.services.nginx) domain; inherit (config.services.nginx) domain;
in in
{ {
networking.firewall.allowedTCPPorts = [
80
443
];
services.tlaternet-webserver = { services.tlaternet-webserver = {
enable = true; enable = true;
listen = { listen = {

View file

@ -1 +1,6 @@
{ imports = [ ./crowdsec ]; } {
imports = [
./crowdsec
./serviceTests/stub.nix
];
}

View file

@ -0,0 +1,27 @@
/**
Module containing mock definitions for service test runners.
*/
{ flake-inputs, lib, ... }:
{
imports = [
flake-inputs.sops-nix.nixosModules.sops
../.
../../configuration/services/backups.nix
];
sops.defaultSopsFile = ../../keys/staging.yaml;
environment.etc."staging.key" = {
mode = "0400";
source = ../../keys/hosts/staging.key;
};
services.openssh = {
enable = true;
hostKeys = lib.mkForce [
{
type = "rsa";
bits = 4096;
path = "/etc/staging.key";
}
];
};
}

View file

@ -0,0 +1,20 @@
/**
Module to make writing service-specific tests easy.
*/
{ lib, ... }:
let
inherit (lib) mkOption types;
in
{
options = {
serviceTests = mkOption {
type = types.attrsOf types.package;
description = ''
NixOS tests to run.
'';
default = { };
};
};
}