Compare commits

...

4 commits

Author SHA1 Message Date
Jet
bbf4473659
fix: fix qemu for using hetzner 2026-03-14 18:34:33 -07:00
Jet Pham
a4ae929c4e feat: add bootstrap config for initial ssh configuation 2026-03-14 18:14:03 -07:00
Jet Pham
7576c1636e feat: add sead and icon and mod changes 2026-03-14 18:13:48 -07:00
Jet Pham
113888b22b feat: add terms and privacy page 2026-03-14 18:06:15 -07:00
12 changed files with 150 additions and 29 deletions

View file

@ -38,4 +38,10 @@
group = "grafana"; group = "grafana";
mode = "0400"; mode = "0400";
}; };
age.secrets.minecraft-seed = {
file = ./secrets/minecraft-seed.age;
owner = "root";
mode = "0400";
};
} }

View file

@ -1,7 +1,8 @@
{ config, pkgs, inputs, ... }: { config, pkgs, inputs, modulesPath, ... }:
{ {
imports = [ imports = [
(modulesPath + "/profiles/qemu-guest.nix")
./agenix.nix ./agenix.nix
./modules/minecraft.nix ./modules/minecraft.nix
./modules/hardening.nix ./modules/hardening.nix
@ -42,16 +43,6 @@
htop htop
tmux tmux
rsync rsync
(writeShellScriptBin "mc-whitelist" ''
docker exec minecraft rcon-cli whitelist add "$1"
'')
(writeShellScriptBin "mc-cmd" ''
docker exec minecraft rcon-cli "$@"
'')
(writeShellScriptBin "mc-logs" ''
docker logs --tail "''${1:-100}" -f minecraft
'')
]; ];
users.users.root.openssh.authorizedKeys.keys = [ users.users.root.openssh.authorizedKeys.keys = [

View file

@ -17,19 +17,25 @@
let let
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
serverHost = "root@compsigh-minecraft";
deploy = pkgs.writeShellScriptBin "nhs" '' deploy = pkgs.writeShellScriptBin "nhs" ''
nh os switch --hostname compsigh-minecraft --target-host root@compsigh-minecraft path:. "$@" nh os switch --hostname compsigh-minecraft --target-host root@compsigh-minecraft path:. "$@"
''; '';
mcWhitelist = pkgs.writeShellScriptBin "mc-whitelist" ''
ssh ${serverHost} "docker exec minecraft rcon-cli whitelist add $1"
'';
mcCmd = pkgs.writeShellScriptBin "mc-cmd" ''
ssh ${serverHost} "docker exec minecraft rcon-cli $*"
'';
mcLogs = pkgs.writeShellScriptBin "mc-logs" '' mcLogs = pkgs.writeShellScriptBin "mc-logs" ''
ssh ${serverHost} "docker logs --tail ''${1:-100} -f minecraft" ssh root@compsigh-minecraft "docker logs --tail ''${1:-100} -f minecraft"
'';
bootstrap = pkgs.writeShellScriptBin "mc-bootstrap" ''
set -euo pipefail
IP="''${1:?Usage: mc-bootstrap <server-ip>}"
echo "==> Installing NixOS (bootstrap config with port 22 open)..."
nix run github:nix-community/nixos-anywhere -- --flake path:.#compsigh-minecraft-bootstrap "root@$IP"
echo ""
echo "==> Removing old host key..."
ssh-keygen -R "$IP"
echo ""
echo "==> Fetching new server host key..."
echo "Run: ssh root@$IP cat /etc/ssh/ssh_host_ed25519_key.pub"
echo "Then update secrets/secrets.nix with the new key and run: agenix -r"
echo "Then run: nhs"
''; '';
in in
{ {
@ -44,11 +50,25 @@
]; ];
}; };
# Bootstrap config: opens port 22 on public interface for initial setup
nixosConfigurations.compsigh-minecraft-bootstrap = nixpkgs.lib.nixosSystem {
inherit system;
specialArgs = { inherit inputs; };
modules = [
disko.nixosModules.disko
inputs.agenix.nixosModules.default
./disk-config.nix
./configuration.nix
{
networking.firewall.allowedTCPPorts = [ 22 ];
}
];
};
devShells.${system}.default = pkgs.mkShell { devShells.${system}.default = pkgs.mkShell {
packages = [ packages = [
deploy deploy
mcWhitelist bootstrap
mcCmd
mcLogs mcLogs
pkgs.nh pkgs.nh
inputs.agenix.packages.${system}.default inputs.agenix.packages.${system}.default
@ -56,9 +76,8 @@
shellHook = '' shellHook = ''
echo "compsigh minecraft server" echo "compsigh minecraft server"
echo " mc-bootstrap first-time install (mc-bootstrap <ip>)"
echo " nhs deploy to server" echo " nhs deploy to server"
echo " mc-whitelist add a player (mc-whitelist PlayerName)"
echo " mc-cmd run rcon command (mc-cmd whitelist list)"
echo " mc-logs tail server logs" echo " mc-logs tail server logs"
echo " agenix manage secrets" echo " agenix manage secrets"
''; '';

View file

@ -12,6 +12,8 @@ in
# minecraft.compsigh.club → redirect to git repo # minecraft.compsigh.club → redirect to git repo
"${domain}" = { "${domain}" = {
extraConfig = '' extraConfig = ''
redir /terms ${gitRepo}/blob/main/terms.txt permanent
redir /privacy ${gitRepo}/blob/main/privacy.txt permanent
redir ${gitRepo} permanent redir ${gitRepo} permanent
''; '';
}; };

View file

@ -27,11 +27,17 @@ in
"channelId": "1482486447591391285", "channelId": "1482486447591391285",
"consoleLogChannelId": "1482487413153464330", "consoleLogChannelId": "1482487413153464330",
"useWebhook": true, "useWebhook": true,
"updateChannelTopic": true,
"channelTopicUpdateInterval": 300000,
"allowedMentions": ["users", "roles"],
"broadcastPlayerCommandExecution": false,
"announceServerStartStop": true, "announceServerStartStop": true,
"announcePlayerJoinLeave": true, "announcePlayerJoinLeave": true,
"announceDeathMessages": true, "announceDeathMessages": true,
"announceAdvancements": true, "announceAdvancements": true,
"broadcastChatMessages": true, "broadcastChatMessages": true,
"notifyUpdates": false,
"mentionAdminsForUpdates": false,
"adminsIds": [ "adminsIds": [
"1008533670426050704", "1008533670426050704",
"839601350865584158", "839601350865584158",

View file

@ -7,6 +7,7 @@
allowedTCPPorts = [ 80 443 25565 ]; # Caddy HTTP/HTTPS + Minecraft allowedTCPPorts = [ 80 443 25565 ]; # Caddy HTTP/HTTPS + Minecraft
allowedUDPPorts = [ 24454 ]; # Simple Voice Chat allowedUDPPorts = [ 24454 ]; # Simple Voice Chat
trustedInterfaces = [ "tailscale0" ]; # Full access over Tailscale (SSH, etc.) trustedInterfaces = [ "tailscale0" ]; # Full access over Tailscale (SSH, etc.)
checkReversePath = "loose"; # Required for Tailscale
logRefusedConnections = true; logRefusedConnections = true;
}; };

View file

@ -51,10 +51,12 @@ let
# QoL # QoL
"oneplayersleep" "oneplayersleep"
"netherportalfix" "netherportalfix"
"blossomlib"
"blossomtpa"
"double-shulker-shell-drops"
"afkplus"
# Moderation # Moderation
"luckperms"
"banhammer"
"ledger" "ledger"
"styled-chat" "styled-chat"
@ -103,15 +105,19 @@ in
MEMORY = "2560M"; MEMORY = "2560M";
MAX_PLAYERS = "10"; MAX_PLAYERS = "10";
DIFFICULTY = "hard"; DIFFICULTY = "hard";
PVP = "FALSE";
VIEW_DISTANCE = "10"; VIEW_DISTANCE = "10";
SIMULATION_DISTANCE = "10"; SIMULATION_DISTANCE = "10";
ENABLE_WHITELIST = "TRUE"; ENABLE_WHITELIST = "TRUE";
ENFORCE_WHITELIST = "TRUE"; ENFORCE_WHITELIST = "TRUE";
WHITELIST = "jetpham"; WHITELIST = "jetpham";
MOTD = "meet cool people \\u0026\\u0026 build cool things"; OPS = "jetpham";
MOTD = "meet cool people \\u00A7e\\u0026\\u0026\\u00A7r build cool things";
OVERRIDE_ICON = "TRUE";
MODRINTH_PROJECTS = modrinthMods; MODRINTH_PROJECTS = modrinthMods;
JVM_XX_OPTS = jvmFlags; JVM_XX_OPTS = jvmFlags;
}; };
environmentFiles = [ "/run/minecraft-seed.env" ];
extraOptions = [ extraOptions = [
"--memory=3g" "--memory=3g"
"--cpus=2" "--cpus=2"
@ -126,14 +132,26 @@ in
"d ${mcDataDir} 0755 root root -" "d ${mcDataDir} 0755 root root -"
]; ];
# Copy Chunky config (concurrency: 1 for background generation) # Write seed env file and copy mod configs before container starts
systemd.services.minecraft-mod-configs = { systemd.services.minecraft-mod-configs = {
description = "Copy mod configs into Minecraft data volume"; description = "Set up mod configs and seed for Minecraft container";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
before = [ "docker-minecraft.service" ]; before = [ "docker-minecraft.service" ];
after = [ "agenix.service" ];
serviceConfig = { serviceConfig = {
Type = "oneshot"; Type = "oneshot";
ExecStart = pkgs.writeShellScript "setup-mod-configs" '' ExecStart = pkgs.writeShellScript "setup-mod-configs" ''
set -euo pipefail
# Write seed from agenix secret
SEED=$(cat ${config.age.secrets.minecraft-seed.path})
printf 'SEED=%s\n' "$SEED" > /run/minecraft-seed.env
chmod 600 /run/minecraft-seed.env
# Server icon
cp ${../server-icon.png} ${mcDataDir}/server-icon.png
# Mod configs
mkdir -p ${mcDataDir}/plugins/Chunky mkdir -p ${mcDataDir}/plugins/Chunky
cp ${../configs/chunky.yml} ${mcDataDir}/plugins/Chunky/config.yml cp ${../configs/chunky.yml} ${mcDataDir}/plugins/Chunky/config.yml

45
privacy.txt Normal file
View file

@ -0,0 +1,45 @@
compsigh Minecraft — Privacy Policy
Last updated: 2026-03-14
1. What We Collect
- Minecraft username and UUID (required to join the server)
- Discord username and user ID (used for chat bridging and admin
commands)
- Chat messages sent in-game and in the bridged Discord channel
(relayed between platforms in real time)
- In-game actions (block placement, breakage, chest access, etc.)
logged by the Ledger mod for grief prevention
- Server logs (connection IPs, join/leave times, errors)
2. How Data Is Used
- Chat messages are bridged between Minecraft and Discord and are
visible in both platforms.
- Action logs are used solely for grief investigation and rollback.
- Server logs are used for debugging and moderation.
- Admin Discord user IDs are stored in the bot configuration to
control who can run server commands from Discord.
3. Data Storage
- World data and action logs are stored on the server and backed up
to Backblaze B2 cloud storage.
- Chat messages are stored by Discord per their own retention
policies. The server does not independently archive chat.
- Server logs are stored on the server and rotate automatically.
4. Data Sharing
We do not sell, share, or provide your data to any third party.
Backblaze B2 is used solely for encrypted backup storage.
5. Data Retention
- World backups are retained per our Backblaze B2 lifecycle policy.
- Server logs are retained for up to 30 days.
- In-game action logs persist in the world data indefinitely.
6. Your Rights
You may request to see what data we have about you or ask for its
deletion by contacting a server admin on Discord. Deleting your
data may require removing you from the whitelist.
7. Contact
For privacy questions, reach out to a server admin on Discord.

BIN
secrets/minecraft-seed.age Normal file

Binary file not shown.

View file

@ -9,4 +9,5 @@ in
"b2-application-key.age".publicKeys = [ server admin ]; "b2-application-key.age".publicKeys = [ server admin ];
"grafana-admin-password.age".publicKeys = [ server admin ]; "grafana-admin-password.age".publicKeys = [ server admin ];
"grafana-secret-key.age".publicKeys = [ server admin ]; "grafana-secret-key.age".publicKeys = [ server admin ];
"minecraft-seed.age".publicKeys = [ server admin ];
} }

BIN
server-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

32
terms.txt Normal file
View file

@ -0,0 +1,32 @@
compsigh Minecraft — Terms of Service
Last updated: 2026-03-14
1. Acceptance
By joining the compsigh Minecraft server or interacting with the
compsigh Minecraft Discord bot, you agree to these terms and the
compsigh Code of Conduct: https://compsigh.club/docs/code-of-conduct
2. Minecraft Server Rules
In addition to the compsigh Code of Conduct:
- No griefing, cheating, or exploiting.
- Server admins reserve the right to ban players at their discretion.
3. Access
The server is whitelist-only. Access may be granted or revoked at
any time without notice.
4. Availability
The server is provided as-is with no uptime guarantees. It may go
offline for maintenance, updates, or any other reason.
5. Data
See our Privacy Policy for details on what data is collected and how
it is used.
6. Changes
These terms may be updated at any time. Continued use of the server
constitutes acceptance of any changes.
7. Contact
For questions, reach out to a server admin on Discord.