catarina: split services to modules

This commit is contained in:
L-Nafaryus 2024-01-25 18:09:52 +05:00
parent 1ad29e30d2
commit 0da77d6559
Signed by: L-Nafaryus
GPG Key ID: 582F8B0866B294A1
7 changed files with 495 additions and 106 deletions

@ -1 +1 @@
Subproject commit d4a686b321770dbe16130e31966e87143440469e Subproject commit 3d189e205d5fc4194726010e5f31178235c1c046

View File

@ -18,7 +18,6 @@
outputs = inputs @ { self, nixpkgs, home-manager, crane, nixgl, simple-nixos-mailserver, sops-nix, ... }: { outputs = inputs @ { self, nixpkgs, home-manager, crane, nixgl, simple-nixos-mailserver, sops-nix, ... }: {
lib = import ./lib {}; lib = import ./lib {};
nixosConfigurations = { nixosConfigurations = {
@ -41,6 +40,7 @@
self.nixosModules.spoofdpi self.nixosModules.spoofdpi
simple-nixos-mailserver.nixosModules.mailserver simple-nixos-mailserver.nixosModules.mailserver
sops-nix.nixosModules.sops sops-nix.nixosModules.sops
self.nixosModules.papermc
]; ];
specialArgs = { inherit inputs self; }; specialArgs = { inherit inputs self; };
}; };
@ -50,6 +50,8 @@
bonfire = import ./nixosModules/bonfire.nix; bonfire = import ./nixosModules/bonfire.nix;
spoofdpi = import ./nixosModules/spoofdpi { inherit self; }; spoofdpi = import ./nixosModules/spoofdpi { inherit self; };
papermc = import ./nixosModules/papermc { inherit self; };
}; };
templates = { templates = {

View File

@ -2,7 +2,11 @@
rec { rec {
system.stateVersion = "23.11"; system.stateVersion = "23.11";
imports = [ ./hardware.nix ./users.nix ]; imports = [
./hardware.nix ./users.nix
./services/papermc.nix
./services/gitea.nix
];
# Nix settings # Nix settings
nix = { nix = {
@ -47,7 +51,6 @@ rec {
autoSuspend = false; autoSuspend = false;
}; };
desktopManager.gnome.enable = true; desktopManager.gnome.enable = true;
windowManager.awesome.enable = true;
}; };
services.printing.enable = true; services.printing.enable = true;
@ -100,14 +103,14 @@ rec {
certs = { certs = {
"elnafo.ru" = { "elnafo.ru" = {
domain = "elnafo.ru"; domain = "elnafo.ru";
extraDomainNames = [ "*.elnafo.ru" ]; extraDomainNames = [ "www.elnafo.ru" "vcs.elnafo.ru" "media.elnafo.ru" "mc.elnafo.ru" "map.mc.elnafo.ru"];
dnsProvider = "webnames"; dnsProvider = "webnames";
credentialsFile = config.sops.secrets."dns".path; credentialsFile = config.sops.secrets."dns".path;
webroot = null; webroot = null;
}; };
}; };
}; };
services.nginx = { services.nginx = {
enable = true; enable = true;
@ -131,12 +134,6 @@ rec {
globalRedirect = "elnafo.ru"; globalRedirect = "elnafo.ru";
}; };
"vcs.elnafo.ru" = {
forceSSL = true;
useACMEHost = "elnafo.ru";
locations."/".proxyPass = "http://127.0.0.1:3001";
};
"media.elnafo.ru" = { "media.elnafo.ru" = {
forceSSL = true; forceSSL = true;
useACMEHost = "elnafo.ru"; useACMEHost = "elnafo.ru";
@ -144,81 +141,6 @@ rec {
locations."/".proxyPass = "http://127.0.0.1:8096"; locations."/".proxyPass = "http://127.0.0.1:8096";
}; };
}; };
};
services.postgresql = {
enable = true;
authentication = ''
# Type Database DB-User Auth-Method Ident-Map(optional)
local git all ident map=gitea-users
'';
identMap = ''
# MapName System-User DB-User
gitea-users git git
'';
ensureDatabases = [ "git" ];
};
services.gitea = {
enable = true;
user = "git";
group = "gitea";
stateDir = "/var/lib/gitea";
settings = {
server = {
DOMAIN = "vcs.elnafo.ru";
ROOT_URL = "https://vcs.elnafo.ru/";
HTTP_ADDRESS = "127.0.0.1";
HTTP_PORT = 3001;
};
session.COOKIE_SECURE = true;
mailer = {
ENABLED = true;
FROM = "git@elnafo.ru";
PROTOCOL = "smtps";
SMTP_ADDR = "smtp.elnafo.ru";
SMTP_PORT = 465;
USER = "git";
USE_CLIENT_CERT = true;
CLIENT_CERT_FILE = "${config.security.acme.certs."elnafo.ru".directory}/cert.pem";
CLIENT_KEY_FILE = "${config.security.acme.certs."elnafo.ru".directory}/key.pem";
};
service.DISABLE_REGISTRATION = true;
other = {
SHOW_FOOTER_VERSION = false;
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false;
};
};
mailerPasswordFile = config.sops.secrets."gitea/mail".path;
database = {
type = "postgres";
passwordFile = config.sops.secrets."database/git".path;
name = "git";
user = "git";
};
lfs.enable = true;
appName = "Elnafo VCS";
};
users.users.${services.gitea.user} = {
description = "Gitea Service";
home = services.gitea.stateDir;
useDefaultShell = true;
group = services.gitea.group;
extraGroups = [ "nginx" ];
isSystemUser = true;
}; };
mailserver = { mailserver = {
@ -238,24 +160,6 @@ rec {
openFirewall = true; openFirewall = true;
}; };
services.minecraft-server = {
enable = true;
eula = true;
declarative = true;
openFirewall = true;
serverProperties = {
server-port = 25565;
gamemode = "survival";
motd = "NixOS Minecraft Server";
max-players = 10;
level-seed = "66666666";
enable-status = true;
enforce-secure-profile = false;
difficulty = "normal";
online-mode = false;
};
};
services.spoofdpi.enable = true; services.spoofdpi.enable = true;
# Packages # Packages

View File

@ -109,7 +109,7 @@
firewall = { firewall = {
enable = true; enable = true;
allowedTCPPorts = [ 80 443 3001 ]; allowedTCPPorts = [ 80 443 3001 25600 ];
}; };
interfaces.enp9s0.ipv4.addresses = [ { interfaces.enp9s0.ipv4.addresses = [ {

View File

@ -0,0 +1,81 @@
{ config, lib, pkgs, ... }:
{
services.postgresql = {
enable = true;
authentication = ''
# Type Database DB-User Auth-Method Ident-Map(optional)
local git all ident map=gitea-users
'';
identMap = ''
# MapName System-User DB-User
gitea-users git git
'';
ensureDatabases = [ "git" ];
};
services.gitea = {
enable = true;
user = "git";
group = "gitea";
stateDir = "/var/lib/gitea";
settings = {
server = {
DOMAIN = "vcs.elnafo.ru";
ROOT_URL = "https://vcs.elnafo.ru/";
HTTP_ADDRESS = "127.0.0.1";
HTTP_PORT = 3001;
};
session.COOKIE_SECURE = true;
mailer = {
ENABLED = true;
FROM = "git@elnafo.ru";
PROTOCOL = "smtps";
SMTP_ADDR = "smtp.elnafo.ru";
SMTP_PORT = 465;
USER = "git";
USE_CLIENT_CERT = true;
CLIENT_CERT_FILE = "${config.security.acme.certs."elnafo.ru".directory}/cert.pem";
CLIENT_KEY_FILE = "${config.security.acme.certs."elnafo.ru".directory}/key.pem";
};
service.DISABLE_REGISTRATION = true;
other = {
SHOW_FOOTER_VERSION = false;
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false;
};
};
mailerPasswordFile = config.sops.secrets."gitea/mail".path;
database = {
type = "postgres";
passwordFile = config.sops.secrets."database/git".path;
name = "git";
user = "git";
};
lfs.enable = true;
appName = "Elnafo VCS";
};
users.users.${config.services.gitea.user} = {
description = "Gitea Service";
home = config.services.gitea.stateDir;
useDefaultShell = true;
group = config.services.gitea.group;
extraGroups = [ "nginx" ];
isSystemUser = true;
};
services.nginx.virtualHosts."vcs.elnafo.ru" = {
forceSSL = true;
useACMEHost = "elnafo.ru";
locations."/".proxyPass = "http://127.0.0.1:3001";
};
}

View File

@ -0,0 +1,165 @@
{ config, lib, pkgs, ... }:
let
inherit (pkgs) stdenv fetchurl;
playerlist = [
{
name = "L_Nafaryus";
uuid = "02c47438-79eb-3938-b5e0-d7c03cb5709f";
level = 4;
}
{
name = "AfroPriest";
uuid = "6fa9251d-11a5-33ad-ada3-312f0632eab1";
level = 3;
}
];
operators = lib.filter (player: player.level > 0) playerlist;
whitelist = map (player: removeAttrs player [ "level" ]) playerlist;
# Plugins
passky = stdenv.mkDerivation rec {
pname = "Passky";
version = "2.1.1";
src = fetchurl {
url = "https://hangarcdn.papermc.io/plugins/Black1_TV/Passky/versions/${version}/PAPER/Passky-${version}.jar";
hash = "sha256-D5NpFrkGLgZNMS5WlMRM3Uv07hPsI9Hdsii2whTAZ2o=";
};
meta.homepage = "https://hangar.papermc.io/Black1_TV/Passky";
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/${pname}.jar
'';
};
grimAnticheat = stdenv.mkDerivation rec {
pname = "GrimAC";
version = "2.3.46";
src = fetchurl {
url = "https://hangarcdn.papermc.io/plugins/GrimAnticheat/GrimAnticheat/versions/${version}/PAPER/grimac-${version}.jar";
hash = "sha256-tG8pBDMU4N/Ijn5RfdsQrtY4/gEhN1wEDCopqOSIqB4=";
};
meta.homepage = "https://hangar.papermc.io/GrimAnticheat/GrimAnticheat";
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/${pname}.jar
'';
};
viaVersion = stdenv.mkDerivation rec {
pname = "ViaVersion";
version = "4.9.2";
src = fetchurl {
url = "https://hangarcdn.papermc.io/plugins/ViaVersion/ViaVersion/versions/${version}/PAPER/ViaVersion-${version}.jar";
hash = "sha256-dvcyqCpIjArKCnUAD/L+lG/5gRQ9fLMKcl/+o8sLmYs=";
};
meta.homepage = "https://hangar.papermc.io/ViaVersion/ViaVersion";
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/${pname}.jar
'';
};
directionHUD = stdenv.mkDerivation rec {
pname = "DirectionHUD";
version = "1.2.2";
src = fetchurl {
url = "https://hangarcdn.papermc.io/plugins/other/DirectionHUD/versions/${version}%2B1.18-1.20.2/PAPER/directionhud-spigot-${version}%2B1.18-1.20.2.jar";
hash = "sha256-F+86Q58+3VoqNoD8P38bu8u1Hx8Si0lxNXZnF/R4hAg=";
};
meta.homepage = "https://hangar.papermc.io/other/DirectionHUD";
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/${pname}.jar
'';
};
miniMOTD = stdenv.mkDerivation rec {
pname = "MiniMOTD";
version = "2.0.14";
src = fetchurl {
url = "https://hangarcdn.papermc.io/plugins/jmp/MiniMOTD/versions/${version}/PAPER/minimotd-bukkit-${version}.jar";
hash = "sha256-d7l/pZGxteS2A9c9PIZASDTACGev8HY5SHZRvcxBc5A=";
};
meta.homepage = "https://hangar.papermc.io/jmp/MiniMOTD";
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/${pname}.jar
'';
};
skinRestorer = stdenv.mkDerivation rec {
pname = "SkinRestorer";
version = "15.0.2";
src = fetchurl {
url = "https://github.com/SkinsRestorer/SkinsRestorerX/releases/download/${version}/SkinsRestorer.jar";
hash = "sha256-fhAegFtl22xKXMi5MbsXCYOjbfqOlQTnILoEJxCDbkc=";
};
meta.homepage = "https://hangar.papermc.io/SRTeam/SkinsRestorer";
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/${pname}.jar
'';
};
squaremap = stdenv.mkDerivation rec {
pname = "squaremap";
version = "1.2.2";
src = fetchurl {
url = "https://hangarcdn.papermc.io/plugins/jmp/squaremap/versions/${version}/PAPER/squaremap-paper-mc1.20.2-${version}.jar";
hash = "sha256-Z8AWzZLlZavF8YYs1kslhtCvzq5fZ7O97mTx3hCgj78=";
};
meta.homepage = "https://hangar.papermc.io/jmp/squaremap";
phases = [ "installPhase" ];
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/${pname}.jar
'';
};
plugins = [
passky grimAnticheat viaVersion directionHUD miniMOTD skinRestorer squaremap
];
in {
services.papermc = {
enable = true;
eula = true;
openFirewall = true;
serverProperties = {
server-port = 25565;
gamemode = "survival";
motd = "NixOS Paper Server";
max-players = 10;
level-seed = "66666666";
enable-status = true;
enforce-secure-profile = false;
difficulty = "normal";
online-mode = false;
enable-rcon = true;
"rcon.port" = 25600;
white-list = true;
};
rconPasswordFile = config.sops.secrets."papermc/rcon".path;
whitelist = whitelist;
ops = operators;
extraPreStart = ''
mkdir -p ${builtins.concatStringsSep " " (map (v: "plugins/${v.pname}") plugins)}
'' + builtins.concatStringsSep "\n" (map (v: "ln -s ${v.outPath}/bin/${v.pname}.jar plugins/") plugins)
;
};
services.nginx.virtualHosts."map.mc.elnafo.ru" = {
forceSSL = true;
useACMEHost = "elnafo.ru";
locations."/".proxyPass = "http://127.0.0.1:8088";
};
}

View File

@ -0,0 +1,237 @@
{ self, ... }:
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.services.papermc;
eulaFile = builtins.toFile "eula.txt" ''
# eula.txt managed by NixOS Configuration
eula=true
'';
whitelistFile = pkgs.writeText "whitelist.json"
(builtins.toJSON cfg.whitelist);
opsFile = pkgs.writeText "whitelist.json"
(builtins.toJSON cfg.ops);
cfgToString = v: if builtins.isBool v then boolToString v else toString v;
serverPropertiesFile = let
serverProperties' = if (cfg.rconPasswordFile == null) then cfg.serverProperties else
(removeAttrs cfg.serverProperties [ "rcon.password" ]);
in pkgs.writeText "server.properties" (''
# server.properties managed by NixOS configuration
'' + concatStringsSep "\n" (mapAttrsToList
(n: v: "${n}=${cfgToString v}") serverProperties') +
lib.optionalString (cfg.rconPasswordFile != null) "\nrcon.password=#rconpass#");
stopScript = pkgs.writeShellScript "minecraft-server-stop" ''
echo stop > ${config.systemd.sockets.papermc.socketConfig.ListenFIFO}
# Wait for the PID of the minecraft server to disappear before
# returning, so systemd doesn't attempt to SIGKILL it.
while kill -0 "$1" 2> /dev/null; do
sleep 1s
done
'';
defaultServerPort = 25565;
serverPort = cfg.serverProperties.server-port or defaultServerPort;
rconPort = if cfg.serverProperties.enable-rcon or false
then cfg.serverProperties."rcon.port" or 25575
else null;
queryPort = if cfg.serverProperties.enable-query or false
then cfg.serverProperties."query.port" or 25565
else null;
in {
options.services.papermc = {
enable = mkEnableOption "Enables the PaperMC service.";
openFirewall = mkOption rec {
type = types.bool;
default = false;
description = lib.mdDoc ''
Whether to open ports in the firewall for the server.
'';
};
eula = mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Whether you agree to [Mojangs EULA](https://account.mojang.com/documents/minecraft_eula).
This option must be set to `true` to run Minecraft server.
'';
};
dataDir = mkOption {
type = types.path;
default = "/var/lib/papermc";
description = lib.mdDoc ''
Directory to store Minecraft database and other state/data files.
'';
};
whitelist = mkOption {
type = types.listOf types.attrs;
default = {};
description = lib.mdDoc ''
This is a mapping from Minecraft usernames to UUIDs.
'';
};
ops = mkOption {
type = types.listOf types.attrs;
default = {};
};
serverProperties = mkOption {
type = with types; attrsOf (oneOf [ bool int str ]);
default = {
"rcon.password" = mkIf (cfg.rconPasswordFile != null) "#rconpass#";
};
example = literalExpression ''
{
server-port = 43000;
difficulty = 3;
gamemode = 1;
max-players = 5;
motd = "NixOS Minecraft server!";
white-list = true;
enable-rcon = true;
"rcon.password" = "hunter2";
}
'';
description = lib.mdDoc ''
Minecraft server properties for the server.properties file. See
<https://minecraft.gamepedia.com/Server.properties#Java_Edition_3>
for documentation on these values.
'';
};
rconPasswordFile = mkOption {
type = types.nullOr types.str;
default = null;
example = "/var/lib/secrets/papermc/rconpw";
};
package = mkPackageOption pkgs "papermc" {
example = "papermc_6_6_6";
};
jvmOpts = mkOption {
type = types.separatedString " ";
default = "-Xmx2048M -Xms2048M";
# Example options from https://minecraft.gamepedia.com/Tutorials/Server_startup_script
example = "-Xms4092M -Xmx4092M -XX:+UseG1GC -XX:+CMSIncrementalPacing "
+ "-XX:+CMSClassUnloadingEnabled -XX:ParallelGCThreads=2 "
+ "-XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=10";
description = lib.mdDoc "JVM options for the Minecraft server.";
};
extraPreStart = mkOption {
type = types.lines;
default = '''';
};
};
config = mkIf cfg.enable {
users.users.papermc = {
description = "Minecraft server service user";
home = cfg.dataDir;
createHome = true;
isSystemUser = true;
group = "papermc";
};
users.groups.papermc = {};
systemd.sockets.papermc = {
bindsTo = [ "papermc.service" ];
socketConfig = {
ListenFIFO = "/run/papermc.stdin";
SocketMode = "0660";
SocketUser = "papermc";
SocketGroup = "papermc";
RemoveOnStop = true;
FlushPending = true;
};
};
systemd.services.papermc = {
description = "PaperMC Service";
wantedBy = [ "multi-user.target" ];
requires = [ "papermc.socket" ];
after = [ "network.target" "papermc.socket" ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/minecraft-server ${cfg.jvmOpts}";
ExecStop = "${stopScript} $MAINPID";
Restart = "always";
User = "papermc";
WorkingDirectory = cfg.dataDir;
StandardInput = "socket";
StandardOutput = "journal";
StandardError = "journal";
# Hardening
CapabilityBoundingSet = [ "" ];
DeviceAllow = [ "" ];
LockPersonality = true;
PrivateDevices = true;
PrivateTmp = true;
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
UMask = "0077";
};
preStart = let
replaceSecretBin = "${pkgs.replace-secret}/bin/replace-secret";
in ''
ln -sf ${eulaFile} eula.txt
cp -b --suffix=.stateful ${whitelistFile} whitelist.json
cp -b --suffix=.stateful ${opsFile} ops.json
cp -b --suffix=.stateful ${serverPropertiesFile} server.properties
chmod +w whitelist.json ops.json server.properties
${lib.optionalString (cfg.rconPasswordFile != null) ''
${replaceSecretBin} '#rconpass#' '${cfg.rconPasswordFile}' server.properties
''}
'' + cfg.extraPreStart;
};
networking.firewall = mkIf cfg.openFirewall ({
allowedUDPPorts = [ serverPort ];
allowedTCPPorts = [ serverPort ]
++ optional (queryPort != null) queryPort
++ optional (rconPort != null) rconPort;
});
assertions = [
{ assertion = cfg.eula;
message = "You must agree to Mojangs EULA to run minecraft-server."
+ " Read https://account.mojang.com/documents/minecraft_eula and"
+ " set `services.minecraft-server.eula` to `true` if you agree.";
}
];
};
}