chore(minecraft): mounts

This commit is contained in:
arcnmx 2024-09-17 12:42:18 -07:00
parent 33b18bc348
commit 75b123776b
15 changed files with 402 additions and 54 deletions

View file

@ -487,6 +487,57 @@ jobs:
command: ci-build-cache command: ci-build-cache
quiet: false quiet: false
stdin: ${{ runner.temp }}/ci.build.cache stdin: ${{ runner.temp }}/ci.build.cache
minecraft:
name: nodes-minecraft
runs-on: ubuntu-latest
steps:
- id: checkout
name: git clone
uses: actions/checkout@v4
with:
submodules: false
- id: nix-install
name: nix install
uses: arcnmx/ci/actions/nix/install@v0.7
- id: ci-dirty
name: nix test dirty
uses: arcnmx/ci/actions/nix/run@v0.7
with:
attrs: ci.job.minecraft.run.test
command: ci-build-dirty
quiet: false
stdout: ${{ runner.temp }}/ci.build.dirty
- id: ci-test
name: nix test build
uses: arcnmx/ci/actions/nix/run@v0.7
with:
attrs: ci.job.minecraft.run.test
command: ci-build-realise
ignore-exit-code: true
quiet: false
stdin: ${{ runner.temp }}/ci.build.dirty
- env:
CI_EXIT_CODE: ${{ steps.ci-test.outputs.exit-code }}
id: ci-summary
name: nix test results
uses: arcnmx/ci/actions/nix/run@v0.7
with:
attrs: ci.job.minecraft.run.test
command: ci-build-summarise
quiet: false
stdin: ${{ runner.temp }}/ci.build.dirty
stdout: ${{ runner.temp }}/ci.build.cache
- env:
CACHIX_SIGNING_KEY: ${{ secrets.CACHIX_SIGNING_KEY }}
id: ci-cache
if: always()
name: nix test cache
uses: arcnmx/ci/actions/nix/run@v0.7
with:
attrs: ci.job.minecraft.run.test
command: ci-build-cache
quiet: false
stdin: ${{ runner.temp }}/ci.build.cache
packages: packages:
name: nodes-packages name: nodes-packages
runs-on: ubuntu-latest runs-on: ubuntu-latest

View file

@ -245,6 +245,24 @@
} }
} }
}, },
"minecraft": {
"network": {
"hostName": "minecraft",
"networks": {
"int": null,
"local": {
"address4": "10.1.1.51",
"address6": "fd0a::be24:11ff:fec4:66ad",
"macAddress": "BC:24:11:C4:66:AD"
},
"tail": {
"address4": "100.73.157.122",
"address6": "fd7a:115c:a1e0::1f01:9d7a",
"macAddress": null
}
}
}
},
"nue": { "nue": {
"network": { "network": {
"hostName": "nue", "hostName": "nue",

View file

@ -32,6 +32,7 @@ aya:: `10.1.1.47`
keycloak:: `10.1.1.48` keycloak:: `10.1.1.48`
kasen:: `10.1.1.49` kasen:: `10.1.1.49`
sakuya:: `10.1.1.50` sakuya:: `10.1.1.50`
minecraft:: `10.1.1.51`
nue:: `10.1.1.62` nue:: `10.1.1.62`
logistics:: `10.1.1.63` logistics:: `10.1.1.63`

View file

@ -0,0 +1,150 @@
{
config,
lib,
pkgs,
...
}: let
inherit (lib.options) mkOption mkEnableOption mkPackageOption;
inherit (lib.modules) mkIf mkMerge mkOptionDefault;
inherit (lib.strings) concatStringsSep;
inherit (lib.meta) getExe;
cfg = config.services.minecraft-katsink-server;
in {
options.services.minecraft-katsink-server = with lib.types; {
enable = mkEnableOption "kat-kitchen-sink";
openFirewall = mkOption {
type = bool;
default = false;
};
port = mkOption {
type = port;
default = 25565;
};
jre.package = mkPackageOption pkgs "jre" {};
dataDir = mkOption {
type = path;
default = "/var/lib/minecraft-katsink";
description = ''
Directory to store Minecraft database and other state/data files.
'';
};
argsFiles = mkOption {
type = listOf str;
default = [ "user_jvm_args.txt" ];
};
jvmOpts = mkOption {
type = listOf str;
default = [];
example = ["-Xmx4G"];
};
user = mkOption {
type = str;
default = "minecraft-bedrock";
};
group = mkOption {
type = str;
default = cfg.user;
};
};
config = let
confService.services.minecraft-katsink-server = {
};
conf.users = mkIf (cfg.user == "minecraft-bedrock") {
users.${cfg.user} = {
inherit (cfg) group;
description = "Minecraft server service user";
home = cfg.dataDir;
createHome = true;
isSystemUser = true;
};
groups.${cfg.group} = {};
};
conf.systemd.services.minecraft-katsink-server = let
execStart = concatStringsSep " " ([
"${getExe cfg.jre.package}"
] ++ map (argsFile: "@${argsFile}") cfg.argsFiles
++ cfg.jvmOpts);
execStop = pkgs.writeShellScriptBin "minecraft-katsink-stop" ''
echo /stop > ${config.systemd.sockets.minecraft-katsink-server.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
'';
in {
description = "Minecraft Kat Kitchen Server";
wantedBy = ["multi-user.target"];
requires = ["minecraft-katsink-server.socket"];
after = ["network.target" "minecraft-katsink-server.socket"];
serviceConfig = {
ExecStart = [execStart];
ExecStop = "${getExe execStop} $MAINPID";
Restart = "on-failure";
User = cfg.user;
WorkingDirectory = cfg.dataDir;
/*LogFilterPatterns = [
"~.*minecraft:trial_chambers/chamber/end"
"~Running AutoCompaction"
];*/
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" "AF_UNIX" ];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
UMask = "0077";
};
};
conf.systemd.sockets.minecraft-katsink-server = {
bindsTo = [ "minecraft-katsink-server.service" ];
socketConfig = {
ListenFIFO = "/run/minecraft-katsink.stdin";
SocketMode = "0660";
SocketUser = mkOptionDefault cfg.user;
SocketGroup = mkOptionDefault cfg.group;
RemoveOnStop = true;
FlushPending = true;
};
};
conf.networking.firewall = mkIf cfg.openFirewall {
allowedUDPPorts = cfg.port;
};
in
mkMerge [
confService
(mkIf cfg.enable conf)
];
}

View file

@ -0,0 +1,37 @@
{
config,
lib,
...
}: let
inherit (lib.modules) mkIf mkDefault;
cfg = config.services.minecraft-katsink-server;
in {
services.minecraft-katsink-server = {
enable = mkDefault true;
argsFiles = [
"user_jvm_args.txt"
"libraries/net/neoforged/neoforge/21.1.54/unix_args.txt"
];
};
users = mkIf cfg.enable {
users.${cfg.user}.uid = 913;
groups.${cfg.group}.gid = config.users.users.${cfg.user}.uid;
};
systemd = mkIf cfg.enable {
services.minecraft-katsink-server = {
# TODO: confinement.enable = true;
gensokyo-zone.sharedMounts."minecraft/katsink/kat-kitchen-server" = {config, ...}: {
root = config.rootDir + "/minecraft/katsink";
path = mkDefault cfg.dataDir;
};
};
sockets.minecraft-katsink-server = {
socketConfig.SocketGroup = "admin";
};
};
networking.firewall = mkIf cfg.enable {
interfaces.tailscale0.allowedTCPPorts = [cfg.port];
interfaces.local.allowedTCPPorts = [cfg.port];
};
}

View file

@ -4,6 +4,8 @@
"/rpool/shared/nix/store nix/store none bind,create=dir", "/rpool/shared/nix/store nix/store none bind,create=dir",
"/rpool/shared/nix/var nix/var none bind,create=dir", "/rpool/shared/nix/var nix/var none bind,create=dir",
"/rpool/shared/minecraft/bedrock mnt/shared/minecraft/bedrock none bind,optional,create=dir", "/rpool/shared/minecraft/bedrock mnt/shared/minecraft/bedrock none bind,optional,create=dir",
"/rpool/shared/minecraft/katsink mnt/shared/minecraft/katsink none bind,optional,create=dir",
"/mnt/kyuuto-data/minecraft mnt/kyuuto-data/minecraft none bind,optional,create=dir",
"/dev/net/tun dev/net/tun none bind,optional,create=file" "/dev/net/tun dev/net/tun none bind,optional,create=file"
], ],
"lxc.idmap": [ "lxc.idmap": [

View file

@ -11,8 +11,8 @@ _: {
]; ];
network.networks = { network.networks = {
tail = { tail = {
address4 = "100.70.124.79"; address4 = "100.73.157.122";
address6 = "fd7a:115c:a1e0::b001:7c4f"; address6 = "fd7a:115c:a1e0::1f01:9d7a";
}; };
}; };
exports = { exports = {

View file

@ -1,8 +1,22 @@
{ {
"lxc": { "lxc": {
"lxc.mount.entry": [ "lxc.mount.entry": [
"/mnt/kyuuto-minecraft mnt/kyuuto-minecraft none bind,optional,create=dir", "/rpool/shared/minecraft/katsink mnt/shared/minecraft/katsink none bind,optional,create=dir",
"/dev/net/tun dev/net/tun none bind,optional,create=file" "/mnt/kyuuto-data/minecraft mnt/kyuuto-data/minecraft none bind,optional,create=dir",
] "/mnt/kyuuto-minecraft mnt/kyuuto-minecraft none bind,optional,create=dir",
"/dev/net/tun dev/net/tun none bind,optional,create=file"
],
"lxc.idmap": [
"u 0 100000 8000",
"g 0 100000 8000",
"u 8000 8000 128",
"g 8000 8000 256",
"u 8128 108128 57406",
"g 8256 108256 57278",
"u 65534 65534 1",
"g 65534 65534 1",
"u 65535 165535 1",
"g 65535 165535 1"
]
} }
} }

View file

@ -1,20 +1,21 @@
{meta, pkgs, ...}:{ {
meta,
config,
...
}: {
imports = let imports = let
inherit (meta) nixos; inherit (meta) nixos;
in [ in [
nixos.sops nixos.sops
nixos.reisen-ct nixos.reisen-ct
nixos.tailscale nixos.tailscale
nixos.minecraft.katsink
]; ];
environment.systemPackages = with pkgs; [ environment.systemPackages = [
jre config.services.minecraft-katsink-server.jre.package
tmux
]; ];
networking.firewall.interfaces.tailscale0.allowedTCPPorts = [ 25565 ];
networking.firewall.interfaces.local.allowedTCPPorts = [ 25565 ];
sops = { sops = {
defaultSopsFile = ./secrets.yaml; defaultSopsFile = ./secrets.yaml;
secrets.tailscale-key.key = "tailscale-key"; secrets.tailscale-key.key = "tailscale-key";

View file

@ -1,6 +1,6 @@
_: { _: {
proxmox = { proxmox = {
vm.id = 106; vm.id = 109;
container = { container = {
enable = true; enable = true;
lxc.configJsonFile = ./lxc.json; lxc.configJsonFile = ./lxc.json;
@ -8,11 +8,10 @@ _: {
network.interfaces = { network.interfaces = {
net0 = { net0 = {
mdns.enable = true; mdns.enable = true;
macAddress = "BC:24:11:C4:66:AB"; macAddress = "BC:24:11:C4:66:AD";
address4 = "dhcp"; address4 = "10.1.1.51/24";
address6 = "auto"; address6 = "auto";
}; };
net1.internal.enable = true;
}; };
}; };
} }

View file

@ -100,31 +100,51 @@ if [[ ! -d /rpool/caches ]]; then
zfs create rpool/caches zfs create rpool/caches
fi fi
mkrpool() { mkzfs() {
local SHARED_PATH SHARED_MODE SHARED_OWNER SHARED_GROUP local ZFS_PATH ZFS_MODE ZFS_OWNER ZFS_GROUP
SHARED_PATH=$1 ZFS_PATH=$1
SHARED_OWNER=$2 ZFS_OWNER=$2
SHARED_GROUP=$3 ZFS_GROUP=$3
SHARED_MODE=$4 ZFS_MODE=$4
shift 4 shift 4
if [[ ! -d "/rpool/$SHARED_PATH" ]]; then ZFS_NAME=${ZFS_PATH#/}
zfs create "rpool/$SHARED_PATH" if [[ $# -gt 0 ]]; then
ZFS_NAME=$1
shift
fi fi
chmod "$SHARED_MODE" "/rpool/$SHARED_PATH"
chown "$SHARED_OWNER:$SHARED_GROUP" "/rpool/$SHARED_PATH" ZFS_ARGS=("$@")
if [[ $ZFS_NAME != ${ZFS_PATH#/} ]]; then
ZFS_ARGS+=(-o "mountpoint=$ZFS_PATH")
fi
if [[ ! -d "$ZFS_PATH" ]]; then
zfs create "$ZFS_NAME" ${ZFS_ARGS[@]+"${ZFS_ARGS[@]}"}
fi
chmod "$ZFS_MODE" "$ZFS_PATH"
chown "$ZFS_OWNER:$ZFS_GROUP" "$ZFS_PATH"
} }
mkshared() { mkshared() {
local SHARED_PATH=$1 local SHARED_PATH=$1
shift shift
mkrpool "shared/$SHARED_PATH" "$@" mkzfs "/rpool/shared/$SHARED_PATH" "$@"
} }
mkcache() { mkcache() {
local SHARED_PATH=$1 local CACHE_PATH=$1
shift shift
mkrpool "caches/$SHARED_PATH" "$@" mkzfs "/rpool/caches/$CACHE_PATH" "$@"
}
mkkyuuto() {
local KYUUTO_PATH KYUUTO_ARGS=()
KYUUTO_NAME=$1
KYUUTO_ARGS=("$2" "$3" "$4")
shift 4
mkzfs "/mnt/kyuuto-$KYUUTO_NAME" "${KYUUTO_ARGS[@]}" "kyuuto/$KYUUTO_NAME" "$@"
} }
mkshared nix 0 0 0755 mkshared nix 0 0 0755
@ -163,6 +183,15 @@ mkshared zigbee2mqtt 100317 100317 0700
mkshared vaultwarden 100915 100915 0750 mkshared vaultwarden 100915 100915 0750
mkshared minecraft 100913 100913 0750 mkshared minecraft 100913 100913 0750
mkshared minecraft/bedrock 100913 100913 0750 mkshared minecraft/bedrock 100913 100913 0750
mkshared minecraft/katsink 100913 100913 0750
mkkyuuto data 0 0 0755 -o compression=on
mkkyuuto data/minecraft 0 8126 0775
if [[ ! -d /mnt/kyuuto-data/minecraft/simplebackups ]]; then
mkdir -p /mnt/kyuuto-data/minecraft/simplebackups
fi
chown 100913:8126 /mnt/kyuuto-data/minecraft/simplebackups
chmod 0775 /mnt/kyuuto-data/minecraft/simplebackups
ln -sf /lib/systemd/system/auth-rpcgss-module.service /etc/systemd/system/ ln -sf /lib/systemd/system/auth-rpcgss-module.service /etc/systemd/system/
mkdir -p /etc/systemd/system/auth-rpcgss-module.service.d mkdir -p /etc/systemd/system/auth-rpcgss-module.service.d

View file

@ -151,6 +151,24 @@
} }
} }
}, },
"minecraft": {
"hostName": "minecraft",
"network": {
"networks": {
"int": null,
"local": {
"address4": "10.1.1.51",
"address6": "fd0a::be24:11ff:fec4:66ad",
"macAddress": "BC:24:11:C4:66:AD"
},
"tail": {
"address4": "100.73.157.122",
"address6": "fd7a:115c:a1e0::1f01:9d7a",
"macAddress": null
}
}
}
},
"reimu": { "reimu": {
"hostName": "reimu", "hostName": "reimu",
"network": { "network": {

View file

@ -92,6 +92,13 @@ module "aya_system_records" {
] ]
} }
module "minecraft_system_records" {
source = "./system/records"
zone_id = cloudflare_zone.gensokyo-zone_zone.id
zone_zone = cloudflare_zone.gensokyo-zone_zone.zone
net_data = local.systems.minecraft.network
}
module "tewi_system_records" { module "tewi_system_records" {
source = "./system/records" source = "./system/records"
zone_id = cloudflare_zone.gensokyo-zone_zone.id zone_id = cloudflare_zone.gensokyo-zone_zone.id

View file

@ -784,15 +784,8 @@ EOT
address = "auto" address = "auto"
} }
ipv4 { ipv4 {
address = "dhcp" address = "10.1.1.51/24"
} gateway = "10.1.1.1"
}
ip_config {
ipv6 {
address = "${cidrhost(local.reisen_int_prefix6, local.proxmox_minecraft_vm_id - local.reisen_int_offset)}/64"
}
ipv4 {
address = "${cidrhost(local.reisen_int_prefix4, local.proxmox_minecraft_vm_id - local.reisen_int_offset)}/24"
} }
} }
} }
@ -807,11 +800,6 @@ EOT
name = "eth0" name = "eth0"
mac_address = "BC:24:11:C4:66:AD" mac_address = "BC:24:11:C4:66:AD"
} }
network_interface {
name = "eth9"
mac_address = "BC:24:19:C4:66:AD"
bridge = proxmox_virtual_environment_network_linux_bridge.internal.name
}
operating_system { operating_system {
template_file_id = var.proxmox_container_template template_file_id = var.proxmox_container_template

View file

@ -1,7 +1,8 @@
locals { locals {
tailscale_tag_infra = "tag:infrastructure" tailscale_tag_infra = "tag:infrastructure"
tailscale_tag_genso = "tag:gensokyo" tailscale_tag_genso = "tag:gensokyo"
tailscale_tag_reisen = "tag:reisen" tailscale_tag_reisen = "tag:reisen"
tailscale_tag_minecraft = "tag:minecraft"
tailscale_tag_arc = "tag:arc" tailscale_tag_arc = "tag:arc"
tailscale_tag_arc_deploy = "tag:arc-deploy" tailscale_tag_arc_deploy = "tag:arc-deploy"
@ -11,7 +12,14 @@ locals {
tailscale_user_arc = "arc@${var.tailscale_tailnet}" tailscale_user_arc = "arc@${var.tailscale_tailnet}"
tailscale_user_kat = "kat@${var.tailscale_tailnet}" tailscale_user_kat = "kat@${var.tailscale_tailnet}"
tailscale_group_admin = "autogroup:admin" tailscale_group_member = "autogroup:member"
tailscale_group_admin = "autogroup:admin"
tailscale_tags_genso = [local.tailscale_tag_infra, local.tailscale_tag_genso]
tailscale_tags_reisen = concat(local.tailscale_tags_genso, [local.tailscale_tag_reisen])
tailscale_tags_arc = [local.tailscale_user_arc, local.tailscale_tag_arc]
tailscale_tags_kat = [local.tailscale_user_kat, local.tailscale_tag_kat]
tailscale_tags_peeps = concat(local.tailscale_tags_arc, local.tailscale_tags_kat)
} }
resource "tailscale_acl" "tailnet" { resource "tailscale_acl" "tailnet" {
@ -20,6 +28,7 @@ resource "tailscale_acl" "tailnet" {
"${local.tailscale_tag_infra}" : [local.tailscale_group_admin], "${local.tailscale_tag_infra}" : [local.tailscale_group_admin],
"${local.tailscale_tag_reisen}" : [local.tailscale_group_admin, local.tailscale_tag_infra], "${local.tailscale_tag_reisen}" : [local.tailscale_group_admin, local.tailscale_tag_infra],
"${local.tailscale_tag_genso}" : [local.tailscale_group_admin, local.tailscale_tag_arc_deploy, local.tailscale_tag_kat_deploy], "${local.tailscale_tag_genso}" : [local.tailscale_group_admin, local.tailscale_tag_arc_deploy, local.tailscale_tag_kat_deploy],
"${local.tailscale_tag_minecraft}" : [local.tailscale_group_admin, local.tailscale_tag_infra],
"${local.tailscale_tag_arc}" : [local.tailscale_user_arc, local.tailscale_tag_arc_deploy], "${local.tailscale_tag_arc}" : [local.tailscale_user_arc, local.tailscale_tag_arc_deploy],
"${local.tailscale_tag_arc_deploy}" : [local.tailscale_user_arc], "${local.tailscale_tag_arc_deploy}" : [local.tailscale_user_arc],
"${local.tailscale_tag_kat}" : [local.tailscale_user_kat, local.tailscale_tag_kat_deploy], "${local.tailscale_tag_kat}" : [local.tailscale_user_kat, local.tailscale_tag_kat_deploy],
@ -27,10 +36,34 @@ resource "tailscale_acl" "tailnet" {
} }
acls = [ acls = [
{ {
# Allow all connections action = "accept"
src = [local.tailscale_group_admin]
dst = ["*:*"]
},
{
action = "accept"
src = [local.tailscale_tag_reisen]
dst = ["${local.tailscale_tag_reisen}:*"]
},
{
action = "accept"
src = concat([local.tailscale_tag_genso], local.tailscale_tags_peeps)
dst = [
"${local.tailscale_tag_genso}:*",
]
},
{
action = "accept" action = "accept"
src = ["*"] src = ["*"]
dst = ["*:*"] dst = [
"autogroup:self:*",
"${local.tailscale_tag_minecraft}:19132,19133,25565",
]
},
{
action = "accept"
src = [local.tailscale_group_member]
dst = ["autogroup:internet:*"]
}, },
] ]
# Define users and devices that can use Tailscale SSH. # Define users and devices that can use Tailscale SSH.
@ -38,7 +71,7 @@ resource "tailscale_acl" "tailnet" {
# Allow all users to SSH into their own devices in check mode. # Allow all users to SSH into their own devices in check mode.
{ {
action = "check", action = "check",
src = ["autogroup:member"], src = [local.tailscale_group_member],
dst = ["autogroup:self"], dst = ["autogroup:self"],
users = ["autogroup:nonroot", "root"], users = ["autogroup:nonroot", "root"],
}, },
@ -51,7 +84,7 @@ resource "tailscale_tailnet_key" "reisen" {
ephemeral = false ephemeral = false
preauthorized = true preauthorized = true
description = "Reisen VM" description = "Reisen VM"
tags = [local.tailscale_tag_infra, local.tailscale_tag_genso, local.tailscale_tag_reisen] tags = local.tailscale_tags_reisen
depends_on = [tailscale_acl.tailnet] depends_on = [tailscale_acl.tailnet]
} }
@ -60,7 +93,7 @@ resource "tailscale_tailnet_key" "gensokyo" {
ephemeral = false ephemeral = false
preauthorized = true preauthorized = true
description = "Reisen VM" description = "Reisen VM"
tags = [local.tailscale_tag_infra, local.tailscale_tag_genso] tags = local.tailscale_tags_genso
depends_on = [tailscale_acl.tailnet] depends_on = [tailscale_acl.tailnet]
} }