initial commit
This commit is contained in:
commit
47c42dc7a6
14 changed files with 490 additions and 0 deletions
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# NixOS Build artifacts
|
||||||
|
result
|
||||||
|
result-*
|
||||||
|
|
||||||
|
# Secrets (Untracked)
|
||||||
|
secrets/secrets.nix
|
||||||
|
secrets/tailscale-auth
|
||||||
|
secrets/forgejo-db-pass
|
||||||
|
secrets/stalwart-admin-pass
|
||||||
|
secrets/searx-secret-key
|
||||||
|
secrets/rcon-pass
|
||||||
|
|
||||||
|
# Only track the example file
|
||||||
|
!secrets.nix.example
|
||||||
|
|
||||||
|
# IDEs
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
19
README.md
Normal file
19
README.md
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# extremist software
|
||||||
|
|
||||||
|
nixos config for the hetzner vps.
|
||||||
|
|
||||||
|
services:
|
||||||
|
- forgejo (git)
|
||||||
|
- stalwart (mail)
|
||||||
|
- searx (search)
|
||||||
|
- conduit (matrix)
|
||||||
|
- minecraft (fabric + optimization mods)
|
||||||
|
- caddy (reverse proxy)
|
||||||
|
- grafana/prometheus (monitoring)
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
`nix run github:nix-community/nixos-anywhere -- --flake .#extremist-software --impure root@<ip>`
|
||||||
|
|
||||||
|
secrets:
|
||||||
|
copy `secrets.nix.example` to `secrets/secrets.nix` and fill it in.
|
||||||
|
repo uses impure build cause i dont want to manage encrypted secret files in git right now.
|
||||||
60
configuration.nix
Normal file
60
configuration.nix
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
{ config, pkgs, modulesPath, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./modules/caddy.nix
|
||||||
|
./modules/forgejo.nix
|
||||||
|
./modules/mail.nix
|
||||||
|
./modules/searx.nix
|
||||||
|
./modules/matrix.nix
|
||||||
|
./modules/minecraft.nix
|
||||||
|
./modules/monitoring.nix
|
||||||
|
# Impure Secrets
|
||||||
|
./secrets/secrets.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
# ... (rest of imports block replaced by ./secrets/secrets.nix being added to imports)
|
||||||
|
|
||||||
|
|
||||||
|
# Bootloader
|
||||||
|
boot.loader.grub.enable = true;
|
||||||
|
boot.loader.grub.efiSupport = true;
|
||||||
|
boot.loader.grub.efiInstallAsRemovable = true;
|
||||||
|
|
||||||
|
# Networking
|
||||||
|
networking.hostName = "extremist-software";
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 443 25565 ]; # HTTP, HTTPS, Minecraft
|
||||||
|
networking.firewall.allowedUDPPorts = [ 25565 ]; # Minecraft
|
||||||
|
|
||||||
|
# Tailscale
|
||||||
|
services.tailscale.enable = true;
|
||||||
|
# We assume the user will authenticate manually or via a one-time key service
|
||||||
|
# For now, let's enable it and allow the user to run `tailscale up` or provision via key
|
||||||
|
|
||||||
|
# Users
|
||||||
|
users.users.root.openssh.authorizedKeys.keys = [
|
||||||
|
# User should add their key here
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5..."
|
||||||
|
];
|
||||||
|
|
||||||
|
# SSH - Secure it
|
||||||
|
services.openssh = {
|
||||||
|
enable = true;
|
||||||
|
settings.PasswordAuthentication = false;
|
||||||
|
settings.PermitRootLogin = "prohibit-password";
|
||||||
|
};
|
||||||
|
|
||||||
|
# System
|
||||||
|
system.stateVersion = "24.05";
|
||||||
|
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||||
|
nixpkgs.config.allowUnfree = true; # Allow unfree packages (Minecraft, etc.)
|
||||||
|
|
||||||
|
# Time
|
||||||
|
time.timeZone = "UTC";
|
||||||
|
|
||||||
|
# ZRAM for limited RAM
|
||||||
|
zramSwap.enable = true;
|
||||||
|
zramSwap.memoryPercent = 50;
|
||||||
|
|
||||||
|
# Secrets handled via ./secrets/secrets.nix import
|
||||||
|
}
|
||||||
36
disk-config.nix
Normal file
36
disk-config.nix
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
disko.devices = {
|
||||||
|
disk = {
|
||||||
|
main = {
|
||||||
|
device = "/dev/sda"; # Usually /dev/sda or /dev/vda on Hetzner VPS
|
||||||
|
type = "disk";
|
||||||
|
content = {
|
||||||
|
type = "gpt";
|
||||||
|
partitions = {
|
||||||
|
boot = {
|
||||||
|
size = "1M";
|
||||||
|
type = "EF02"; # for grub MBR
|
||||||
|
};
|
||||||
|
ESP = {
|
||||||
|
size = "512M";
|
||||||
|
type = "EF00";
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = "vfat";
|
||||||
|
mountpoint = "/boot";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
root = {
|
||||||
|
size = "100%";
|
||||||
|
content = {
|
||||||
|
type = "filesystem";
|
||||||
|
format = "ext4";
|
||||||
|
mountpoint = "/";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
102
flake.lock
generated
Normal file
102
flake.lock
generated
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"disko": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1771271879,
|
||||||
|
"narHash": "sha256-Vn32sMuvV35ChjVGZE4d8NNmCq3E/6HjaK2uVUUp2JI=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "disko",
|
||||||
|
"rev": "e963ed5aea88ad0c093adde7c1c2abd4e1b48beb",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "disko",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-compat": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1747046372,
|
||||||
|
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nix-minecraft": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1771296409,
|
||||||
|
"narHash": "sha256-p0fEFcqNnhYBKsHTint5pwkcnQk1b68OeQJh95B9Adg=",
|
||||||
|
"owner": "Infinidoge",
|
||||||
|
"repo": "nix-minecraft",
|
||||||
|
"rev": "22cb60087e549a90f6b0347e84ac178c0c9085ad",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "Infinidoge",
|
||||||
|
"repo": "nix-minecraft",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1771008912,
|
||||||
|
"narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=",
|
||||||
|
"owner": "nixos",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "a82ccc39b39b621151d6732718e3e250109076fa",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nixos",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"disko": "disko",
|
||||||
|
"nix-minecraft": "nix-minecraft",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
26
flake.nix
Normal file
26
flake.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
description = "NixOS Configuration for extremist.software Hetzner VPS";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
|
disko.url = "github:nix-community/disko";
|
||||||
|
disko.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
|
||||||
|
nix-minecraft.url = "github:Infinidoge/nix-minecraft";
|
||||||
|
nix-minecraft.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, disko, nix-minecraft, ... }@inputs: {
|
||||||
|
nixosConfigurations.extremist-software = nixpkgs.lib.nixosSystem {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
specialArgs = { inherit inputs; };
|
||||||
|
modules = [
|
||||||
|
disko.nixosModules.disko
|
||||||
|
nix-minecraft.nixosModules.minecraft-servers
|
||||||
|
./disk-config.nix
|
||||||
|
./configuration.nix
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
49
modules/caddy.nix
Normal file
49
modules/caddy.nix
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.caddy = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"extremist.software" = {
|
||||||
|
extraConfig = ''
|
||||||
|
respond "Hi"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
"git.extremist.software" = {
|
||||||
|
extraConfig = ''
|
||||||
|
reverse_proxy localhost:3000
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
"mail.extremist.software" = {
|
||||||
|
# Stalwart handles its own certs usually, or we can proxy UI here
|
||||||
|
# Stalwart UI is usually on 8080
|
||||||
|
extraConfig = ''
|
||||||
|
reverse_proxy localhost:8080
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
"search.extremist.software" = {
|
||||||
|
extraConfig = ''
|
||||||
|
reverse_proxy localhost:8082
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
"status.extremist.software" = {
|
||||||
|
extraConfig = ''
|
||||||
|
reverse_proxy localhost:3001 # Grafana
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
"matrix.extremist.software" = {
|
||||||
|
extraConfig = ''
|
||||||
|
reverse_proxy /_matrix/* localhost:6167
|
||||||
|
reverse_proxy /_synapse/client/* localhost:6167
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
}
|
||||||
24
modules/forgejo.nix
Normal file
24
modules/forgejo.nix
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.forgejo = {
|
||||||
|
enable = true;
|
||||||
|
database.type = "postgres";
|
||||||
|
# Enable support for Large File Storage
|
||||||
|
lfs.enable = true;
|
||||||
|
settings = {
|
||||||
|
server = {
|
||||||
|
DOMAIN = "git.extremist.software";
|
||||||
|
ROOT_URL = "https://git.extremist.software/";
|
||||||
|
HTTP_PORT = 3000;
|
||||||
|
};
|
||||||
|
# You can configure SMTP here using secrets if needed
|
||||||
|
};
|
||||||
|
# Secret for DB password set in secrets.nix
|
||||||
|
};
|
||||||
|
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.postgresql_15;
|
||||||
|
};
|
||||||
|
}
|
||||||
28
modules/mail.nix
Normal file
28
modules/mail.nix
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.stalwart = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
server = {
|
||||||
|
hostname = "mail.extremist.software";
|
||||||
|
tls = {
|
||||||
|
enable = true;
|
||||||
|
implicit = false; # StartTLS usually on 587
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# authentication.fallback-admin set in secrets.nix
|
||||||
|
# Stalwart configuration is quite extensive.
|
||||||
|
# By default it listens on standard ports (25, 465, 587, 993, 4190)
|
||||||
|
# and provides a web admin UI on 8080.
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Open Firewalls for Mail
|
||||||
|
networking.firewall.allowedTCPPorts = [
|
||||||
|
25 465 587 # SMTP
|
||||||
|
993 # IMAP (Secure)
|
||||||
|
4190 # Sieve
|
||||||
|
8080 # Admin UI (Reverse proxied, but good to double check loopback)
|
||||||
|
];
|
||||||
|
}
|
||||||
16
modules/matrix.nix
Normal file
16
modules/matrix.nix
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.matrix-conduit = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
global = {
|
||||||
|
server_name = "matrix.extremist.software";
|
||||||
|
allow_registration = true; # Disable after creating first user
|
||||||
|
port = 6167;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ 6167 8448 ];
|
||||||
|
}
|
||||||
33
modules/minecraft.nix
Normal file
33
modules/minecraft.nix
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
{ config, pkgs, inputs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [ inputs.nix-minecraft.nixosModules.minecraft-servers ];
|
||||||
|
|
||||||
|
nixpkgs.overlays = [ inputs.nix-minecraft.overlay ];
|
||||||
|
|
||||||
|
services.minecraft-servers = {
|
||||||
|
enable = true;
|
||||||
|
eula = true;
|
||||||
|
|
||||||
|
servers = {
|
||||||
|
fabric = {
|
||||||
|
enable = true;
|
||||||
|
# Use fetchPackwizModpack to get the server with mods
|
||||||
|
package = pkgs.fetchPackwizModpack {
|
||||||
|
url = "https://raw.githubusercontent.com/Fabulously-Optimized/fabulously-optimized/main/Packwiz/1.20.1/pack.toml";
|
||||||
|
packHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # User must update this hash!
|
||||||
|
};
|
||||||
|
serverProperties = {
|
||||||
|
motd = "Extremist Software Optimized Server";
|
||||||
|
difficulty = "hard";
|
||||||
|
view-distance = 10;
|
||||||
|
simulation-distance = 10;
|
||||||
|
max-players = 5;
|
||||||
|
enable-rcon = true;
|
||||||
|
# "rcon.password" set in secrets.nix
|
||||||
|
};
|
||||||
|
jvmOpts = "-Xms2G -Xmx2500M -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 -XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 -XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -Dusing.aikars.flags=https://mcflags.emc.gs -Daikars.new.flags=true";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
35
modules/monitoring.nix
Normal file
35
modules/monitoring.nix
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.prometheus = {
|
||||||
|
enable = true;
|
||||||
|
port = 9090;
|
||||||
|
exporters = {
|
||||||
|
node = {
|
||||||
|
enable = true;
|
||||||
|
enabledCollectors = [ "systemd" ];
|
||||||
|
port = 9100;
|
||||||
|
};
|
||||||
|
# Stalwart and Conduit might have exporters too
|
||||||
|
};
|
||||||
|
scrapeConfigs = [
|
||||||
|
{
|
||||||
|
job_name = "node";
|
||||||
|
static_configs = [{
|
||||||
|
targets = [ "127.0.0.1:9100" ];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.grafana = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
server = {
|
||||||
|
http_port = 3001;
|
||||||
|
http_addr = "127.0.0.1";
|
||||||
|
domain = "status.extremist.software";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
19
modules/searx.nix
Normal file
19
modules/searx.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.searx = {
|
||||||
|
enable = true;
|
||||||
|
# settings.server.secret_key set in secrets.nix
|
||||||
|
settings = {
|
||||||
|
server = {
|
||||||
|
port = 8082;
|
||||||
|
bind_address = "127.0.0.1";
|
||||||
|
# secret_key = ...; # Set via env var in file
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Inject secret via env vars or file substitution if possible
|
||||||
|
# Or use `environment.etc` to place config file if service allows.
|
||||||
|
# For now, simplistic setup.
|
||||||
|
}
|
||||||
25
secrets.nix.example
Normal file
25
secrets.nix.example
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{ pkgs, config, lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# Forgejo
|
||||||
|
services.forgejo.settings.database.PASSWORD = "changeme_forgejo_db";
|
||||||
|
|
||||||
|
# Stalwart Mail
|
||||||
|
services.stalwart.settings.authentication.fallback-admin.secret = "changeme_stalwart_admin";
|
||||||
|
|
||||||
|
# Searx
|
||||||
|
services.searx.settings.server.secret_key = "changeme_searx_secret";
|
||||||
|
|
||||||
|
# Minecraft RCON
|
||||||
|
services.minecraft-servers.servers.fabric.serverProperties."rcon.password" = "changeme_rcon";
|
||||||
|
|
||||||
|
# Tailscale Auth Key (needs to be a file for the service usually, or use pre-auth)
|
||||||
|
# For Tailscale, standard module uses 'authKeyFile'.
|
||||||
|
# We can create a file in the store for it since this is an impure secrets file anyway.
|
||||||
|
|
||||||
|
# For Tailscale, let's just write valid one-liner to a file via environment.etc if needed,
|
||||||
|
# or use the 'authKey' option if available (it is not, usually).
|
||||||
|
# We will stick to environment.etc JUST for Tailscale or file-based secrets.
|
||||||
|
environment.etc."secrets/tailscale-auth".text = "tskey-auth-PLACEHOLDER";
|
||||||
|
services.tailscale.authKeyFile = "/etc/secrets/tailscale-auth";
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue